From 02d24d4688bf624384a41a30199bb7dbd37570e7 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 28 Aug 2020 13:28:23 -1000 Subject: [PATCH 001/283] Initial commit --- .babelrc | 18 + .circleci/config.yml | 97 + .env.example | 9 + .eslintrc.json | 201 + .gitignore | 33 + .haml-lint.yml | 6 + .overcommit.yml | 963 + .pairs | 15 + .postcssrc.yml | 3 + .rubocop.yml | 212 + .ruby-version | 1 + .stylelintrc | 161 + Gemfile | 94 + Gemfile.lock | 492 + Procfile | 3 + Procfile.local | 3 + README.md | 109 + Rakefile | 6 + app.json | 168 + app/assets/config/manifest.js | 3 + app/assets/images/favicon.ico | Bin 0 -> 1437 bytes app/assets/images/loader-black.svg | 12 + app/assets/images/loader-cyan.svg | 12 + app/assets/images/loader-white.svg | 12 + app/assets/images/lost.jpg | Bin 0 -> 319991 bytes app/assets/images/spinner.gif | Bin 0 -> 24772 bytes app/assets/images/svg/baseline-notes-24px.svg | 4 + app/assets/images/svg/g-learn-lockup.svg | 37 + app/assets/images/svg/galvanize-logo.svg | 48 + app/assets/images/svg/github-icon.svg | 6 + app/assets/images/svg/mobile-logo.svg | 24 + app/assets/images/svg/octicon-git-branch.svg | 1 + .../images/svg/svg-sprite-action-symbol.svg | 1 + .../images/svg/svg-sprite-av-symbol.svg | 1 + .../images/svg/svg-sprite-device-symbol.svg | 1 + .../images/svg/svg-sprite-image-symbol.svg | 1 + .../svg/svg-sprite-navigation-symbol.svg | 1 + app/assets/javascripts/application.js | 7 + app/assets/javascripts/mobile.js | 10 + app/assets/stylesheets/application.scss | 103 + app/assets/stylesheets/base.scss | 66 + app/assets/stylesheets/bootstrap-custom.scss | 13 + app/assets/stylesheets/cohorts.scss | 9 + .../components/_404-container.scss | 43 + .../stylesheets/components/_action-menu.scss | 53 + .../components/_activity-dashboard.scss | 253 + .../components/_activity-feed.scss | 69 + .../components/_api-interactions.scss | 62 + .../stylesheets/components/_api_token.scss | 37 + .../components/_auth-style-search.scss | 26 + .../stylesheets/components/_blocks-index.scss | 133 + .../stylesheets/components/_blocks-stats.scss | 70 + .../stylesheets/components/_button.scss | 57 + .../stylesheets/components/_callouts.scss | 54 + .../components/_challenge-block.scss | 698 + .../components/_challenge_status.scss | 18 + .../components/_checkbox-input.scss | 15 + .../components/_checkpoint-landing.scss | 170 + .../components/_checkpoint-submission.scss | 152 + ...heckpoint-submissions-columns-student.scss | 72 + .../_checkpoint-submissions-columns.scss | 36 + .../_checkpoint-submissions-index.scss | 5 + .../_checkpoint_student_scores.scss | 184 + .../_checkpoint_submisstion_state.scss | 29 + .../components/_checkpoint_toolbar.scss | 207 + .../stylesheets/components/_code-block.scss | 21 + .../components/_cohort-submissions-table.scss | 798 + .../components/_cohort_releases.scss | 205 + .../stylesheets/components/_cohorts.scss | 957 + .../components/_content-file-show.scss | 342 + .../components/_content-file-sidebar.scss | 308 + .../_curriculum-checkpoint-summary.scss | 46 + .../components/_curriculum-progress.scss | 239 + .../stylesheets/components/_curriculum.scss | 277 + .../components/_dropdown-component.scss | 79 + .../components/_external-link.scss | 13 + .../components/_flash-message.scss | 21 + .../stylesheets/components/_footer.scss | 66 + .../components/_grade-buttons.scss | 12 + .../components/_integer_picker.scss | 57 + .../components/_lp-style-button.scss | 127 + .../components/_mastery-table.scss | 382 + app/assets/stylesheets/components/_modal.scss | 195 + .../components/_navigation-dropdown.scss | 103 + .../components/_notifications.scss | 202 + .../stylesheets/components/_pagination.scss | 46 + app/assets/stylesheets/components/_pill.scss | 78 + .../components/_point_grade_buttons.scss | 19 + .../components/_primary-header.scss | 100 + .../components/_primary-navigation.scss | 132 + .../stylesheets/components/_progress.scss | 59 + .../components/_progress_thresholds_key.scss | 35 + .../_progress_thresholds_modal.scss | 20 + .../_progress_thresholds_slider.scss | 8 + .../stylesheets/components/_search-bar.scss | 44 + .../components/_secondary-navigation.scss | 58 + .../stylesheets/components/_slideshow.scss | 264 + .../components/_sort-dropdown-component.scss | 52 + .../components/_standard-card.scss | 234 + .../components/_standard-cards.scss | 159 + .../components/_standards-mastery-beans.scss | 35 + .../components/_status_picker.scss | 132 + .../components/_student-mastery-table.scss | 156 + .../components/_student-name-bar.scss | 92 + .../_submissions-dashboard-table.scss | 506 + .../stylesheets/components/_svg-icon.scss | 33 + .../stylesheets/components/_thresholds.scss | 33 + .../components/_universal-list.scss | 46 + .../components/_universal-row.scss | 68 + .../components/_universal-table.scss | 121 + .../stylesheets/components/_user-avatar.scss | 65 + .../stylesheets/components/_video-player.scss | 10 + app/assets/stylesheets/components/badge.scss | 26 + .../components/challenge-detail-comments.scss | 94 + .../components/challenge-detail-view.scss | 38 + .../components/challenge-timeline.scss | 69 + .../components/new-comment-form.scss | 94 + .../stylesheets/components/partnerup.scss | 249 + .../components/progress-table.scss | 355 + .../stylesheets/hopscotch-overrides.scss | 100 + app/assets/stylesheets/mixins.scss | 197 + app/assets/stylesheets/mobile.scss | 1 + .../mobile/_submissions-dashboard-table.scss | 51 + app/assets/stylesheets/typography.scss | 5 + app/assets/stylesheets/variables.scss | 136 + .../activity_feed_item_component_props.rb | 120 + .../notifications_component_props.rb | 22 + .../standard_card_component_props.rb | 9 + app/controllers/api/application_controller.rb | 114 + .../api/v1/blocks/releases_controller.rb | 28 + app/controllers/api/v1/blocks_controller.rb | 52 + .../blocks/content_files_controller.rb | 218 + .../api/v1/cohorts/blocks/units_controller.rb | 19 + .../api/v1/cohorts/cohorts_controller.rb | 118 + .../api/v1/cohorts/users_controller.rb | 163 + .../api/v1/content_files_controller.rb | 34 + .../api/v1/pineapple_controller.rb | 6 + app/controllers/api/v1/releases_controller.rb | 70 + app/controllers/api/v1/users_controller.rb | 55 + app/controllers/application_controller.rb | 147 + app/controllers/blocks/releases_controller.rb | 69 + app/controllers/blocks_controller.rb | 77 + .../blocks/content_files_controller.rb | 306 + .../activities_controller.rb | 80 + .../cohorts/cohort_releases_controller.rb | 156 + .../checkpoint_submissions_controller.rb | 338 + .../submitted_challenge_answers_controller.rb | 346 + .../cohorts/content_files_controller.rb | 260 + .../cohorts/pairings_controller.rb | 49 + .../cohorts/standards_controller.rb | 43 + .../activities_controller.rb | 84 + .../cohorts/users/challenges_controller.rb | 182 + .../cohorts/users/performances_controller.rb | 41 + app/controllers/cohorts/users_controller.rb | 154 + app/controllers/cohorts_controller.rb | 463 + .../concerns/api/content_visibility_crud.rb | 58 + .../concerns/api/exception_handler.rb | 75 + app/controllers/concerns/api/response.rb | 5 + app/controllers/home_controller.rb | 28 + app/controllers/notifications_controller.rb | 32 + app/controllers/permalinks_controller.rb | 85 + .../submitted_challenge_answers_controller.rb | 120 + .../webhooks/auth/cohorts_controller.rb | 34 + .../webhooks/auth/users_controller.rb | 24 + app/exporters/performance_exporter.rb | 55 + app/exporters/progress_exporter.rb | 107 + app/finders/block_finder.rb | 7 + app/finders/checkpoint_submission_finder.rb | 74 + app/finders/cohort_user_finder.rb | 9 + app/finders/content_file_finder.rb | 20 + app/finders/performance_finder.rb | 71 + app/finders/release_finder.rb | 24 + app/finders/standard_finder.rb | 10 + .../submitted_challenge_answer_finder.rb | 28 + app/finders/user_finder.rb | 8 + app/helpers/application_helper.rb | 34 + app/helpers/json_helper.rb | 9 + app/helpers/secondary_navigation_helper.rb | 10 + app/helpers/standard_navigation_helper.rb | 165 + app/javascript/api.d.ts | 550 + app/javascript/components/AceEditor.tsx | 133 + app/javascript/components/Badge.tsx | 18 + app/javascript/components/Button.tsx | 26 + app/javascript/components/ButtonTo.tsx | 75 + app/javascript/components/Dropdown.tsx | 40 + app/javascript/components/Icon.tsx | 20 + app/javascript/components/Loading.tsx | 59 + app/javascript/components/Marked.tsx | 25 + app/javascript/components/Menu.tsx | 45 + app/javascript/components/Notifications.tsx | 116 + app/javascript/components/ProcessingIcon.tsx | 31 + app/javascript/components/RowKebab.tsx | 36 + app/javascript/components/ScoreCircle.tsx | 23 + app/javascript/components/SidebarProgress.tsx | 28 + app/javascript/components/SortDropdown.tsx | 36 + app/javascript/components/StandardBean.tsx | 36 + app/javascript/components/SvgRenderer.tsx | 26 + app/javascript/components/Timestamp.tsx | 16 + app/javascript/components/UserAvatar.tsx | 29 + .../components/activities/NewActivityForm.tsx | 138 + .../components/api/ApiInteractions.tsx | 142 + app/javascript/components/api/ApiToken.tsx | 86 + .../components/blocks/BlockPage-v2.tsx | 331 + .../components/blocks/BlocksIndex-v2.tsx | 140 + .../components/blocks/BlocksNewModal.tsx | 187 + .../components/blocks/BlocksNewRelease.tsx | 82 + .../components/blocks/BlocksRow.tsx | 105 + .../components/blocks/BlocksShow.tsx | 131 + .../components/blocks/BlocksStats.tsx | 59 + .../components/blocks/CohortsTooltip.tsx | 22 + .../components/challenges/AvatarBar.tsx | 45 + .../challenges/ChallengeDetailView.tsx | 69 + .../components/challenges/ChallengeShow.tsx | 128 + .../challenge_block/ChallengeActionBlock.tsx | 71 + .../challenge_block/ChallengeBlock.tsx | 1042 + .../ChallengeDetailActivities.tsx | 45 + .../ChallengeExplanationBlock.tsx | 42 + .../ChallengeFeedbackBlock.tsx | 109 + .../challenge_block/ChallengeHintsBlock.tsx | 86 + .../challenge_block/ChallengeInputs.tsx | 199 + .../ChallengeLocalTestResults.tsx | 47 + .../challenge_block/ChallengeRubricBlock.tsx | 42 + .../challenge_block/ChallengeStatus.tsx | 73 + .../challenge_block/ChallengeStatusBar.tsx | 77 + .../challenge_block/ChallengeTestResults.tsx | 34 + .../challenge_block/ChallengeTests.tsx | 42 + .../challenge_block/ChallengeTimeLine.tsx | 56 + .../challenge_block/GradeIndicator.tsx | 58 + .../challenge_block/GradedTimestamp.tsx | 33 + .../challenge_block/StatusPicker.tsx | 33 + .../challenges/local/run-local-challenge.ts | 137 + .../components/challenges/local/sandbox.ts | 192 + .../challenges/local/stack-traces.ts | 48 + .../CheckpointAfterSubmitButton.tsx | 17 + .../CheckpointAfterSubmitModal.tsx | 136 + .../CheckpointAfterSubmitModalError.tsx | 46 + .../CheckpointSubmissionChallenges.tsx | 62 + .../checkpoints/CheckpointSubmissionShow.tsx | 364 + .../checkpoints/CheckpointSubmissionState.tsx | 41 + .../CheckpointSubmissionStudentNameBar.tsx | 118 + .../components/cohorts/CohortsIndex.tsx | 494 + .../activity_dashboard/ActivityDashboard.tsx | 207 + .../cohorts/activity_feed/ActivityFeed.tsx | 67 + .../cohort_releases/ReleaseVersionsTable.tsx | 81 + .../cohort_submissions/CohortSubmissions.tsx | 602 + .../CohortSubmissionsChallengeItem.tsx | 113 + .../CohortSubmissionsLessonRow.tsx | 97 + .../CohortSubmissionsPerformanceModal.tsx | 110 + .../CohortSubmissionsStandardRow.tsx | 97 + .../CohortSubmissionsStudentColumn.tsx | 226 + .../CohortSubmissionsStudentNameBar.tsx | 70 + .../CohortSubmissionsStudentStandard.tsx | 208 + .../CohortSubmissionsTable.tsx | 73 + .../CohortSubmissionsUnitPercent.tsx | 104 + .../cohorts/mastery/MasteryTable.tsx | 312 + .../components/cohorts/mastery/MetricRow.tsx | 25 + .../cohorts/mastery/MetricsBody.tsx | 79 + .../cohorts/mastery/PerformanceCell.tsx | 53 + .../cohorts/mastery/PerformanceRow.tsx | 65 + .../cohorts/mastery/ReleaseBody.tsx | 75 + .../cohorts/mastery/StandardRow.tsx | 62 + .../cohorts/mastery/StudentHeader.tsx | 30 + .../cohorts/mastery/StudentMasteryTable.tsx | 310 + .../cohorts/mastery/StudentReleaseRow.tsx | 50 + .../components/cohorts/pairing/GroupPairs.tsx | 243 + .../cohorts/pairing/InnerStudentList.tsx | 48 + .../components/cohorts/pairing/NewPairing.tsx | 294 + .../cohorts/pairing/PairingBoard.tsx | 62 + .../cohorts/pairing/StudentItem.tsx | 77 + .../cohorts/pairing/StudentList.tsx | 51 + .../progress/MasteryProgressionBar.tsx | 40 + .../progress/ProgressThresholdCellHeaders.tsx | 89 + .../cohorts/progress/StudentProgress.tsx | 409 + .../cohorts/progress/StudentProgressBar.tsx | 40 + .../cohorts/progress/StudentProgressCells.tsx | 75 + .../cohorts/progress/StudentProgressRow.tsx | 64 + .../progress/StudentProgressSortArrow.tsx | 22 + .../cohorts/settings/BranchReleaseModal.tsx | 73 + .../settings/CohortBlockReleaseRow.tsx | 374 + .../cohorts/settings/CohortContentTab.tsx | 204 + .../cohorts/settings/CohortInfo.tsx | 40 + .../cohorts/settings/CohortSettingsResync.tsx | 327 + .../cohorts/settings/CohortSettingsTabs.tsx | 176 + .../settings/CohortVisibilitySection.tsx | 197 + .../settings/CurriculumSettingsTab.tsx | 198 + .../cohorts/settings/ReleaseVersionModal.tsx | 97 + .../cohorts/settings/ReleaseVersionRow.tsx | 160 + .../cohorts/settings/UserImport.tsx | 138 + .../components/cohorts/settings/UserKebab.tsx | 71 + .../AnswerStatusRollup.tsx | 150 + .../HeaderStandardContainer.tsx | 79 + .../StandardContainer.tsx | 56 + .../SubmissionsDashboard.tsx | 389 + .../SubmissionsDashboardChallengeItem.tsx | 69 + .../SubmissionsDashboardContentFileRow.tsx | 100 + .../SubmissionsDashboardStudentColumn.tsx | 69 + .../SubmissionsDashboardStudentNameBar.tsx | 68 + .../SubmissionsDashboardTable.tsx | 61 + .../components/content_files/ActionMenus.tsx | 150 + .../components/content_files/Lesson.tsx | 158 + .../content_files/MarkdownRenderer.tsx | 43 + .../components/content_files/PDFRenderer.tsx | 57 + .../components/content_files/SideBar.tsx | 248 + .../content_files/SubmissionRenderer.tsx | 92 + .../content_files/checkpoints/Checkpoint.tsx | 680 + .../checkpoints/CheckpointActionBar.tsx | 192 + .../checkpoints/CheckpointDetails.tsx | 271 + .../checkpoints/CheckpointLanding.tsx | 159 + .../CheckpointLandingAttribute.tsx | 39 + .../checkpoints/CheckpointPairs.tsx | 172 + .../content_files/checkpoints/PairAvatars.tsx | 31 + .../student_scores/CheckpointStudentRow.tsx | 175 + .../CheckpointStudentScores.tsx | 187 + .../curriculum/CheckpointSummary.tsx | 36 + .../curriculum/CohortCurriculum.tsx | 186 + .../curriculum/CurriculumStandardCard.tsx | 126 + .../curriculum/ProgressIndicators.tsx | 134 + .../components/curriculum/StandardBeans.tsx | 28 + .../curriculum/StandardsRenderer.tsx | 123 + .../StudentOverallProgressDoughnut.tsx | 105 + app/javascript/components/lib/ace.ts | 92 + .../notifications/NotificationsIcon.tsx | 26 + .../shared/ActionMenu/ActionMenu.tsx | 32 + .../components/shared/Button/Button.tsx | 39 + .../ChallengePoints/ChallengePoints.tsx | 123 + .../ChallengePoints/PartialCreditBaton.tsx | 18 + .../shared/ChallengePoints/SpinText.tsx | 79 + .../IntegerPicker/IntegerPicker.tsx | 29 + .../components/shared/DonutRing/DonutRing.tsx | 177 + .../components/ColorDonut/ColorDonut.tsx | 74 + .../CompleteDonut/CompleteDonut.tsx | 43 + .../UngradedDonut/UngradedDonut.tsx | 24 + .../UngradedDonut/UngradedDonut.tsx | 31 + .../ErrorMessagesTable/ErrorMessagesTable.tsx | 26 + .../shared/FlashAlert/FlashAlert.tsx | 29 + .../shared/FormatNumber/FormatNumber.tsx | 20 + .../components/shared/Icons/AlertSign.tsx | 16 + .../components/shared/Icons/Clear.tsx | 18 + .../components/shared/Icons/CloseButton.tsx | 16 + .../components/shared/Icons/Done.tsx | 16 + .../shared/Icons/KeyboardArrowDown.tsx | 16 + .../shared/Icons/KeyboardArrowUp.tsx | 16 + .../components/shared/Icons/SettingsCog.tsx | 15 + .../components/shared/Icons/StatusCircle.tsx | 17 + .../MasteryProgressBar/MasteryProgressBar.tsx | 74 + .../components/shared/Modal/Modal.tsx | 77 + .../shared/Pagination/Pagination.tsx | 40 + .../PercentageProgressBar.tsx | 107 + .../components/shared/Pill/Pill.tsx | 35 + .../PointGradeButtons/PointGradeButtons.tsx | 78 + .../shared/PointGradeButtons/SpinText.tsx | 79 + .../shared/ProgressBar/ProgressBar.tsx | 43 + .../ProgressThresholdsKey.tsx | 32 + .../ProgressThresholdsModal.tsx | 70 + .../ProgressThresholdsSlider.tsx | 46 + .../components/shared/SearchBar/SearchBar.tsx | 102 + .../components/shared/Slideshow/Slideshow.tsx | 210 + .../shared/UngradedDonut/UngradedDonut.tsx | 31 + .../shared/UniversalList/UniversalList.tsx | 44 + .../shared/UniversalRow/UniversalRow.tsx | 66 + .../shared/UniversalTable/UniversalTable.tsx | 163 + .../standards/CompletionScoringBlock.tsx | 128 + .../standards/MasteryScoringBlock.tsx | 100 + .../components/standards/StandardCard.tsx | 211 + .../standards/StandardScoreButton.tsx | 41 + .../standards/StandardScoringBlock.tsx | 72 + .../standards/StandardTopicsRollups.tsx | 67 + .../components/vendor/ReactTooltip.js | 3 + app/javascript/generated/routes.ts | 548 + app/javascript/globals.ts | 145 + app/javascript/lib/http.ts | 58 + app/javascript/lib/utils.ts | 191 + app/javascript/packs/application.js | 13 + app/javascript/packs/server_rendering.js | 5 + app/jobs/application_job.rb | 2 + app/jobs/branch_release_notifier_job.rb | 16 + app/jobs/checkpoint_paired_submission_job.rb | 42 + .../content_file_default_visibility_job.rb | 42 + app/jobs/content_file_visit_job.rb | 28 + app/jobs/create_api_interaction_job.rb | 29 + app/jobs/create_release_job.rb | 110 + app/jobs/evaluate_code_snippet_job.rb | 17 + app/jobs/evaluate_custom_snippet_job.rb | 17 + app/jobs/evaluate_project_job.rb | 16 + app/jobs/grade_timed_checkpoint_job.rb | 90 + app/jobs/import_student_work_job.rb | 121 + app/jobs/progress_csv_job.rb | 16 + app/jobs/release_notifier_job.rb | 15 + app/jobs/resync_course_job.rb | 27 + app/jobs/set_block_caches_job.rb | 11 + app/jobs/slack_challenge_performance_job.rb | 29 + app/jobs/slack_dev_notify_job.rb | 5 + app/jobs/slack_ds_prep_job.rb | 5 + app/jobs/slack_job.rb | 30 + app/jobs/slack_se_prep_job.rb | 5 + app/jobs/slack_student_job.rb | 5 + app/jobs/student_progress_auth_job.rb | 20 + app/jobs/switch_to_branch_job.rb | 68 + app/mailers/application_mailer.rb | 10 + app/mailers/user_mailer.rb | 13 + app/models/activity.rb | 27 + app/models/api_interaction.rb | 12 + app/models/application_record.rb | 3 + app/models/block.rb | 59 + app/models/challenge.rb | 95 + app/models/checkpoint_submission.rb | 126 + app/models/cohort.rb | 117 + app/models/cohort_release.rb | 15 + app/models/cohort_user.rb | 13 + app/models/concerns/findable_by_uid.rb | 13 + app/models/concerns/read_only_model.rb | 8 + app/models/content_file.rb | 51 + app/models/content_visibility.rb | 19 + app/models/job_result.rb | 4 + app/models/lesson_visit.rb | 31 + app/models/notification.rb | 9 + app/models/pairing.rb | 7 + app/models/performance.rb | 22 + app/models/release.rb | 87 + app/models/resync_job_result.rb | 82 + app/models/section.rb | 15 + app/models/standard.rb | 30 + app/models/submitted_challenge_answer.rb | 107 + app/models/unit.rb | 1 + app/models/user.rb | 125 + app/models/user_last_viewed_standard_path.rb | 6 + app/policies/activity_policy.rb | 5 + app/policies/application_policy.rb | 58 + app/policies/block_policy.rb | 8 + app/policies/checkpoint_submission_policy.rb | 11 + app/policies/cohort_policy.rb | 87 + app/policies/cohort_release_policy.rb | 9 + app/policies/cohort_user_policy.rb | 9 + app/policies/content_file_policy.rb | 36 + app/policies/notification_policy.rb | 26 + app/policies/performance_policy.rb | 7 + app/policies/release_policy.rb | 4 + .../submitted_challenge_answer_policy.rb | 26 + app/policies/user_policy.rb | 45 + app/presenters/activity_presenter.rb | 14 + app/presenters/block_presenter/for_block.rb | 35 + .../block_presenter/for_cohort_releases.rb | 41 + .../for_cohort_releases_new.rb | 12 + .../block_presenter/for_releases.rb | 33 + ...h_submitted_challenge_answers_presenter.rb | 138 + .../checkpoint_submission_presenter.rb | 60 + .../for_index.rb | 103 + .../for_student_row.rb | 9 + .../for_cohort_setup.rb | 33 + app/presenters/cohort_setup/visibility.rb | 40 + .../for_curriculum_last_viewed.rb | 48 + .../content_file_presenter/for_footer.rb | 26 + .../content_file_presenter/for_show.rb | 100 + .../content_file_presenter/for_sidebar.rb | 15 + app/presenters/performance_presenter.rb | 20 + .../standard_card_component_props.rb | 9 + .../for_challenge_detail_view.rb | 15 + .../for_checkpoint_submission.rb | 15 + .../standard_presenter/for_standard_card.rb | 109 + .../for_submissions_dashboard.rb | 80 + app/presenters/stat_progress_presenter.rb | 29 + app/presenters/student_progress_presenter.rb | 117 + .../submissions_dashboard_presenter.rb | 184 + .../submitted_challenge_answer_presenter.rb | 123 + app/presenters/user_presenter/for_avatar.rb | 13 + app/services/activity_aggregator_service.rb | 135 + app/services/assessment_service.rb | 156 + app/services/auth_resolver_service.rb | 83 + app/services/auto_assign_release_service.rb | 7 + app/services/checkpoint_submission_service.rb | 56 + .../cohort_standard_progress_service.rb | 130 + .../cohort_student_progress_service.rb | 75 + .../completion_mode_percent_service.rb | 31 + app/services/course_validator.rb | 221 + ...eate_submitted_challenge_answer_service.rb | 205 + app/services/curriculum_progress_service.rb | 181 + .../download_github_repository_service.rb | 61 + .../download_gitlab_repository_service.rb | 71 + app/services/download_repository_service.rb | 40 + .../download_s3_repository_service.rb | 42 + app/services/git_url_service.rb | 53 + app/services/mastery_average_service.rb | 7 + app/services/mastery_mode_percent_service.rb | 14 + app/services/mock_mixpanel.rb | 13 + app/services/notification_service.rb | 58 + app/services/preview_content_file_service.rb | 136 + app/services/release_destroyer_service.rb | 39 + app/services/release_helper_service.rb | 182 + app/services/resync_course_service.rb | 121 + app/services/s3_asset_uploader_service.rb | 51 + app/services/segment_track_service.rb | 33 + app/services/sql_challenge_db_service.rb | 63 + app/services/standard_submissions_service.rb | 362 + app/views/api_interactions.html.haml | 5 + app/views/api_token.html.haml | 2 + app/views/apitome/docs/_headers.html.erb | 6 + app/views/apitome/docs/_params.html.erb | 30 + app/views/blocks/blockpagev2.html.haml | 3 + app/views/blocks/index.html.haml | 3 + app/views/blocks/new.html.haml | 12 + app/views/blocks/releases/new.html.haml | 7 + app/views/blocks/show.html.haml | 6 + app/views/cohorts/_cohort_info.html.haml | 23 + .../_completion_progress_donut.html.haml | 13 + app/views/cohorts/_user_table.html.haml | 30 + .../cohorts/activity_dashboard.html.haml | 3 + .../blocks/content_files/_footer.html.haml | 23 + .../blocks/content_files/show.html.haml | 223 + .../cohorts/cohort_releases/index.html.haml | 56 + app/views/cohorts/content.html.haml | 15 + .../checkpoint_submissions/show.html.haml | 28 + app/views/cohorts/course_stats.html.haml | 5 + app/views/cohorts/error.html.haml | 4 + app/views/cohorts/feed.html.haml | 24 + app/views/cohorts/index.html.haml | 23 + app/views/cohorts/partnerup.html.haml | 27 + app/views/cohorts/setup.html.haml | 20 + app/views/cohorts/show.html.haml | 29 + .../checkpoint_submissions/index.html.haml | 9 + app/views/cohorts/unit_progress.html.haml | 15 + app/views/cohorts/users.html.haml | 54 + .../cohorts/users/challenges/show.html.haml | 31 + .../cohorts/users/mastery/index.html.haml | 8 + .../users/submissions_dashboard.html.haml | 9 + app/views/error_404.html.haml | 8 + app/views/error_500.html.haml | 7 + app/views/home/index.html.haml | 3 + .../layouts/_primary_navigation.html.haml | 56 + .../layouts/_secondary_navigation.html.haml | 9 + app/views/layouts/application.html.haml | 53 + app/views/layouts/mailer.html.erb | 13 + app/views/layouts/mailer.text.erb | 1 + app/views/permalinks/permalink.html.haml | 15 + app/views/shared/_content_file_js.html.haml | 103 + .../shared/_hopscotch_callbacks_js.html.haml | 19 + app/views/shared/_intercom_js.html.haml | 42 + app/views/shared/_segment_js.html.haml | 7 + app/views/user_mailer/send_file.html | 1 + .../user_mailer/user_import_work.html.haml | 4 + bin/bundle | 3 + bin/rails | 4 + bin/rake | 4 + bin/setup | 38 + bin/update | 29 + bin/webpack | 15 + bin/webpack-dev-server | 15 + bin/yarn | 11 + config.ru | 5 + config/application.rb | 58 + config/boot.rb | 3 + config/database.yml | 16 + config/environment.rb | 5 + config/environments/development.rb | 61 + config/environments/production.rb | 105 + config/environments/test.rb | 47 + config/get-routes-audit.md | 169 + config/honeybadger.yml | 2 + config/initializers/apitome.rb | 66 + .../application_controller_renderer.rb | 8 + config/initializers/assets.rb | 14 + config/initializers/auth_api.rb | 21 + config/initializers/aws.rb | 39 + config/initializers/backtrace_silencers.rb | 7 + config/initializers/cookies_serializer.rb | 5 + .../initializers/filter_parameter_logging.rb | 4 + config/initializers/inflections.rb | 16 + config/initializers/mime_types.rb | 4 + .../new_framework_defaults_5_1.rb | 14 + config/initializers/octokit.rb | 4 + config/initializers/pagy.rb | 158 + config/initializers/pundit.rb | 15 + config/initializers/rack_attack.rb | 19 + config/initializers/segment.rb | 17 + config/initializers/sidekiq.rb | 4 + config/initializers/wrap_parameters.rb | 14 + config/locales/en.yml | 33 + config/puma.rb | 57 + config/routes.rb | 184 + config/secrets.yml | 65 + config/sidekiq.yml | 4 + config/spring.rb | 6 + config/webpack/development.js | 17 + config/webpack/environment.js | 5 + config/webpack/loaders/typescript.js | 10 + config/webpack/production.js | 5 + config/webpack/test.js | 5 + config/webpacker.yml | 70 + db/drawio_schema_with_explanations.xml | 1 + db/migrate/20171003191909_create_users.rb | 15 + .../20171005135550_add_admin_to_users.rb | 6 + ...05140042_rename_users_profile_image_url.rb | 5 + db/migrate/20171006195948_create_blocks.rb | 9 + db/migrate/20171009194124_create_releases.rb | 11 + ...20171011232501_add_sync_errors_to_block.rb | 5 + db/migrate/20171012200106_create_standards.rb | 15 + db/migrate/20171016192627_create_cohorts.rb | 20 + .../20171017205306_create_cohort_users.rb | 13 + ...s_from_label_and_pretty_name_on_cohorts.rb | 8 + .../20171019165527_create_content_files.rb | 12 + .../20171019192005_create_cohort_releases.rb | 10 + .../20171023211301_create_challenges.rb | 23 + ...024202210_create_checkpoint_submissions.rb | 13 + ...3630_create_submitted_challenge_answers.rb | 19 + .../20171025211916_create_performances.rb | 16 + ...25223250_add_autoscore_to_content_files.rb | 5 + ...171026193413_add_title_to_content_files.rb | 5 + ...71102144822_cohort_release_unique_index.rb | 5 + ...14_add_unique_constraint_to_block_title.rb | 5 + ...2171128_add_position_to_cohort_releases.rb | 5 + .../20171127223701_create_activities.rb | 19 + ...3_create_user_last_viewed_standard_path.rb | 18 + ...20171130185636_add_uid_to_content_files.rb | 5 + .../20171205211624_add_slack_data_to_user.rb | 7 + ...213519_add_standard_uid_to_performances.rb | 9 + ..._relative_display_name_to_content_files.rb | 5 + .../20180110223429_add_auth_roles_to_user.rb | 5 + ...denormalize_submitted_challenge_answers.rb | 9 + ...20180110233303_add_roles_to_cohort_user.rb | 5 + ...4504_add_last_viewed_cohort_id_to_users.rb | 5 + ...0116174519_add_github_user_name_to_user.rb | 5 + ...16181937_add_taught_in_learn_to_cohorts.rb | 5 + ...80116213927_remove_forge_admin_and_role.rb | 6 + ...cohort_id_to_submitted_challenge_answer.rb | 6 + ...1642_denormalize_checkpoint_submissions.rb | 11 + .../20180125212203_rename_taught_in_learn.rb | 5 + .../20180125222044_change_learn_v2_default.rb | 5 + .../20180131220605_create_notifications.rb | 13 + ...180202225951_add_github_sha_to_releases.rb | 13 + ...d_use_latest_release_to_cohort_releases.rb | 5 + ...add_docker_directory_path_to_challenges.rb | 5 + ...80316222140_rename_cohort_title_to_name.rb | 5 + ...0180320162849_add_deleted_at_to_cohorts.rb | 5 + ...02212114_remove_pretty_name_from_cohort.rb | 5 + ...4504_add_used_by_application_to_cohorts.rb | 5 + ...0412223312_populate_used_by_application.rb | 15 + ..._add_feature_branch_columns_to_releases.rb | 7 + ...d_pending_release_id_to_cohort_releases.rb | 6 + ...180813205413_add_readme_text_to_release.rb | 5 + .../20180813213358_add_mode_to_cohort.rb | 5 + .../20180813214453_populate_mode_cohorts.rb | 11 + ...rt_id_to_user_last_viewed_standard_path.rb | 6 + .../20180824200753_create_lesson_visits.rb | 19 + ...112215710_add_preferred_campus_to_users.rb | 5 + .../20181114190340_create_job_results.rb | 14 + db/migrate/20181120221622_create_sections.rb | 10 + ...02104_add_section_id_to_cohort_releases.rb | 6 + ...add_challenge_completion_to_performance.rb | 5 + ...1213180900_add_show_tests_to_challenges.rb | 5 + ...81214175640_create_content_visibilities.rb | 12 + ...add_default_visibility_to_content_files.rb | 5 + db/migrate/20190410171829_create_pairings.rb | 12 + ...190423171448_add_data_path_to_challenge.rb | 6 + ...10_add_last_setup_visit_to_cohort_users.rb | 5 + ...23958_add_max_attempts_to_content_files.rb | 6 + ...70059_add_allowed_attempts_to_challenge.rb | 5 + ...000_remove_max_attempts_from_challenges.rb | 6 + ...ints_and_success_criteria_to_challenges.rb | 6 + ...1_drop_learn_version_columns_on_cohorts.rb | 6 + .../20190829203949_add_settings_to_cohorts.rb | 5 + ...dd_points_to_submitted_challenge_answer.rb | 5 + ...03_add_points_to_checkpoint_submissions.rb | 6 + ...uccess_criteria_to_rubric_on_challenges.rb | 6 + ...20191001214559_add_topics_to_challenges.rb | 5 + ...1001221324_add_perf_data_to_submissions.rb | 8 + ...1008211403_add_release_id_to_challenges.rb | 5 + .../20191009214248_add_user_id_to_release.rb | 5 + ...visibility_type_to_content_visibilities.rb | 5 + .../20191031212058_add_api_token_to_user.rb | 5 + .../20191108211234_add_preview_to_releases.rb | 6 + .../20191114211938_create_api_interactions.rb | 16 + ...19225902_add_sandbox_boolean_to_cohorts.rb | 6 + .../20191206230913_add_sync_warnings.rb | 7 + ...165026_add_metadata_to_api_interactions.rb | 5 + ...add_assign_partial_credig_to_challenges.rb | 5 + ..._add_end_time_to_checkpoint_submissions.rb | 5 + ...201253_change_cohort_default_percentage.rb | 5 + ...13201649_add_time_limit_to_content_file.rb | 5 + ..._submitted_at_to_checkpoint_submissions.rb | 5 + ..._add_allow_paired_submissions_to_cohort.rb | 5 + ...ubmission_ids_to_checkpoint_submissinos.rb | 5 + ...0200430165251_add_external_to_challenge.rb | 6 + .../20200702155846_add_cache_to_blocks.rb | 7 + ...0200707164932_add_archived_at_to_blocks.rb | 5 + ...20_add_block_location_details_to_blocks.rb | 6 + ...00724195251_add_whitelabeled_to_cohorts.rb | 6 + ...4247_remove_block_uniqueness_pg_columns.rb | 6 + ...13_add_student_import_status_to_cohorts.rb | 6 + ...addd_docker_directory_zip_to_challenges.rb | 5 + ...0828165130_default_block_org_tog_school.rb | 5 + db/schema.rb | 400 + db/seeds.rb | 119 + doc/api.md | 29 + doc/api/cohorts/creating_a_new_cohort.json | 86 + .../cohorts/viewing_curriculum_details.json | 50 + .../content/update_content_visibility.json | 68 + .../creating_a_user_and_their_enrollment.json | 80 + .../unenrolling_a_user_from_a_cohort.json | 56 + .../updating_a_user's_enrollment_roles.json | 68 + .../viewing_cohort_enrollments.json | 50 + doc/api/index.json | 97 + doc/api/units/update_unit_visibility.json | 68 + doc/api/users/regenerate_user_token.json | 45 + lib/tasks/challenge_release_ids.rake | 8 + lib/tasks/checkpoint_resubmission.rake | 45 + lib/tasks/checkpoint_submission_points.rake | 30 + lib/tasks/content_visibility_update.rake | 8 + lib/tasks/course_progress.rake | 216 + lib/tasks/course_yaml_backfill.rake | 65 + lib/tasks/grade_checkpoints.rake | 9 + lib/tasks/object_space_count.rake | 11 + lib/tasks/prep_notifier.rake | 34 + lib/tasks/set_block_caches.rake | 16 + lib/tasks/spec.rake | 9 + lib/tasks/ts_routes.rake | 12 + lintspec.sh | 4 + package.json | 83 + public/404.html | 67 + public/422.html | 67 + public/500.html | 66 + public/apple-touch-icon-152x152.png | 0 .../apple-touch-icon-precomposed-152x152.png | 0 public/apple-touch-icon-precomposed.png | 0 public/apple-touch-icon.png | 0 .../assets/images/hopscotch-sprite-green.png | Bin 0 -> 5405 bytes .../assets/images/hopscotch-sprite-orange.png | Bin 0 -> 5374 bytes public/assets/images/jupyter-logo.png | Bin 0 -> 5922 bytes .../images/svg/checkpoint-is-rejected.svg | 15 + .../images/svg/checkpoint-is-scored.svg | 13 + .../images/svg/checkpoint-is-submitted.svg | 17 + public/assets/images/svg/github-icon.svg | 6 + public/assets/images/svg/gitlab-icon-rgb.svg | 1 + .../assets/images/svg/octicon-git-branch.svg | 1 + .../images/svg/redpriority_high-24px.svg | 12 + .../assets/images/svg/svg-link_off-24px.svg | 5 + .../images/svg/svg-sprite-action-symbol.svg | 1 + .../images/svg/svg-sprite-alert-symbol.svg | 1 + .../images/svg/svg-sprite-av-symbol.svg | 1 + .../images/svg/svg-sprite-content-symbol.svg | 1 + .../images/svg/svg-sprite-custom-symbol.svg | 18 + .../svg/svg-sprite-custom_material-symbol.svg | 1 + .../images/svg/svg-sprite-device-symbol.svg | 1 + .../images/svg/svg-sprite-file-symbol.svg | 1 + .../images/svg/svg-sprite-hardware-symbol.svg | 1 + .../svg/svg-sprite-navigation-symbol.svg | 1 + .../svg/svg-sprite-notification-symbol.svg | 1 + .../images/svg/svg-sprite-social-symbol.svg | 1 + public/favicon.ico | 0 public/javascripts/apitome/application.js | 31 + public/robots.txt | 1 + public/sandbox/chai.js | 5430 ++++++ public/sandbox/challenge-worker.js | 141 + public/sandbox/jasmine/boot.js | 207 + public/sandbox/jasmine/jasmine.js | 3298 ++++ public/sandbox/mocha/boot.js | 46 + public/sandbox/mocha/mocha.js | 16046 ++++++++++++++++ public/sandbox/mocha/test.html | 3 + public/sandbox/sandbox.html | 2 + public/sandbox/stacktrace.js | 489 + public/sandbox/worker.js | 2 + public/stylesheets/apitome/application.css | 269 + requirements.txt | 1 + scripts/sh/cohort_curriculum.sh | 10 + scripts/sh/content_file_mark_hidden.sh | 13 + scripts/sh/content_file_mark_visible.sh | 13 + scripts/sh/unit_mark_hidden.sh | 13 + scripts/sh/unit_mark_visible.sh | 13 + scripts/sql/checkpoint_answers.sql | 29 + .../sql/cohort_challenges_with_answers.sql | 27 + scripts/sql/cohort_prune_for_testing.sql | 194 + scripts/sql/percent_metrics.sql | 204 + scripts/sql/scrub_cohort_data.sql | 30 + ...activity_feed_item_component_props_spec.rb | 154 + .../notifications_component_props_spec.rb | 40 + .../standard_card_component_props_spec.rb | 29 + .../api/v1/blocks/releases_controller_spec.rb | 45 + .../api/v1/blocks_controller_spec.rb | 122 + .../blocks/content_files_controller_spec.rb | 339 + .../cohorts/blocks/units_controller_spec.rb | 59 + .../api/v1/cohorts/cohorts_controller_spec.rb | 162 + .../api/v1/cohorts/users_controller_spec.rb | 307 + .../api/v1/content_files_controller_spec.rb | 83 + .../api/v1/users_controller_spec.rb | 93 + .../application_controller_spec.rb | 26 + .../blocks/releases_controller_spec.rb | 56 + spec/controllers/blocks_controller_spec.rb | 54 + .../blocks/content_files_controller_spec.rb | 234 + .../activities_controller_spec.rb | 113 + .../cohort_releases_controller_spec.rb | 162 + .../checkpoint_submissions_controller_spec.rb | 492 + ...itted_challenge_answers_controller_spec.rb | 857 + .../cohorts/content_files_controller_spec.rb | 407 + .../cohorts/pairings_controller_spec.rb | 61 + .../cohorts/standards_controller_spec.rb | 116 + .../activities_controller_spec.rb | 99 + .../users/challenges_controller_spec.rb | 207 + .../users/performances_controller_spec.rb | 69 + .../cohorts/users_controller_spec.rb | 137 + spec/controllers/cohorts_controller_spec.rb | 543 + spec/controllers/home_controller_spec.rb | 116 + .../notifications_controller_spec.rb | 67 + .../controllers/permalinks_controller_spec.rb | 179 + ...itted_challenge_answers_controller_spec.rb | 151 + .../webhooks/auth/cohorts_controller_spec.rb | 154 + .../webhooks/auth/users_controller_spec.rb | 112 + spec/exporters/performance_exporter_spec.rb | 44 + spec/factories.rb | 246 + .../blocks/management_feature_spec.rb | 76 + .../cohorts/activity_dashboard_spec.rb | 50 + .../cohorts/checkpoint_submissions_spec.rb | 181 + .../cohorts/curriculum_feature_spec.rb | 360 + spec/features/cohorts/feed_feature_spec.rb | 25 + .../cohorts/management_feature_spec.rb | 737 + spec/features/cohorts/sandboxes_spec.rb | 37 + .../features/cohorts/student_progress_spec.rb | 320 + spec/features/cohorts/submissions_spec.rb | 491 + .../cohorts/users/challenges_feature_spec.rb | 352 + .../submissions_dashboard_feature_spec.rb | 52 + .../checkpoint_assessments_spec.rb | 632 + .../checkpoint_submissions_spec.rb | 375 + .../content_files/navigation_feature_spec.rb | 127 + .../features/content_files/permalinks_spec.rb | 62 + .../content_files/view_feature_spec.rb | 1885 ++ spec/features/home/header_feature_spec.rb | 181 + spec/features_helper.rb | 96 + spec/finders/block_finder_spec.rb | 30 + .../checkpoint_submission_finder_spec.rb | 183 + spec/finders/cohort_user_finder_spec.rb | 33 + spec/finders/content_file_finder_spec.rb | 99 + spec/finders/performance_finder_spec.rb | 167 + spec/finders/release_finder_spec.rb | 74 + spec/finders/standard_finder_spec.rb | 41 + .../submitted_challenge_answer_finder_spec.rb | 72 + spec/finders/user_finder_spec.rb | 15 + spec/fixtures/preview-content-file/preview.md | 105 + ..._docker_directories_test-docker-folder.zip | Bin 0 -> 212 bytes spec/fixtures/test-block-repo/README.md | 3 + .../test-block-repo/challenges-smoketest.md | 567 + spec/fixtures/test-block-repo/config.yaml | 18 + .../test-docker-folder/Dockerfile | 0 .../test-docker-folder/test.sh | 0 .../test-block-repo/folder/sibling.md | 3 + .../fixtures/test-block-repo/folder/target.md | 1 + .../test-block-repo/images/galvanize-logo.png | Bin 0 -> 4134 bytes .../test-block-repo/images/register_klass.gif | Bin 0 -> 20804 bytes .../test-block-repo/markdown-smoketesT.md | 107 + spec/fixtures/test-block-repo/target.md | 1 + spec/fixtures/test-block-repo/test.sql | 0 .../vcr_cassettes/github-branch-success.yml | 206 + .../github-course-yaml-not-found.yml | 70 + .../github-course-yaml-success-2.yml | 285 + .../github-course-yaml-success.yml | 295 + .../vcr_cassettes/github-not-found.yml | 69 + .../vcr_cassettes/github-repo-success.yml | 199 + .../gitlab-course-yaml-branch-failure.yml | 287 + .../gitlab-course-yaml-success.yml | 367 + .../vcr_cassettes/gitlab-not-found.yml | 115 + .../fixtures/vcr_cassettes/gitlab-success.yml | 239 + .../resync-course-job-success.yml | 587 + spec/helpers/json_helper_spec.rb | 66 + .../mastery_mode_percent_helper_spec.rb | 46 + .../standard_navigation_helper_spec.rb | 288 + spec/integration_helper.rb | 16 + spec/jobs/branch_release_notifier_job_spec.rb | 33 + .../checkpoint_paired_submission_job_spec.rb | 53 + ...ontent_file_default_visibility_job_spec.rb | 41 + spec/jobs/content_file_visit_job_spec.rb | 66 + spec/jobs/create_api_interaction_job_spec.rb | 39 + spec/jobs/create_release_job_spec.rb | 231 + spec/jobs/evaluate_code_snippet_job_spec.rb | 19 + spec/jobs/evaluate_custom_snippet_job_spec.rb | 19 + spec/jobs/evaluate_project_job_spec.rb | 20 + spec/jobs/grade_timed_checkpoint_job_spec.rb | 99 + spec/jobs/import_student_work_job_spec.rb | 78 + spec/jobs/release_notifier_job_spec.rb | 33 + spec/jobs/resync_course_job_spec.rb | 95 + spec/jobs/set_block_caches_job_spec.rb | 29 + spec/jobs/slack_ds_prep_job_spec.rb | 19 + spec/jobs/slack_se_prep_job_spec.rb | 19 + spec/jobs/slack_student_job_spec.rb | 21 + spec/jobs/switch_to_branch_job_spec.rb | 185 + spec/models/activity_spec.rb | 11 + spec/models/api_interaction_spec.rb | 16 + spec/models/block_spec.rb | 79 + spec/models/challenge_spec.rb | 184 + spec/models/checkpoint_submission_spec.rb | 276 + spec/models/cohort_release_spec.rb | 40 + spec/models/cohort_spec.rb | 278 + spec/models/cohort_user_spec.rb | 35 + spec/models/content_file_spec.rb | 90 + spec/models/content_visibility_spec.rb | 55 + spec/models/lesson_visit_spec.rb | 89 + spec/models/notification_spec.rb | 21 + spec/models/pairing_spec.rb | 10 + spec/models/performance_spec.rb | 51 + spec/models/release_spec.rb | 148 + spec/models/resync_job_result_spec.rb | 60 + spec/models/section_spec.rb | 7 + spec/models/standard_spec.rb | 52 + .../models/submitted_challenge_answer_spec.rb | 189 + .../user_last_viewed_standard_path_spec.rb | 21 + spec/models/user_spec.rb | 300 + spec/policies/cohort_policy_spec.rb | 41 + spec/policies/content_file_policy_spec.rb | 65 + spec/policies/user_policy_spec.rb | 42 + .../for_cohort_releases_new_spec.rb | 27 + .../for_cohort_releases_spec.rb | 77 + .../block_presenter/for_releases_spec.rb | 18 + ...mitted_challenge_answers_presenter_spec.rb | 169 + .../for_index_spec.rb | 161 + .../checkpoint_submission_presenter_spec.rb | 66 + .../for_curriculum_last_viewed_spec.rb | 35 + .../content_file_presenter/for_show_spec.rb | 232 + .../for_sidebar_spec.rb | 15 + .../for_checkpoint_submission_spec.rb | 29 + .../for_standard_card_spec.rb | 151 + .../student_progress_presenter_spec.rb | 186 + .../submissions_dashboard_presenter_spec.rb | 68 + ...bmitted_challenge_answer_presenter_spec.rb | 130 + .../activity_aggregator_service_spec.rb | 258 + spec/services/assessment_service_spec.rb | 334 + spec/services/auth_resolver_service_spec.rb | 334 + .../auto_assign_release_service_spec.rb | 27 + .../checkpoint_submission_service_spec.rb | 135 + .../cohort_standard_progress_service_spec.rb | 216 + spec/services/course_validator_spec.rb | 222 + .../curriculum_progress_service_spec.rb | 268 + .../download_repository_service_spec.rb | 78 + spec/services/git_url_service_spec.rb | 158 + spec/services/mastery_average_service_spec.rb | 23 + spec/services/notification_service_spec.rb | 122 + .../preview_content_file_service_spec.rb | 24 + .../release_destroyer_service_spec.rb | 45 + spec/services/resync_course_service_spec.rb | 200 + .../s3_asset_uploader_service_spec.rb | 18 + .../standard_submissions_service_spec.rb | 483 + spec/spec_helper.rb | 73 + spec/support/json_spec_matchers.rb | 76 + spec/support/mocktokit.rb | 31 + spec/support/object_creation_methods.rb | 21 + tsconfig.json | 26 + .../javascripts/bootstrap-datepicker.js | 8 + vendor/assets/javascripts/hopscotch.js | 17 + vendor/assets/javascripts/react-tooltip.js | 2405 +++ .../stylesheets/bootstrap-datepicker.css | 7 + vendor/assets/stylesheets/hopscotch.css | 17 + yarn.lock | 8233 ++++++++ 946 files changed, 114047 insertions(+) create mode 100644 .babelrc create mode 100644 .circleci/config.yml create mode 100644 .env.example create mode 100644 .eslintrc.json create mode 100644 .gitignore create mode 100644 .haml-lint.yml create mode 100644 .overcommit.yml create mode 100644 .pairs create mode 100644 .postcssrc.yml create mode 100644 .rubocop.yml create mode 100644 .ruby-version create mode 100644 .stylelintrc create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 Procfile create mode 100644 Procfile.local create mode 100644 README.md create mode 100644 Rakefile create mode 100644 app.json create mode 100644 app/assets/config/manifest.js create mode 100644 app/assets/images/favicon.ico create mode 100644 app/assets/images/loader-black.svg create mode 100644 app/assets/images/loader-cyan.svg create mode 100644 app/assets/images/loader-white.svg create mode 100644 app/assets/images/lost.jpg create mode 100644 app/assets/images/spinner.gif create mode 100644 app/assets/images/svg/baseline-notes-24px.svg create mode 100644 app/assets/images/svg/g-learn-lockup.svg create mode 100644 app/assets/images/svg/galvanize-logo.svg create mode 100644 app/assets/images/svg/github-icon.svg create mode 100644 app/assets/images/svg/mobile-logo.svg create mode 100644 app/assets/images/svg/octicon-git-branch.svg create mode 100755 app/assets/images/svg/svg-sprite-action-symbol.svg create mode 100644 app/assets/images/svg/svg-sprite-av-symbol.svg create mode 100644 app/assets/images/svg/svg-sprite-device-symbol.svg create mode 100644 app/assets/images/svg/svg-sprite-image-symbol.svg create mode 100755 app/assets/images/svg/svg-sprite-navigation-symbol.svg create mode 100644 app/assets/javascripts/application.js create mode 100644 app/assets/javascripts/mobile.js create mode 100644 app/assets/stylesheets/application.scss create mode 100644 app/assets/stylesheets/base.scss create mode 100644 app/assets/stylesheets/bootstrap-custom.scss create mode 100644 app/assets/stylesheets/cohorts.scss create mode 100644 app/assets/stylesheets/components/_404-container.scss create mode 100644 app/assets/stylesheets/components/_action-menu.scss create mode 100644 app/assets/stylesheets/components/_activity-dashboard.scss create mode 100644 app/assets/stylesheets/components/_activity-feed.scss create mode 100644 app/assets/stylesheets/components/_api-interactions.scss create mode 100644 app/assets/stylesheets/components/_api_token.scss create mode 100644 app/assets/stylesheets/components/_auth-style-search.scss create mode 100644 app/assets/stylesheets/components/_blocks-index.scss create mode 100644 app/assets/stylesheets/components/_blocks-stats.scss create mode 100644 app/assets/stylesheets/components/_button.scss create mode 100644 app/assets/stylesheets/components/_callouts.scss create mode 100644 app/assets/stylesheets/components/_challenge-block.scss create mode 100644 app/assets/stylesheets/components/_challenge_status.scss create mode 100644 app/assets/stylesheets/components/_checkbox-input.scss create mode 100644 app/assets/stylesheets/components/_checkpoint-landing.scss create mode 100644 app/assets/stylesheets/components/_checkpoint-submission.scss create mode 100644 app/assets/stylesheets/components/_checkpoint-submissions-columns-student.scss create mode 100644 app/assets/stylesheets/components/_checkpoint-submissions-columns.scss create mode 100644 app/assets/stylesheets/components/_checkpoint-submissions-index.scss create mode 100644 app/assets/stylesheets/components/_checkpoint_student_scores.scss create mode 100644 app/assets/stylesheets/components/_checkpoint_submisstion_state.scss create mode 100644 app/assets/stylesheets/components/_checkpoint_toolbar.scss create mode 100644 app/assets/stylesheets/components/_code-block.scss create mode 100644 app/assets/stylesheets/components/_cohort-submissions-table.scss create mode 100644 app/assets/stylesheets/components/_cohort_releases.scss create mode 100644 app/assets/stylesheets/components/_cohorts.scss create mode 100644 app/assets/stylesheets/components/_content-file-show.scss create mode 100644 app/assets/stylesheets/components/_content-file-sidebar.scss create mode 100644 app/assets/stylesheets/components/_curriculum-checkpoint-summary.scss create mode 100644 app/assets/stylesheets/components/_curriculum-progress.scss create mode 100644 app/assets/stylesheets/components/_curriculum.scss create mode 100644 app/assets/stylesheets/components/_dropdown-component.scss create mode 100644 app/assets/stylesheets/components/_external-link.scss create mode 100644 app/assets/stylesheets/components/_flash-message.scss create mode 100644 app/assets/stylesheets/components/_footer.scss create mode 100644 app/assets/stylesheets/components/_grade-buttons.scss create mode 100644 app/assets/stylesheets/components/_integer_picker.scss create mode 100644 app/assets/stylesheets/components/_lp-style-button.scss create mode 100644 app/assets/stylesheets/components/_mastery-table.scss create mode 100644 app/assets/stylesheets/components/_modal.scss create mode 100644 app/assets/stylesheets/components/_navigation-dropdown.scss create mode 100644 app/assets/stylesheets/components/_notifications.scss create mode 100644 app/assets/stylesheets/components/_pagination.scss create mode 100644 app/assets/stylesheets/components/_pill.scss create mode 100644 app/assets/stylesheets/components/_point_grade_buttons.scss create mode 100644 app/assets/stylesheets/components/_primary-header.scss create mode 100644 app/assets/stylesheets/components/_primary-navigation.scss create mode 100644 app/assets/stylesheets/components/_progress.scss create mode 100644 app/assets/stylesheets/components/_progress_thresholds_key.scss create mode 100644 app/assets/stylesheets/components/_progress_thresholds_modal.scss create mode 100644 app/assets/stylesheets/components/_progress_thresholds_slider.scss create mode 100644 app/assets/stylesheets/components/_search-bar.scss create mode 100644 app/assets/stylesheets/components/_secondary-navigation.scss create mode 100644 app/assets/stylesheets/components/_slideshow.scss create mode 100644 app/assets/stylesheets/components/_sort-dropdown-component.scss create mode 100644 app/assets/stylesheets/components/_standard-card.scss create mode 100644 app/assets/stylesheets/components/_standard-cards.scss create mode 100644 app/assets/stylesheets/components/_standards-mastery-beans.scss create mode 100644 app/assets/stylesheets/components/_status_picker.scss create mode 100644 app/assets/stylesheets/components/_student-mastery-table.scss create mode 100644 app/assets/stylesheets/components/_student-name-bar.scss create mode 100644 app/assets/stylesheets/components/_submissions-dashboard-table.scss create mode 100644 app/assets/stylesheets/components/_svg-icon.scss create mode 100644 app/assets/stylesheets/components/_thresholds.scss create mode 100644 app/assets/stylesheets/components/_universal-list.scss create mode 100644 app/assets/stylesheets/components/_universal-row.scss create mode 100644 app/assets/stylesheets/components/_universal-table.scss create mode 100644 app/assets/stylesheets/components/_user-avatar.scss create mode 100644 app/assets/stylesheets/components/_video-player.scss create mode 100644 app/assets/stylesheets/components/badge.scss create mode 100644 app/assets/stylesheets/components/challenge-detail-comments.scss create mode 100644 app/assets/stylesheets/components/challenge-detail-view.scss create mode 100644 app/assets/stylesheets/components/challenge-timeline.scss create mode 100644 app/assets/stylesheets/components/new-comment-form.scss create mode 100644 app/assets/stylesheets/components/partnerup.scss create mode 100644 app/assets/stylesheets/components/progress-table.scss create mode 100644 app/assets/stylesheets/hopscotch-overrides.scss create mode 100644 app/assets/stylesheets/mixins.scss create mode 100644 app/assets/stylesheets/mobile.scss create mode 100644 app/assets/stylesheets/mobile/_submissions-dashboard-table.scss create mode 100644 app/assets/stylesheets/typography.scss create mode 100644 app/assets/stylesheets/variables.scss create mode 100644 app/component_props/activity_feed_item_component_props.rb create mode 100644 app/component_props/notifications_component_props.rb create mode 100644 app/component_props/standard_card_component_props.rb create mode 100644 app/controllers/api/application_controller.rb create mode 100644 app/controllers/api/v1/blocks/releases_controller.rb create mode 100644 app/controllers/api/v1/blocks_controller.rb create mode 100644 app/controllers/api/v1/cohorts/blocks/content_files_controller.rb create mode 100644 app/controllers/api/v1/cohorts/blocks/units_controller.rb create mode 100644 app/controllers/api/v1/cohorts/cohorts_controller.rb create mode 100644 app/controllers/api/v1/cohorts/users_controller.rb create mode 100644 app/controllers/api/v1/content_files_controller.rb create mode 100644 app/controllers/api/v1/pineapple_controller.rb create mode 100644 app/controllers/api/v1/releases_controller.rb create mode 100644 app/controllers/api/v1/users_controller.rb create mode 100644 app/controllers/application_controller.rb create mode 100644 app/controllers/blocks/releases_controller.rb create mode 100644 app/controllers/blocks_controller.rb create mode 100644 app/controllers/cohorts/blocks/content_files_controller.rb create mode 100644 app/controllers/cohorts/checkpoint_submissions/activities_controller.rb create mode 100644 app/controllers/cohorts/cohort_releases_controller.rb create mode 100644 app/controllers/cohorts/content_files/checkpoint_submissions_controller.rb create mode 100644 app/controllers/cohorts/content_files/submitted_challenge_answers_controller.rb create mode 100644 app/controllers/cohorts/content_files_controller.rb create mode 100644 app/controllers/cohorts/pairings_controller.rb create mode 100644 app/controllers/cohorts/standards_controller.rb create mode 100644 app/controllers/cohorts/submitted_challenge_answers/activities_controller.rb create mode 100644 app/controllers/cohorts/users/challenges_controller.rb create mode 100644 app/controllers/cohorts/users/performances_controller.rb create mode 100644 app/controllers/cohorts/users_controller.rb create mode 100644 app/controllers/cohorts_controller.rb create mode 100644 app/controllers/concerns/api/content_visibility_crud.rb create mode 100644 app/controllers/concerns/api/exception_handler.rb create mode 100644 app/controllers/concerns/api/response.rb create mode 100644 app/controllers/home_controller.rb create mode 100644 app/controllers/notifications_controller.rb create mode 100644 app/controllers/permalinks_controller.rb create mode 100644 app/controllers/webhooks/assessments_service/submitted_challenge_answers_controller.rb create mode 100644 app/controllers/webhooks/auth/cohorts_controller.rb create mode 100644 app/controllers/webhooks/auth/users_controller.rb create mode 100644 app/exporters/performance_exporter.rb create mode 100644 app/exporters/progress_exporter.rb create mode 100644 app/finders/block_finder.rb create mode 100644 app/finders/checkpoint_submission_finder.rb create mode 100644 app/finders/cohort_user_finder.rb create mode 100644 app/finders/content_file_finder.rb create mode 100644 app/finders/performance_finder.rb create mode 100644 app/finders/release_finder.rb create mode 100644 app/finders/standard_finder.rb create mode 100644 app/finders/submitted_challenge_answer_finder.rb create mode 100644 app/finders/user_finder.rb create mode 100644 app/helpers/application_helper.rb create mode 100644 app/helpers/json_helper.rb create mode 100644 app/helpers/secondary_navigation_helper.rb create mode 100644 app/helpers/standard_navigation_helper.rb create mode 100644 app/javascript/api.d.ts create mode 100644 app/javascript/components/AceEditor.tsx create mode 100644 app/javascript/components/Badge.tsx create mode 100644 app/javascript/components/Button.tsx create mode 100644 app/javascript/components/ButtonTo.tsx create mode 100644 app/javascript/components/Dropdown.tsx create mode 100644 app/javascript/components/Icon.tsx create mode 100644 app/javascript/components/Loading.tsx create mode 100644 app/javascript/components/Marked.tsx create mode 100644 app/javascript/components/Menu.tsx create mode 100644 app/javascript/components/Notifications.tsx create mode 100644 app/javascript/components/ProcessingIcon.tsx create mode 100644 app/javascript/components/RowKebab.tsx create mode 100644 app/javascript/components/ScoreCircle.tsx create mode 100644 app/javascript/components/SidebarProgress.tsx create mode 100644 app/javascript/components/SortDropdown.tsx create mode 100644 app/javascript/components/StandardBean.tsx create mode 100644 app/javascript/components/SvgRenderer.tsx create mode 100644 app/javascript/components/Timestamp.tsx create mode 100644 app/javascript/components/UserAvatar.tsx create mode 100644 app/javascript/components/activities/NewActivityForm.tsx create mode 100644 app/javascript/components/api/ApiInteractions.tsx create mode 100644 app/javascript/components/api/ApiToken.tsx create mode 100644 app/javascript/components/blocks/BlockPage-v2.tsx create mode 100644 app/javascript/components/blocks/BlocksIndex-v2.tsx create mode 100644 app/javascript/components/blocks/BlocksNewModal.tsx create mode 100644 app/javascript/components/blocks/BlocksNewRelease.tsx create mode 100644 app/javascript/components/blocks/BlocksRow.tsx create mode 100644 app/javascript/components/blocks/BlocksShow.tsx create mode 100644 app/javascript/components/blocks/BlocksStats.tsx create mode 100644 app/javascript/components/blocks/CohortsTooltip.tsx create mode 100644 app/javascript/components/challenges/AvatarBar.tsx create mode 100644 app/javascript/components/challenges/ChallengeDetailView.tsx create mode 100644 app/javascript/components/challenges/ChallengeShow.tsx create mode 100644 app/javascript/components/challenges/challenge_block/ChallengeActionBlock.tsx create mode 100644 app/javascript/components/challenges/challenge_block/ChallengeBlock.tsx create mode 100644 app/javascript/components/challenges/challenge_block/ChallengeDetailActivities.tsx create mode 100644 app/javascript/components/challenges/challenge_block/ChallengeExplanationBlock.tsx create mode 100644 app/javascript/components/challenges/challenge_block/ChallengeFeedbackBlock.tsx create mode 100644 app/javascript/components/challenges/challenge_block/ChallengeHintsBlock.tsx create mode 100644 app/javascript/components/challenges/challenge_block/ChallengeInputs.tsx create mode 100644 app/javascript/components/challenges/challenge_block/ChallengeLocalTestResults.tsx create mode 100644 app/javascript/components/challenges/challenge_block/ChallengeRubricBlock.tsx create mode 100644 app/javascript/components/challenges/challenge_block/ChallengeStatus.tsx create mode 100644 app/javascript/components/challenges/challenge_block/ChallengeStatusBar.tsx create mode 100644 app/javascript/components/challenges/challenge_block/ChallengeTestResults.tsx create mode 100644 app/javascript/components/challenges/challenge_block/ChallengeTests.tsx create mode 100644 app/javascript/components/challenges/challenge_block/ChallengeTimeLine.tsx create mode 100644 app/javascript/components/challenges/challenge_block/GradeIndicator.tsx create mode 100644 app/javascript/components/challenges/challenge_block/GradedTimestamp.tsx create mode 100644 app/javascript/components/challenges/challenge_block/StatusPicker.tsx create mode 100644 app/javascript/components/challenges/local/run-local-challenge.ts create mode 100644 app/javascript/components/challenges/local/sandbox.ts create mode 100644 app/javascript/components/challenges/local/stack-traces.ts create mode 100644 app/javascript/components/checkpoints/CheckpointAfterSubmitButton.tsx create mode 100644 app/javascript/components/checkpoints/CheckpointAfterSubmitModal.tsx create mode 100644 app/javascript/components/checkpoints/CheckpointAfterSubmitModalError.tsx create mode 100644 app/javascript/components/checkpoints/CheckpointSubmissionChallenges.tsx create mode 100644 app/javascript/components/checkpoints/CheckpointSubmissionShow.tsx create mode 100644 app/javascript/components/checkpoints/CheckpointSubmissionState.tsx create mode 100644 app/javascript/components/checkpoints/CheckpointSubmissionStudentNameBar.tsx create mode 100644 app/javascript/components/cohorts/CohortsIndex.tsx create mode 100644 app/javascript/components/cohorts/activity_dashboard/ActivityDashboard.tsx create mode 100644 app/javascript/components/cohorts/activity_feed/ActivityFeed.tsx create mode 100644 app/javascript/components/cohorts/cohort_releases/ReleaseVersionsTable.tsx create mode 100644 app/javascript/components/cohorts/cohort_submissions/CohortSubmissions.tsx create mode 100644 app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsChallengeItem.tsx create mode 100644 app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsLessonRow.tsx create mode 100644 app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsPerformanceModal.tsx create mode 100644 app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsStandardRow.tsx create mode 100644 app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsStudentColumn.tsx create mode 100644 app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsStudentNameBar.tsx create mode 100644 app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsStudentStandard.tsx create mode 100644 app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsTable.tsx create mode 100644 app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsUnitPercent.tsx create mode 100644 app/javascript/components/cohorts/mastery/MasteryTable.tsx create mode 100644 app/javascript/components/cohorts/mastery/MetricRow.tsx create mode 100644 app/javascript/components/cohorts/mastery/MetricsBody.tsx create mode 100644 app/javascript/components/cohorts/mastery/PerformanceCell.tsx create mode 100644 app/javascript/components/cohorts/mastery/PerformanceRow.tsx create mode 100644 app/javascript/components/cohorts/mastery/ReleaseBody.tsx create mode 100644 app/javascript/components/cohorts/mastery/StandardRow.tsx create mode 100644 app/javascript/components/cohorts/mastery/StudentHeader.tsx create mode 100644 app/javascript/components/cohorts/mastery/StudentMasteryTable.tsx create mode 100644 app/javascript/components/cohorts/mastery/StudentReleaseRow.tsx create mode 100644 app/javascript/components/cohorts/pairing/GroupPairs.tsx create mode 100644 app/javascript/components/cohorts/pairing/InnerStudentList.tsx create mode 100644 app/javascript/components/cohorts/pairing/NewPairing.tsx create mode 100644 app/javascript/components/cohorts/pairing/PairingBoard.tsx create mode 100644 app/javascript/components/cohorts/pairing/StudentItem.tsx create mode 100644 app/javascript/components/cohorts/pairing/StudentList.tsx create mode 100644 app/javascript/components/cohorts/progress/MasteryProgressionBar.tsx create mode 100644 app/javascript/components/cohorts/progress/ProgressThresholdCellHeaders.tsx create mode 100644 app/javascript/components/cohorts/progress/StudentProgress.tsx create mode 100644 app/javascript/components/cohorts/progress/StudentProgressBar.tsx create mode 100644 app/javascript/components/cohorts/progress/StudentProgressCells.tsx create mode 100644 app/javascript/components/cohorts/progress/StudentProgressRow.tsx create mode 100644 app/javascript/components/cohorts/progress/StudentProgressSortArrow.tsx create mode 100644 app/javascript/components/cohorts/settings/BranchReleaseModal.tsx create mode 100644 app/javascript/components/cohorts/settings/CohortBlockReleaseRow.tsx create mode 100644 app/javascript/components/cohorts/settings/CohortContentTab.tsx create mode 100644 app/javascript/components/cohorts/settings/CohortInfo.tsx create mode 100644 app/javascript/components/cohorts/settings/CohortSettingsResync.tsx create mode 100644 app/javascript/components/cohorts/settings/CohortSettingsTabs.tsx create mode 100644 app/javascript/components/cohorts/settings/CohortVisibilitySection.tsx create mode 100644 app/javascript/components/cohorts/settings/CurriculumSettingsTab.tsx create mode 100644 app/javascript/components/cohorts/settings/ReleaseVersionModal.tsx create mode 100644 app/javascript/components/cohorts/settings/ReleaseVersionRow.tsx create mode 100644 app/javascript/components/cohorts/settings/UserImport.tsx create mode 100644 app/javascript/components/cohorts/settings/UserKebab.tsx create mode 100644 app/javascript/components/cohorts/submissions_dashboard/AnswerStatusRollup.tsx create mode 100644 app/javascript/components/cohorts/submissions_dashboard/HeaderStandardContainer.tsx create mode 100644 app/javascript/components/cohorts/submissions_dashboard/StandardContainer.tsx create mode 100644 app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboard.tsx create mode 100644 app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardChallengeItem.tsx create mode 100644 app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardContentFileRow.tsx create mode 100644 app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardStudentColumn.tsx create mode 100644 app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardStudentNameBar.tsx create mode 100644 app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardTable.tsx create mode 100644 app/javascript/components/content_files/ActionMenus.tsx create mode 100644 app/javascript/components/content_files/Lesson.tsx create mode 100644 app/javascript/components/content_files/MarkdownRenderer.tsx create mode 100644 app/javascript/components/content_files/PDFRenderer.tsx create mode 100644 app/javascript/components/content_files/SideBar.tsx create mode 100644 app/javascript/components/content_files/SubmissionRenderer.tsx create mode 100644 app/javascript/components/content_files/checkpoints/Checkpoint.tsx create mode 100644 app/javascript/components/content_files/checkpoints/CheckpointActionBar.tsx create mode 100644 app/javascript/components/content_files/checkpoints/CheckpointDetails.tsx create mode 100644 app/javascript/components/content_files/checkpoints/CheckpointLanding.tsx create mode 100644 app/javascript/components/content_files/checkpoints/CheckpointLandingAttribute.tsx create mode 100644 app/javascript/components/content_files/checkpoints/CheckpointPairs.tsx create mode 100644 app/javascript/components/content_files/checkpoints/PairAvatars.tsx create mode 100644 app/javascript/components/content_files/checkpoints/student_scores/CheckpointStudentRow.tsx create mode 100644 app/javascript/components/content_files/checkpoints/student_scores/CheckpointStudentScores.tsx create mode 100644 app/javascript/components/curriculum/CheckpointSummary.tsx create mode 100644 app/javascript/components/curriculum/CohortCurriculum.tsx create mode 100644 app/javascript/components/curriculum/CurriculumStandardCard.tsx create mode 100644 app/javascript/components/curriculum/ProgressIndicators.tsx create mode 100644 app/javascript/components/curriculum/StandardBeans.tsx create mode 100644 app/javascript/components/curriculum/StandardsRenderer.tsx create mode 100644 app/javascript/components/curriculum/StudentOverallProgressDoughnut.tsx create mode 100644 app/javascript/components/lib/ace.ts create mode 100644 app/javascript/components/notifications/NotificationsIcon.tsx create mode 100644 app/javascript/components/shared/ActionMenu/ActionMenu.tsx create mode 100644 app/javascript/components/shared/Button/Button.tsx create mode 100644 app/javascript/components/shared/ChallengePoints/ChallengePoints.tsx create mode 100644 app/javascript/components/shared/ChallengePoints/PartialCreditBaton.tsx create mode 100644 app/javascript/components/shared/ChallengePoints/SpinText.tsx create mode 100644 app/javascript/components/shared/ChallengePoints/components/IntegerPicker/IntegerPicker.tsx create mode 100644 app/javascript/components/shared/DonutRing/DonutRing.tsx create mode 100644 app/javascript/components/shared/DonutRing/components/ColorDonut/ColorDonut.tsx create mode 100644 app/javascript/components/shared/DonutRing/components/CompleteDonut/CompleteDonut.tsx create mode 100644 app/javascript/components/shared/DonutRing/components/UngradedDonut/UngradedDonut.tsx create mode 100644 app/javascript/components/shared/DonutRing/components/UngradedDonut/UngradedDonut/UngradedDonut.tsx create mode 100644 app/javascript/components/shared/ErrorMessagesTable/ErrorMessagesTable.tsx create mode 100644 app/javascript/components/shared/FlashAlert/FlashAlert.tsx create mode 100644 app/javascript/components/shared/FormatNumber/FormatNumber.tsx create mode 100644 app/javascript/components/shared/Icons/AlertSign.tsx create mode 100644 app/javascript/components/shared/Icons/Clear.tsx create mode 100644 app/javascript/components/shared/Icons/CloseButton.tsx create mode 100644 app/javascript/components/shared/Icons/Done.tsx create mode 100644 app/javascript/components/shared/Icons/KeyboardArrowDown.tsx create mode 100644 app/javascript/components/shared/Icons/KeyboardArrowUp.tsx create mode 100644 app/javascript/components/shared/Icons/SettingsCog.tsx create mode 100644 app/javascript/components/shared/Icons/StatusCircle.tsx create mode 100644 app/javascript/components/shared/MasteryProgressBar/MasteryProgressBar.tsx create mode 100644 app/javascript/components/shared/Modal/Modal.tsx create mode 100644 app/javascript/components/shared/Pagination/Pagination.tsx create mode 100644 app/javascript/components/shared/PercentageProgressBar/PercentageProgressBar.tsx create mode 100644 app/javascript/components/shared/Pill/Pill.tsx create mode 100644 app/javascript/components/shared/PointGradeButtons/PointGradeButtons.tsx create mode 100644 app/javascript/components/shared/PointGradeButtons/SpinText.tsx create mode 100644 app/javascript/components/shared/ProgressBar/ProgressBar.tsx create mode 100644 app/javascript/components/shared/ProgressThresholdsKey/ProgressThresholdsKey.tsx create mode 100644 app/javascript/components/shared/ProgressThresholdsModal/ProgressThresholdsModal.tsx create mode 100644 app/javascript/components/shared/ProgressThresholdsSlider/ProgressThresholdsSlider.tsx create mode 100644 app/javascript/components/shared/SearchBar/SearchBar.tsx create mode 100644 app/javascript/components/shared/Slideshow/Slideshow.tsx create mode 100644 app/javascript/components/shared/UngradedDonut/UngradedDonut.tsx create mode 100644 app/javascript/components/shared/UniversalList/UniversalList.tsx create mode 100644 app/javascript/components/shared/UniversalRow/UniversalRow.tsx create mode 100644 app/javascript/components/shared/UniversalTable/UniversalTable.tsx create mode 100644 app/javascript/components/standards/CompletionScoringBlock.tsx create mode 100644 app/javascript/components/standards/MasteryScoringBlock.tsx create mode 100644 app/javascript/components/standards/StandardCard.tsx create mode 100644 app/javascript/components/standards/StandardScoreButton.tsx create mode 100644 app/javascript/components/standards/StandardScoringBlock.tsx create mode 100644 app/javascript/components/standards/StandardTopicsRollups.tsx create mode 100644 app/javascript/components/vendor/ReactTooltip.js create mode 100644 app/javascript/generated/routes.ts create mode 100644 app/javascript/globals.ts create mode 100644 app/javascript/lib/http.ts create mode 100644 app/javascript/lib/utils.ts create mode 100644 app/javascript/packs/application.js create mode 100644 app/javascript/packs/server_rendering.js create mode 100644 app/jobs/application_job.rb create mode 100644 app/jobs/branch_release_notifier_job.rb create mode 100644 app/jobs/checkpoint_paired_submission_job.rb create mode 100644 app/jobs/content_file_default_visibility_job.rb create mode 100644 app/jobs/content_file_visit_job.rb create mode 100644 app/jobs/create_api_interaction_job.rb create mode 100644 app/jobs/create_release_job.rb create mode 100644 app/jobs/evaluate_code_snippet_job.rb create mode 100644 app/jobs/evaluate_custom_snippet_job.rb create mode 100644 app/jobs/evaluate_project_job.rb create mode 100644 app/jobs/grade_timed_checkpoint_job.rb create mode 100644 app/jobs/import_student_work_job.rb create mode 100644 app/jobs/progress_csv_job.rb create mode 100644 app/jobs/release_notifier_job.rb create mode 100644 app/jobs/resync_course_job.rb create mode 100644 app/jobs/set_block_caches_job.rb create mode 100644 app/jobs/slack_challenge_performance_job.rb create mode 100644 app/jobs/slack_dev_notify_job.rb create mode 100644 app/jobs/slack_ds_prep_job.rb create mode 100644 app/jobs/slack_job.rb create mode 100644 app/jobs/slack_se_prep_job.rb create mode 100644 app/jobs/slack_student_job.rb create mode 100644 app/jobs/student_progress_auth_job.rb create mode 100644 app/jobs/switch_to_branch_job.rb create mode 100644 app/mailers/application_mailer.rb create mode 100644 app/mailers/user_mailer.rb create mode 100644 app/models/activity.rb create mode 100644 app/models/api_interaction.rb create mode 100644 app/models/application_record.rb create mode 100644 app/models/block.rb create mode 100644 app/models/challenge.rb create mode 100644 app/models/checkpoint_submission.rb create mode 100644 app/models/cohort.rb create mode 100644 app/models/cohort_release.rb create mode 100644 app/models/cohort_user.rb create mode 100644 app/models/concerns/findable_by_uid.rb create mode 100644 app/models/concerns/read_only_model.rb create mode 100644 app/models/content_file.rb create mode 100644 app/models/content_visibility.rb create mode 100644 app/models/job_result.rb create mode 100644 app/models/lesson_visit.rb create mode 100644 app/models/notification.rb create mode 100644 app/models/pairing.rb create mode 100644 app/models/performance.rb create mode 100644 app/models/release.rb create mode 100644 app/models/resync_job_result.rb create mode 100644 app/models/section.rb create mode 100644 app/models/standard.rb create mode 100644 app/models/submitted_challenge_answer.rb create mode 100644 app/models/unit.rb create mode 100644 app/models/user.rb create mode 100644 app/models/user_last_viewed_standard_path.rb create mode 100644 app/policies/activity_policy.rb create mode 100644 app/policies/application_policy.rb create mode 100644 app/policies/block_policy.rb create mode 100644 app/policies/checkpoint_submission_policy.rb create mode 100644 app/policies/cohort_policy.rb create mode 100644 app/policies/cohort_release_policy.rb create mode 100644 app/policies/cohort_user_policy.rb create mode 100644 app/policies/content_file_policy.rb create mode 100644 app/policies/notification_policy.rb create mode 100644 app/policies/performance_policy.rb create mode 100644 app/policies/release_policy.rb create mode 100644 app/policies/submitted_challenge_answer_policy.rb create mode 100644 app/policies/user_policy.rb create mode 100644 app/presenters/activity_presenter.rb create mode 100644 app/presenters/block_presenter/for_block.rb create mode 100644 app/presenters/block_presenter/for_cohort_releases.rb create mode 100644 app/presenters/block_presenter/for_cohort_releases_new.rb create mode 100644 app/presenters/block_presenter/for_releases.rb create mode 100644 app/presenters/challenge_with_submitted_challenge_answers_presenter.rb create mode 100644 app/presenters/checkpoint_submission_presenter.rb create mode 100644 app/presenters/checkpoint_submission_presenter/for_index.rb create mode 100644 app/presenters/checkpoint_submission_presenter/for_student_row.rb create mode 100644 app/presenters/cohort_release_presenter/for_cohort_setup.rb create mode 100644 app/presenters/cohort_setup/visibility.rb create mode 100644 app/presenters/content_file_presenter/for_curriculum_last_viewed.rb create mode 100644 app/presenters/content_file_presenter/for_footer.rb create mode 100644 app/presenters/content_file_presenter/for_show.rb create mode 100644 app/presenters/content_file_presenter/for_sidebar.rb create mode 100644 app/presenters/performance_presenter.rb create mode 100644 app/presenters/standard_card_component_props.rb create mode 100644 app/presenters/standard_presenter/for_challenge_detail_view.rb create mode 100644 app/presenters/standard_presenter/for_checkpoint_submission.rb create mode 100644 app/presenters/standard_presenter/for_standard_card.rb create mode 100644 app/presenters/standard_presenter/for_submissions_dashboard.rb create mode 100644 app/presenters/stat_progress_presenter.rb create mode 100644 app/presenters/student_progress_presenter.rb create mode 100644 app/presenters/submissions_dashboard_presenter.rb create mode 100644 app/presenters/submitted_challenge_answer_presenter.rb create mode 100644 app/presenters/user_presenter/for_avatar.rb create mode 100644 app/services/activity_aggregator_service.rb create mode 100644 app/services/assessment_service.rb create mode 100644 app/services/auth_resolver_service.rb create mode 100644 app/services/auto_assign_release_service.rb create mode 100644 app/services/checkpoint_submission_service.rb create mode 100644 app/services/cohort_standard_progress_service.rb create mode 100644 app/services/cohort_student_progress_service.rb create mode 100644 app/services/completion_mode_percent_service.rb create mode 100644 app/services/course_validator.rb create mode 100644 app/services/create_submitted_challenge_answer_service.rb create mode 100644 app/services/curriculum_progress_service.rb create mode 100644 app/services/download_github_repository_service.rb create mode 100644 app/services/download_gitlab_repository_service.rb create mode 100644 app/services/download_repository_service.rb create mode 100644 app/services/download_s3_repository_service.rb create mode 100644 app/services/git_url_service.rb create mode 100644 app/services/mastery_average_service.rb create mode 100644 app/services/mastery_mode_percent_service.rb create mode 100644 app/services/mock_mixpanel.rb create mode 100644 app/services/notification_service.rb create mode 100644 app/services/preview_content_file_service.rb create mode 100644 app/services/release_destroyer_service.rb create mode 100644 app/services/release_helper_service.rb create mode 100644 app/services/resync_course_service.rb create mode 100644 app/services/s3_asset_uploader_service.rb create mode 100644 app/services/segment_track_service.rb create mode 100644 app/services/sql_challenge_db_service.rb create mode 100644 app/services/standard_submissions_service.rb create mode 100644 app/views/api_interactions.html.haml create mode 100644 app/views/api_token.html.haml create mode 100644 app/views/apitome/docs/_headers.html.erb create mode 100644 app/views/apitome/docs/_params.html.erb create mode 100644 app/views/blocks/blockpagev2.html.haml create mode 100644 app/views/blocks/index.html.haml create mode 100644 app/views/blocks/new.html.haml create mode 100644 app/views/blocks/releases/new.html.haml create mode 100644 app/views/blocks/show.html.haml create mode 100644 app/views/cohorts/_cohort_info.html.haml create mode 100644 app/views/cohorts/_completion_progress_donut.html.haml create mode 100644 app/views/cohorts/_user_table.html.haml create mode 100644 app/views/cohorts/activity_dashboard.html.haml create mode 100644 app/views/cohorts/blocks/content_files/_footer.html.haml create mode 100644 app/views/cohorts/blocks/content_files/show.html.haml create mode 100644 app/views/cohorts/cohort_releases/index.html.haml create mode 100644 app/views/cohorts/content.html.haml create mode 100644 app/views/cohorts/content_files/checkpoint_submissions/show.html.haml create mode 100644 app/views/cohorts/course_stats.html.haml create mode 100644 app/views/cohorts/error.html.haml create mode 100644 app/views/cohorts/feed.html.haml create mode 100644 app/views/cohorts/index.html.haml create mode 100644 app/views/cohorts/partnerup.html.haml create mode 100644 app/views/cohorts/setup.html.haml create mode 100644 app/views/cohorts/show.html.haml create mode 100644 app/views/cohorts/standards/checkpoint_submissions/index.html.haml create mode 100644 app/views/cohorts/unit_progress.html.haml create mode 100644 app/views/cohorts/users.html.haml create mode 100644 app/views/cohorts/users/challenges/show.html.haml create mode 100644 app/views/cohorts/users/mastery/index.html.haml create mode 100644 app/views/cohorts/users/submissions_dashboard.html.haml create mode 100644 app/views/error_404.html.haml create mode 100644 app/views/error_500.html.haml create mode 100644 app/views/home/index.html.haml create mode 100644 app/views/layouts/_primary_navigation.html.haml create mode 100644 app/views/layouts/_secondary_navigation.html.haml create mode 100644 app/views/layouts/application.html.haml create mode 100644 app/views/layouts/mailer.html.erb create mode 100644 app/views/layouts/mailer.text.erb create mode 100644 app/views/permalinks/permalink.html.haml create mode 100644 app/views/shared/_content_file_js.html.haml create mode 100644 app/views/shared/_hopscotch_callbacks_js.html.haml create mode 100644 app/views/shared/_intercom_js.html.haml create mode 100644 app/views/shared/_segment_js.html.haml create mode 100644 app/views/user_mailer/send_file.html create mode 100644 app/views/user_mailer/user_import_work.html.haml create mode 100755 bin/bundle create mode 100755 bin/rails create mode 100755 bin/rake create mode 100755 bin/setup create mode 100755 bin/update create mode 100755 bin/webpack create mode 100755 bin/webpack-dev-server create mode 100755 bin/yarn create mode 100644 config.ru create mode 100644 config/application.rb create mode 100644 config/boot.rb create mode 100644 config/database.yml create mode 100644 config/environment.rb create mode 100644 config/environments/development.rb create mode 100644 config/environments/production.rb create mode 100644 config/environments/test.rb create mode 100644 config/get-routes-audit.md create mode 100644 config/honeybadger.yml create mode 100644 config/initializers/apitome.rb create mode 100644 config/initializers/application_controller_renderer.rb create mode 100644 config/initializers/assets.rb create mode 100644 config/initializers/auth_api.rb create mode 100644 config/initializers/aws.rb create mode 100644 config/initializers/backtrace_silencers.rb create mode 100644 config/initializers/cookies_serializer.rb create mode 100644 config/initializers/filter_parameter_logging.rb create mode 100644 config/initializers/inflections.rb create mode 100644 config/initializers/mime_types.rb create mode 100644 config/initializers/new_framework_defaults_5_1.rb create mode 100644 config/initializers/octokit.rb create mode 100644 config/initializers/pagy.rb create mode 100644 config/initializers/pundit.rb create mode 100644 config/initializers/rack_attack.rb create mode 100644 config/initializers/segment.rb create mode 100644 config/initializers/sidekiq.rb create mode 100644 config/initializers/wrap_parameters.rb create mode 100644 config/locales/en.yml create mode 100644 config/puma.rb create mode 100644 config/routes.rb create mode 100644 config/secrets.yml create mode 100644 config/sidekiq.yml create mode 100644 config/spring.rb create mode 100644 config/webpack/development.js create mode 100644 config/webpack/environment.js create mode 100644 config/webpack/loaders/typescript.js create mode 100644 config/webpack/production.js create mode 100644 config/webpack/test.js create mode 100644 config/webpacker.yml create mode 100644 db/drawio_schema_with_explanations.xml create mode 100644 db/migrate/20171003191909_create_users.rb create mode 100644 db/migrate/20171005135550_add_admin_to_users.rb create mode 100644 db/migrate/20171005140042_rename_users_profile_image_url.rb create mode 100644 db/migrate/20171006195948_create_blocks.rb create mode 100644 db/migrate/20171009194124_create_releases.rb create mode 100644 db/migrate/20171011232501_add_sync_errors_to_block.rb create mode 100644 db/migrate/20171012200106_create_standards.rb create mode 100644 db/migrate/20171016192627_create_cohorts.rb create mode 100644 db/migrate/20171017205306_create_cohort_users.rb create mode 100644 db/migrate/20171017221501_remove_presence_indices_from_label_and_pretty_name_on_cohorts.rb create mode 100644 db/migrate/20171019165527_create_content_files.rb create mode 100644 db/migrate/20171019192005_create_cohort_releases.rb create mode 100644 db/migrate/20171023211301_create_challenges.rb create mode 100644 db/migrate/20171024202210_create_checkpoint_submissions.rb create mode 100644 db/migrate/20171024203630_create_submitted_challenge_answers.rb create mode 100644 db/migrate/20171025211916_create_performances.rb create mode 100644 db/migrate/20171025223250_add_autoscore_to_content_files.rb create mode 100644 db/migrate/20171026193413_add_title_to_content_files.rb create mode 100644 db/migrate/20171102144822_cohort_release_unique_index.rb create mode 100644 db/migrate/20171102165314_add_unique_constraint_to_block_title.rb create mode 100644 db/migrate/20171102171128_add_position_to_cohort_releases.rb create mode 100644 db/migrate/20171127223701_create_activities.rb create mode 100644 db/migrate/20171130183523_create_user_last_viewed_standard_path.rb create mode 100644 db/migrate/20171130185636_add_uid_to_content_files.rb create mode 100644 db/migrate/20171205211624_add_slack_data_to_user.rb create mode 100644 db/migrate/20180104213519_add_standard_uid_to_performances.rb create mode 100644 db/migrate/20180110174447_add_type_relative_display_name_to_content_files.rb create mode 100644 db/migrate/20180110223429_add_auth_roles_to_user.rb create mode 100644 db/migrate/20180110224150_denormalize_submitted_challenge_answers.rb create mode 100644 db/migrate/20180110233303_add_roles_to_cohort_user.rb create mode 100644 db/migrate/20180112234504_add_last_viewed_cohort_id_to_users.rb create mode 100644 db/migrate/20180116174519_add_github_user_name_to_user.rb create mode 100644 db/migrate/20180116181937_add_taught_in_learn_to_cohorts.rb create mode 100644 db/migrate/20180116213927_remove_forge_admin_and_role.rb create mode 100644 db/migrate/20180119184121_add_cohort_id_to_submitted_challenge_answer.rb create mode 100644 db/migrate/20180124221642_denormalize_checkpoint_submissions.rb create mode 100644 db/migrate/20180125212203_rename_taught_in_learn.rb create mode 100644 db/migrate/20180125222044_change_learn_v2_default.rb create mode 100644 db/migrate/20180131220605_create_notifications.rb create mode 100644 db/migrate/20180202225951_add_github_sha_to_releases.rb create mode 100644 db/migrate/20180209175941_add_use_latest_release_to_cohort_releases.rb create mode 100644 db/migrate/20180313220132_add_docker_directory_path_to_challenges.rb create mode 100644 db/migrate/20180316222140_rename_cohort_title_to_name.rb create mode 100644 db/migrate/20180320162849_add_deleted_at_to_cohorts.rb create mode 100644 db/migrate/20180402212114_remove_pretty_name_from_cohort.rb create mode 100644 db/migrate/20180412214504_add_used_by_application_to_cohorts.rb create mode 100644 db/migrate/20180412223312_populate_used_by_application.rb create mode 100644 db/migrate/20180504193033_add_feature_branch_columns_to_releases.rb create mode 100644 db/migrate/20180504200226_add_pending_release_id_to_cohort_releases.rb create mode 100644 db/migrate/20180813205413_add_readme_text_to_release.rb create mode 100644 db/migrate/20180813213358_add_mode_to_cohort.rb create mode 100644 db/migrate/20180813214453_populate_mode_cohorts.rb create mode 100644 db/migrate/20180817181129_add_cohort_id_to_user_last_viewed_standard_path.rb create mode 100644 db/migrate/20180824200753_create_lesson_visits.rb create mode 100644 db/migrate/20181112215710_add_preferred_campus_to_users.rb create mode 100644 db/migrate/20181114190340_create_job_results.rb create mode 100644 db/migrate/20181120221622_create_sections.rb create mode 100644 db/migrate/20181121202104_add_section_id_to_cohort_releases.rb create mode 100644 db/migrate/20181203215524_add_challenge_completion_to_performance.rb create mode 100644 db/migrate/20181213180900_add_show_tests_to_challenges.rb create mode 100644 db/migrate/20181214175640_create_content_visibilities.rb create mode 100644 db/migrate/20181220005015_add_default_visibility_to_content_files.rb create mode 100644 db/migrate/20190410171829_create_pairings.rb create mode 100644 db/migrate/20190423171448_add_data_path_to_challenge.rb create mode 100644 db/migrate/20190510193410_add_last_setup_visit_to_cohort_users.rb create mode 100644 db/migrate/20190520223958_add_max_attempts_to_content_files.rb create mode 100644 db/migrate/20190529170059_add_allowed_attempts_to_challenge.rb create mode 100644 db/migrate/20190624222000_remove_max_attempts_from_challenges.rb create mode 100644 db/migrate/20190625173725_add_points_and_success_criteria_to_challenges.rb create mode 100644 db/migrate/20190709170851_drop_learn_version_columns_on_cohorts.rb create mode 100644 db/migrate/20190829203949_add_settings_to_cohorts.rb create mode 100644 db/migrate/20190910161219_add_points_to_submitted_challenge_answer.rb create mode 100644 db/migrate/20190910161303_add_points_to_checkpoint_submissions.rb create mode 100644 db/migrate/20190919173956_change_success_criteria_to_rubric_on_challenges.rb create mode 100644 db/migrate/20191001214559_add_topics_to_challenges.rb create mode 100644 db/migrate/20191001221324_add_perf_data_to_submissions.rb create mode 100644 db/migrate/20191008211403_add_release_id_to_challenges.rb create mode 100644 db/migrate/20191009214248_add_user_id_to_release.rb create mode 100644 db/migrate/20191024200444_add_visibility_type_to_content_visibilities.rb create mode 100644 db/migrate/20191031212058_add_api_token_to_user.rb create mode 100644 db/migrate/20191108211234_add_preview_to_releases.rb create mode 100644 db/migrate/20191114211938_create_api_interactions.rb create mode 100644 db/migrate/20191119225902_add_sandbox_boolean_to_cohorts.rb create mode 100644 db/migrate/20191206230913_add_sync_warnings.rb create mode 100644 db/migrate/20191209165026_add_metadata_to_api_interactions.rb create mode 100644 db/migrate/20191218232717_add_assign_partial_credig_to_challenges.rb create mode 100644 db/migrate/20200108184027_add_end_time_to_checkpoint_submissions.rb create mode 100644 db/migrate/20200110201253_change_cohort_default_percentage.rb create mode 100644 db/migrate/20200213201649_add_time_limit_to_content_file.rb create mode 100644 db/migrate/20200310222235_add_submitted_at_to_checkpoint_submissions.rb create mode 100644 db/migrate/20200408212051_add_allow_paired_submissions_to_cohort.rb create mode 100644 db/migrate/20200416155234_add_pair_submission_ids_to_checkpoint_submissinos.rb create mode 100644 db/migrate/20200430165251_add_external_to_challenge.rb create mode 100644 db/migrate/20200702155846_add_cache_to_blocks.rb create mode 100644 db/migrate/20200707164932_add_archived_at_to_blocks.rb create mode 100644 db/migrate/20200720213420_add_block_location_details_to_blocks.rb create mode 100644 db/migrate/20200724195251_add_whitelabeled_to_cohorts.rb create mode 100644 db/migrate/20200729214247_remove_block_uniqueness_pg_columns.rb create mode 100644 db/migrate/20200811215713_add_student_import_status_to_cohorts.rb create mode 100644 db/migrate/20200818172419_addd_docker_directory_zip_to_challenges.rb create mode 100644 db/migrate/20200828165130_default_block_org_tog_school.rb create mode 100644 db/schema.rb create mode 100644 db/seeds.rb create mode 100644 doc/api.md create mode 100644 doc/api/cohorts/creating_a_new_cohort.json create mode 100644 doc/api/cohorts/viewing_curriculum_details.json create mode 100644 doc/api/content/update_content_visibility.json create mode 100644 doc/api/enrollments/creating_a_user_and_their_enrollment.json create mode 100644 doc/api/enrollments/unenrolling_a_user_from_a_cohort.json create mode 100644 doc/api/enrollments/updating_a_user's_enrollment_roles.json create mode 100644 doc/api/enrollments/viewing_cohort_enrollments.json create mode 100644 doc/api/index.json create mode 100644 doc/api/units/update_unit_visibility.json create mode 100644 doc/api/users/regenerate_user_token.json create mode 100644 lib/tasks/challenge_release_ids.rake create mode 100644 lib/tasks/checkpoint_resubmission.rake create mode 100644 lib/tasks/checkpoint_submission_points.rake create mode 100644 lib/tasks/content_visibility_update.rake create mode 100644 lib/tasks/course_progress.rake create mode 100644 lib/tasks/course_yaml_backfill.rake create mode 100644 lib/tasks/grade_checkpoints.rake create mode 100644 lib/tasks/object_space_count.rake create mode 100644 lib/tasks/prep_notifier.rake create mode 100644 lib/tasks/set_block_caches.rake create mode 100644 lib/tasks/spec.rake create mode 100644 lib/tasks/ts_routes.rake create mode 100755 lintspec.sh create mode 100644 package.json create mode 100644 public/404.html create mode 100644 public/422.html create mode 100644 public/500.html create mode 100644 public/apple-touch-icon-152x152.png create mode 100644 public/apple-touch-icon-precomposed-152x152.png create mode 100644 public/apple-touch-icon-precomposed.png create mode 100644 public/apple-touch-icon.png create mode 100755 public/assets/images/hopscotch-sprite-green.png create mode 100755 public/assets/images/hopscotch-sprite-orange.png create mode 100644 public/assets/images/jupyter-logo.png create mode 100644 public/assets/images/svg/checkpoint-is-rejected.svg create mode 100644 public/assets/images/svg/checkpoint-is-scored.svg create mode 100644 public/assets/images/svg/checkpoint-is-submitted.svg create mode 100644 public/assets/images/svg/github-icon.svg create mode 100644 public/assets/images/svg/gitlab-icon-rgb.svg create mode 100644 public/assets/images/svg/octicon-git-branch.svg create mode 100644 public/assets/images/svg/redpriority_high-24px.svg create mode 100644 public/assets/images/svg/svg-link_off-24px.svg create mode 100755 public/assets/images/svg/svg-sprite-action-symbol.svg create mode 100644 public/assets/images/svg/svg-sprite-alert-symbol.svg create mode 100644 public/assets/images/svg/svg-sprite-av-symbol.svg create mode 100644 public/assets/images/svg/svg-sprite-content-symbol.svg create mode 100644 public/assets/images/svg/svg-sprite-custom-symbol.svg create mode 100644 public/assets/images/svg/svg-sprite-custom_material-symbol.svg create mode 100644 public/assets/images/svg/svg-sprite-device-symbol.svg create mode 100644 public/assets/images/svg/svg-sprite-file-symbol.svg create mode 100644 public/assets/images/svg/svg-sprite-hardware-symbol.svg create mode 100644 public/assets/images/svg/svg-sprite-navigation-symbol.svg create mode 100644 public/assets/images/svg/svg-sprite-notification-symbol.svg create mode 100644 public/assets/images/svg/svg-sprite-social-symbol.svg create mode 100644 public/favicon.ico create mode 100644 public/javascripts/apitome/application.js create mode 100644 public/robots.txt create mode 100755 public/sandbox/chai.js create mode 100644 public/sandbox/challenge-worker.js create mode 100755 public/sandbox/jasmine/boot.js create mode 100755 public/sandbox/jasmine/jasmine.js create mode 100644 public/sandbox/mocha/boot.js create mode 100644 public/sandbox/mocha/mocha.js create mode 100644 public/sandbox/mocha/test.html create mode 100644 public/sandbox/sandbox.html create mode 100644 public/sandbox/stacktrace.js create mode 100644 public/sandbox/worker.js create mode 100644 public/stylesheets/apitome/application.css create mode 100644 requirements.txt create mode 100755 scripts/sh/cohort_curriculum.sh create mode 100644 scripts/sh/content_file_mark_hidden.sh create mode 100644 scripts/sh/content_file_mark_visible.sh create mode 100644 scripts/sh/unit_mark_hidden.sh create mode 100644 scripts/sh/unit_mark_visible.sh create mode 100644 scripts/sql/checkpoint_answers.sql create mode 100644 scripts/sql/cohort_challenges_with_answers.sql create mode 100644 scripts/sql/cohort_prune_for_testing.sql create mode 100644 scripts/sql/percent_metrics.sql create mode 100644 scripts/sql/scrub_cohort_data.sql create mode 100644 spec/component_props/activity_feed_item_component_props_spec.rb create mode 100644 spec/component_props/notifications_component_props_spec.rb create mode 100644 spec/component_props/standard_card_component_props_spec.rb create mode 100644 spec/controllers/api/v1/blocks/releases_controller_spec.rb create mode 100644 spec/controllers/api/v1/blocks_controller_spec.rb create mode 100644 spec/controllers/api/v1/cohorts/blocks/content_files_controller_spec.rb create mode 100644 spec/controllers/api/v1/cohorts/blocks/units_controller_spec.rb create mode 100644 spec/controllers/api/v1/cohorts/cohorts_controller_spec.rb create mode 100644 spec/controllers/api/v1/cohorts/users_controller_spec.rb create mode 100644 spec/controllers/api/v1/content_files_controller_spec.rb create mode 100644 spec/controllers/api/v1/users_controller_spec.rb create mode 100644 spec/controllers/application_controller_spec.rb create mode 100644 spec/controllers/blocks/releases_controller_spec.rb create mode 100644 spec/controllers/blocks_controller_spec.rb create mode 100644 spec/controllers/cohorts/blocks/content_files_controller_spec.rb create mode 100644 spec/controllers/cohorts/checkpoint_submissions/activities_controller_spec.rb create mode 100644 spec/controllers/cohorts/cohort_releases_controller_spec.rb create mode 100644 spec/controllers/cohorts/content_files/checkpoint_submissions_controller_spec.rb create mode 100644 spec/controllers/cohorts/content_files/submitted_challenge_answers_controller_spec.rb create mode 100644 spec/controllers/cohorts/content_files_controller_spec.rb create mode 100644 spec/controllers/cohorts/pairings_controller_spec.rb create mode 100644 spec/controllers/cohorts/standards_controller_spec.rb create mode 100644 spec/controllers/cohorts/submitted_challenge_answers/activities_controller_spec.rb create mode 100644 spec/controllers/cohorts/users/challenges_controller_spec.rb create mode 100644 spec/controllers/cohorts/users/performances_controller_spec.rb create mode 100644 spec/controllers/cohorts/users_controller_spec.rb create mode 100644 spec/controllers/cohorts_controller_spec.rb create mode 100644 spec/controllers/home_controller_spec.rb create mode 100644 spec/controllers/notifications_controller_spec.rb create mode 100644 spec/controllers/permalinks_controller_spec.rb create mode 100644 spec/controllers/webhooks/assessments_service/submitted_challenge_answers_controller_spec.rb create mode 100644 spec/controllers/webhooks/auth/cohorts_controller_spec.rb create mode 100644 spec/controllers/webhooks/auth/users_controller_spec.rb create mode 100644 spec/exporters/performance_exporter_spec.rb create mode 100644 spec/factories.rb create mode 100644 spec/features/blocks/management_feature_spec.rb create mode 100644 spec/features/cohorts/activity_dashboard_spec.rb create mode 100644 spec/features/cohorts/checkpoint_submissions_spec.rb create mode 100644 spec/features/cohorts/curriculum_feature_spec.rb create mode 100644 spec/features/cohorts/feed_feature_spec.rb create mode 100644 spec/features/cohorts/management_feature_spec.rb create mode 100644 spec/features/cohorts/sandboxes_spec.rb create mode 100644 spec/features/cohorts/student_progress_spec.rb create mode 100644 spec/features/cohorts/submissions_spec.rb create mode 100644 spec/features/cohorts/users/challenges_feature_spec.rb create mode 100644 spec/features/cohorts/users/submissions_dashboard_feature_spec.rb create mode 100644 spec/features/content_files/checkpoint_assessments_spec.rb create mode 100644 spec/features/content_files/checkpoint_submissions_spec.rb create mode 100644 spec/features/content_files/navigation_feature_spec.rb create mode 100644 spec/features/content_files/permalinks_spec.rb create mode 100644 spec/features/content_files/view_feature_spec.rb create mode 100644 spec/features/home/header_feature_spec.rb create mode 100644 spec/features_helper.rb create mode 100644 spec/finders/block_finder_spec.rb create mode 100644 spec/finders/checkpoint_submission_finder_spec.rb create mode 100644 spec/finders/cohort_user_finder_spec.rb create mode 100644 spec/finders/content_file_finder_spec.rb create mode 100644 spec/finders/performance_finder_spec.rb create mode 100644 spec/finders/release_finder_spec.rb create mode 100644 spec/finders/standard_finder_spec.rb create mode 100644 spec/finders/submitted_challenge_answer_finder_spec.rb create mode 100644 spec/finders/user_finder_spec.rb create mode 100644 spec/fixtures/preview-content-file/preview.md create mode 100644 spec/fixtures/test-block-repo/._docker_directories_test-docker-folder.zip create mode 100644 spec/fixtures/test-block-repo/README.md create mode 100644 spec/fixtures/test-block-repo/challenges-smoketest.md create mode 100644 spec/fixtures/test-block-repo/config.yaml create mode 100644 spec/fixtures/test-block-repo/docker_directories/test-docker-folder/Dockerfile create mode 100644 spec/fixtures/test-block-repo/docker_directories/test-docker-folder/test.sh create mode 100644 spec/fixtures/test-block-repo/folder/sibling.md create mode 100644 spec/fixtures/test-block-repo/folder/target.md create mode 100644 spec/fixtures/test-block-repo/images/galvanize-logo.png create mode 100644 spec/fixtures/test-block-repo/images/register_klass.gif create mode 100644 spec/fixtures/test-block-repo/markdown-smoketesT.md create mode 100644 spec/fixtures/test-block-repo/target.md create mode 100644 spec/fixtures/test-block-repo/test.sql create mode 100644 spec/fixtures/vcr_cassettes/github-branch-success.yml create mode 100644 spec/fixtures/vcr_cassettes/github-course-yaml-not-found.yml create mode 100644 spec/fixtures/vcr_cassettes/github-course-yaml-success-2.yml create mode 100644 spec/fixtures/vcr_cassettes/github-course-yaml-success.yml create mode 100644 spec/fixtures/vcr_cassettes/github-not-found.yml create mode 100644 spec/fixtures/vcr_cassettes/github-repo-success.yml create mode 100644 spec/fixtures/vcr_cassettes/gitlab-course-yaml-branch-failure.yml create mode 100644 spec/fixtures/vcr_cassettes/gitlab-course-yaml-success.yml create mode 100644 spec/fixtures/vcr_cassettes/gitlab-not-found.yml create mode 100644 spec/fixtures/vcr_cassettes/gitlab-success.yml create mode 100644 spec/fixtures/vcr_cassettes/resync-course-job-success.yml create mode 100644 spec/helpers/json_helper_spec.rb create mode 100644 spec/helpers/mastery_mode_percent_helper_spec.rb create mode 100644 spec/helpers/standard_navigation_helper_spec.rb create mode 100644 spec/integration_helper.rb create mode 100644 spec/jobs/branch_release_notifier_job_spec.rb create mode 100644 spec/jobs/checkpoint_paired_submission_job_spec.rb create mode 100644 spec/jobs/content_file_default_visibility_job_spec.rb create mode 100644 spec/jobs/content_file_visit_job_spec.rb create mode 100644 spec/jobs/create_api_interaction_job_spec.rb create mode 100644 spec/jobs/create_release_job_spec.rb create mode 100644 spec/jobs/evaluate_code_snippet_job_spec.rb create mode 100644 spec/jobs/evaluate_custom_snippet_job_spec.rb create mode 100644 spec/jobs/evaluate_project_job_spec.rb create mode 100644 spec/jobs/grade_timed_checkpoint_job_spec.rb create mode 100644 spec/jobs/import_student_work_job_spec.rb create mode 100644 spec/jobs/release_notifier_job_spec.rb create mode 100644 spec/jobs/resync_course_job_spec.rb create mode 100644 spec/jobs/set_block_caches_job_spec.rb create mode 100644 spec/jobs/slack_ds_prep_job_spec.rb create mode 100644 spec/jobs/slack_se_prep_job_spec.rb create mode 100644 spec/jobs/slack_student_job_spec.rb create mode 100644 spec/jobs/switch_to_branch_job_spec.rb create mode 100644 spec/models/activity_spec.rb create mode 100644 spec/models/api_interaction_spec.rb create mode 100644 spec/models/block_spec.rb create mode 100644 spec/models/challenge_spec.rb create mode 100644 spec/models/checkpoint_submission_spec.rb create mode 100644 spec/models/cohort_release_spec.rb create mode 100644 spec/models/cohort_spec.rb create mode 100644 spec/models/cohort_user_spec.rb create mode 100644 spec/models/content_file_spec.rb create mode 100644 spec/models/content_visibility_spec.rb create mode 100644 spec/models/lesson_visit_spec.rb create mode 100644 spec/models/notification_spec.rb create mode 100644 spec/models/pairing_spec.rb create mode 100644 spec/models/performance_spec.rb create mode 100644 spec/models/release_spec.rb create mode 100644 spec/models/resync_job_result_spec.rb create mode 100644 spec/models/section_spec.rb create mode 100644 spec/models/standard_spec.rb create mode 100644 spec/models/submitted_challenge_answer_spec.rb create mode 100644 spec/models/user_last_viewed_standard_path_spec.rb create mode 100644 spec/models/user_spec.rb create mode 100644 spec/policies/cohort_policy_spec.rb create mode 100644 spec/policies/content_file_policy_spec.rb create mode 100644 spec/policies/user_policy_spec.rb create mode 100644 spec/presenters/block_presenter/for_cohort_releases_new_spec.rb create mode 100644 spec/presenters/block_presenter/for_cohort_releases_spec.rb create mode 100644 spec/presenters/block_presenter/for_releases_spec.rb create mode 100644 spec/presenters/challenge_with_submitted_challenge_answers_presenter_spec.rb create mode 100644 spec/presenters/checkpoint_submission_presenter/for_index_spec.rb create mode 100644 spec/presenters/checkpoint_submission_presenter_spec.rb create mode 100644 spec/presenters/content_file_presenter/for_curriculum_last_viewed_spec.rb create mode 100644 spec/presenters/content_file_presenter/for_show_spec.rb create mode 100644 spec/presenters/content_file_presenter/for_sidebar_spec.rb create mode 100644 spec/presenters/standard_presenter/for_checkpoint_submission_spec.rb create mode 100644 spec/presenters/standard_presenter/for_standard_card_spec.rb create mode 100644 spec/presenters/student_progress_presenter_spec.rb create mode 100644 spec/presenters/submissions_dashboard_presenter_spec.rb create mode 100644 spec/presenters/submitted_challenge_answer_presenter_spec.rb create mode 100644 spec/services/activity_aggregator_service_spec.rb create mode 100644 spec/services/assessment_service_spec.rb create mode 100644 spec/services/auth_resolver_service_spec.rb create mode 100644 spec/services/auto_assign_release_service_spec.rb create mode 100644 spec/services/checkpoint_submission_service_spec.rb create mode 100644 spec/services/cohort_standard_progress_service_spec.rb create mode 100644 spec/services/course_validator_spec.rb create mode 100644 spec/services/curriculum_progress_service_spec.rb create mode 100644 spec/services/download_repository_service_spec.rb create mode 100644 spec/services/git_url_service_spec.rb create mode 100644 spec/services/mastery_average_service_spec.rb create mode 100644 spec/services/notification_service_spec.rb create mode 100644 spec/services/preview_content_file_service_spec.rb create mode 100644 spec/services/release_destroyer_service_spec.rb create mode 100644 spec/services/resync_course_service_spec.rb create mode 100644 spec/services/s3_asset_uploader_service_spec.rb create mode 100644 spec/services/standard_submissions_service_spec.rb create mode 100644 spec/spec_helper.rb create mode 100644 spec/support/json_spec_matchers.rb create mode 100644 spec/support/mocktokit.rb create mode 100644 spec/support/object_creation_methods.rb create mode 100644 tsconfig.json create mode 100644 vendor/assets/javascripts/bootstrap-datepicker.js create mode 100755 vendor/assets/javascripts/hopscotch.js create mode 100644 vendor/assets/javascripts/react-tooltip.js create mode 100644 vendor/assets/stylesheets/bootstrap-datepicker.css create mode 100755 vendor/assets/stylesheets/hopscotch.css create mode 100644 yarn.lock diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..ded31c0 --- /dev/null +++ b/.babelrc @@ -0,0 +1,18 @@ +{ + "presets": [ + ["env", { + "modules": false, + "targets": { + "browsers": "> 1%", + "uglify": true + }, + "useBuiltIns": true + }] + ], + + "plugins": [ + "syntax-dynamic-import", + "transform-object-rest-spread", + ["transform-class-properties", { "spec": true }] + ] +} diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..837f2f3 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,97 @@ +version: 2.0 + +defaults: &defaults + docker: + - image: circleci/ruby:2.6.0-node-browsers + environment: + - PG_HOST: localhost + - PG_USER: ubuntu + - RAILS_ENV: test + - RACK_ENV: test + - image: circleci/postgres:9.5-alpine + environment: + POSTGRES_USER: ubuntu + POSTGRES_DB: forge_test + - image: redis + working_directory: ~/forge + +jobs: + install_dependencies: + <<: *defaults + parallelism: 1 + steps: + - checkout + - attach_workspace: + at: ~/forge + - restore_cache: + key: v1-bundle-{{ checksum "Gemfile.lock" }} + - run: bundle install --path vendor/bundle + - save_cache: + key: v1-bundle-{{ checksum "Gemfile.lock" }} + paths: + - ~/forge/vendor/bundle + - persist_to_workspace: + root: . + paths: vendor/bundle + - restore_cache: + key: v1-yarn-{{ checksum "package.json" }} + - run: + name: Yarn Install JS Dependencies + command: yarn install + - save_cache: + key: v1-yarn-{{ checksum "package.json" }} + paths: + - ~/forge/node_modules + - persist_to_workspace: + root: . + paths: node_modules + + lint: + <<: *defaults + parallelism: 1 + steps: + - checkout + - attach_workspace: + at: ~/forge + - run: bundle --path vendor/bundle + - run: + name: Run Rubocop + command: bundle exec rubocop + - run: + name: Run tsc + command: ./node_modules/.bin/tsc --version && ./node_modules/.bin/tsc + + rake_test: + <<: *defaults + parallelism: 1 + steps: + - checkout + - attach_workspace: + at: ~/forge + - run: bundle --path vendor/bundle + - run: + name: Create DB + command: bundle exec rake db:create db:schema:load + environment: + DATABASE_URL: "postgres://ubuntu@localhost:5432/forge_test" + - run: + name: Run Rspec Tests + command: | + TESTFILES=$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings) + bundle exec rspec --profile 10 --format RspecJunitFormatter --out ~/forge/test-results/rspec.xml --format progress -- ${TESTFILES} + environment: + DATABASE_URL: "postgres://ubuntu@localhost:5432/forge_test" + - store_test_results: + path: ~/forge/test-results + +workflows: + version: 2 + build-and-deploy: + jobs: + - install_dependencies + - lint: + requires: + - install_dependencies + - rake_test: + requires: + - install_dependencies diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..ce45694 --- /dev/null +++ b/.env.example @@ -0,0 +1,9 @@ +AUTH_CLIENT_ID=forge +AUTH_CLIENT_SECRET= +AUTH_WEBHOOK_TOKEN= +GITHUB_TOKEN= +ASSESSMENTS_API_KEY= +ASSESSMENTS_CALLBACK_TOKEN= +LEARN_FIND_COHORT_URL="http://localhost:3002/cohorts/find" +DS_PREP_UID="01t0a000005He03AAC" +STANDARD_EVENT_UIDS="40f3bb48-1d23-4105-a22a-7f07b90bd1e6,cc22ef7e-d9c9-4e3d-ae9f-39f3477c5861" diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..53cbea6 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,201 @@ +{ + "parserOptions": { + "ecmaVersion": 8, + "ecmaFeatures": { + "experimentalObjectRestSpread": true, + "jsx": true + }, + "sourceType": "module" + }, + + "env": { + "es6": true, + "node": false + }, + + "plugins": [ + "import", + "promise", + "react", + "jsx-a11y", + "standard" + ], + + "globals": { + "document": false, + "navigator": false, + "window": false + }, + + "rules": { + "array-bracket-spacing": ["error", "never"], + "curly": ["error", "multi-line"], + "block-spacing": ["error", "always"], + "brace-style": ["error", "1tbs", { "allowSingleLine": true }], + "semi": ["error", "always"], + "quotes": ["error", "single", { "avoidEscape": true, "allowTemplateLiterals": true }], + "comma-spacing": ["error", { "before": false, "after": true }], + "no-debugger": "error", + "no-extra-parens": ["error", "functions"], + "no-floating-decimal": "error", + "no-implicit-coercion": "error", + "no-irregular-whitespace": "error", + "no-multi-spaces": "error", + "no-regex-spaces": "error", + "no-undef-init": "error", + "no-unsafe-negation": "error", + "no-unused-labels": "error", + "no-useless-return": "error", + "wrap-iife": ["error", "any", { "functionPrototypeMethods": true }], + "yoda": ["error", "never"], + "eol-last": "error", + "func-call-spacing": ["error", "never"], + "indent": ["error", 2], + "key-spacing": ["error", { "beforeColon": false, "afterColon": true }], + "keyword-spacing": ["error", { "before": true, "after": true }], + "new-parens": "error", + "newline-after-var": ["error", "always"], + "newline-before-return": "error", + "no-lonely-if": "error", + "no-multiple-empty-lines": ["error", { "max": 1 }], + "no-trailing-spaces": "error", + "no-unneeded-ternary": ["error", { "defaultAssignment": false }], + "no-whitespace-before-property": "error", + "nonblock-statement-body-position": "error", + "object-curly-spacing": ["error", "always"], + "operator-assignment": "error", + "space-before-blocks": ["error", "always"], + "space-before-function-paren": ["error", "never"], + "space-in-parens": ["error", "never"], + "space-infix-ops": "error", +// "spaced-comment": ["error", "always", { +// "line": { "markers": ["*package", "!", "//", ","] }, +// "block": { "balanced": true, "markers": ["*package", "!", ",", ":", "::", "flow-include"], "exceptions": ["*", "//"] } +// }], + "wrap-regex": "error" +// "accessor-pairs": "error", +// "arrow-spacing": ["error", { "before": true, "after": true }], +// "camelcase": ["error", { "properties": "never" }], +// "comma-dangle": ["error", { +// "arrays": "never", +// "objects": "never", +// "imports": "never", +// "exports": "never", +// "functions": "never" +// }], +// "comma-style": ["error", "last"], +// "constructor-super": "error", +// "dot-location": ["error", "property"], +// "eqeqeq": ["error", "always", { "null": "ignore" }], +// "generator-star-spacing": ["error", { "before": true, "after": true }], +// "handle-callback-err": ["error", "^(err|error)$" ], +// "new-cap": ["error", { "newIsCap": true, "capIsNew": false }], +// "no-array-constructor": "error", +// "no-caller": "error", +// "no-class-assign": "error", +// "no-compare-neg-zero": "error", +// "no-cond-assign": "error", +// "no-const-assign": "error", +// "no-constant-condition": ["error", { "checkLoops": false }], +// "no-control-regex": "error", +// "no-delete-var": "error", +// "no-dupe-args": "error", +// "no-dupe-class-members": "error", +// "no-dupe-keys": "error", +// "no-duplicate-case": "error", +// "no-empty-character-class": "error", +// "no-empty-pattern": "error", +// "no-eval": "error", +// "no-ex-assign": "error", +// "no-extend-native": "error", +// "no-extra-bind": "error", +// "no-extra-boolean-cast": "error", +// "no-fallthrough": "error", +// "no-func-assign": "error", +// "no-global-assign": "error", +// "no-implied-eval": "error", +// "no-inner-declarations": ["error", "functions"], +// "no-invalid-regexp": "error", +// "no-iterator": "error", +// "no-label-var": "error", +// "no-labels": ["error", { "allowLoop": false, "allowSwitch": false }], +// "no-lone-blocks": "error", +// "no-mixed-operators": ["error", { +// "groups": [ +// ["==", "!=", "===", "!==", ">", ">=", "<", "<="], +// ["&&", "||"], +// ["in", "instanceof"] +// ], +// "allowSamePrecedence": true +// }], +// "no-mixed-spaces-and-tabs": "error", +// "no-multi-str": "error", +// "no-negated-in-lhs": "error", +// "no-new": "error", +// "no-new-func": "error", +// "no-new-object": "error", +// "no-new-require": "error", +// "no-new-symbol": "error", +// "no-new-wrappers": "error", +// "no-obj-calls": "error", +// "no-octal": "error", +// "no-octal-escape": "error", +// "no-path-concat": "error", +// "no-proto": "error", +// "no-redeclare": "error", +// "no-return-assign": ["error", "except-parens"], +// "no-return-await": "error", +// "no-self-assign": "error", +// "no-self-compare": "error", +// "no-sequences": "error", +// "no-shadow-restricted-names": "error", +// "no-sparse-arrays": "error", +// "no-tabs": "error", +// "no-template-curly-in-string": "error", +// "no-this-before-super": "error", +// "no-throw-literal": "error", +// "no-undef": "error", +// "no-unexpected-multiline": "error", +// "no-unmodified-loop-condition": "error", +// "no-unreachable": "error", +// "no-unsafe-finally": "error", +// "no-unused-expressions": ["error", { "allowShortCircuit": true, "allowTernary": true, "allowTaggedTemplates": true }], +// "no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": true }], +// "no-use-before-define": ["error", { "functions": false, "classes": false, "variables": false }], +// "no-useless-call": "error", +// "no-useless-computed-key": "error", +// "no-useless-constructor": "error", +// "no-useless-escape": "error", +// "no-useless-rename": "error", +// "no-with": "error", +// "object-property-newline": ["error", { "allowMultiplePropertiesPerLine": true }], +// "one-var": ["error", { "initialized": "never" }], +// "operator-linebreak": ["error", "after", { "overrides": { "?": "before", ":": "before" } }], +// "padded-blocks": ["error", { "blocks": "never", "switches": "never", "classes": "never" }], +// "prefer-promise-reject-errors": "error", +// "rest-spread-spacing": ["error", "never"], +// "semi-spacing": ["error", { "before": false, "after": true }], +// "space-unary-ops": ["error", { "words": true, "nonwords": false }], +// "symbol-description": "error", +// "template-curly-spacing": ["error", "never"], +// "template-tag-spacing": ["error", "never"], +// "unicode-bom": ["error", "never"], +// "use-isnan": "error", +// "valid-typeof": ["error", { "requireStringLiterals": true }], +// "yield-star-spacing": ["error", "both"], +// "import/export": "error", +// "import/first": "error", +// "import/no-duplicates": "error", +// "import/no-webpack-loader-syntax": "error", +// +// "node/no-deprecated-api": "error", +// "node/process-exit-as-throw": "error", +// +// "promise/param-names": "error", +// +// "standard/array-bracket-even-spacing": ["error", "either"], +// "standard/computed-property-even-spacing": ["error", "even"], +// "standard/no-callback-literal": "error", +// "standard/object-curly-even-spacing": ["error", "either"] + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e644a12 --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +# See https://help.github.com/articles/ignoring-files for more about ignoring files. +# +# If you find yourself ignoring temporary files generated by your text editor +# or operating system, you probably want to add a global ignore instead: +# git config --global core.excludesfile '~/.gitignore_global' + +# Ignore bundler config. +/.bundle + +# Ignore all logfiles and tempfiles. +/log/* +/tmp/* + +/node_modules + +.byebug_history +.DS_Store +.env +.idea/* +/public/packs-test +/node_modules +.rspec_status +.idea/* +.vscode/* +/public/packs +/public/packs-test +/node_modules +yarn-debug.log* +.yarn-integrity +yarn-error.log +tags +.zshrc +.solargraph.yml \ No newline at end of file diff --git a/.haml-lint.yml b/.haml-lint.yml new file mode 100644 index 0000000..c82c789 --- /dev/null +++ b/.haml-lint.yml @@ -0,0 +1,6 @@ +linters: + LineLength: + max: 200 + + InlineStyles: + enabled: false diff --git a/.overcommit.yml b/.overcommit.yml new file mode 100644 index 0000000..13aa9ce --- /dev/null +++ b/.overcommit.yml @@ -0,0 +1,963 @@ +# Default configuration that all Overcommit configurations inherit from. +# +# This is an opinionated list of which hooks are valuable to run and what their +# out-of-the-box settings should be. +#------------------------------------------------------------------------------- + +# Loads Bundler context from a Gemfile. If false, does nothing (default). +# +# Specifying a Gemfile for Bundler to load allows you to control which gems are +# available in the load path (i.e. loadable via `require`) within your hook +# runs. Note that having a Gemfile requires you to include `overcommit` itself +# in your Gemfile (otherwise Overcommit can't load itself!). +# +# This is useful if you want to: +# +# - Enforce a specific version of Overcommit to use for all hook runs +# (or to use a version from the master branch that has not been released yet) +# - Enforce a specific version or unreleased branch is used for a gem you want +# to use in your git hooks +# +# WARNING: This makes your hook runs slower, but you can work around this! +# +# Loading a Bundler context necessarily adds a startup delay to your hook runs +# as Bundler parses the Gemfile and checks that the dependencies are satisfied. +# Thus for projects with many gems this can introduce a noticeable delay. +# +# The recommended workaround is to create a separate Gemfile in the root of your +# repository (call it `.overcommit_gems.rb`), and include only the gems that +# your Overcommit hooks need in order to run. This significantly reduces the +# startup delay in your hook runs. Make sure to commit both +# `.overcommit_gems.rb` and the resulting `.overcommit_gems.rb.lock` file to +# your repository, and then set the `gemfile` option below to the name you gave +# the file. +# (Generate lock file by running `bundle install --gemfile=.overcommit_gems.rb`) +gemfile: false + +# Where to store hook plugins specific to a repository. These are loaded in +# addition to the default hooks Overcommit comes with. The location is relative +# to the root of the repository. +plugin_directory: '.git-hooks' + +# Whether to hide hook output by default. This results in completely silent hook +# runs except in the case of warning or failure. +quiet: false + +# Number of hooks that can be run concurrently. Typically this won't need to be +# adjusted, but if you know that some of your hooks themselves use multiple +# processors you can lower this value accordingly. You can define +# single-operator mathematical expressions, e.g. '%{processors} * 2', or +# '%{processors} / 2'. +concurrency: '%{processors}' + +# Whether to check if a hook plugin has changed since Overcommit last ran it. +# This is a defense mechanism when working with repositories which can contain +# untrusted code (e.g. when you fetch a pull request from a third party). +# See https://github.com/brigade/overcommit#security for more information. +verify_signatures: false + +# Hooks that are run against every commit message after a user has written it. +# These hooks are useful for enforcing policies on commit messages written for a +# project. +CommitMsg: + ALL: + requires_files: false + quiet: false + + CapitalizedSubject: + enabled: false + description: 'Check subject capitalization' + + EmptyMessage: + enabled: false + description: 'Check for empty commit message' + quiet: true + + GerritChangeId: + enabled: false + description: 'Ensure Gerrit Change-Id is present' + required: true + + HardTabs: + enabled: false + description: 'Check for hard tabs' + + MessageFormat: + enabled: false + description: 'Check commit message matches expected pattern' + pattern: '(.+)[|](.+)[|](.+)' + expected_pattern_message: ' | | ' + sample_message: 'DEFECT-1234 | Refactored Onboarding flow | John Doe' + + RussianNovel: + enabled: false + description: 'Check length of commit message' + quiet: true + + SingleLineSubject: + enabled: false + description: 'Check subject line' + + SpellCheck: + enabled: false + description: 'Check for misspelled words' + required_executable: 'hunspell' + flags: ['-a'] + + TextWidth: + enabled: false + description: 'Check text width' + max_subject_width: 60 + max_body_width: 72 + + TrailingPeriod: + enabled: false + description: 'Check for trailing periods in subject' + +# Hooks that are run after `git commit` is executed, before the commit message +# editor is displayed. These hooks are ideal for syntax checkers, linters, and +# other checks that you want to run before you allow a commit object to be +# created. +PreCommit: + ALL: + problem_on_unmodified_line: report + requires_files: true + required: false + quiet: false + + AuthorEmail: + enabled: false + description: 'Check author email' + requires_files: false + required: true + quiet: true + pattern: '^[^@]+@.*$' + + AuthorName: + enabled: false + description: 'Check for author name' + requires_files: false + required: true + quiet: true + + BerksfileCheck: + enabled: false + description: 'Check Berksfile lock' + required_executable: 'berks' + flags: ['list', '--quiet'] + install_command: 'gem install berks' + include: + - 'Berksfile' + - 'Berksfile.lock' + + BrokenSymlinks: + enabled: false + description: 'Check for broken symlinks' + quiet: true + + BundleAudit: + enabled: false + description: 'Check for vulnerable versions of gems' + required_executable: 'bundle-audit' + install_command: 'gem install bundler-audit' + + BundleCheck: + enabled: false + description: 'Check Gemfile dependencies' + required_executable: 'bundle' + flags: ['check'] + install_command: 'gem install bundler' + include: + - 'Gemfile' + - 'Gemfile.lock' + - '*.gemspec' + + BundleOutdated: + enabled: false + description: 'List installed gems with newer versions available' + required_executable: 'bundle' + flags: ['outdated', '--strict', '--parseable'] + install_command: 'gem install bundler' + + CaseConflicts: + enabled: false + description: 'Check for case-insensitivity conflicts' + quiet: true + + ChamberSecurity: + enabled: false + description: 'Check that settings have been secured with Chamber' + required_executable: 'chamber' + flags: ['secure', '--files'] + install_command: 'gem install chamber' + include: + - 'config/settings.yml' + - 'config/settings/**/*.yml' + + CoffeeLint: + enabled: false + description: 'Analyze with coffeelint' + required_executable: 'coffeelint' + flags: ['--reporter=csv'] + install_command: 'npm install -g coffeelint' + include: '**/*.coffee' + + Credo: + enabled: false + description: 'Analyze with credo' + required_executable: 'mix' + flags: ['credo', '--all', '--strict', '--format', 'flycheck'] + include: + - '**/*.ex' + - '**/*.exs' + + CssLint: + enabled: false + description: 'Analyze with csslint' + required_executable: 'csslint' + flags: ['--quiet', '--format=compact'] + install_command: 'npm install -g csslint' + include: '**/*.css' + + Dogma: + enabled: false + description: 'Analyze with dogma' + required_executable: 'mix' + flags: ['dogma'] + include: + - '**/*.ex' + - '**/*.exs' + + EsLint: + enabled: true + on_warn: fail + required_executable: './node_modules/.bin/eslint' + include: + - 'app/**/*.js' + - 'app/**/*.jsx' + + ExecutePermissions: + enabled: false + description: 'Check for file execute permissions' + quiet: true + + Fasterer: + enabled: false + description: 'Analyzing for potential speed improvements' + required_executable: 'fasterer' + install_command: 'gem install fasterer' + include: '**/*.rb' + + FixMe: + enabled: false + description: 'Check for "token" strings' + required_executable: 'grep' + flags: ['-IEHnw'] + keywords: ['BROKEN', 'BUG', 'ERROR', 'FIXME', 'HACK', 'NOTE', 'OPTIMIZE', 'REVIEW', 'TODO', 'WTF', 'XXX'] + + Foodcritic: + enabled: false + description: 'Analyze with Foodcritic' + required_executable: 'foodcritic' + flags: ['--epic-fail=any'] + install_command: 'gem install foodcritic' + + ForbiddenBranches: + enabled: false + description: 'Check for commit to forbidden branch' + quiet: true + branch_patterns: ['master'] + + GoLint: + enabled: false + description: 'Analyze with golint' + required_executable: 'golint' + install_command: 'go get github.com/golang/lint/golint' + include: '**/*.go' + + GoVet: + enabled: false + description: 'Analyze with go vet' + required_executable: 'go' + flags: ['tool', 'vet'] + install_command: 'go get golang.org/x/tools/cmd/vet' + include: '**/*.go' + + HamlLint: + enabled: false + description: 'Analyze with haml-lint' + required_executable: 'haml-lint' + install_command: 'gem install haml-lint' + include: '**/*.haml' + on_warn: 'fail' + + HardTabs: + enabled: false + description: 'Check for hard tabs' + quiet: true + required_executable: 'grep' + flags: ['-IHn', "\t"] + + Hlint: + enabled: false + description: 'Analyze with hlint' + required_executable: 'hlint' + install_command: 'cabal install hlint' + include: '**/*.hs' + + HtmlHint: + enabled: false + description: 'Analyze with HTMLHint' + required_executable: 'htmlhint' + install_command: 'npm install -g htmlhint' + include: '**/*.html' + + HtmlTidy: + enabled: false + description: 'Analyze HTML with tidy' + required_executable: 'tidy' + flags: ['-errors', '-quiet', '-utf8'] + include: '**/*.html' + + ImageOptim: + enabled: false + description: 'Check for optimizable images' + required_executable: 'image_optim' + install_command: 'gem install image_optim' + include: + - '**/*.gif' + - '**/*.jpeg' + - '**/*.jpg' + - '**/*.png' + - '**/*.svg' + + JavaCheckstyle: + enabled: false + description: 'Analyze with checkstyle' + required_executable: 'checkstyle' + flags: ['-c', '/sun_checks.xml'] + include: '**/*.java' + + Jscs: + enabled: false + description: 'Analyze with JSCS' + required_executable: 'jscs' + flags: ['--reporter=inline'] + install_command: 'npm install -g jscs' + include: '**/*.js' + + JsHint: + enabled: false + description: 'Analyze with JSHint' + required_executable: 'jshint' + flags: ['--verbose'] + install_command: 'npm install -g jshint' + include: '**/*.js' + + JsLint: + enabled: false + description: 'Analyze with JSLint' + required_executable: 'jslint' + flags: ['--terse'] + install_command: 'npm install -g jslint' + include: '**/*.js' + + Jsl: + enabled: false + description: 'Analyze with JSL' + required_executable: 'jsl' + flags: ['-nologo', '-nofilelisting', '-nocontext', '-nosummary'] + include: '**/*.js' + + JsonSyntax: + enabled: false + description: 'Validate JSON syntax' + required_library: 'json' + install_command: 'gem install json' + include: '**/*.json' + + LicenseHeader: + enabled: false + license_file: 'LICENSE.txt' + description: 'Check source files for license headers' + + LocalPathsInGemfile: + enabled: false + description: 'Check for local paths in Gemfile' + required_executable: 'grep' + flags: ['-IHnE', "^[^#]*((\\bpath:)|(:path[ \t]*=>))"] + include: '**/Gemfile' + + Mdl: + enabled: false + description: 'Analyze with mdl' + required_executable: 'mdl' + install_command: 'gem install mdl' + include: '**/*.md' + + MergeConflicts: + enabled: false + description: 'Check for merge conflicts' + quiet: true + required_executable: 'grep' + flags: ['-IHn', "^<<<<<<<[ \t]"] + + NginxTest: + enabled: false + description: 'Test nginx configs' + required_executable: 'nginx' + flags: ['-t'] + include: '**/nginx.conf' + + Pep257: + enabled: false + description: 'Analyze docstrings with pep257' + required_executable: 'pep257' + install_command: 'pip install pep257' + include: '**/*.py' + + Pep8: + enabled: false + description: 'Analyze with pep8' + required_executable: 'pep8' + install_command: 'pip install pep8' + include: '**/*.py' + + PuppetLint: + enabled: false + description: 'Analyze with puppet-lint' + required_executable: 'puppet-lint' + install_command: 'gem install puppet-lint' + flags: + - '--log-format="%{fullpath}:%{line}:%{column}:%{KIND}: %{message} (%{check})"' + - '--fail-on-warnings' + - '--error-level=all' + include: '**/*.pp' + + Pyflakes: + enabled: false + description: 'Analyze with pyflakes' + required_executable: 'pyflakes' + install_command: 'pip install pyflakes' + include: '**/*.py' + + Pylint: + enabled: false + description: 'Analyze with Pylint' + required_executable: 'pylint' + install_command: 'pip install pylint' + flags: + - '--msg-template="{path}:{line}:{C}: {msg} ({symbol})"' + - '--reports=n' + - '--persistent=n' + include: '**/*.py' + + PythonFlake8: + enabled: false + description: 'Analyze with flake8' + required_executable: 'flake8' + install_command: 'pip install flake8' + include: '**/*.py' + + RakeTarget: + enabled: false + description: 'Run rake targets' + # targets: + # - 'lint' + # - 'validate' + # - '...' + required_executable: 'rake' + install_command: 'gem install rake' + + RailsBestPractices: + enabled: false + description: 'Analyze with RailsBestPractices' + required_executable: 'rails_best_practices' + flags: ['--without-color'] + install_command: 'gem install rails_best_practices' + + RailsSchemaUpToDate: + enabled: false + description: 'Check if database schema is up to date' + include: + - 'db/migrate/*.rb' + - 'db/schema.rb' + - 'db/structure.sql' + + Reek: + enabled: false + description: 'Analyze with Reek' + required_executable: 'reek' + flags: ['--single-line', '--no-color'] + install_command: 'gem install reek' + include: + - '**/*.gemspec' + - '**/*.rake' + - '**/*.rb' + - '**/Gemfile' + - '**/Rakefile' + + RuboCop: + enabled: true + description: 'Analyze with RuboCop' + required_executable: 'rubocop' + flags: ['--format=emacs', '--force-exclusion', '--display-cop-names'] + install_command: 'gem install rubocop' + on_warn: 'fail' + include: + - '**/*.gemspec' + - '**/*.rake' + - '**/*.rb' + - '**/*.ru' + - '**/Gemfile' + - '**/Rakefile' + + RubyLint: + enabled: false + description: 'Analyze with ruby-lint' + required_executable: 'ruby-lint' + flags: ['--presenter=syntastic', '--levels=error,warning'] + install_command: 'gem install ruby-lint' + include: + - '**/*.gemspec' + - '**/*.rb' + + Scalariform: + enabled: false + description: 'Check formatting with Scalariform' + required_executable: 'scalariform' + flags: ['--test'] + include: '**/*.scala' + + Scalastyle: + enabled: false + description: 'Analyze with Scalastyle' + required_executable: 'scalastyle' + include: '**/*.scala' + + StyleLint: + enabled: false + description: 'Analyze with style-lint' + required_library: 'json' + required_executable: 'stylelint' + flags: ['app/**/*.css', 'app/**/*.scss'] + install_command: 'npm install -g stylelint' + include: + - '**/*.scss' + - '**/*.css' + + SemiStandard: + enabled: false + description: 'Analyze with semistandard' + required_executable: 'semistandard' + flags: ['--verbose'] + install_command: 'npm install -g semistandard' + include: '**/*.js' + + ShellCheck: + enabled: false + description: 'Analyze with ShellCheck' + required_executable: 'shellcheck' + flags: ['--format=gcc'] + include: '**/*.sh' + + SlimLint: + enabled: false + description: 'Analyze with slim-lint' + required_executable: 'slim-lint' + install_command: 'gem install slim_lint' + include: '**/*.slim' + + Sqlint: + enabled: false + description: 'Analyze with sqlint' + required_executable: 'sqlint' + install_command: 'gem install sqlint' + include: '**/*.sql' + + Standard: + enabled: false + description: 'Analyze with standard' + required_executable: 'standard' + flags: ['--verbose'] + install_command: 'npm install -g standard' + include: '**/*.js' + + TsLint: + enabled: false + description: 'Analyze with TSLint' + required_executable: 'tslint' + install_command: 'npm install -g tslint typescript' + flags: ['--t=prose'] + include: '**/*.ts' + + TrailingWhitespace: + enabled: false + description: 'Check for trailing whitespace' + required_executable: 'grep' + flags: ['-IHn', "[ \t]$"] + + TravisLint: + enabled: false + description: 'Check Travis CI configuration' + required_executable: 'travis' + flags: ['lint'] + install_command: 'gem install travis' + include: '.travis.yml' + + Vint: + enabled: false + description: 'Analyze with Vint' + required_executable: 'vint' + install_command: 'pip install vim-vint' + include: + - '**/*.vim' + - '**/*.vimrc' + + W3cCss: + enabled: false + description: 'Analyze with W3C CSS validation service' + required_library: 'w3c_validators' + install_command: 'gem install w3c_validators' + validator_uri: 'http://jigsaw.w3.org/css-validator/validator' + language: 'en' + profile: 'css3' + warn_level: 2 + include: + - '**/*.css' + + W3cHtml: + enabled: false + description: 'Analyze with W3C HTML validation service' + required_library: 'w3c_validators' + install_command: 'gem install w3c_validators' + validator_uri: 'http://validator.w3.org/check' + charset: 'utf-8' + doctype: 'HTML5' + include: + - '**/*.html' + + LineEndings: + description: 'Check line endings' + enabled: false + eol: "\n" # or "\r\n" for Windows-style newlines + + XmlLint: + enabled: false + description: 'Analyze with xmllint' + required_executable: 'xmllint' + flags: ['--noout'] + include: + - '**/*.xml' + - '**/*.svg' + + XmlSyntax: + enabled: false + description: 'Check XML syntax' + required_library: 'rexml/document' + include: + - '**/*.xml' + - '**/*.svg' + + YamlLint: + enabled: false + description: 'Analyze with YAMLlint' + required_executable: 'yamllint' + flags: ['--format=parsable'] + install_command: 'pip install yamllint' + include: + - '**/*.yaml' + - '**/*.yml' + + YamlSyntax: + enabled: false + description: 'Check YAML syntax' + required_library: 'yaml' + include: + - '**/*.yaml' + - '**/*.yml' + +# Hooks that run after HEAD changes or a file is explicitly checked out. +PostCheckout: + ALL: + required: false + quiet: false + skip_file_checkout: true + + BowerInstall: + enabled: false + description: 'Install bower dependencies' + requires_files: true + required_executable: 'bower' + install_command: 'npm install -g bower' + flags: ['install'] + include: 'bower.json' + + BundleInstall: + enabled: false + description: 'Install Bundler dependencies' + requires_files: true + required_executable: 'bundle' + install_command: 'gem install bundler' + flags: ['install'] + include: + - 'Gemfile' + - 'Gemfile.lock' + - '*.gemspec' + + IndexTags: + enabled: false + description: 'Generate tags file from source' + quiet: true + required_executable: 'ctags' + + NpmInstall: + enabled: false + description: 'Install NPM dependencies' + requires_files: true + required_executable: 'npm' + flags: ['install'] + include: + - 'package.json' + - 'npm-shrinkwrap.json' + + SubmoduleStatus: + enabled: false + description: 'Check submodule status' + quiet: true + recursive: false + +# Hooks that run after a commit is created. +PostCommit: + ALL: + requires_files: false + required: false + quiet: false + + BowerInstall: + enabled: false + description: 'Install bower dependencies' + requires_files: true + required_executable: 'bower' + install_command: 'npm install -g bower' + flags: ['install'] + include: 'bower.json' + + BundleInstall: + enabled: false + description: 'Install Bundler dependencies' + requires_files: true + required_executable: 'bundle' + install_command: 'gem install bundler' + flags: ['install'] + include: + - 'Gemfile' + - 'Gemfile.lock' + - '*.gemspec' + + Commitplease: + enabled: false + description: 'Analyze with Commitplease' + required_executable: './node_modules/.bin/commitplease' + install_command: 'npm install --save-dev commitplease' + flags: ['-1'] + + GitGuilt: + enabled: false + description: 'Calculate changes in blame since last commit' + requires_files: true + required_executable: 'git-guilt' + flags: ['HEAD~', 'HEAD'] + install_command: 'npm install -g git-guilt' + + IndexTags: + enabled: false + description: 'Generate tags file from source' + quiet: true + required_executable: 'ctags' + + NpmInstall: + enabled: false + description: 'Install NPM dependencies' + requires_files: true + required_executable: 'npm' + flags: ['install'] + include: + - 'package.json' + - 'npm-shrinkwrap.json' + + SubmoduleStatus: + enabled: false + description: 'Check submodule status' + quiet: true + recursive: false + +# Hooks that run after `git merge` executes successfully (no merge conflicts). +PostMerge: + ALL: + requires_files: false + quiet: false + + BowerInstall: + enabled: false + description: 'Install bower dependencies' + requires_files: true + required_executable: 'bower' + install_command: 'npm install -g bower' + flags: ['install'] + include: 'bower.json' + + BundleInstall: + enabled: false + description: 'Install Bundler dependencies' + requires_files: true + required_executable: 'bundle' + install_command: 'gem install bundler' + flags: ['install'] + include: + - 'Gemfile' + - 'Gemfile.lock' + - '*.gemspec' + + IndexTags: + enabled: false + description: 'Generate tags file from source' + quiet: true + required_executable: 'ctags' + + NpmInstall: + enabled: false + description: 'Install NPM dependencies' + requires_files: true + required_executable: 'npm' + flags: ['install'] + include: + - 'package.json' + - 'npm-shrinkwrap.json' + + SubmoduleStatus: + enabled: false + description: 'Check submodule status' + quiet: true + recursive: false + +# Hooks that run after a commit is modified by an amend or rebase. +PostRewrite: + ALL: + requires_files: false + quiet: false + + BowerInstall: + enabled: false + description: 'Install bower dependencies' + requires_files: true + required_executable: 'bower' + install_command: 'npm install -g bower' + flags: ['install'] + include: 'bower.json' + + BundleInstall: + enabled: false + description: 'Install Bundler dependencies' + requires_files: true + required_executable: 'bundle' + install_command: 'gem install bundler' + flags: ['install'] + include: + - 'Gemfile' + - 'Gemfile.lock' + - '*.gemspec' + + IndexTags: + enabled: false + description: 'Generate tags file from source' + quiet: true + required_executable: 'ctags' + + NpmInstall: + enabled: false + description: 'Install NPM dependencies' + requires_files: true + required_executable: 'npm' + flags: ['install'] + include: + - 'package.json' + - 'npm-shrinkwrap.json' + + SubmoduleStatus: + enabled: false + description: 'Check submodule status' + quiet: true + recursive: false + +# Hooks that run during `git push`, after remote refs have been updated but +# before any objects have been transferred. +PrePush: + ALL: + requires_files: false + required: false + quiet: false + + ProtectedBranches: + enabled: false + description: 'Check for illegal pushes to protected branches' + destructive_only: true + branches: ['master'] + + Pytest: + enabled: false + description: 'Run pytest test suite' + required_executable: 'pytest' + install_command: 'pip install -U pytest' + + PythonNose: + enabled: false + description: 'Run nose test suite' + required_executable: 'nosetests' + install_command: 'pip install -U nose' + + RSpec: + enabled: false + description: 'Run RSpec test suite' + required_executable: 'rspec' + + RakeTarget: + enabled: false + description: 'Run rake targets' + # targets: + # - 'lint' + # - 'validate' + # - '...' + required_executable: 'rake' + install_command: 'gem install rake' + + Minitest: + enabled: false + description: 'Run Minitest test suite' + command: ['ruby', '-Ilib:test', '-rminitest', "-e 'exit! Minitest.run'"] + include: 'test/**/*_test.rb' + + TestUnit: + enabled: false + description: 'Run Test::Unit test suite' + command: ['ruby', '-Ilib:test', '-rtest/unit', "-e 'exit! Test::Unit::AutoRunner.run'"] + + Brakeman: + enabled: false + description: 'Check for security vulnerabilities' + required_executable: 'brakeman' + flags: ['--exit-on-warn', '--quiet', '--summary'] + install_command: 'gem install brakeman' + +# Hooks that run during `git rebase`, before any commits are rebased. +# If a hook fails, the rebase is aborted. +PreRebase: + ALL: + requires_files: false + required: false + quiet: false + + MergedCommits: + enabled: false + description: 'Check for commits that have already been merged' + branches: ['master'] diff --git a/.pairs b/.pairs new file mode 100644 index 0000000..8add478 --- /dev/null +++ b/.pairs @@ -0,0 +1,15 @@ +authors: + jj: Jeremy Jackson; jejacks0n + mb: Martha Berner; martha + pg: Peter Grunde; peter.a.grunde + dl: Derik Linch; derik.linch + cl: Chad Lillquist; chad.lillquist + jh: Joel Hawksley; joel + +email: + domain: galvanize.com + +email_addresses: + jj: jejacks0n@gmail.com + pg: peter.a.grunde@gmail.com + jh: joel@hawksley.org diff --git a/.postcssrc.yml b/.postcssrc.yml new file mode 100644 index 0000000..150dac3 --- /dev/null +++ b/.postcssrc.yml @@ -0,0 +1,3 @@ +plugins: + postcss-import: {} + postcss-cssnext: {} diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..267ce07 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,212 @@ +AllCops: + Exclude: + - 'bin/**/*' + - 'vendor/**/*' + - 'db/schema.rb' + - 'node_modules/**/*' + - 'spec/**/*' + - 'db/seeds.rb' + +Bundler/OrderedGems: + Enabled: false + +Style/Semicolon: + Enabled: true + +Lint/AssignmentInCondition: + Enabled: true + +Style/FloatDivision: + Enabled: false + +Naming/MemoizedInstanceVariableName: + Enabled: false + +Layout/EndAlignment: + Enabled: true + +Lint/HandleExceptions: + Enabled: true + +Lint/IneffectiveAccessModifier: + Enabled: true + +Lint/UselessAccessModifier: + Enabled: true + +Lint/RescueException: + Enabled: true + +Lint/ParenthesesAsGroupedExpression: + Enabled: false + +Lint/NonLocalExitFromIterator: + Enabled: false + +Lint/UriEscapeUnescape: + Enabled: false + +Style/DoubleNegation: + Enabled: false + +Style/IfUnlessModifier: + Enabled: false + +Style/MultilineBlockChain: + Enabled: false + +Naming/PredicateName: + Enabled: true + Exclude: + - app/controllers/application_controller.rb + +Naming/VariableNumber: + Enabled: true + Exclude: + - spec/**/* + +Metrics/AbcSize: + Enabled: false + +Metrics/BlockLength: + Enabled: true + Max: 1200 + +Metrics/BlockNesting: + Enabled: true + Max: 6 + +Metrics/ClassLength: + Enabled: true + Max: 500 + +Metrics/CyclomaticComplexity: + Enabled: true + Max: 30 + +Metrics/LineLength: + Enabled: true + Max: 140 + Exclude: + - app/controllers/cohorts_controller.rb + - app/jobs/create_release_job.rb + - app/services/standard_submissions_service.rb + - app/services/sql_challenge_db_service.rb + - spec/**/* + +Metrics/MethodLength: + Enabled: true + Max: 200 + +Metrics/ModuleLength: + Enabled: true + Max: 500 + +Metrics/ParameterLists: + Enabled: true + Max: 8 + +Metrics/PerceivedComplexity: + Enabled: false + +Layout/DotPosition: + EnforcedStyle: trailing + +Layout/EmptyLinesAroundArguments: + Enabled: false + +Layout/SpaceInsideBlockBraces: + Enabled: false + +Layout/MultilineMethodCallIndentation: + Enabled: false + +Style/SpecialGlobalVars: + EnforcedStyle: use_perl_names + +Style/StringLiterals: + EnforcedStyle: double_quotes + +Style/TrivialAccessors: + Enabled: true + +Security/YAMLLoad: + Enabled: false + +Style/AndOr: + Enabled: false + +Layout/CaseIndentation: + Enabled: false + +Style/Documentation: + Enabled: false + +Style/EmptyMethod: + Enabled: false + +Style/FrozenStringLiteralComment: + Enabled: false + +Style/MutableConstant: + Enabled: false + +Style/NumericLiteralPrefix: + Enabled: false + +Style/NumericLiterals: + Enabled: false + +Style/NumericPredicate: + Enabled: false + +Style/RedundantParentheses: + Enabled: false + +Style/RegexpLiteral: + Enabled: false + +Style/UnneededPercentQ: + Enabled: false + +Naming/VariableName: + Enabled: true + +Style/WordArray: + Enabled: false + +Style/ClassAndModuleChildren: + Enabled: false + +Style/ClassVars: + Enabled: false + +Style/DateTime: + Enabled: false + +Style/Next: + Enabled: false + +Style/GuardClause: + Enabled: false + +Style/SignalException: + Enabled: false + +Style/SymbolProc: + Enabled: true + Exclude: + - app/controllers/cohorts_controller.rb + +Style/FormatStringToken: + Enabled: false + +Layout/AlignHash: + Enabled: false + +Layout/AlignParameters: + Enabled: false + EnforcedStyle: with_fixed_indentation + +Layout/EmptyLinesAroundBlockBody: + Enabled: true diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000..e70b452 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +2.6.0 diff --git a/.stylelintrc b/.stylelintrc new file mode 100644 index 0000000..2c85a99 --- /dev/null +++ b/.stylelintrc @@ -0,0 +1,161 @@ +{ + "rules": { + # "at-rule-empty-line-before": "always", + # "at-rule-blacklist": string|[], + # "at-rule-name-case": "lower"|"upper", + # "at-rule-name-newline-after": "always"|"always-multi-line", + # "at-rule-name-space-after": "always"|"always-single-line", + # "at-rule-no-unknown": true, + # "at-rule-no-vendor-prefix": true, + # "at-rule-semicolon-newline-after": "always", + # "at-rule-semicolon-space-before": "always"|"never", + # "at-rule-whitelist": string|[], + # "block-closing-brace-empty-line-before": "always-multi-line"|"never", + "block-closing-brace-newline-after": "always", + "block-closing-brace-newline-before": "always", + # "block-closing-brace-space-after": "always"|"always-single-line"|"never-single-line"|"always-multi-line"|"never-multi-line", + # "block-closing-brace-space-before": "always"|"never"|"always-single-line"|"never-single-line"|"always-multi-line"|"never-multi-line", + # "block-no-empty": true, + # "color-hex-case": "lower"|"upper", + # "color-hex-length": "short"|"long", + # "color-named": "always-where-possible"|"never", + # "color-no-hex": true, + # "color-no-invalid-hex": true, + # "comment-empty-line-before": "always"|"never", + # "comment-no-empty": true, + # "comment-whitespace-inside": "always"|"never", + # "comment-word-blacklist": string|[], + # "custom-media-pattern": string, + # "custom-property-empty-line-before": "always"|"never", + # "custom-property-pattern": string, + # "declaration-bang-space-after": "always"|"never", + # "declaration-bang-space-before": "always"|"never", + # "declaration-block-no-duplicate-properties": true, + # "declaration-block-no-redundant-longhand-properties": true, + # "declaration-block-no-shorthand-property-overrides": true, + # "declaration-block-semicolon-newline-after": "always"|"always-multi-line"|"never-multi-line", + # "declaration-block-semicolon-newline-before": "always"|"always-multi-line"|"never-multi-line", + # "declaration-block-semicolon-space-after": "always"|"never"|"always-single-line"|"never-single-line", + # "declaration-block-semicolon-space-before": "always"|"never"|"always-single-line"|"never-single-line", + # "declaration-block-single-line-max-declarations": int, + # "declaration-block-trailing-semicolon": "always"|"never", + # "declaration-colon-newline-after": "always"|"always-multi-line", + "declaration-colon-space-after": "always", + "declaration-colon-space-before": "never", + "declaration-empty-line-before": "never", + # "declaration-no-important": true, + # "declaration-property-unit-blacklist": {}, + # "declaration-property-unit-whitelist": {}, + # "declaration-property-value-blacklist": {}, + # "declaration-property-value-whitelist": {}, + # "font-family-name-quotes": "always-where-required"|"always-where-recommended"|"always-unless-keyword", + # "font-family-no-duplicate-names": true, + # "font-weight-notation": "numeric"|"named", + # "function-blacklist": string|[], + # "function-calc-no-unspaced-operator": true, + # "function-comma-newline-after": "always"|"always-multi-line"|"never-multi-line", + # "function-comma-newline-before": "always"|"always-multi-line"|"never-multi-line", + # "function-comma-space-after": "always"|"never"|"always-single-line"|"never-single-line", + # "function-comma-space-before": "always"|"never"|"always-single-line"|"never-single-line", + # "function-linear-gradient-no-nonstandard-direction": true, + # "function-max-empty-lines": int, + # "function-name-case": "lower"|"upper", + # "function-parentheses-newline-inside": "always"|"always-multi-line"|"never-multi-line", + # "function-parentheses-space-inside": "always"|"never"|"always-single-line"|"never-single-line", + # "function-url-data-uris": "always"|"never", + # "function-url-no-scheme-relative": true, + # "function-url-quotes": "always"|"never", + # "function-url-scheme-whitelist": string|[], + # "function-whitelist": string|[], + # "function-whitespace-after": "always"|"never", + "indentation": 2, + # "keyframe-declaration-no-important": true, + # "length-zero-no-unit": true, + # "max-empty-lines": int, + # "max-line-length": int, + # "max-nesting-depth": int, + # "media-feature-colon-space-after": "always"|"never", + # "media-feature-colon-space-before": "always"|"never", + # "media-feature-name-blacklist": string|[], + # "media-feature-name-case": "lower"|"upper", + # "media-feature-name-no-unknown": true, + # "media-feature-name-no-vendor-prefix": true, + # "media-feature-name-whitelist": string|[], + # "media-feature-parentheses-space-inside": "always"|"never", + # "media-feature-range-operator-space-after": "always"|"never", + # "media-feature-range-operator-space-before": "always"|"never", + # "media-query-list-comma-newline-after": "always"|"always-multi-line"|"never-multi-line", + # "media-query-list-comma-newline-before": "always"|"always-multi-line"|"never-multi-line", + # "media-query-list-comma-space-after": "always"|"never"|"always-single-line"|"never-single-line", + # "media-query-list-comma-space-before": "always"|"never"|"always-single-line"|"never-single-line", + # "no-descending-specificity": true, + # "no-duplicate-selectors": true, + # "no-empty-source": true, + # "no-eol-whitespace": true, + # "no-extra-semicolons": true, + # "no-invalid-double-slash-comments": true, + # "no-missing-end-of-source-newline": true, + # "no-unknown-animations": true, + "number-leading-zero": "always", + # "number-max-precision": int, + "number-no-trailing-zeros": true, + # "property-blacklist": string|[], + # "property-case": "lower"|"upper", + # "property-no-unknown": true, + # "property-no-vendor-prefix": true, + # "property-whitelist": string|[], + # "rule-empty-line-before": "always"|"never"|"always-multi-line"|"never-multi-line", + # "selector-attribute-brackets-space-inside": "always"|"never", + # "selector-attribute-operator-blacklist": string|[], + # "selector-attribute-operator-space-after": "always"|"never", + # "selector-attribute-operator-space-before": "always"|"never", + # "selector-attribute-operator-whitelist": string|[], + # "selector-attribute-quotes": "always"|"never", + # "selector-class-pattern": string, + "selector-combinator-space-after": "always", + "selector-combinator-space-before": "always", + # "selector-descendant-combinator-no-non-space": true, + # "selector-id-pattern": string, + # "selector-list-comma-newline-after": "always"|"always-multi-line"|"never-multi-line", + # "selector-list-comma-newline-before": "always"|"always-multi-line"|"never-multi-line", + # "selector-list-comma-space-after": "always"|"never"|"always-single-line"|"never-single-line", + "selector-list-comma-space-before": "never", + # "selector-max-empty-lines": int, + # "selector-max-class": int, + # "selector-max-compound-selectors": int, + # "selector-max-specificity": string, + # "selector-nested-pattern": string, + # "selector-no-attribute": true, + # "selector-no-combinator": true, + # "selector-no-id": true, + # "selector-no-qualifying-type": true, + # "selector-no-type": true, + # "selector-no-universal": true, + # "selector-no-vendor-prefix": true, + # "selector-pseudo-class-blacklist": string|[], + # "selector-pseudo-class-case": "lower"|"upper", + # "selector-pseudo-class-no-unknown": true, + # "selector-pseudo-class-parentheses-space-inside": "always"|"never", + # "selector-pseudo-class-whitelist": string|[], + # "selector-pseudo-element-case": "lower"|"upper", + # "selector-pseudo-element-colon-notation": "single"|"double", + # "selector-pseudo-element-no-unknown": true, + # "selector-type-case": "lower"|"upper", + # "selector-type-no-unknown": true, + "shorthand-property-no-redundant-values": true, + # "string-no-newline": true, + "string-quotes": "double", + # "time-min-milliseconds": int, + # "unit-blacklist": string|[], + # "unit-case": "lower"|"upper", + # "unit-no-unknown": true, + # "unit-whitelist": string|[], + # "value-keyword-case": "lower"|"upper", + # "value-list-comma-newline-after": "always"|"always-multi-line"|"never-multi-line", + # "value-list-comma-newline-before": "always"|"always-multi-line"|"never-multi-line", + # "value-list-comma-space-after": "always"|"never"|"always-single-line"|"never-single-line", + # "value-list-comma-space-before": "always"|"never"|"always-single-line"|"never-single-line", + # "value-list-max-empty-lines": int, + # "value-no-vendor-prefix": true + } +} diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..581729e --- /dev/null +++ b/Gemfile @@ -0,0 +1,94 @@ +source "https://rubygems.org" +ruby "2.6.0" + +git_source(:github) do |repo_name| + repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/") + "https://github.com/#{repo_name}.git" +end + +# architecture +gem "aws-sdk", "~> 2.6.5" +gem "pg", "~> 0.18" +gem "redis", "~> 3.0" +gem "puma", "~> 3.12.0" +gem "pundit" +gem "httparty" +gem "pagy" +gem "rails", "~> 5.2.1" +gem "sidekiq" +gem "dotenv-rails" +gem "rubyzip", ">= 1.0.0" +gem "zip-zip" +gem "tzinfo-data", platforms: %i[mingw mswin x64_mingw jruby] +gem "rack-attack" + +# assets +gem "ts_routes" +gem "webpacker", "~> 3.5" +gem "bootstrap", "4.0.0" +gem "font-awesome-rails" +gem "sass-rails", "~> 5.0" +gem "uglifier", ">= 1.3.0" + +# views +gem "haml" +gem "jquery-rails" +gem "mathjax-rails" +gem "react-rails", "2.4.5" +gem "underscore-rails", "1.8.3" +gem "js-routes" +gem "browser" +gem "apitome" + +# services +gem "auth-api", github: "Galvanize-IT/auth-api", ref: "81cd1ec61544746ee71d03287dc9d23126fdcf27" +gem "honeybadger", "~> 3.1" +gem "github_url", "0.2.1" +gem "gitlab" +gem "analytics-ruby", "~> 2.0.0", require: "segment/analytics" +gem "octokit" +gem "barnes" +gem "scout_apm" +gem "solid_use_case", "~> 2.2.0" +gem "dry-validation", "~> 0.12.2" + +# file processing +gem "block_parser", github: "Galvanize-IT/block_parser", ref: "6d0fc6c3f2d2d7d06b9ad51d52f57430b7e438bc" + +# Reduces boot times through caching; required in config/boot.rb +gem "bootsnap", ">= 1.1.0" + +# performance +gem "rack-mini-profiler" +gem "memory_profiler" +gem "flamegraph" +gem "stackprof" + +group :development, :test do + gem "json_spec" + gem "byebug" + gem "factory_bot_rails" + gem "rspec-rails" +end + +group :development do + gem "foreman" + gem "overcommit" + gem "rubocop" + gem "better_errors" + gem "binding_of_caller" + gem "letter_opener" +end + +group :test do + gem "capybara" + gem "database_cleaner" + gem "rspec_junit_formatter" + gem "selenium-webdriver" + gem "shoulda-matchers" + gem "timecop" + gem "vcr" + gem "webmock" + gem "rails-controller-testing" + gem "rspec_api_documentation" +end diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..efc3766 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,492 @@ +GIT + remote: https://github.com/Galvanize-IT/auth-api.git + revision: 81cd1ec61544746ee71d03287dc9d23126fdcf27 + ref: 81cd1ec61544746ee71d03287dc9d23126fdcf27 + specs: + auth-api (0.0.2) + omniauth-oauth2 (< 1.4.0) + railties (< 6) + +GIT + remote: https://github.com/Galvanize-IT/block_parser.git + revision: 6d0fc6c3f2d2d7d06b9ad51d52f57430b7e438bc + ref: 6d0fc6c3f2d2d7d06b9ad51d52f57430b7e438bc + specs: + block_parser (0.1.0) + activemodel (> 4.2) + github-markdown (= 0.6.9) + github-markup (= 1.6.1) + github_url (= 0.2.1) + gitlab (= 4.14.1) + nokogiri (= 1.8.0) + octokit (= 4.3.0) + psych (= 2.2.4) + redcarpet (= 3.3.4) + rspec_junit_formatter (> 0.2.3) + +GEM + remote: https://rubygems.org/ + specs: + actioncable (5.2.1) + actionpack (= 5.2.1) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailer (5.2.1) + actionpack (= 5.2.1) + actionview (= 5.2.1) + activejob (= 5.2.1) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 2.0) + actionpack (5.2.1) + actionview (= 5.2.1) + activesupport (= 5.2.1) + rack (~> 2.0) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (5.2.1) + activesupport (= 5.2.1) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + activejob (5.2.1) + activesupport (= 5.2.1) + globalid (>= 0.3.6) + activemodel (5.2.1) + activesupport (= 5.2.1) + activerecord (5.2.1) + activemodel (= 5.2.1) + activesupport (= 5.2.1) + arel (>= 9.0) + activestorage (5.2.1) + actionpack (= 5.2.1) + activerecord (= 5.2.1) + marcel (~> 0.3.1) + activesupport (5.2.1) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + addressable (2.4.0) + analytics-ruby (2.0.13) + apitome (0.3.0) + kramdown + railties + arel (9.0.0) + ast (2.4.0) + autoprefixer-rails (7.2.5) + execjs + aws-sdk (2.6.50) + aws-sdk-resources (= 2.6.50) + aws-sdk-core (2.6.50) + aws-sigv4 (~> 1.0) + jmespath (~> 1.0) + aws-sdk-resources (2.6.50) + aws-sdk-core (= 2.6.50) + aws-sigv4 (1.0.2) + babel-source (5.8.35) + babel-transpiler (0.7.0) + babel-source (>= 4.0, < 6) + execjs (~> 2.0) + barnes (0.0.7) + multi_json (~> 1) + statsd-ruby (~> 1.1) + better_errors (2.5.0) + coderay (>= 1.0.0) + erubi (>= 1.0.0) + rack (>= 0.9.0) + binding_of_caller (0.8.0) + debug_inspector (>= 0.0.1) + bootsnap (1.3.1) + msgpack (~> 1.0) + bootstrap (4.0.0) + autoprefixer-rails (>= 6.0.3) + popper_js (>= 1.12.9, < 2) + sass (>= 3.5.2) + browser (2.5.2) + builder (3.2.3) + byebug (9.1.0) + capybara (2.16.1) + addressable + mini_mime (>= 0.1.3) + nokogiri (>= 1.3.3) + rack (>= 1.0.0) + rack-test (>= 0.5.4) + xpath (~> 2.0) + childprocess (0.8.0) + ffi (~> 1.0, >= 1.0.11) + coderay (1.1.2) + concurrent-ruby (1.1.5) + connection_pool (2.2.1) + crack (0.4.3) + safe_yaml (~> 1.0.0) + crass (1.0.4) + database_cleaner (1.6.2) + debug_inspector (0.0.3) + deterministic (0.6.0) + diff-lcs (1.3) + dotenv (2.5.0) + dotenv-rails (2.5.0) + dotenv (= 2.5.0) + railties (>= 3.2, < 6.0) + dry-configurable (0.7.0) + concurrent-ruby (~> 1.0) + dry-container (0.6.0) + concurrent-ruby (~> 1.0) + dry-configurable (~> 0.1, >= 0.1.3) + dry-core (0.4.7) + concurrent-ruby (~> 1.0) + dry-equalizer (0.2.1) + dry-inflector (0.1.2) + dry-logic (0.4.2) + dry-container (~> 0.2, >= 0.2.6) + dry-core (~> 0.2) + dry-equalizer (~> 0.2) + dry-types (0.13.2) + concurrent-ruby (~> 1.0) + dry-container (~> 0.3) + dry-core (~> 0.4, >= 0.4.4) + dry-equalizer (~> 0.2) + dry-inflector (~> 0.1, >= 0.1.2) + dry-logic (~> 0.4, >= 0.4.2) + dry-validation (0.12.2) + concurrent-ruby (~> 1.0) + dry-configurable (~> 0.1, >= 0.1.3) + dry-core (~> 0.2, >= 0.2.1) + dry-equalizer (~> 0.2) + dry-logic (~> 0.4, >= 0.4.0) + dry-types (~> 0.13.1) + erubi (1.7.1) + execjs (2.7.0) + factory_bot (4.8.2) + activesupport (>= 3.0.0) + factory_bot_rails (4.8.2) + factory_bot (~> 4.8.2) + railties (>= 3.0.0) + faraday (0.9.2) + multipart-post (>= 1.2, < 3) + ffi (1.9.18) + flamegraph (0.9.5) + font-awesome-rails (4.7.0.4) + railties (>= 3.2, < 6.0) + foreman (0.84.0) + thor (~> 0.19.1) + github-markdown (0.6.9) + github-markup (1.6.1) + github_url (0.2.1) + gitlab (4.14.1) + httparty (~> 0.14, >= 0.14.0) + terminal-table (~> 1.5, >= 1.5.1) + globalid (0.4.1) + activesupport (>= 4.2.0) + haml (5.0.4) + temple (>= 0.8.0) + tilt + hashdiff (0.4.0) + hashie (4.1.0) + honeybadger (3.2.0) + httparty (0.15.6) + multi_xml (>= 0.5.2) + i18n (1.6.0) + concurrent-ruby (~> 1.0) + iniparse (1.4.4) + jaro_winkler (1.5.3) + jmespath (1.3.1) + jquery-rails (4.3.1) + rails-dom-testing (>= 1, < 3) + railties (>= 4.2.0) + thor (>= 0.14, < 2.0) + js-routes (1.4.2) + railties (>= 3.2) + sprockets-rails + json_spec (1.1.5) + multi_json (~> 1.0) + rspec (>= 2.0, < 4.0) + jwt (2.2.2) + kramdown (2.1.0) + launchy (2.4.3) + addressable (~> 2.3) + letter_opener (1.7.0) + launchy (~> 2.2) + loofah (2.2.2) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + mail (2.7.0) + mini_mime (>= 0.1.1) + marcel (0.3.2) + mimemagic (~> 0.3.2) + mathjax-rails (2.6.1) + railties (>= 3.0) + memory_profiler (0.9.12) + method_source (0.9.0) + mimemagic (0.3.2) + mini_mime (1.0.0) + mini_portile2 (2.2.0) + minitest (5.11.3) + msgpack (1.2.4) + multi_json (1.13.1) + multi_xml (0.6.0) + multipart-post (2.0.0) + mustache (1.1.0) + nio4r (2.3.1) + nokogiri (1.8.0) + mini_portile2 (~> 2.2.0) + oauth2 (1.4.4) + faraday (>= 0.8, < 2.0) + jwt (>= 1.0, < 3.0) + multi_json (~> 1.3) + multi_xml (~> 0.5) + rack (>= 1.2, < 3) + octokit (4.3.0) + sawyer (~> 0.7.0, >= 0.5.3) + omniauth (1.9.1) + hashie (>= 3.4.6) + rack (>= 1.6.2, < 3) + omniauth-oauth2 (1.3.1) + oauth2 (~> 1.0) + omniauth (~> 1.2) + overcommit (0.41.0) + childprocess (~> 0.6, >= 0.6.3) + iniparse (~> 1.4) + pagy (3.7.1) + parallel (1.17.0) + parser (2.6.3.0) + ast (~> 2.4.0) + pg (0.21.0) + popper_js (1.12.9) + psych (2.2.4) + puma (3.12.1) + pundit (1.1.0) + activesupport (>= 3.0.0) + rack (2.0.3) + rack-attack (6.2.1) + rack (>= 1.0, < 3) + rack-mini-profiler (1.0.0) + rack (>= 1.2.0) + rack-protection (2.0.0) + rack + rack-proxy (0.6.4) + rack + rack-test (0.8.2) + rack (>= 1.0, < 3) + rails (5.2.1) + actioncable (= 5.2.1) + actionmailer (= 5.2.1) + actionpack (= 5.2.1) + actionview (= 5.2.1) + activejob (= 5.2.1) + activemodel (= 5.2.1) + activerecord (= 5.2.1) + activestorage (= 5.2.1) + activesupport (= 5.2.1) + bundler (>= 1.3.0) + railties (= 5.2.1) + sprockets-rails (>= 2.0.0) + rails-controller-testing (1.0.2) + actionpack (~> 5.x, >= 5.0.1) + actionview (~> 5.x, >= 5.0.1) + activesupport (~> 5.x) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-html-sanitizer (1.0.4) + loofah (~> 2.2, >= 2.2.2) + railties (5.2.1) + actionpack (= 5.2.1) + activesupport (= 5.2.1) + method_source + rake (>= 0.8.7) + thor (>= 0.19.0, < 2.0) + rainbow (3.0.0) + rake (12.3.1) + rb-fsevent (0.10.2) + rb-inotify (0.9.10) + ffi (>= 0.5.0, < 2) + react-rails (2.4.5) + babel-transpiler (>= 0.7.0) + connection_pool + execjs + railties (>= 3.2) + tilt + redcarpet (3.3.4) + redis (3.3.5) + rspec (3.7.0) + rspec-core (~> 3.7.0) + rspec-expectations (~> 3.7.0) + rspec-mocks (~> 3.7.0) + rspec-core (3.7.0) + rspec-support (~> 3.7.0) + rspec-expectations (3.7.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.7.0) + rspec-mocks (3.7.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.7.0) + rspec-rails (3.7.2) + actionpack (>= 3.0) + activesupport (>= 3.0) + railties (>= 3.0) + rspec-core (~> 3.7.0) + rspec-expectations (~> 3.7.0) + rspec-mocks (~> 3.7.0) + rspec-support (~> 3.7.0) + rspec-support (3.7.0) + rspec_api_documentation (6.1.0) + activesupport (>= 3.0.0) + mustache (~> 1.0, >= 0.99.4) + rspec (~> 3.0) + rspec_junit_formatter (0.3.0) + rspec-core (>= 2, < 4, != 2.12.0) + rubocop (0.72.0) + jaro_winkler (~> 1.5.1) + parallel (~> 1.10) + parser (>= 2.6) + rainbow (>= 2.2.2, < 4.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 1.4.0, < 1.7) + ruby-progressbar (1.10.1) + rubyzip (1.2.1) + safe_yaml (1.0.5) + sass (3.5.3) + sass-listen (~> 4.0.0) + sass-listen (4.0.0) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + sass-rails (5.0.7) + railties (>= 4.0.0, < 6) + sass (~> 3.1) + sprockets (>= 2.8, < 4.0) + sprockets-rails (>= 2.0, < 4.0) + tilt (>= 1.1, < 3) + sawyer (0.7.0) + addressable (>= 2.3.5, < 2.5) + faraday (~> 0.8, < 0.10) + scout_apm (2.4.19) + selenium-webdriver (3.8.0) + childprocess (~> 0.5) + rubyzip (~> 1.0) + shoulda-matchers (3.1.2) + activesupport (>= 4.0.0) + sidekiq (5.0.5) + concurrent-ruby (~> 1.0) + connection_pool (~> 2.2, >= 2.2.0) + rack-protection (>= 1.5.0) + redis (>= 3.3.4, < 5) + solid_use_case (2.2.0) + deterministic (~> 0.6.0) + sprockets (3.7.1) + concurrent-ruby (~> 1.0) + rack (> 1, < 3) + sprockets-rails (3.2.1) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) + stackprof (0.2.12) + statsd-ruby (1.4.0) + temple (0.8.0) + terminal-table (1.8.0) + unicode-display_width (~> 1.1, >= 1.1.1) + thor (0.19.4) + thread_safe (0.3.6) + tilt (2.0.8) + timecop (0.9.1) + ts_routes (1.0.1) + railties (>= 5.0) + tzinfo (1.2.5) + thread_safe (~> 0.1) + uglifier (4.0.2) + execjs (>= 0.3.0, < 3) + underscore-rails (1.8.3) + unicode-display_width (1.6.0) + vcr (4.0.0) + webmock (3.6.0) + addressable (>= 2.3.6) + crack (>= 0.3.2) + hashdiff (>= 0.4.0, < 2.0.0) + webpacker (3.5.5) + activesupport (>= 4.2) + rack-proxy (>= 0.6.1) + railties (>= 4.2) + websocket-driver (0.7.0) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.3) + xpath (2.1.0) + nokogiri (~> 1.3) + zip-zip (0.3) + rubyzip (>= 1.0.0) + +PLATFORMS + ruby + +DEPENDENCIES + analytics-ruby (~> 2.0.0) + apitome + auth-api! + aws-sdk (~> 2.6.5) + barnes + better_errors + binding_of_caller + block_parser! + bootsnap (>= 1.1.0) + bootstrap (= 4.0.0) + browser + byebug + capybara + database_cleaner + dotenv-rails + dry-validation (~> 0.12.2) + factory_bot_rails + flamegraph + font-awesome-rails + foreman + github_url (= 0.2.1) + gitlab + haml + honeybadger (~> 3.1) + httparty + jquery-rails + js-routes + json_spec + letter_opener + mathjax-rails + memory_profiler + octokit + overcommit + pagy + pg (~> 0.18) + puma (~> 3.12.0) + pundit + rack-attack + rack-mini-profiler + rails (~> 5.2.1) + rails-controller-testing + react-rails (= 2.4.5) + redis (~> 3.0) + rspec-rails + rspec_api_documentation + rspec_junit_formatter + rubocop + rubyzip (>= 1.0.0) + sass-rails (~> 5.0) + scout_apm + selenium-webdriver + shoulda-matchers + sidekiq + solid_use_case (~> 2.2.0) + stackprof + timecop + ts_routes + tzinfo-data + uglifier (>= 1.3.0) + underscore-rails (= 1.8.3) + vcr + webmock + webpacker (~> 3.5) + zip-zip + +RUBY VERSION + ruby 2.6.0p0 + +BUNDLED WITH + 1.17.3 diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..ed57e30 --- /dev/null +++ b/Procfile @@ -0,0 +1,3 @@ +web: bundle exec rails server -p $PORT +worker: sidekiq +release: rake db:migrate diff --git a/Procfile.local b/Procfile.local new file mode 100644 index 0000000..0e0c11f --- /dev/null +++ b/Procfile.local @@ -0,0 +1,3 @@ +web: bundle exec rails server -p 3003 +worker: bundle exec sidekiq +webpack: ./bin/webpack-dev-server diff --git a/README.md b/README.md new file mode 100644 index 0000000..fc701f1 --- /dev/null +++ b/README.md @@ -0,0 +1,109 @@ +Forge +===== + +## Standards +See the [software-team-standards](https://www.github.com/Galvanize-IT/software-team-standards) for git aliases. + +## Dependency Setup + +[install Homebrew](http://brew.sh/) if you don't already have it. + +Install rbenv and get the right version of ruby (the version here may change, so check the Gemfile for the correct +version. ) + +- `brew install rbenv` +- `rbenv install 2.6.0` + +Install our data stores: + +- `brew install postgresql` +- `brew install redis` +- `brew services start redis` + +To simplify your postgres installation, once you've installed it with homebrew, it's recommended that you use the +[Postgres.app](http://postgresapp.com/), which is an easy download and install. This allows you to not need to specify a +username/password in your `database.yml`. + + +## Installation + +You will need a [Github access token](https://github.com/settings/tokens). Replace the `YOUR_GENERATED_PERSONAL_ACCESS_TOKEN` with your token. + +The token will need **Full control of private repositories** + +- `git clone git@github.com:Galvanize-IT/forge.git && cd forge` +- `rbenv local 2.6.0` +- `gem install bundler` +- `bundle config --local GITHUB__COM YOUR_GENERATED_PERSONAL_ACCESS_TOKEN:x-oauth-basic` +- `bundle` +- `yarn install` + +## Data + +- `rake db:create` +- `rake db:migrate` + +## Auth + +Set up [Auth](https://github.com/Galvanize-IT/auth) before running Forge. + +## Configuration + +Ask a co-developer for their .env example. + +### Sidekiq + +As an admin, you can view Sidekiq jobs at `/admin/sidekiq`. + +## Starting the server + +`heroku local -p 3003` + +or: +`rails s -p 3003` +`sidekiq` +`bin/webpack-dev-server` + +## Deployment + +PRs are automatically deployed to their own one-off environments. To test webhook-related Auth features, be sure to update the webhooks for Forge at `auth-staging.herokuapp.com` to point to your review enviroment. + +Sign in to your review environment using your credentials for `auth-staging.herokuapp.com`, or `dev+auth@galvanize.com:password`. + +`master` is automatically deployed to `staging` once CI passes. + +Migrations are run as part of the deployment release phase. + +Note: `galvanize-forge` will need to have access to any repos used for project challenges. + +## Mailer previews + +To preview our mailers, go to `http://localhost:3003/rails/mailers`. + +## End-to-end Tests (e2e) + +The [Forge e2e suite](https://github.com/Galvanize-IT/forge-e2e) is run on every deploy to staging, and the results are posted to `#forge_devops`. + +## Code Generators + +The `ts_routes` gem generates typesafe routes for use in TypeScript. To update them: + +`rake ts:routes` + +### API Documentation + +The specs for the API use a specific DSL that allows the tests to generate our API documentation. You can then run the +integration specs and generate the documentation. The documentation can be committed if you’ve made changes to the API, +otherwise they can be disregard. + +Run `rails spec:api:docs` to generate the documentation files and then browse to `/api/docs` to see what the +documentation looks like. + +## Linters + +We use `rubocop` and `eslint`. + +You can use overcommit to automatically run our linters in a pre-commit hook: (`gem install overcommit; overcommit --install`). +Note: If you want to disable it inline (i.e. for a WIP commit), use `OVERCOMMIT_DISABLE=1 git commit -m "wip"`. + +You can also run the linters manually with auto-correction, along with the test suite, by running `bash lintspec.sh`. diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..9a5ea73 --- /dev/null +++ b/Rakefile @@ -0,0 +1,6 @@ +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. + +require_relative "config/application" + +Rails.application.load_tasks diff --git a/app.json b/app.json new file mode 100644 index 0000000..ac9eda1 --- /dev/null +++ b/app.json @@ -0,0 +1,168 @@ +{ + "name": "forge", + "scripts": { + "postdeploy": "bundle exec rake db:seed" + }, + "env": { + "ACTIONMAILER_HOST": { + "required": true + }, + "ASSESSMENTS_API_KEY": { + "required": true + }, + "ASSESSMENTS_CALLBACK_TOKEN": { + "required": true + }, + "ASSESSMENTS_SERVICE_DOMAIN": { + "required": true + }, + "AUTH_CLIENT_ID": { + "required": true + }, + "AUTH_CLIENT_SECRET": { + "required": true + }, + "AUTH_URL": { + "required": true + }, + "AUTH_WEBHOOK_TOKEN": { + "required": true + }, + "AWS_ACCESS_KEY_ID": { + "required": true + }, + "AWS_SECRET_ACCESS_KEY": { + "required": true + }, + "BUNDLE_GITHUB__COM": { + "required": true + }, + "LEARN_FIND_COHORT_URL": { + "required": true + }, + "GITHUB_TOKEN": { + "required": true + }, + "GITHUB_COM_TOKEN": { + "required": true + }, + "GITLAB_COM_TOKEN": { + "required": true + }, + "GLEARN_ACCESS_KEY_ID": { + "required": true + }, + "GLEARN_BUCKET_NAME": { + "required": true + }, + "GLEARN_KEY_PREFIX": { + "required": true + }, + "GLEARN_SECRET_ACCESS_KEY": { + "required": true + }, + "HEROKU_APP_NAME": { + "required": true + }, + "HONEYBADGER_API_KEY": { + "required": true + }, + "HONEYBADGER_ENV": { + "value": "review" + }, + "INTERCOM_APP_ID": { + "required": true + }, + "LANG": { + "required": true + }, + "MIXPANEL_PROJECT_TOKEN": { + "required": true + }, + "PROTOCOL": { + "required": true + }, + "RACK_ENV": { + "required": true + }, + "RAILS_ENV": { + "required": true + }, + "RAILS_LOG_TO_STDOUT": { + "required": true + }, + "RAILS_SERVE_STATIC_FILES": { + "required": true + }, + "REDIS_PROVIDER": { + "required": true + }, + "REDIS_URL": { + "required": true + }, + "SECRET_KEY_BASE": { + "required": true + }, + "SENDGRID_PASSWORD": { + "required": true + }, + "SENDGRID_USERNAME": { + "required": true + }, + "S3_BUCKET_NAME": { + "required": true + }, + "DS_PREP_UID": { + "required": true + }, + "SE_PREP_UID": { + "required": true + }, + "STANDARD_EVENT_UIDS": { + "required": true + }, + "SEGMENT_WRITE_KEY_SERVER": { + "required": true + }, + "SEGMENT_WRITE_KEY_CLIENT": { + "required": true + }, + "AWS_SQLSNIPPETS_PASSWORD": { + "required": true + }, + "AWS_SQLSNIPPETS_USER": { + "required": true + }, + "AWS_SQLSNIPPETS_HOST": { + "required": true + }, + "GITLAB_GALVANIZE_COM_TOKEN": { + "required": true + } + }, + "formation": { + "web": { + "quantity": 1, + "size": "hobby" + }, + "worker": { + "quantity": 1, + "size": "hobby" + } + }, + "addons": [ + "heroku-postgresql", + "heroku-redis" + ], + "buildpacks": [ + { + "url": "heroku/python" + }, + { + "url": "heroku/nodejs" + }, + { + "url": "heroku/ruby" + } + ] +} diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js new file mode 100644 index 0000000..b16e53d --- /dev/null +++ b/app/assets/config/manifest.js @@ -0,0 +1,3 @@ +//= link_tree ../images +//= link_directory ../javascripts .js +//= link_directory ../stylesheets .css diff --git a/app/assets/images/favicon.ico b/app/assets/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..d44fabf799ec51b278a628f5185ac4ed1bce7b90 GIT binary patch literal 1437 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzwj^(N7a$D;Kb?2i11Zh|kH}&m z?E%JaC$sH9f@KAc=|EZmjN5Ipk zKxk2SWaa~BG0~F4*Oy$#GU!k=SftWAV-fe)1o1VBJY6iEOR7GuY&Yoj+T9qIBF=th z5$D=Hfsaj$Z&{{)-*D~X-GXy-Y9Cx+pS}5f)a&Ti`~Tf9Rgcn0X0|O5JJ;*1Y{Bt% zb$iyUEn7c4PzusHs_e0WIs1dZ?cF;JX8AGfn+vtKJub+PumAdi<$DriUt(a$Z_{&E zr>03-$bV0i=Sx2({@C!$!TuEs1SDsMaQQOb=zjX6>d+7W3f~PsQ+xC7iZD<7RcxRw zSF&RJ`u|sIe!o%#+U)+(W|_NM5%Y{GjTJva_B8Mpdao_Lc=&XMu=A`5Hg*$|Bpw&m z9)H&RTJH#>Oe>GFv&0cr-9&}F8lnD2Rd0@T|KP|^c*ioe@J)VOW1HWN+t=4`Uth0s zuYzkD$G-w*y>$zVwn#GY`UdzK9eu2S{??_PS!<^F+?*9~DD2Iug+{lG*d9IHuw_l| z&22AF|34<|WK<<|IP`b^%NW;Lla#*|8&0sSQJv?#WcE7A`t{QMixyi+D!Y1pI@i-~ zcE9q^(rqT1+s?3rKg=vyoE?=~k~T|4yD+YI>(fP_&be4EmgJJMOl046h<9@3XRm7a zqp!l8>t@gDd*?4&)Se*6uslhYTYT;fOY_hli_YEhUnf`p-$QHWeJ=*~kG39@-X%pv z8LHZT^g4BI)$xg5H_I<=`FeNhLe)u6E`>2!H0CiQfiFhzzV;8Tf7hn&dAj3O!PBaHGEcp9dfwYVE`C)% z#e`+T#@A<^>~|#QEJ)Ybotbvlwc=E!@Sdf!T-7J;lAC?=hg;5pnwkd2n(qCN{>=P% zExRyQ=C-!Vx`S*zPrI5HU7jCi&Z&D--cNkxO(&0S$NyJ<*l=Nv*%X_VGX%c(bJr$> z^X@e<`m{2k?XFMW?-&NPh79qbk6WD~Z>x=hjR5x_X!N&w1#0UH$H&aorT8?1KME|7+*ZczdqBa9ZQ! zSw@DneiCa+MD?X4>WMDL6n5AhUXap*1kW7Xu4$n*}$v{!NR975SG$|pe z_07ypEvYO3`}j1-$5-`Fc(XGIRx?+`Te?3&Gubx;s2pPCHj_;TW(EevtPI?$Ol<5= zo`wR|N+6jWoLL1?dfJbPf$=UQOVeXB3!oYqBsHNyo*>h_!C`s*Iy(c;ET)Vp4uPwH P>KHs-{an^LB{Ts5c-mw6 literal 0 HcmV?d00001 diff --git a/app/assets/images/loader-black.svg b/app/assets/images/loader-black.svg new file mode 100644 index 0000000..a33da18 --- /dev/null +++ b/app/assets/images/loader-black.svg @@ -0,0 +1,12 @@ + + + + + diff --git a/app/assets/images/loader-cyan.svg b/app/assets/images/loader-cyan.svg new file mode 100644 index 0000000..50f34dd --- /dev/null +++ b/app/assets/images/loader-cyan.svg @@ -0,0 +1,12 @@ + + + + + diff --git a/app/assets/images/loader-white.svg b/app/assets/images/loader-white.svg new file mode 100644 index 0000000..0e73c3c --- /dev/null +++ b/app/assets/images/loader-white.svg @@ -0,0 +1,12 @@ + + + + + diff --git a/app/assets/images/lost.jpg b/app/assets/images/lost.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a6c5f225f7816ed95b5a4ecf5f7675adddda6a43 GIT binary patch literal 319991 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

T(aw?JniBw#d@o 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

q=Pg-E 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®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 N^F!rBE%%q7|34(qFxdbA literal 0 HcmV?d00001 diff --git a/app/assets/images/spinner.gif b/app/assets/images/spinner.gif new file mode 100644 index 0000000000000000000000000000000000000000..f83606ab0f82a916187f525f8e998eca7b11f899 GIT binary patch literal 24772 zcmeI)|6f!0-T(3PEy+m;$w^2sAi@Cx0-_CmMMZl80V5&?OBI#2L9s>WyrQ!mx_&wN zf`s}lAX@6I3rJhqxn5|!R@d5ICx9(&T^F6}T<5xAX^Wj}(b`r!=RVKwT$i_bU4H(7 z%l4<<`cqGCPMn*Xd#U@++O`KC{w9tZ^1uV24^|9*$Vk(`{o zc=6)={QTnL;`;jf0|yR-!{M&3uKVx5|GDR$>*?vadiCn%%a<=+ym^ zv--(l`zmK&Get8N_Pj)<(pkkRHH24hPEdz>gT-MVH!a_E)*|*d#U(L2i(E&9UAl1_ z4+Uz(Hy7yQ9BtNUjCjvHRx!!5nRJLx=TMULD{GJR4AbeTStbp>8($qRi+Jzx&(BQM zBy*8Y#U4uY;PFjWm!zGB!kNx?Pk&iL1~b89$@jf!9)Fjr&^;KV-eZ;3{9*gkOhmye z_3zg?2)3C{I(nAOP_G{Atgg+qh{3pDr=+H6`Hzq880+dy)cV4VN}nFDe4#FL>(*FG zR=M^_*y(Rx^ti2t?|zk2kecHb>Ghw)4fpA95SB$Z#DUL8RN`Gd;_;sl##f$S6#iq_ zr~iV?f7-$aegDv~c9PalbTyfYJZ@kM=?IA`>!BH(g3B2a9%GUSpDJaGL~LbPG7{t} z+-Ca{HrlD0>=Fs4nCli8hsDLTa87TnVcdbR*Q>Vn`Z=S6cRWPdIESflvE4O8p89NB9O zYg#EqXuc-Gs7^zv%9++F5Sd)>eQ)V2Z8}lxb&}hLP+=nKV>|D8<+)R zAgipb3~E(ZSA$}h1~W}26L9x7&B@7;T?MBg5u5@{Xb;lC zJCFyhk|e=Ws184sN+lpYcI+6`g{7cX<`kCVrhvP~ci*1x|M@@t3Eb*p&Pwb2?_4xl z&K@jQkTlJRg}sDg%w5xs(YnJyL6KEfH00zZF@Ee`*19ZG?~POGws)|HMMDRDe0%GG@;`#?|*0 z3;LwJbpws*``lvw#6rEtV-xnAu?2F5){L?W6KxD$oI{nF*#6mTYu_M9fAjJ}>oVan z(x@<&if7-u&vE&~^tm^JX%E;lzWI`WV@%QHH~!vyal{^sJ?642zDb+BPU~@aeK+DN zVy@z)Ba-yQyp+yXyTaivq2@&Ag{a9y*k^EB>qWhKQ-|~;RW2z735PvmP^5Qyo7IPG z5r(ZV3{mCo);^V$5{hXiJvOAa5n!AxWV#xd@eG zCFdn5hmG8wXyQcBJ6d8^toAlJ@8LF=7$4aBD`Gb{@H?Y&LRPn^cVtBQ4g+UX>|W5* z%qbjShY9lG#4Q8HiX(3?);sdjUES0VBi#w*tLvDAj1765V$o<%`(8TN-m{oZ$rXnW zrYM-((5TgF<*o!gGL48w$N~9)*8iXpy2w!`>xjApA@Bz5p(|kwfV^3kXi3B!v;#{Z z4SK;vzy|QZ-s6uy4&GoMJOg`ZSV)YtL_bcNGzoAP78ZIu9w-P_p`g)d1ZnUOf&xyk zinN62P#GM`bt!WQ=O7}$cDY<|8gMo=G=Oa=j>bd_4-O7;90v%2E-b`N0CkC)hT=dG zb^=A6PWOLWgzqozzdnImX~frYflTAbM}0SGq!K4hHy*3I)GR1wx7U0}BcV@CWv!bd z^(3j%jetgi>!1_AqcPI7KexshyL`HT7cuo``vzYqX((n5*@?Zx?tr(a?7;9z&txPAc$-9uvn5m?=dBAWvy-zzVq}#jqNS;qxjqGTGC}(|k$Zkf*qNzx4T$!c7bL~q zXOw&E>il{n<5}+fD&=ZR!TsWUH76V~DPE_vZA@0SuxgqY3c^iJe@VMk(>CKj z@O7iTW;qn<&My5Ca%WSO&V7Bo+!}}L#s^8v1R1? zGE)n)g-wrrq&I!rvVvG*x-e$J-B($!@T8_*442=RE-Ewb&5JTF+w;}-nzb|Y9QGq@ z)$KYFtpp4~3XqX8L@^=0AR7i>IT8T{=m2*zGJpjD0!Abl6as)C5#|6N6e7F=L1;aI zhC+mLpmNEQCBP7!2yl>oFc9v+D5wYn(TN}t#6d+UC&wTFOiWA!iLex|0!g3;8)XCK z=^t}H9D{!7R+xq!1jQiHVzFdoWS|p4H^hc-U=YaT@BsLu5TP_AMAbrC*odygDFP(K zK#y@8U?OI}_u@|Y1a84FdqYf`Cu5i+1cGtjb)wVLqUOe`FZR~h-Mhxj;5}AO>KDlp zW~Zs@h}6Uy)>jOV#8#^n8S{-b68X^1J&fsCO1P8Iw~_8x3OTit%$nVNynU!UVOg{e>DcIX$UG@ce?j9y$=>*9v9wkeWRtmy`_q&-c& zHl^dZKTN6CkOwWku&>`czp{`Ut-I_^R?mHi*+|)93Kea!J;pb+1;~JP)Rxs9A!g|6 zJ7Pa|lRJ`k)XcveB3rGRt_dTjR-NC@oPGH>IX7mPG=CABal?7Ca&DwDuvGf_7yP9y z*HS*!e;w<6!ynv{{O`4D&xt|$cdDdNKQ(9Mm9!r-CT>92bz+`NpB9Z3E9O|Q^ee{K zH&P;P<`nV#Y0hUp_Z9EmI{xISU|LXJ$kBI+;SyDP>LqF&J+ZS+TVnAx5mZgoPbzan znjo~7{Ho=F!V{b44|s|Vy=IXJaTbxF?DgVsLK!nksHQsW1iRMOdk-yac`l1m77>cJ zDHSG($;;YwLLq4E(odC4RMEB~HrUDu_q)==C2PFh8a8#{dE%iPzgqol0pBuUo=_k( zG3f>6L|~%HkUOvI$fnQAmvV3C&Z9{3Hid{ke4IAI8{`{MgowZix}e~o3&v(xf{c<; zgd)%d)B!3Gh(H5}Pzn%2N3aK60T{{-!!QP8^dRPN_=h^fEDdRZ5Ku%UB0u3JP((rk zFn9?Op(7{-SBONQ2tk1&LK1^L+yYvl3qpfo=!?pOwZIssoG=muVpa!=pc-JqOLG9nK~?Cb%oKnrM=#h{!rWQ1^Z3aqZt9hN_zH-7oI&Y z(&-!fqRtZv#-L^M)b_#wdXmEZh)c4))x3YnrtTooc|_?`k0yQ|9UdenX3)dE8wh{k z9WEmrU2KzfCN-7h6k5W>S~lgSQENwOc?-AV5&gghx-V!QyJA7@0piL2!0ac7ox(G- zbS=r{4S(KgFZ@EQ?7Ok;H=!))>o2p8>&N`&Lt(RaWWlB!7xe^9)dIpqFOnUX=p63BBmY{EyvUqD-4!Wz^2};;)e( zEon92&SOeybd{2diM^szYr7&Q=DA;>%nnm7v2?zzGnFhHm7*r{s9IDn>u^~UU#{E3 znYEW}UFw>BoJi%HlKP%uE^HRu%+(7G#B@`VV;fEt1J6)vW*Kxwi$p)m%%AFFbu}5$ zs*UAIOg-z&F>|*85(jhu61>T)89<1%f-#7>n?Rz>U?kK8Gq49b!Y5D!FR_S0O@hXo zyBM&CY6O!o53nIdVII5$gg_BGB1WMvCU$U$76gHS6D+|_m;@bx6AVVc!CPD4 zFaH)GKku;BmCIWf07>xlvrYghwZ`9-ZDdz&@CoC_yRLHAY+_KGwEdqz68xA+VfWLc z*%gesY_GMKc2ufU6xlZNN5#axgzj^LGx-LGKVDOzbu*u^dFCHX9tkD9{kCeZCJ&nw zVh=HErF7Jo7!2+oKXtC!&`Hrg{dD$24{s+sCOv687s(iJ%A1to+$nByQ@nr1vC&Hh zI|qr`hbq{C-ZB^yIklPeGN$ra$W9h{BU>%Cy#bx#g4@w# zEW|9lNVJ@yk_N;Rnv|6xFO^?l@6s1v^hl&WA4wS3VC&cFb3#5%%HHu&Q=)UUUuT@t z`;n2wpCC0(n`Ea*+YqTNH@P@-QShj=ldIj}+cUnXU?5bu?yC~B+Q^^K&n`Ad`-tIb zeWA*n=&2Id#jAAi(Veg{Pun6q!whYfC@L$j)m-vHIK!dg4=;XpN#2Wmypr!Qk;eGy zkN1qTYYckD-IxErTNk(pa$uMoj&KOr{BIXQrhJfy3Iv=$2ta}>8AzxJ4q+sSMb806 zG#SbdgE>${Sz^PC@fj$BNrWTf5*&g?zzLEeB@Ba|U==PxO)!a}8%)ATcnLV=O$+J} z4T|X-2@BHxH7Fq^*oKiX6+ogF!66XENh$ONfiMze0#4iwfF+7nmJ*1{QUb_3lZQL@ zs&8>o*~+K?^JtN=G{*XyGq8<5S@Z0hyIPq1n*BV-QVENMxmql=sSK+0aXu+LD3aOL z*@rG%cKAY>YR10d%Sf45U3sjX6Fy<`sr8RvO*+NX$^^P-LsGH#9_57f*|`^n=i9AQ zSGrvs;nY1fHt+F}=lp{$M2+U?pj5}&GYY7;#E|HHcWm6)H;ye6$Q|0y6w9~{!WXm5 zXt%b874;%-w$@qzTv7+pM*=xeIa*H~ukK zmoO>UX!U-{l!?wFKK$xe^zk3=4oa`jR=2$0e{^5ZsX!M4YKEVjdMa-xdk%3Td! zCO*LTQwJtS`{K=K!<}R`-?^AHr4mgBjv&OixB%Bj85(2W1WkbOZJpKAeS%CZtV`#V zBOP{j_C>CbD1OrIAnpyhg@kxhH?e|YJpP@F1+TD&tv=-sy|(9RhiTXlmJG8VcN>37 z_VD!y&ibRf)w5C$Gvp6G7X?CN;jP+-9}J8qW>mC~bdfA?O-L;^5z17D@VjRdavMqv zt;Q>V7Hri?#bufo=2{)BjoonDl{AjtfFmMM-n*a=K?#U~XoyC6ki}q)NP~tqS1iC0 zP=Y*EA4J1O1VM;U1Y0tKfDg=pJU9sZFg;^vmWxq7TLhZ$5e~|&h_gRL9khkK2t}|c zQwS5GEfADX7(pTY0(>A32Z%r%6FD@5uo#HJD2@SOBCrF6NL)CGh0Xt%q%lLw3usK_ zh+(jJ)Au{ph&%SeZ^2QwdDQ)1Q+1={Q>1-|qot{7M+=iuQ^dPeTlJN|(M8kB@l@$@ zJ}DLv$+YThZLI&BI2yteF| zV{x0h!l!9Cc{P$L?n#+6zWV5>aAKj>_-w}@=O-iCQ>fqC+QQOn~Z3XUu_KYdh z>pLFZtnI*nyQe_N9i_2e2{U?2 zZ7f}vmo+Mp3mba;H zt4QYFH6O&3cMZH!^)T%fvsi6XmF5)1i_%EhZ4Vu>i2;wmN8ZGsrEacaJai^4Fi|pB!omb0w~x5XE0yOM~^5-v?HjLmoc)Oa1S*J_rNCLmCqevCj3NDqTygB zrgCH}v;><-MtLg(C!s5lgpgRwVBUwH805h+{DhWJ5mZ7sNC*`HJNgx1LT@N4uVlbG zs6;qIeo%>gWLXvniH(&bub!SD>SW$+1`YlkaB^Xi?>e_UF1-cO%>c}Bs3OAIzKi@w{$ zeE3cOgxGI?6gt~|-TR#WiEh_#(wmkHlP_5>oQ@4qaVxHSPKZmdf9)q05N=7&{=JuC z##Kn+bqhs8Y9dUYCOc^(BF$X8>%>+j*XA=>@~UXf_|ZhU;t1ILB5I`PWB^6PaTd?BV%>r~dx2 zidf&S!ip=O9yBIxu;vw5N<)5e@#gE0Vd%J23wFLmm0i;lmHTR;g}HC$|E+sL{4ICm-jRX zNuK91!cU$&88bD=gro2hB7#Y|E@3396FS001SxO@jSv)E!S9lv^O zn9-6T7JOm=hu^>wYGS^|m=6>|Blwrk4Umwy56Be>HRUFS+`t~Ug*(KC?=KUdz%4-D z-@?^lxK@onRAZ=fdnrzx92=!Gy_$satk$z?VE1-Lvx(z{Cxy@ihcOu9BWyd<-g_|| zTjiu?yU#epdm`mzIqPDV5#_%&%t@H+wz)L##>eelT<_`nq^)&frSTj|QcdF+%8eY# zDCMU82w}u;WzE$;-#hU&hh4vyd&G9mc8=C7x&4t>MLC>?VP~(o#DTH)< zbL+b*+G-JA-{K?4eLqlzKdKWyi>Yq7XB-|Una&+~zWMHg-+!}n+|oyEgZ7W>{Asg8 ztMsu`mzu`dqtW{|Wi+@bDr%?}m?UP%%`FZu4Ux&!J>IxQ&KyoZy~x5CW(-Kh_frM7 zK7}RV?o<}!3!GM;+F7hm2njxJ&LB_I=}takj5`zaHl=V^1`PH_&rfwZXM=vND#hiG zoBKgnAeDIPo{P^35=Q!dcV@!k0dBSS-ul?VM9LgZ};#H@(3cr6_lAQA{r582KImxL`0MQ>qFj<1{6UTU<3J}4r~J?kP?-K z=XCycB?H*tB18m)nAm|F#%~~pK^oNv`M@NOBta33l*17^f=rxBA{@aaEQEHj5GRPB z4o8w;Ql8tfn}NQt93!{9p#f&dM6ic;1eQP=%ws(R@DQx<8!kdY7>QB@ib!F=k2?TR zmtzrLe(%H`^$FY}qOp~;BNQC_X1%FDd-88)0Tx@t#=v09y@ zLsswjyaH`{Y_fHC!jxTSt3!*069*Lh$?Gv&ok2;z(9_);9#0#m{46+iWgBl`Icq-8 z5x(;A##~KDZnr?t(`L1c$>#i;%o0maK(ZDy88aSCt_gMehjhg%rETSyVsn03@|IuN zhMe2_$JwT49dj42%234>O0^%^i%-qtd8Z}jXl52s7OlqDP+&JxERS$1v4?+-{5*JoD*^W8*Xb+O8v z$Uc=ytcnoS%2==A@##;-XQpg;#;$ONNgaEhD19RNhq0J)Qhp6bPqhYV)!dFK9^NkS z_y}ikG^WhnJ}snCPda6%S&wAb#h>$(&>1!ENW!wKT%X^<)ejg8*Kvv;^2Z8`<5ejh zf86x<;NX(uy>|U`%QlrNey@&o>0FP7y46dD-I+$p%y~_WuDwY$sqCTRwlv1=+mYVU zQAJJKLhN};b>=9cpZ=};&n1f9x9yze^*=l>j5&Lj_OoV}H@a)g|RvvPcHcc8_rW_o&80mIVNB4C(V>Me1F&u(ZFxjin5^DHy4 zx~CJ?<~gqkgOwpgXz*lbtZuJrmfBUdCc-XKPOnckUmLL6*?S3B5P50bV{BX*S~k>0 zrm8D!y&Z&jUv5^4&DBz$&hS+IteR2YJH(7rO}FqTCW)!jx(e6K;+$Te@98joMJKirf;=*MA=6)FAdl;h*Jw|A0jk!+9o_t{LL+L zXsxa`RloB+7k=CWJG<5bhxbPO(3Xb1Go*@dJZMny5=bRn+TH*5$K;$- zk@(O4@Ma&8?Q-#UhbJ2GkE=M$lX|Uth_E_qLR@Z)7$T{w0!1@x_LLeX)b{l0<2XhU zxa%0+Wmcu|6fInrBu$FP1`&HabxNl6Qn6~5BQ{n)?YU7}X(3vLUD<{8goYl7CEMBj zp?2l84{RrNu5aCfeokV#i!_AyMyau9f_*=9eePMYi$2>2= zYBTpKnd}}ed4{?#dQg*)e00E&SNK&!IOA8YJ|;MKU_TD|)Pd5@53C_hAU2$sfBVO} zZ~Lwb#%0g~sBZ2r&{K#(c?<>_0VPO@_L+b%TPzMF!ACSZN3;$&5 zU=qp>ZHQz8dvf<-bt0bt!cLe6>cA>IMwtRFU_jJw|G|3NeCXn1=L#9H_%-xQ@F4&P;**oyNnRdA+xw z_@2$}E|WJb4Fu^^at39`C><=J=I18|dlb#>+nEQeNrG>ZLTs7Q#tVe5oy_YkDyF-g z)XerXN4;&tj?8>JBhGA_zc3{s;lt?U0#UQKENJ^Uqchtd)UGvIHwKy%R&ryCdyO}E zLRq?YZMutRb-JuBZ9dV|^g!OY#B=VXE>(ZhthJ{{HXLM{->PI!TZa1Yiqm9;#Tvn* zNywO9UG(OP;g2Mu_@$Z$>%vkb=itoPNQdP;kH>#Olq4U*;<6etTtZ5Cu_KjIV{kP8qaoNtl zeY2*5`)TOSy(z}|)^na&wNU;GgGn-)t&+pXq_=w2rhO6-VDep&t!9s_#8$!{DW;x{7RS-im`GPWYLkfX-gVhNgF7RU+53fnBlY4j zFKuwd2z5zzEM(5D=BXdj4_|UrvljnhFS_5+N-ZLRQK96QBbt5poDN zScWFVunYmAD)@snuoA!lJ50^+QC^{-01=Ha2&7_I2A7zT!6-b%St5!NSqL{FEYOsv zW+Wo&PJXdP&R6-h7a$0}VKjOVwt_RD3E;56!2}IM;W#!h&=A-`I_L=^;VjUE>97)# zLQm8qW^hmoh#}*h3B;Xt)wh61&D_xS&mW0kENAf>J4pahkXFspd$aOi4O$pq|ModA zjzqmwx6`ZScrnx}hzS#Z?n&p2f{Jnk29Gb^E$R2nn#GL#p;IzF&1Gk6yXsdGVZBr>&-TPtxk>YU>PI7^nSr9Dj8>@&=m8HNukC+?d@ZRDEcR^0(Vw_J-KMEQOhg*pWxRY#!lUs+~*5uxJD;c z{2vi2fhlU>fASxW7Dr-z!)R2Mm@#MPf}_7062JP(*hkayLy^EYUnFU6Fvluyh}8kb z8$X|s{>GNghEHGl@dI}cuh%QCUb;(=iiUhS8pb7wCw`$Ml?E;M=e224sLvE(p+4;n*=u-B|p4+|-jg1Nvgk znq9@I#096MGL4Ryp6x)6X-)B9$5o8gdIZX#d?~a1ian);QfpH;<_gEJ4eUtMI)8S<{!N5PbT<6?e#iMMUnmd# z?fySi9taGK#2#kuvPkyLM&0ypg|_hHzO?^L%L}%-5B}q;8b^p`a)Pg{&}Mk}Chx_C zLlnam6X)zg(A~*WjNzO<+ripZ358t0K1DI=r%TwX{-%taR>E#^I7yYpxgnxR&k-2I z-GgDTQepKF+ZJ+XL<6_o)#OM%*FYI)t>Dn#y)jlo2u|Lo)^H{%p|~S4vSTKGRHt2+ zZ|mFDSXwP?ycj=lf|#KZPdrTz%!uq_j}NvHGkmtO2XtJBh`W2z;SbmI=PYDtKyzkb zS4RFj2e>J{?&aNvR(GFi@8{2%+83`it(~{*;>gl@oK}0|Tw-AV^ zB?O`@BIJNK;1J$`84w78z$C&EK!Qdn2(ge^Kn|4#*gz4&4#*)5VH?U1GcmjblPEK}3rDo+@Iy2qG zdhsh_zU(>KMo-=0CPATUtI3fHBvO}>!&-mUUr!hb!fLqIOT>2+w*T{|a$5J_Rj8>A z(Rf8=>I(L7>y&px&82%Q@&)oaJw2{`uD9*C0f}-Xnx=}Y-W2l`CdQl8b$%yv_r}z- zh22gCb07O*hut!7o1)Zxqd^Jz5Qt;=54UU{`>Fbo2k!O?WV+KdveZ^z{G&jL%j+N%rl5;h z9>7CJms;j|+3cEAJh^0$k2D!=wz2lOV62lJ!yQg1mj=a7hIeI4_tN)y1;ah(Mmt$U zju2H?)_VH6d)M`PpmMXoAR?pz6#xVN!9_R(jldGh5A_D^z@fZAfojkc!eQEldGZ1U z?14i_DL+vIAORkrf{OqTcH-avRt@(+ivm@LAW|U z?kC2r#31uqB;(vi_KvQJj@M-r7)-DKVb#EUX&R$aSQ)_VT(HnNvu@+tyPuhIJTX$` z(HQ8IF2)&3|Ag3P8Gq4qI#b}XRH@aMoc&@Qo>}2r-uBy@w`LPodt3NzKiv`6SRFbK zRH(V#Ij1KJ_zgnMh?H{dZKrQ~hjz49d_nlnL;9Rwwc5P2MJXO%|KzaPs`zE*2Q}+6 zy}k+B)NHr(=*(XSQ}~8Izvn&pK5f8HL)|@e`ECx z(-%p9zUEEQD^5A6spgJaqRbp3V2$6%m*!Fwg~)QLl+^55@Eu8L2qh~z#t zcaHcmo%+nT(RhXZ^82?PoaMJyfDn34e)Abk1|g7ca1k2G=ZH`QQ3#W;1ObYG5Sa*0 z&}t9`vnl`sSD+CM2d*$I!z!Q%DZwXDgo21dCLmcyOf_r;i5QUjMAgE zonNW;uCVqN3Wlzo8l~333a9HG6Q{51ZMbF=wsjbNXNEm(Z#}u6ZJb-pr+?B+WLJDP z5}NXs&O0?eZ+>xs5a^hf?8wrrc2;Ul2{n!3c05KiPQy5fjOW;GmKno`!nD(MT=!OUo*6t2_LKNrUxHQ)+#s!n3n8%ddCYIt|J5Z>=Tu+9=l2pzZz?48-zo|s!GzkX<@S3|ioWIy&K^)Kjjt{>RJaUeOM(@1 zw5~DO$7mjjMpUy+RSt8)@zFj?o#Q22{P9N#E!{4zAhOt8znIL45GcN&*e z3Eo;`@pEp)Q|#5Spe--={*Gc32Y#D4p1mLto^LtPQ2tIYa7^Kc)%S8-4yisFwk{o~ xh(4rhpIa`N$~D5!<5k + + + diff --git a/app/assets/images/svg/g-learn-lockup.svg b/app/assets/images/svg/g-learn-lockup.svg new file mode 100644 index 0000000..745a726 --- /dev/null +++ b/app/assets/images/svg/g-learn-lockup.svg @@ -0,0 +1,37 @@ + + + + g-learn-lockup + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/assets/images/svg/galvanize-logo.svg b/app/assets/images/svg/galvanize-logo.svg new file mode 100644 index 0000000..30d6af4 --- /dev/null +++ b/app/assets/images/svg/galvanize-logo.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/assets/images/svg/github-icon.svg b/app/assets/images/svg/github-icon.svg new file mode 100644 index 0000000..1c6c9ec --- /dev/null +++ b/app/assets/images/svg/github-icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/assets/images/svg/mobile-logo.svg b/app/assets/images/svg/mobile-logo.svg new file mode 100644 index 0000000..d51b17a --- /dev/null +++ b/app/assets/images/svg/mobile-logo.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + diff --git a/app/assets/images/svg/octicon-git-branch.svg b/app/assets/images/svg/octicon-git-branch.svg new file mode 100644 index 0000000..4a41892 --- /dev/null +++ b/app/assets/images/svg/octicon-git-branch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/images/svg/svg-sprite-action-symbol.svg b/app/assets/images/svg/svg-sprite-action-symbol.svg new file mode 100755 index 0000000..c8abe24 --- /dev/null +++ b/app/assets/images/svg/svg-sprite-action-symbol.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/images/svg/svg-sprite-av-symbol.svg b/app/assets/images/svg/svg-sprite-av-symbol.svg new file mode 100644 index 0000000..84aaa88 --- /dev/null +++ b/app/assets/images/svg/svg-sprite-av-symbol.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/images/svg/svg-sprite-device-symbol.svg b/app/assets/images/svg/svg-sprite-device-symbol.svg new file mode 100644 index 0000000..ad4bc20 --- /dev/null +++ b/app/assets/images/svg/svg-sprite-device-symbol.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/images/svg/svg-sprite-image-symbol.svg b/app/assets/images/svg/svg-sprite-image-symbol.svg new file mode 100644 index 0000000..5431358 --- /dev/null +++ b/app/assets/images/svg/svg-sprite-image-symbol.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/images/svg/svg-sprite-navigation-symbol.svg b/app/assets/images/svg/svg-sprite-navigation-symbol.svg new file mode 100755 index 0000000..af09449 --- /dev/null +++ b/app/assets/images/svg/svg-sprite-navigation-symbol.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js new file mode 100644 index 0000000..8cc897f --- /dev/null +++ b/app/assets/javascripts/application.js @@ -0,0 +1,7 @@ +//= require jquery +//= require rails-ujs +//= require popper +//= require bootstrap-sprockets +//= require bootstrap-datepicker +//= require hopscotch +//= require gsap diff --git a/app/assets/javascripts/mobile.js b/app/assets/javascripts/mobile.js new file mode 100644 index 0000000..b3b4c3d --- /dev/null +++ b/app/assets/javascripts/mobile.js @@ -0,0 +1,10 @@ +window.onDocumentReady(function() { + $('body').on('touchmove', function() { + // + // What does the :hover selector do?? + // + if ($('.navigation-dropdown:hover').is(':visible')) { + $('.navigation-dropdown').unbind('hover'); + } + }); +}); diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss new file mode 100644 index 0000000..5cf0878 --- /dev/null +++ b/app/assets/stylesheets/application.scss @@ -0,0 +1,103 @@ +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's + * vendor/assets/stylesheets directory can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the bottom of the + * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS + * files in this directory. Styles in this file should be added after the last require_* statement. + * It is generally better to create a new file per style scope. + *= require font-awesome + */ + +@import "font-awesome"; +@import "bootstrap-custom"; +@import "bootstrap-datepicker"; +@import "hopscotch"; + +@import "variables"; +@import "mixins"; +@import "base"; +@import "typography"; +@import "hopscotch-overrides"; + +@import "rc-slider/assets/index"; +@import "rc-tooltip/assets/bootstrap"; + +@import "components/activity-feed"; +@import "components/auth-style-search"; +@import "components/action-menu"; +@import "components/badge"; +@import "components/blocks-index"; +@import "components/blocks-stats"; +@import "components/callouts"; +@import "components/challenge-block"; +@import "components/challenge-detail-comments"; +@import "components/challenge-detail-view"; +@import "components/challenge-timeline"; +@import "components/checkpoint-landing"; +@import "components/checkpoint-submission"; +@import "components/checkpoint-submissions-columns"; +@import "components/checkpoint-submissions-columns-student"; +@import "components/checkpoint-submissions-index"; +@import "components/checkpoint_submisstion_state"; +@import "components/checkpoint_student_scores"; +@import "components/checkpoint_toolbar"; +@import "components/code-block"; +@import "components/cohorts"; +@import "cohorts"; +@import "components/content-file-show"; +@import "components/content-file-sidebar"; +@import "components/curriculum"; +@import "components/curriculum-progress"; +@import "components/curriculum-checkpoint-summary"; +@import "components/dropdown-component"; +@import "components/footer"; +@import "components/flash-message"; +@import "components/activity-dashboard"; +@import "components/external-link"; +@import "components/grade-buttons"; +@import "components/lp-style-button"; +@import "components/mastery-table"; +@import "components/navigation-dropdown"; +@import "components/notifications"; +@import "components/new-comment-form"; +@import "components/primary-header"; +@import "components/primary-navigation"; +@import "components/progress"; +@import "components/thresholds"; +@import "components/progress-table"; +@import "components/search-bar"; +@import "components/secondary-navigation"; +@import "components/sort-dropdown-component"; +@import "components/standard-card"; +@import "components/standards-mastery-beans"; +@import "components/student-mastery-table"; +@import "components/student-name-bar"; +@import "components/submissions-dashboard-table"; +@import "components/cohort-submissions-table"; +@import "components/svg-icon"; +@import "components/user-avatar"; +@import "components/universal-list"; +@import "components/universal-row"; +@import "components/universal-table"; +@import "components/404-container"; +@import "components/video-player.scss"; +@import "components/cohort_releases"; +@import "components/checkbox-input"; +@import "components/partnerup"; +@import "components/integer_picker"; +@import "components/challenge_status"; +@import "components/status_picker"; +@import "components/slideshow"; +@import "components/progress_thresholds_slider"; +@import "components/progress_thresholds_key"; +@import "components/progress_thresholds_modal"; +@import "components/modal"; +@import "components/pill"; +@import "components/api-interactions"; +@import "components/pagination"; +@import "components/api_token"; +@import "components/button"; diff --git a/app/assets/stylesheets/base.scss b/app/assets/stylesheets/base.scss new file mode 100644 index 0000000..1e9d53d --- /dev/null +++ b/app/assets/stylesheets/base.scss @@ -0,0 +1,66 @@ +html, +body { + overflow-x: hidden; + overflow-y: auto; +} + +body { + margin: 0; + width: 100%; + max-width: 100%; + background-color: $color-black-98-2; +} + +main { + min-height: calc(100vh - 6.5rem); + > .with-margins { + margin: 0 auto; + padding: 1rem ; + } +} + +body > main > .container-404 { + background-color: #e9eaec; + text-align: center; + font-family: sans-serif; + background: url("#{image_path("lost.jpg")}") no-repeat center center fixed; + background-size: cover; + -webkit-font-smoothing: antialiased; + margin: 0; + vertical-align: middle; + width: 100%; + + .logo { + padding-top: 2rem; + } + + h1, h2, h3 { + color: #fff; + } + + h1 { + font-size: 4rem; + font-weight: 200; + margin: 3rem 0 3rem; + } + + h2 { + font-size: 2rem; + font-weight: 200; + margin-bottom: 3rem; + padding-left: 20%; + padding-right: 20%; + } + + h3 { + font-size: 1.5rem; + text-transform: uppercase; + letter-spacing: .1rem; + font-weight: 600; + } + + a { + color: rgb(247, 144, 30); + text-decoration: none; + } +} diff --git a/app/assets/stylesheets/bootstrap-custom.scss b/app/assets/stylesheets/bootstrap-custom.scss new file mode 100644 index 0000000..7859210 --- /dev/null +++ b/app/assets/stylesheets/bootstrap-custom.scss @@ -0,0 +1,13 @@ +@import "bootstrap"; + +.alert { + margin: 1.5rem 2rem 0; +} + +.table p:last-child { + margin-bottom: 0; +} + +.card .table { + margin-bottom: 0; +} diff --git a/app/assets/stylesheets/cohorts.scss b/app/assets/stylesheets/cohorts.scss new file mode 100644 index 0000000..aaf876c --- /dev/null +++ b/app/assets/stylesheets/cohorts.scss @@ -0,0 +1,9 @@ +.center { + text-align: center; +} + +.alert-danger { + a { + color: $color-lightened-black; + } +} diff --git a/app/assets/stylesheets/components/_404-container.scss b/app/assets/stylesheets/components/_404-container.scss new file mode 100644 index 0000000..8638f2b --- /dev/null +++ b/app/assets/stylesheets/components/_404-container.scss @@ -0,0 +1,43 @@ +.container-404 { + position: absolute; + width: 100%; + height: 100%; + text-align: center; + background: url("#{image_path("lost.jpg")}") no-repeat center center fixed; + background-size: cover; + margin: 0; + + .logo { + padding-top: 2rem; + } + + h1, h2, h3 { + color: #fff; + } + + h1 { + font-size: 4rem; + font-weight: 200; + margin: 3rem 0 3rem; + } + + h2 { + font-size: 2rem; + font-weight: 200; + margin-bottom: 3rem; + padding-left: 20%; + padding-right: 20%; + } + + h3 { + font-size: 1.5rem; + text-transform: uppercase; + letter-spacing: .1rem; + font-weight: 600; + } + + a { + color: rgb(247, 144, 30); + text-decoration: none; + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/components/_action-menu.scss b/app/assets/stylesheets/components/_action-menu.scss new file mode 100644 index 0000000..87ebbd7 --- /dev/null +++ b/app/assets/stylesheets/components/_action-menu.scss @@ -0,0 +1,53 @@ +.action-menu-list, #action-menu-list { + position: absolute; + margin: 0; + right: 0; + top: 40px; + z-index: 10; + white-space: nowrap; + + &#action-menu { + margin: 48px 48px 0 0; + top: unset; + } + + &.lesson { + margin: -6px 156px 0 0 + } + + ul { + background: white; + border: 1px solid $color-black-77; + list-style-type: none; + margin: 0; + padding: 0; + border-radius: 8px; + box-shadow: 0 1px 10px 0 rgba(0,0,0,0.05); + border-color: rgb(238,238,238); + + li { + margin: 0; + + a, p { + color: $color-tundora; + text-decoration: none; + font-size: 16px; + font-weight: 400; + cursor: pointer; + line-height: 48px; + padding-left: 16px; + padding-right: 16px; + display: flex; + &:hover { + background: rgb(223,243,245); + } + + &.remove { + color: $color-valencia; + } + } + } + } + + +} diff --git a/app/assets/stylesheets/components/_activity-dashboard.scss b/app/assets/stylesheets/components/_activity-dashboard.scss new file mode 100644 index 0000000..85de563 --- /dev/null +++ b/app/assets/stylesheets/components/_activity-dashboard.scss @@ -0,0 +1,253 @@ +.activity-dashboard { + & { + background-color: $color-white; + overflow-x: scroll; + overflow-y: hidden; + white-space: nowrap; + } + + > .headerrow { + height: 67px; + position: relative; + z-index: 6; + + &.-is-sticky { + position: fixed; + top: 0; + } + } + + > .headerspacer { + height: 67px; + border-bottom: 1px solid $color-black-83-1; + position: relative; + z-index: 9; + left: 0; + box-shadow: 1px 0px 0px 0px $color-black-83-1; + + &.-is-sticky { + position: fixed; + top: 0; + } + } + + > .headerspacer, + > .headerrow > .headermonths { + background-color: $color-black-97-3; + display: inline-block; + height: 67px; + vertical-align: top; + } + + > .headerrow > .headermonths { + position: relative; + z-index: 6; + } + + > .headerspacer, + > .studentrow > .studentnameplate { + width: 225px; + left: 0; + position: absolute; + } + + > .headerrow > .headermonths, > .studentrow > .studentdata { + margin-left: 225px; + } + + > .headerrow > .headermonths > .headermonth { + display: inline-block; + + &:last-child { + border-right: 1px solid $color-black-76-5; + } + } + + > .headerrow > .headermonths > .headermonth > .monthname { + border-left: 1px solid $color-black-76-5; + border-bottom: 1px solid $color-black-83-1; + font-size: 12px; + font-weight: bold; + padding: 4px 12px; + overflow: hidden; + text-overflow: ellipsis; + } + + > .headerrow > .headermonths > .headermonth > .dates > .dateitem { + border-bottom: 1px solid $color-black-83-1; + border-left: 1px solid $color-black-83-1; + width: 40px; + height: 40px; + display: inline-block; + font-size: 12px; + text-align: center; + position: relative; + + &.-is-first-of-month { + border-left-color: $color-black-76-5; + } + + &.-is-highlighted { + background-color: rgba(0,165,181,0.1); + border-left-color: $color-cyan; + box-shadow: 1px 0px 0px 0px $color-cyan, 0px -1px 0px 0px $color-cyan; + position: relative; + z-index: 7; + border-bottom: 1px solid #00A5B5; + + &::after { + width: 0; + height: 0; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + content: " "; + border-top: 5px solid $color-cyan; + position: absolute; + left: 14px; + bottom: -5px; + } + } + } + + > .headerrow > .headermonths > .headermonth > .dates > .dateitem > .dayofmonth { + font-weight: bold; + padding-top: 6px; + line-height: 1; + } + + > .headerrow > .headermonths > .headermonth > .dates > .dateitem > .dayofweek { + color: $color-black-66-7; + text-transform: uppercase; + padding-top: 3px; + font-size: 10px; + } + + > .studentrow { + height: 40px; + } + + > .studentrow > .studentnameplate { + display: flex; + flex-flow: row nowrap; + align-items: center; + height: 40px; + padding: 0 1rem; + border-bottom: 1px solid $color-black-83-1; + background: $color-white; + box-shadow: 1px 0px 0px 0px #d4d4d4; + overflow: hidden; + z-index: 8; + } + + > .studentrow > .studentnameplate > .avatarfullname { + font-weight: 500; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + + > .studentrow > .studentnameplate > .user-avatar { + flex: 0 0 auto; + margin-right: .5rem; + } + + > .studentrow > .studentdata { + position: relative; + margin-left: 225px; + height: 40px; + } + + > .studentrow > .studentdata > .chart { + height: 40px; + position: absolute; + top: 0; + left: 0; + z-index: 1; + } + + > .studentrow > .studentdata > .studentdataitems { + position: absolute; + z-index: 2; + border-right: 1px solid $color-black-76-5; + } + + > .studentrow > .studentdata > .studentdataitems > .studentdataitem { + height: 40px; + width: 40px; + border-bottom: 1px solid $color-black-83-1; + border-left: 1px solid $color-black-83-1; + line-height: 40px; + text-align: center; + display: inline-block; + overflow: hidden; + + &.-is-weekend { + background-color: rgba(0,0,0,0.02); + } + + &.-is-first-of-month { + border-left-color: $color-black-76-5; + } + + &.-is-highlighted { + background-color: rgba(0,165,181,0.1); + border-left-color: $color-cyan; + box-shadow: 1px 0px 0px 0px $color-cyan; + position: relative; + z-index: 99; + } + } +} + +.activity-loadmore { + margin: 0; + margin-left: 1rem; + align-items: center; + display: flex; + + a { + margin-left: 0.5rem; + } +} + +.activity-dashboard-legendrow { + & { + position: relative; + display: flex; + flex-flow: row; + justify-content: flex-end; + background: $color-black-97-3; + border-bottom: 1px solid $color-black-90-2; + } + + > .svg { + opacity: .6; + margin: .5rem; + cursor: help; + + &:hover + .infomodal { + display: block; + } + } + + > .infomodal { + font-size: 14px; + max-width: 360px; + margin: .5rem; + padding: 1rem 1.5rem; + border-radius: .5rem; + color: $color-white; + background-color: $color-black-10-2; + box-shadow: 0 2px 8px 0 rgba(0,0,0,0.3); + cursor: help; + display: none; + position: absolute; + top: 0; + right: 0; + z-index: 10; + + &:hover { + display: block; + } + } +} diff --git a/app/assets/stylesheets/components/_activity-feed.scss b/app/assets/stylesheets/components/_activity-feed.scss new file mode 100644 index 0000000..c32a868 --- /dev/null +++ b/app/assets/stylesheets/components/_activity-feed.scss @@ -0,0 +1,69 @@ +.activityfeed { + > .table > tbody > .activityitem > .message * { + vertical-align: middle; + } + + > .table > tbody > .activityitem > .message > .user-avatar { + display: inline-block; + margin-right: 8px; + } +} + +.activitylegend { + display: inline-block; + list-style-type: none; +} + +.activitylegend > .activitylegenditem { + display: inline-block; + vertical-align: middle; + margin-left: 16px; +} + +.activitylegend > .activitylegenditem * { + vertical-align: middle; +} + +.activitylegend > .activitylegenditem > .activitylabel { + margin-right: 4px; +} + +.activitylabel { + display: inline-block; + width: 8px; + height: 8px; + border-radius: 100%; + margin-right: 8px; + + &.-primary { + background-color: $color-cyan; + } + + &.-warning { + background-color: $color-banana-yellow; + } + + &.-default { + background-color: $color-black-80; + } + + &.-danger { + background-color: $color-valencia; + } + + &.-success { + background-color: $color-med-green; + } + + &.-score-1 { + background-color: $color-tangerine-orange; + } + + &.-score-2 { + background-color: $color-banana-yellow; + } + + &.-score-3 { + background-color: $color-lime-green; + } +} diff --git a/app/assets/stylesheets/components/_api-interactions.scss b/app/assets/stylesheets/components/_api-interactions.scss new file mode 100644 index 0000000..7603cf1 --- /dev/null +++ b/app/assets/stylesheets/components/_api-interactions.scss @@ -0,0 +1,62 @@ +.api-interactions-wrapper { + margin: 60px 100px 30px 100px; + + h3 { + margin-bottom: 15px; + } + + .api-interactions-display { + box-shadow: 0px 0px 10px 1px rgba(0, 0, 0, 0.2); + border-radius: 5px; + + .api-interactions-table { + text-align: center; + font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; + border-collapse: collapse; + width: 100%; + + th { + font-size: 13px; + } + + .td-metadata { + display: flex; + justify-content: flex-end; + padding-right: 45px; + } + } + + .api-interactions-table td, .api-interactions-table th { + padding: 14px; + text-align: left; + } + + .tr { + cursor: pointer; + border-bottom: 0.5px solid #e6e6e6; + background-color: white; + } + + .tr:hover { + background-color: #e6e6e6; + } + + .api-interactions-table th { + padding-top: 12px; + padding-bottom: 12px; + background-color: $color-galvanize-orange; + color: white; + } + } + + .metadata-wrapper { + p { + color: white; + margin-bottom: 0px; + } + } + + .pagination-wrapper { + margin-bottom: 100px; + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/components/_api_token.scss b/app/assets/stylesheets/components/_api_token.scss new file mode 100644 index 0000000..67554ab --- /dev/null +++ b/app/assets/stylesheets/components/_api_token.scss @@ -0,0 +1,37 @@ +.api_token-wrapper { + + h3 { + @include font-h3; + } + + p { + @include font-paragraph; + margin-bottom: 0; + } + + .one-column { + @include one-column; + } + + .container-large { + @include container-large; + } + + .caption { + @include font-caption; + margin-bottom: 0; + margin-top: $font-default-line-height; + } + + .token-row { + margin: 20px -$input-spacing 0 -$input-spacing; + } + + input { + @include input; + + &.disabled { + @include input-disabled; + } + } +} diff --git a/app/assets/stylesheets/components/_auth-style-search.scss b/app/assets/stylesheets/components/_auth-style-search.scss new file mode 100644 index 0000000..a246cb3 --- /dev/null +++ b/app/assets/stylesheets/components/_auth-style-search.scss @@ -0,0 +1,26 @@ +.auth-style-search { + width: 100%; + box-shadow: rgba(0, 0, 0, 0.13) 1px 1px 2px 0px; + border-bottom-color: rgba(0, 0, 0, 0.15); + border-radius: 40px 40px 40px 40px; + border-bottom-style: solid; + border-bottom-width: 1px; + border-image-outset: 0px; + border-image-repeat: stretch; + border-image-slice: 100%; + border-image-source: none; + border-image-width: 1; + border-left-color: rgba(0, 0, 0, 0.15); + border-left-style: solid; + border-left-width: 1px; + border-right-color: rgba(0, 0, 0, 0.15); + border-right-style: solid; + border-right-width: 1px; + border-top-color: rgba(0, 0, 0, 0.15); + border-top-style: solid; + border-top-width: 1px; + padding-bottom: 8px; + padding-left: 28px; + padding-right: 12px; + padding-top: 8px; +} \ No newline at end of file diff --git a/app/assets/stylesheets/components/_blocks-index.scss b/app/assets/stylesheets/components/_blocks-index.scss new file mode 100644 index 0000000..ba7ff61 --- /dev/null +++ b/app/assets/stylesheets/components/_blocks-index.scss @@ -0,0 +1,133 @@ +.blocks-table{ + overflow: scroll; + max-height: 616px; + width: 100%; + margin: 0 auto; + z-index: 1000000; + background-color: $color-black-98-2; + + .createdcolumn { + padding-left: 24px; + } + + thead { + background-color: #FFFFFF; + border-top: 1px solid $color-black-77; + border-bottom: 1px solid $color-black-77; + height: 40px; + + tr { + font-size: 14px; + line-height: 16px; + text-transform: uppercase; + color: #999999; + } + + tr > th { + font-weight: 500; + padding: 12px; + } + } + + tbody { + background-color: #FFFFFF; + + .releaserow { + position: relative; + border-bottom: 1px solid #e7e7e7; + + .readme-text { + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + } + + &.current-release { + background-color: rgba(0,165,181,0.05); + } + } + + .releaserow > td { + position: relative; + padding: 16px; + font-size: 16px; + vertical-align: top; + + &:nth-child(2) { + max-width: 360px; + } + + &.createdcolumn { + padding-left: 24px; + } + } + + .releaserow > td > h5 { + font-weight: bold; + line-height: 16px; + font-size: 16px; + } + + .releaserow > td > p { + line-height: 16px; + margin-bottom: 8px; + } + + .releaserow > td > a.gitlink { + line-height: 16px; + font-weight: 300; + margin-right: 24px; + position: relative; + } + + .releaserow > td > a.gitlink > svg { + width: 16px; + position: absolute; + margin-left: 3px; + + } + + .releaserow > td > span.currentlabel { + line-height: 16px; + color: $color-cyan; + text-transform: uppercase; + font-size: 12px; + font-weight: bold; + letter-spacing: 1px; + text-align: center; + padding: 0 24px; + } + + .releaserow > td .cohorts-tooltip { + position: absolute; + right: calc(100% - 2rem); + top: 1rem; + display: flex; + flex-direction: column; + width: 360px; + border-radius: .5rem; + background-color: $color-black-10-2; + color: $color-white; + overflow: hidden; + box-shadow: 0 2px 8px 0 rgba(0,0,0,0.3); + z-index: 9; + } + + .releaserow > td .cohorts-tooltip > .body > div { + padding: 24px; + } + + .releaserow > td .cohorts-tooltip > .body > div > p > a { + text-decoration: none; + color: white; + + } + + .releaserow > td .cohorts-tooltip > .body > div > p > a > svg { + height: 16px; + margin-left: 8px; + } + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/components/_blocks-stats.scss b/app/assets/stylesheets/components/_blocks-stats.scss new file mode 100644 index 0000000..46c8a0b --- /dev/null +++ b/app/assets/stylesheets/components/_blocks-stats.scss @@ -0,0 +1,70 @@ +.block-stats { + display: flex; + flex-direction: column; + flex-basis: 380px; + flex-shrink: 0; + + .block-stats__user-row { + display: flex; + justify-content: flex-start; + align-items: center; + margin-bottom: 15px; + flex-wrap: wrap; + @include font-paragraph; + font-size: 15px; + line-height: 20px; + + .block-stats__user-name { + margin-left: 8px; + margin-right: 8px; + } + + .block-stats__latest_version { + color: $color-silver-chalice; + font-weight: 500; + } + } + + .block-stats__stats-row { + display: flex; + justify-content: flex-start; + font-size: 14px; + color: $color-tundora; + font-weight: 400; + + a { + width: fit-content; + } + + &.vertical { + flex-direction: column; + + a { + margin-bottom: 10px; + font-weight: 500; + + &:last-child { + margin-bottom: 0; + } + } + } + } + + .block-stats__stats-icon { + margin-right: 15px; + display: flex; + align-items: center; + } + + .stats--verbose { + margin-left: 5px;; + } + + &.--vertical { + flex-basis: auto; + } + + svg { + margin-right: 3px; + } +} diff --git a/app/assets/stylesheets/components/_button.scss b/app/assets/stylesheets/components/_button.scss new file mode 100644 index 0000000..f6c709f --- /dev/null +++ b/app/assets/stylesheets/components/_button.scss @@ -0,0 +1,57 @@ +.button-wrapper { + @include button; + + &.button-solid-primary { + @include button-theme($color-primary-teal, primary); + + &:hover { + background-color: lighten( $color-primary-teal, $lighten ); + .submit-with-avatars .user-avatar { + border: 2px solid lighten( $color-primary-teal, $lighten ); + } + } + + &:active { + background-color: darken( $color-primary-teal, $darken ); + .submit-with-avatars .user-avatar { + border: 2px solid darken( $color-primary-teal, $darken ); + } + } + } + + &.button-outline-primary { + @include button-theme($color-primary-teal, outline); + + &:hover { + background-color: adjust-color($color-primary-teal, $alpha: -0.9); + } + + &:active { + background-color: adjust-color($color-primary-teal, $alpha: -0.7); + } + } + + &.button-solid-red { + @include button-theme($color-red, primary); + + &:hover { + background-color: lighten( $color-red, $lighten ); + } + + &:active { + background-color: darken( $color-red, $darken ); + } + } + + &.button-outline-red { + @include button-theme($color-red, outline); + + &:hover { + background-color: adjust-color($color-red, $alpha: -0.9); + } + + &:active { + background-color: adjust-color($color-red, $alpha: -0.7); + } + } +} diff --git a/app/assets/stylesheets/components/_callouts.scss b/app/assets/stylesheets/components/_callouts.scss new file mode 100644 index 0000000..71efbba --- /dev/null +++ b/app/assets/stylesheets/components/_callouts.scss @@ -0,0 +1,54 @@ +.callout { + border-left: 4px solid rgb(77, 169, 179); + border-radius: 4px; + padding: 25px 30px; + margin: 25px auto; + background: rgb(245, 245, 245); + max-width: 700px; + + h1,h2,h3,h4,h5,h6 { + font-size: 20px!important; + font-weight: 500!important; + letter-spacing: -0.75px!important; + margin-bottom: 0.5rem!important; + margin-top: 0!important; + color: rgb(77, 169, 179)!important; + } + + svg + h1,svg + h2,svg + h3,svg + h4,svg + h5,svg + h6 { + display: inline-block; + position: relative; + top: -5px; + padding-left: 10px; + } + + p { + margin: 0px!important; + } + + &.callout-info, &.callout-attention, &.callout-note, &.callout-tip, &.callout-hint, &.callout-primary { + border-left: 4px solid rgb(77, 169, 179); + h1,h2,h3,h4,h5,h6 { color: rgb(77, 169, 179)!important; } + svg { fill: rgb(77, 169, 179)!important; } + } + &.callout-warning, &.callout-caution { + border-left: 4px solid rgb(214, 146, 28); + h1,h2,h3,h4,h5,h6 { color: rgb(214, 146, 28)!important; } + svg { fill: rgb(214, 146, 28)!important; } + } + &.callout-danger, &.callout-error { + border-left: 4px solid rgb(199, 76, 76); + h1,h2,h3,h4,h5,h6 { color: rgb(199, 76, 76)!important; } + svg { fill: rgb(199, 76, 76)!important; } + } + &.callout-success, &.callout-important { + border-left: 4px solid rgb(109, 179, 104); + h1,h2,h3,h4,h5,h6 { color: rgb(109, 179, 104)!important; } + svg { fill: rgb(109, 179, 104)!important; } + } + &.callout-secondary, &.callout-light, &.callout-dark, &.callout-admonition { + border-left: 4px solid rgb(128, 128, 128); + h1,h2,h3,h4,h5,h6 { color: rgb(128, 128, 128)!important; } + svg { fill: rgb(128, 128, 128)!important; } + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/components/_challenge-block.scss b/app/assets/stylesheets/components/_challenge-block.scss new file mode 100644 index 0000000..1307045 --- /dev/null +++ b/app/assets/stylesheets/components/_challenge-block.scss @@ -0,0 +1,698 @@ +form.challenge-block { + border-width: 0; + + .topics { + background-color: $color-black-97-3; + display: flex; + justify-content: flex-start; + padding-bottom: 30px; + flex-direction: row; + flex-wrap: wrap; + } +} + +.challenge-legendrow { + margin-left: 14px !important; +} + +form[data-challenge-type="code-snippet"] .challenge-legendrow, +form[data-challenge-type="paragraph"] .challenge-legendrow, +form[data-challenge-type="multiple-choice"] .challenge-legendrow, +form[data-challenge-type="checkbox"] .challenge-legendrow, +form[data-challenge-type="short-answer"] .challenge-legendrow, +form[data-challenge-type="custom-snippet"] .challenge-legendrow, +form[data-challenge-type="testable-project"] .challenge-legendrow { + display: inline-block !important; + top: 5px; +} + +form[data-challenge-type="code-snippet"] .actions.checkpoint, +form[data-challenge-type="custom-snippet"] .actions.checkpoint, +form[data-challenge-type="testable-project"] .actions.checkpoint { + padding: 5px 16px 24px; +} + +.body-container .mdown-container .challenge-block, .challenge-block { + $em: 8; + + & { + position: relative; + background: $color-white; + box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1); + margin: ($em * 3 + px) 0; + } + + > .challenge-header { + position: relative; + background: $color-white; + border-bottom: 1px solid $color-black-90-2; + padding: ($em * 2 + px); + display: flex; + flex-flow: row nowrap; + align-items: center; + min-height: ($em * 9 + px); + } + + > .challenge-header .vertical-dots { + position: relative; + height: ($em * 3 + px); + width: ($em * 3 + px); + display: flex; + flex: 0 0 auto; + margin-left: auto; + margin-right: 0; + color: $color-black-60; + + &:hover { + cursor: pointer; + color: $color-cyan; + } + } + + > .challenge-header > .textcontainer { + flex: 1 1 auto; + margin-left: ($em * 2 + px); + margin-right: ($em * 2 + px); + display: flex; + flex-flow: column; + justify-content: center; + } + + > .challenge-header > .textcontainer > .title { + height: ($em * 3 + px); + color: $color-darker-gray-blue; + font-size: ($em * 2 + px); + font-weight: bold; + line-height: ($em * 3 + px); + } + + > .challenge-header > .textcontainer > .info { + height: ($em * 2 + px); + color: $color-black-60; + font-size: ($em * 1.5 + px); + line-height: ($em * 2 + px); + } + + > .challenge-header > .icon-container { + position: absolute; + top: 0; + bottom: 0; + left: -($em * 2 + px); + right: auto; + margin: auto; + background: $color-darkest-blue-gray; + height: ($em * 4 + px); + width: ($em * 4 + px); + overflow: hidden; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + color: white; + font-size: 0.8rem; + font-weight: 400; + } + + > .challenge-header > .icon-container > svg { + height: 100%; + width: 100%; + } + + > .problem { + background: $color-white; + border-bottom: 1px solid $color-black-90-2; + padding: ($em * 3 + px); + + p { + color: $color-black-46-7; + } + + blockquote { + border-left: 3px solid $color-black-46-7; + font-style: italic; + padding-left: 20px; + } + + p, ul, ol, li { + margin-top: 12px; + margin-bottom: 0px; + &:first-child, &.first-child > img { + margin-top: 0px; + } + } + + h1 + p, h2 + p, h3 + p, h4 + p, h5 + p, h6 + p { + margin-top: 8px; + } + + h1, h1:first-of-type, h2, h3, h4, h5, h6 { + margin-top: 24px; + margin-bottom: 0px; + &:first-child { + margin-top: 0px; + } + } + + table, pre, blockquote { + margin-top: 24px; + margin-bottom: 24px; + &:first-child { + margin-top: 0px; + } + } + + p > img { + margin-top: 24px; + margin-bottom: 24px; + } + + img { + max-width: 100%; + } + + &.-truncate { + height: 200px; + overflow: hidden; + } + } + + .show-all { + background: white; + box-shadow: 0px -20px 20px 0px rgba(255,255,255,1); + color: $color-cyan; + text-align: center; + position: relative; + padding: 8px; + cursor: pointer; + } + + > .answer { + background: $color-black-97-3; + border-bottom: 1px solid $color-black-90-2; + padding: ($em * 3 + px); + + &.-codeeditor { + position: relative; + min-height: 400px; + width: 100%; + padding: 0; + overflow: scroll; + } + } + + > .answer > .checkbox-challenge-label > .renderedmdown > ul, + > .answer > .checkbox-challenge-label > .renderedmdown > h3 { + margin-top: 12px; + margin-bottom: 12px; + } + + > .answer .checkbox-challenge-info { + font-size: 14px; + color: $color-black-60; + font-weight: 400; + text-transform: uppercase; + } + + .input-lang { + background: #25282c; + text-align: right; + font-size: 12px; + text-transform: uppercase; + padding: 2px 4px; + color: #C5C8C6; + } + + > .answer > input { + height: ($em * 5 + px); + width: 100%; + padding: 0 ($em * 2 + px); + border: 1px solid $color-black-83-1; + border-radius: 4px; + background-color: $color-white; + box-shadow: inset 0 1px 2px 0 rgba(0, 0, 0, 0.1); + } + + > .answer > input::placeholder, > .answer > textarea::placeholder { + color: $color-black-83-1; + font-style: italic; + } + + > .answer > textarea { + width: 100%; + padding: ($em * 2 + px); + border: 1px solid $color-black-83-1; + border-radius: 4px; + background-color: $color-white; + box-shadow: inset 0 1px 2px 0 rgba(0, 0, 0, 0.1); + resize: vertical; + } + + > .actions { + min-height: ($em * 9 + px); + padding: ($em * 2 + px) ($em * 3 + px); + background-color: $color-black-97-3; + display: flex; + flex-flow: column-reverse nowrap; + align-items: center; + + .draft-timestamp { + font-size: 14px; + color: $color-black-60; + font-weight: 400; + } + + @media screen and (min-width: $tablet-breakpoint) { + flex-flow: row nowrap; + } + } + + > .actions .feedback { + display: flex; + flex-flow: row; + align-items: center; + font-size: ($em * 2.25 + px); + line-height: ($em * 3 + px); + margin-right: 10px; + } + + > .actions .feedback > .icon-container { + flex: 0 0 auto; + height: ($em * 3 + px); + width: ($em * 3 + px); + display: flex; + align-items: center; + justify-content: center; + margin-right: ($em * 1 + px); + } + + > .actions > .buttons { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + margin-bottom: 1rem; + + @media screen and (min-width: $tablet-breakpoint) { + margin: 0 0 0 auto; + } + } + + > .actions > .buttons > .resetbutton { + background-color: inherit; + color: $color-cyan; + width: 135px; + } + + .multi-and-checkbox { + & { + display: flex; + flex-flow: row nowrap; + align-items: center; + margin: ($em * 1 + px) 0; + } + + &:hover { + background: rgba($color-cyan, 0.05); + border-radius: 8px; + user-select: none; + cursor: pointer; + } + + > .renderedmdown { + flex: 1; + padding: 0.5rem 1rem; + border: 1px solid rgba(0,0,0, 0.1); + border-radius: 0.5rem; + overflow: hidden; + pointer-events: none; + } + + > .renderedmdown > pre, + > .renderedmdown > pre > code { + background: none; + margin: 0; + white-space: pre-wrap; + } + } + + .checkbox-challenge-label { + @extend .multi-and-checkbox; + + > input[type="checkbox"]:checked + .renderedmdown { + border-color: $color-cyan; + background: rgba($color-cyan, 0.05); + } + + > input[type="checkbox"] { + box-sizing: border-box; + padding: 0; + display: inline-block; + vertical-align: middle; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + cursor: pointer; + height: ($em * 3 + px); + width: ($em * 3 + px); + background: none center no-repeat; + background-size: cover; + margin: ($em * 1 + px); + margin-right: ($em * 2 + px); + flex: 0 0 auto; + } + + > input[type="checkbox"] { + background-image: url("data:image/svg+xml;charset=utf-8, %3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20style%3D%22fill%3A%23cccccc%3B%22%3E%3Cpath%20d%3D%22M19%205v14H5V5h14m0-2H5c-1.1%200-2%20.9-2%202v14c0%201.1.9%202%202%202h14c1.1%200%202-.9%202-2V5c0-1.1-.9-2-2-2z%22%2F%3E%3C%2Fsvg%3E"); + } + + > input[type="checkbox"]:checked { + background-image: url("data:image/svg+xml;charset=utf-8, %3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20style%3D%22fill%3A%2369A2D7%3B%22%3E%3Cpath%20d%3D%22M19%203H5c-1.11%200-2%20.9-2%202v14c0%201.1.89%202%202%202h14c1.11%200%202-.9%202-2V5c0-1.1-.89-2-2-2zm-9%2014l-5-5%201.41-1.41L10%2014.17l7.59-7.59L19%208l-9%209z%22%2F%3E%3C%2Fsvg%3E"); + } + + > .renderedmdown > p { + margin-top: 12px !important; + margin-bottom: 12px !important; + font-size: 18px !important; + } + } + + .multi-choice-challenge-label { + @extend .multi-and-checkbox; + + > input[type="radio"]:checked + .renderedmdown { + border-color: $color-cyan; + background: rgba($color-cyan, 0.05); + } + + > input[type="radio"] { + box-sizing: border-box; + padding: 0; + display: inline-block; + vertical-align: middle; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + cursor: pointer; + height: ($em * 3 + px); + width: ($em * 3 + px); + background: none center no-repeat; + background-size: cover; + margin: ($em * 1 + px); + margin-right: ($em * 2 + px); + flex: 0 0 auto; + } + + > input[type="radio"] { + background-image: url("data:image/svg+xml, %3Csvg%20width%3D%2220%22%20height%3D%2220%22%20viewBox%3D%220%200%2020%2020%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Cpath%20d%3D%22M10%200C4.48%200%200%204.48%200%2010s4.48%2010%2010%2010%2010-4.48%2010-10S15.52%200%2010%200z%22%20fill%3D%22%23FFF%22%20fill-rule%3D%22nonzero%22%2F%3E%3Cpath%20d%3D%22M10%200C4.48%200%200%204.48%200%2010s4.48%2010%2010%2010%2010-4.48%2010-10S15.52%200%2010%200zm0%2018c-4.42%200-8-3.58-8-8s3.58-8%208-8%208%203.58%208%208-3.58%208-8%208z%22%20fill%3D%22%23D4D4D4%22%20fill-rule%3D%22nonzero%22%2F%3E%3Cpath%20d%3D%22M-2-2h24v24H-2z%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E"); + } + + > input[type="radio"]:checked { + background-image: url("data:image/svg+xml, %3Csvg%20width%3D%2220%22%20height%3D%2220%22%20viewBox%3D%220%200%2020%2020%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Cpath%20d%3D%22M10%205c-2.76%200-5%202.24-5%205s2.24%205%205%205%205-2.24%205-5-2.24-5-5-5zm0-5C4.48%200%200%204.48%200%2010s4.48%2010%2010%2010%2010-4.48%2010-10S15.52%200%2010%200zm0%2018c-4.42%200-8-3.58-8-8s3.58-8%208-8%208%203.58%208%208-3.58%208-8%208z%22%20fill%3D%22%2300A5B5%22%20fill-rule%3D%22nonzero%22%2F%3E%3Cpath%20d%3D%22M-2-2h24v24H-2z%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E"); + } + + > .renderedmdown > p { + margin-top: 12px !important; + margin-bottom: 12px !important; + font-size: 18px !important; + } + } + + + .challenge-grading-buttons { + & { + display: flex; + flex-flow: row nowrap; + align-items: center; + justify-content: space-between; + min-height: 72px; + background-color: $color-black-97-3; + padding: 0 24px; + + border: solid $color-black-90-2; + border-width: 1px 0; + } + + .grading-details { + & { + display: flex; + flex-flow: row nowrap; + align-items: center; + justify-content: flex-end; + margin-left: auto; + } + .timestamp { + flex: 0 1 auto; + font-size: 16px; + color: $color-black-60-8; + font-weight: 500; + margin-right: 18px; + } + + .buttons { + display: flex; + flex-flow: row nowrap; + margin-left: 16px; + } + + .points-ratio { + font-size: 24px; + } + + .points-section { + display: flex; + align-items: center; + position: relative; + + .points { + margin-left: 5px; + font-weight: 500; + color: $color-black-60-8; + font-weight: 500; + margin-left: 15px; + } + + .correct-check { + color: $color-cyan; + width: 32px; + height: 32px; + } + + .incorrect-check { + color: $color-valencia; + width: 32px; + height: 32px; + } + } + } + } + + .topics { + padding: 10px 16px 16px; + } + +} + +//challenge-accordion +.challenge-accordion { + $em: 8; + + & { + position: relative; + background: $color-white; + } + + &.-is-expanded > .heading > .icon-container { + transform: rotate(0deg); + } + + &.-is-expanded > .body > .hint-container { + margin-left: 1em; + margin-right: 0.5em; + + p { + margin-bottom: 1.5em; + } + } + + &.-is-expanded > .body > .text-center > p.get-hint-text { + color: $color-cyan; + cursor: pointer; + } + + > .heading { + user-select: none; + height: ($em * 5 + px); + padding: 0 ($em * 2 + px); + border: solid $color-black-90-2; + border-width: 1px 0; + display: flex; + flex-flow: row nowrap; + align-items: center; + cursor: pointer; + } + + > .heading > .headingtitle { + flex: 1 1 100%; + height: ($em * 1.5 + px); + color: $color-cyan; + font-size: ($em * 1.5 + px); + font-weight: bold; + letter-spacing: 1px; + line-height: ($em * 1.5 + px); + margin: 0 ($em * 1 + px); + text-transform: uppercase; + } + + > .heading > .icon-container { + flex: 0 0 auto; + height: ($em * 3 + px); + width: ($em * 3 + px); + display: flex; + align-items: center; + justify-content: center; + transform: rotate(-90deg); + } + + > .body { + padding: ($em * 3 + px); + overflow-x: scroll; + + pre { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + margin: 0 0 10px; + padding: 9.5px; + background-color: $color-black-97-3; + font-size: 13px; + word-wrap: normal; + margin-top: 0px !important; + } + + p, h1, h2, h3, h4, h5, h6, table { + margin-top: 0px !important; + } + + .problem pre { + word-break: none; + word-wrap: normal; + color: $color-black-20; + background-color: $color-black-97-3; + border: none; + border-radius: 0px; + } + } +} + +.challenge-legendrow { + & { + position: relative; + display: flex; + flex-flow: row; + background: $color-black-97-3; + } + + > .svg { + opacity: .6; + margin: .5rem; + cursor: help; + margin-right: 10px; + margin-left: auto; + + &:hover + .infomodal { + display: block; + } + } + + > .infomodal { + font-size: 14px; + width: 260px; + margin: .5rem; + padding: 1rem 1.5rem; + border-radius: .5rem; + color: $color-white; + background-color: $color-black-10-2; + box-shadow: 0 2px 8px 0 rgba(0,0,0,0.3); + cursor: help; + display: none; + position: absolute; + top: 0; + right: 0; + z-index: 10; + + &:hover { + display: block; + } + } +} + +// menu.js.jsx +.menu-default { + $em: 8; + + & { + position: absolute; + top: 0; + right: 0; + background: $color-white; + border-radius: 4px; + border: 1px solid $color-black-83-1; + box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1); + overflow: hidden; + width: 100%; + min-width: 200px; + } + + > ul { + margin: 0; + padding: 0; + list-style: none; + } + + > ul > li { + margin: 0; + padding: 0; + height: ($em * 5 + px); + line-height: ($em * 5 + px); + background-color: $color-white; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + cursor: pointer; + user-select: none; + font-size: ($em * 2 + px); + color: black; + + &:hover { + color: $color-cyan; + background-color: rgba($color-cyan, 0.02); + } + } + + a { + display: block; + height: inherit; + line-height: inherit; + font-style: inherit; + color: inherit; + text-decoration: none; + padding: 0 ($em * 2 + px); + } +} + +// icon.js.jsx +.svg { + &.primary-color { + color: $color-cyan; + } + + &.error-color { + color: #E36875; + } +} + +.ace_editor { + display: block; + position: relative; + min-height: 400px; + min-width: 500px; + width: 100%; +} diff --git a/app/assets/stylesheets/components/_challenge_status.scss b/app/assets/stylesheets/components/_challenge_status.scss new file mode 100644 index 0000000..05fae01 --- /dev/null +++ b/app/assets/stylesheets/components/_challenge_status.scss @@ -0,0 +1,18 @@ +.status-section { + display: flex; + align-items: center; + position: relative; + margin-left: 25px; + + .incorrect-check { + color: $color-valencia; + width: 40px; + height: 45px; + } + + .correct-check { + color: $color-cyan; + width: 40px; + height: 45px; + } +} diff --git a/app/assets/stylesheets/components/_checkbox-input.scss b/app/assets/stylesheets/components/_checkbox-input.scss new file mode 100644 index 0000000..47f92e9 --- /dev/null +++ b/app/assets/stylesheets/components/_checkbox-input.scss @@ -0,0 +1,15 @@ +input[type="checkbox"].checkbox-input { + display: inline-block; + vertical-align: middle; + appearance: none; + cursor: pointer; + height: 24px; + width: 24px; + background: none center no-repeat; + background-size: cover; + background-image: url("data:image/svg+xml;charset=utf-8, %3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20style%3D%22fill%3A%23cccccc%3B%22%3E%3Cpath%20d%3D%22M19%205v14H5V5h14m0-2H5c-1.1%200-2%20.9-2%202v14c0%201.1.9%202%202%202h14c1.1%200%202-.9%202-2V5c0-1.1-.9-2-2-2z%22%2F%3E%3C%2Fsvg%3E"); + + &:checked { + background-image: url("data:image/svg+xml;charset=utf-8, %3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20style%3D%22fill%3A%2369A2D7%3B%22%3E%3Cpath%20d%3D%22M19%203H5c-1.11%200-2%20.9-2%202v14c0%201.1.89%202%202%202h14c1.11%200%202-.9%202-2V5c0-1.1-.89-2-2-2zm-9%2014l-5-5%201.41-1.41L10%2014.17l7.59-7.59L19%208l-9%209z%22%2F%3E%3C%2Fsvg%3E"); + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/components/_checkpoint-landing.scss b/app/assets/stylesheets/components/_checkpoint-landing.scss new file mode 100644 index 0000000..c13e740 --- /dev/null +++ b/app/assets/stylesheets/components/_checkpoint-landing.scss @@ -0,0 +1,170 @@ +.instructor-actions { + color: $color-dove-gray; + display: flex; + flex-flow: row nowrap; + width: 170px; + justify-content: flex-end; + position: relative; + + a { + text-decoration: none; + } + div { + display: flex; + flex-direction: row; + margin-left: 2rem; + } + span { + font-size: 16px; + } +} + +.checkpoint-landing { + @include font-base; + margin-bottom: 50px; +} + +.checkpoint-attributes, .checkpoint-attributes .checkpoint-attribute { + display: flex; + flex-flow: row nowrap; + background-color: white; +} + +.checkpoint-landing-title { + @include font-h1; + margin: 66px 0 60px 0; +} + +.checkpoint-attributes { + margin-bottom: 1rem; +} + +.checkpoint-attributes .checkpoint-attribute:not(:last-child) { + margin-right: 5rem; +} + +.checkpoint-attribute svg { + margin-right: 10px; + position: relative; + top: -2px; +} + +.checkpoint-points-earned svg, .checkpoint-scoring svg { + margin-right: 5px; + position: relative; + top: 4px; + height: 21px; +} + +.checkpoint-attribute .quantity-attribute { + @include font-base; + line-height: 20px; + color: $color-mine-shaft; + font-weight: 500; +} + +.checkpoint-attribute .quantity-attribute { + b { + @include font-base; + font-weight: 500; + color: $color-mine-shaft; + + text-align: right; + line-height: normal; + } + + .subtext { + @include font-small; + color: $color-gray; + margin-left: 8px; + line-height: normal; + } +} + +.checkpoint-attribute .text-attribute, .checkpoint-scored-at { + @include font-small; + color: $color-gray; +} + +.checkpoint-scoring { + @include font-small; +} + +.checkpoint-scored-at { + line-height: 1.7; +} + +.checkpoint-scoring > .view-checkpoint { + line-height: 1.4; +} + +.checkpoint-scoring .actioncircle { + --actioncircle-size: 24px; + line-height: 0; +} + +.checkpoint-landing-summary { + margin-bottom: 30px; +} + +.checkpoint-centered { + margin: 0 auto 1rem; +} + +.checkpoint-points-earned { + @include font-base; + line-height: 1; + color: $color-mine-shaft; + display: inline; +} + +.checkpoint-started-at { + @include font-small; + font-weight: 400; + margin: 0 auto 1rem; +} + +.checkpoint-end-message { + text-align: center; + font-size: 18px; + color: $color-mine-shaft; + margin: 2rem 0 4rem; +} + +.checkpoint-details { + display: flex; + flex-flow: column nowrap; + padding: 2rem; + background-color: #FBFBFB; + border-radius: 5px; + border: 1px solid #E1E1E1; + margin-top: 2rem; + + .checkpoint-scoring { + margin-bottom: 32px; + } + + .button-wrapper.checkpoint-landing-button { + margin: 0 auto; + max-width: 275px; + position: relative; + } + + &.timed-checkpoint { + background-color: #FFFCF0; + + .checkpoint-started-at { + @include font-paragraph; + } + + .time-remaining svg{ + position: relative; + top: 6px; + margin-right: 8px; + } + } +} + +.primary-teal { + color: $color-primary-teal; +} \ No newline at end of file diff --git a/app/assets/stylesheets/components/_checkpoint-submission.scss b/app/assets/stylesheets/components/_checkpoint-submission.scss new file mode 100644 index 0000000..f7b309a --- /dev/null +++ b/app/assets/stylesheets/components/_checkpoint-submission.scss @@ -0,0 +1,152 @@ +.checkpoint-submission { + .header { + background: $color-darkest-blue-gray; + height: 112px; + padding: 32px; + display: flex; + justify-content: space-between; + } + + .header > div > .label { + color: $color-black-60-8; + font-size: 12px; + letter-spacing: 2px; + margin-bottom: 8px; + font-weight: 300; + padding-left: 0; + } + + .header > div > .title { + color: $color-white; + font-size: 24px; + } + + .header > .header-right .lp-badge { + margin-bottom: 8px; + } + + .header > .header-right > .title { + text-align: center; + } + + .challenge-block > .problem { + h3 { + font-size: 24px; + font-weight: 500; + line-height: 1.1; + color: $color-black-20; + margin: 20px 0 10px; + } + + p { + margin: 0 0 10px; + } + + pre, + pre > code, + pre > code > span { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + } + } +} + +.checkpoint-submission .body-container { + & { + display: flex; + flex-flow: row wrap; + height: auto; + + @media screen and (min-width: $tablet-breakpoint) { + min-height: 100vh; + } + } + + > .challenges { + flex: 1 1 auto; + width: 60%; + padding: 0 1.5rem; + overflow: hidden; + background: $color-white; + } + + > .standards-wrapper { + flex: 0 0 auto; + width: 480px; + max-width: 100%; + } + + > .standards-wrapper > .standards { + background: $color-black-97-3; + padding: 1.5rem 1rem 0; + + &.-is-sticky { + flex: 0 0 auto; + width: 480px; + overflow: scroll; + position: fixed; + z-index: 9999; + height: calc(100% - 4rem); + top: 4rem; + right: 0; + } + &.-is-student { + height: 100%; + top: 0; + } + } + + > .standards-wrapper > .standards .standard-score-info { + flex: 1 1 100%; + } + + > .standards-wrapper > .standards .standard-score-info > .label { + height: 20px; + font-size: 12px; + font-weight: bold; + letter-spacing: 1px; + line-height: 12px; + text-transform: uppercase; + padding-left: 0; + color: $color-dark-blue-gray; + + &.gray-label { + color: $color-black-60-8; + } + + &.cyan-label { + color: $color-cyan; + } + + > .svg { + flex: 0 0 auto; + position: absolute; + left: auto; + margin: auto; + pointer-events: none; + right: 60px; + } + } + + .standards .standard-score-info > p { + margin: 0; + height: 16px; + font-size: 12px; + font-weight: 400; + line-height: 16px; + color: $color-black-60-8; + } + + .standard-topics-rollups { + display: flex; + flex-flow: row wrap; + margin-top: 10px; + + > .pill-wrapper.small { + margin: 0 10px 10px 0; + } + + &.hide-rollups { + display: none; + } + } +} diff --git a/app/assets/stylesheets/components/_checkpoint-submissions-columns-student.scss b/app/assets/stylesheets/components/_checkpoint-submissions-columns-student.scss new file mode 100644 index 0000000..4ab3c53 --- /dev/null +++ b/app/assets/stylesheets/components/_checkpoint-submissions-columns-student.scss @@ -0,0 +1,72 @@ +.checkpoint-submissions-columns-student { + & { + position: relative; + display: flex; + flex-flow: row nowrap; + background: white; + height: 56px; + border: 1px solid transparent; + border-bottom-color: $color-black-83-1; + padding: 8px 16px; + } + + &.-is-not-submitted { + align-items: center; + background: none; + + &:hover { + border-color: transparent; + border-bottom: 1px solid $color-black-83-1; + box-shadow: none; + cursor: auto; + } + + > .usercel > .usertimestamp { + display: none; + } + + > .lp-badge { + display: none; + } + } + + &:hover { + border-color: $color-cyan; + box-shadow: 0 2px 8px 0 rgba(0,0,0,0.2); + cursor: pointer; + } + + > .user-avatar { + padding: 0; + flex: 0 0 auto; + } + + > .usercel { + margin: 0 8px; + flex: 1 1 auto; + min-width: 0; + } + + > .usercel > .username { + color: $color-darker-gray-blue; + font-size: 18px; + line-height: 24px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + + > .usercel > .usertimestamp { + color: $color-black-60-8; + font-size: 12px; + line-height: 16px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + + > .lp-badge { + flex: 0 0 auto; + margin: 2px 0; + } +} diff --git a/app/assets/stylesheets/components/_checkpoint-submissions-columns.scss b/app/assets/stylesheets/components/_checkpoint-submissions-columns.scss new file mode 100644 index 0000000..4013512 --- /dev/null +++ b/app/assets/stylesheets/components/_checkpoint-submissions-columns.scss @@ -0,0 +1,36 @@ +.checkpoint-submissions-columns { + & { + display: flex; + flex-flow: row nowrap; + } + + > .column { + flex: 1 1 auto; + width: calc(100%/3 - 64px); + + &.-no-shadow > .colbody { + box-shadow: none; + } + } + > .column:not(:last-of-type) { + margin-right: 32px; + } + + > .column > .colbody { + box-shadow: 0 2px 8px 0 rgba(0,0,0,0.1); + } + + > .column > .colbody > a { + text-decoration: none; + } + + > .column > .colheading { + height: 56px; + border-bottom: 2px solid $color-black-83-1; + color: $color-black; + font-size: 20px; + display: flex; + align-items: center; + justify-content: center; + } +} diff --git a/app/assets/stylesheets/components/_checkpoint-submissions-index.scss b/app/assets/stylesheets/components/_checkpoint-submissions-index.scss new file mode 100644 index 0000000..5d102a6 --- /dev/null +++ b/app/assets/stylesheets/components/_checkpoint-submissions-index.scss @@ -0,0 +1,5 @@ +.checkpoint-submissions-index { + background: $color-black-97-3; + overflow: hidden; + padding: 0 32px 40px; +} diff --git a/app/assets/stylesheets/components/_checkpoint_student_scores.scss b/app/assets/stylesheets/components/_checkpoint_student_scores.scss new file mode 100644 index 0000000..c31efc4 --- /dev/null +++ b/app/assets/stylesheets/components/_checkpoint_student_scores.scss @@ -0,0 +1,184 @@ +.lesson-layout .body-container .checkpoint-student-scores { + background: $color-alabaster; + + .mdown-container .checkpoint-results { + h1:first-of-type { + margin-top: 45px; + margin-bottom: 40px; + } + h2:first-of-type { + margin-top: 45px; + margin-bottom: 40px; + } + } + + table.checkpoints-scores { + font-size: 16px; + width: 100%; + margin-top: 24px; + + tbody { + color: $color-tundora; + border: 1px solid $color-mercury; + box-shadow: 0 1px 10px 0 rgba(0,0,0,0.06); + background: white; + + tr { + border-bottom: 1px solid $color-black-93-3; + height: 56px; + + &:hover, &.never-signed-in:hover { + border-bottom: 1px solid #d0d0d0; + box-shadow: 0 0 10px 0 rgba(0,0,0,0.08); + } + + &.never-signed-in { + background: $color-alabaster; + span, div { + color: $color-black-60; + } + } + + &.row-selected td { + background: rgba(77, 169, 179, 0.1); + } + + &:last-of-type { + td { + border-bottom: none; + } + } + } + } + + th, td { + white-space: nowrap; + + &.checkbox-col { + width: 5%; + text-align: center; + } + + &.name-col > span, &.name-col > a { + padding: 0 20px 0 40px; + } + + &.score-col { + > a, > span { + padding: 0 20px; + } + } + + &.status-col { + width: 170px; + + > a, > span { + padding: 0 40px 0 20px; + } + } + + > input[type="checkbox"] { + box-sizing: border-box; + padding: 0; + display: inline-block; + vertical-align: middle; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + cursor: pointer; + height: (8 * 3 + px); + width: (8 * 3 + px); + background: none center no-repeat; + background-size: cover; + margin: (8 * 1 + px); + margin-right: (8 * 2 + px); + flex: 0 0 auto; + } + + > input[type="checkbox"] { + background-image: url("data:image/svg+xml;charset=utf-8, %3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20style%3D%22fill%3A%23cccccc%3B%22%3E%3Cpath%20d%3D%22M19%205v14H5V5h14m0-2H5c-1.1%200-2%20.9-2%202v14c0%201.1.9%202%202%202h14c1.1%200%202-.9%202-2V5c0-1.1-.9-2-2-2z%22%2F%3E%3C%2Fsvg%3E"); + } + + } + + th { + height: 36px; + > span { + color: $color-dove-gray; + font-weight: 400; + } + + > input[type="checkbox"]:checked { + background-image: url("data:image/svg+xml;charset=utf-8, %3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%2224%22%20height=%2224%22%20viewBox=%220%200%2024%2024%22%3E%3Cpath%20stroke=%22666%22%20strok-width=%221%22%20d=%22M19%206.41L17.59%205%2012%2010.59%206.41%205%205%206.41%2010.59%2012%205%2017.59%206.41%2019%2012%2013.41%2017.59%2019%2019%2017.59%2013.41%2012z%22/%3E%3C/svg%3E"); + } + } + + td { + height: inherit; + + > input[type="checkbox"]:checked { + border-color: $color-cyan; + background: rgba($color-cyan, 0.05); + background-image: url("data:image/svg+xml;charset=utf-8, %3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20style%3D%22fill%3A%234DA9B3%3B%22%3E%3Cpath%20d%3D%22M19%203H5c-1.11%200-2%20.9-2%202v14c0%201.1.89%202%202%202h14c1.11%200%202-.9%202-2V5c0-1.1-.89-2-2-2zm-9%2014l-5-5%201.41-1.41L10%2014.17l7.59-7.59L19%208l-9%209z%22%2F%3E%3C%2Fsvg%3E"); + } + + > a, > span { + color: $color-tundora; + text-decoration: none; + height: 100%; + display: flex; + align-items: center; + } + + > a:hover { + color: $color-link-blue; + } + + &.name-col { + width: 100px; + height: inherit; + + .user-avatar { + margin-right: 10px; + } + + div { + max-width: 170px; + overflow: hidden; + text-overflow: ellipsis; + } + } + + &.score-col { + .checkpoint-score-text { + width: 18%; + } + + .checkpoint-score-bar { + width: 82%; + + div { + border-radius: 4px; + height: 12px; + } + } + } + + &.status-col { + svg { + margin-left: -2px; + margin-right: 5px; + } + + div.pending-submission { + border-radius: 100%; + height: 6px; + width: 6px; + background-color: #DC3D48; + margin-left: 2px; + margin-right: 8px; + } + } + } + } +} diff --git a/app/assets/stylesheets/components/_checkpoint_submisstion_state.scss b/app/assets/stylesheets/components/_checkpoint_submisstion_state.scss new file mode 100644 index 0000000..8edd6dc --- /dev/null +++ b/app/assets/stylesheets/components/_checkpoint_submisstion_state.scss @@ -0,0 +1,29 @@ +.checkpoint-submission-state-wrapper { + & { + text-align: right; + } + + >.badgerow { + display: flex; + flex-flow: row nowrap; + align-items: center; + justify-content: flex-end; + height: auto; + } + + > .badgerow > .lp-badge { + flex: 0 0 auto; + } + + > .badgerow > a { + color: $color-cyan; + text-transform: uppercase; + margin-left: 8px; + } + + > .timestamp { + color: $color-darkest-blue-gray; + font-size: 14px; + line-height: 24px; + } +} diff --git a/app/assets/stylesheets/components/_checkpoint_toolbar.scss b/app/assets/stylesheets/components/_checkpoint_toolbar.scss new file mode 100644 index 0000000..84d7a6d --- /dev/null +++ b/app/assets/stylesheets/components/_checkpoint_toolbar.scss @@ -0,0 +1,207 @@ +$sidebar-width: 280px; +$max-content-width: 1280px; + +.checkpoint-submit { + & { + width: 100%; + height: auto; + text-align: center; + z-index: 9; + + .lesson-layout.-is-collapsed & { + padding-left: 0; + } + } + + > .checkpoint-toolbar { + position: relative; + display: flex; + flex-flow: column; + justify-content: center; + width: 100%; + max-width: $max-content-width; + margin: 0 auto; + padding: 0 1rem; + color: $color-white; + height: auto; + min-height: 4.5rem; + @media screen and (min-width: $tablet-breakpoint) { + padding: 0 3rem; + } + } + + .bodyrow { + flex: 0 0 auto; + margin-top: 40px; + max-width: 78%; + color: $color-white; + font-size: 20px; + font-weight: 500; + line-height: 24px; + display: none; + @media screen and (min-width: $tablet-breakpoint) { + display: block; + } + } + + .actionrow { + flex: 0 0 auto; + display: flex; + flex-flow: column; + align-items: center; + justify-content: center; + padding: 1rem 0; + } + + .actionrow > .-submitbttn { + margin: 1rem; + } + + .actionrow > .-savebttn { + margin: 1rem; + } + + .closebttn { + position: absolute; + top: 0; + right: 80px; + display: none; + align-items: center; + justify-content: center; + padding: 20px 8px; + cursor: pointer; + + &:hover { + color: $color-white; + } + @media screen and (min-width: $tablet-breakpoint) { + display: flex; + } + + } + + .afterSubmitModal { + position: fixed; + top: 0; + left: 0; + z-index: 1000000; + background: rgba(0, 0, 0, 0.4); + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + + .error-wrapper { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + } + + .error-svg { + height: 24px; + width: 24px; + + svg { + fill: red; + } + } + + .error-header { + font-size: 22px; + font-weight: 600; + margin: 0 !important; + text-transform: uppercase; + color: #616161; + } + + .error-header-wrapper { + display: flex; + align-items: center; + height: 47px; + margin-left: 5px; + } + + .error-subheader { + margin: 16px 0 25px 0 !important; + text-align: left; + font-weight: 500; + color: #616161 !important; + } + + .error-message-wrapper { + margin-bottom: 20px; + } + + .error-challenge-number { + text-align: left; + text-transform: uppercase; + color: #b7b7b7; + font-size: 17px; + margin: 0 !important; + } + + .error-message { + text-align: left; + margin: 0 !important; + font-weight: 500; + color: #616161 !important; + } + } + + .afterSubmitModal .theModal .results-link { + color: $color-cyan; + font-size: 12px; + font-weight: bold; + text-decoration: none; + } + + .afterSubmitModal .theModal { + width: 500px; + border: 1px solid $color-black-60; + background: $color-white; + border-radius: 3px; + padding: 3rem; + position: relative; + } + + .afterSubmitModal .theModal h3 { + color: $color-dark-gray; + text-transform: uppercase; + } + + .afterSubmitModal .theModal h3 svg { + position: relative; + top: 6px; + margin-right: 0.5rem; + color: $color-black-60; + height: 30px; + width: 30px; + } + + .afterSubmitModal .theModal h3 img { + position: relative; + top: -3px; + margin-right: 0.5rem + } + + .afterSubmitModal .theModal p { + color: $color-black-60; + margin: 2rem 0; + } + + .afterSubmitModal .theModal p span { + font-size: 2rem; + + span { + color: $color-cyan; + font-weight: bold; + } + } + + .afterSubmitModal .theModal .closebttn { + right: 15px; + color: $color-black-60; + } +} diff --git a/app/assets/stylesheets/components/_code-block.scss b/app/assets/stylesheets/components/_code-block.scss new file mode 100644 index 0000000..3762468 --- /dev/null +++ b/app/assets/stylesheets/components/_code-block.scss @@ -0,0 +1,21 @@ +@import "highlightjs/styles/atom-one-light"; + +.hljs { + background: #f6f8fa; + padding: 16px; +} + +pre { + background: $color-white; + border-color: $color-black-83-1; +} + +pre.text { + background: $color-black-97-3; + padding: 0.5em; +} + +code { + color: black; + background-color: #f8f8f8; +} diff --git a/app/assets/stylesheets/components/_cohort-submissions-table.scss b/app/assets/stylesheets/components/_cohort-submissions-table.scss new file mode 100644 index 0000000..da27f81 --- /dev/null +++ b/app/assets/stylesheets/components/_cohort-submissions-table.scss @@ -0,0 +1,798 @@ +$submissions-cell-height: 56px; +.cohort-submissions { + %student-column { + & { + flex: 0 0 auto; + width: 40px; + } + + > .block-title-spacer { + background: $color-black-70-2; + height: 56px; + } + + > .student { + background: $color-white; + display: flex; + flex-flow: column; + align-items: center; + justify-content: center; + height: $submissions-cell-height; + padding: 8px; + cursor: pointer; + + &:hover { + background: $color-black-97-3; + } + } + + > .standard > .standarditem { + position: relative; + width: 100%; + border-right: 1px solid $color-black-94-3; + border-bottom: 1px solid $color-black-94-3; + + &:not(:last-of-type) { + border-bottom: 2px solid $color-black-83-1; + } + + &.checkpoint { + border-bottom: 21px solid $color-black-84-7; + } + } + + > .standard > .standarditem > .itemheading { + position: relative; + display: flex; + flex-flow: column; + align-items: center; + justify-content: center; + height: $submissions-cell-height; + background: $color-black-97-3; + padding: 8px; + } + + > .standard > .standarditem > .itemheading.performance { + background: $color-white; + } + + > .standard > .standarditem > .itemheading .tinybang { + position: absolute; + bottom: 26px; + right: 28px; + height: 12px; + } + + > .standard > .standarditem > .itemheading .actioncircle.tinyscore { + position: absolute; + bottom: 38px; + right: 24px; + height: 12px; + width: 12px; + } + + > .standard > .standarditem > .itemheading .actioncircle.pending-submission { + position: absolute; + bottom: 40px; + left: 27px; + height: 8px; + width: 8px; + background-color: #DC3D48; + } + + > .standard > .standarditem > .itemheading a { + text-decoration: none; + } + + > .standard > .standarditem > .itemheading .emdash { + &::before { + content: "—" + } + color: $color-dark-gray; + } + + > .standard > .standarditem > .itemheading .percent-correctness { + font-size: 13px; + font-weight: 300; + color: $color-dark-gray; + } + + > .standard > .standarditem > .itemheading .actioncircle { + &{ + border-radius: 100%; + color: $color-white; + display: flex; + align-items: center; + justify-content: center; + height: 23px; + width: 23px; + font-size: 10px; + line-height: 15px; + font-weight: 200; + } + + &.-score-3 { + background-color: $color-lime-green; + } + + &.-score-2 { + background-color: $color-banana-yellow; + } + + &.-score-1 { + background-color: $color-tangerine-orange; + } + + &.-ungraded { + border: 2px solid $color-black-20; + } + } + + > .standard > .standarditem > .itembody { + display: flex; + flex-flow: column; + align-items: center; + justify-content: center; + position: relative; + overflow: hidden; + background: $color-black-99-3; + height: $submissions-cell-height; + border-top: 1px solid $color-black-94-3; + } + + > .standard > .standarditem > .itembody > a { + flex: 1 1 100%; + display: inherit; + align-items: inherit; + justify-content: inherit; + padding: 8px; + + &:hover { + background: $color-black-92-2; + } + } + + > .standard > .emptyrow { + height: 56px; + background: $color-black-92-2; + } + + > .standard > .standarditem > .itemheading > svg.donut, + > .standard > .standarditem > .itembody > svg.donut { + height: 100%; + width: 100%; + } + } + + %standard-item { + & { + } + + > .standardtitle { + display: flex; + flex-flow: row nowrap; + align-items: center; + background: $color-white; + color: $color-dark-blue-gray; + font-size: 12px; + font-weight: bold; + letter-spacing: 2px; + height: 56px; + line-height: 56px; + text-transform: uppercase; + user-select: none; + cursor: pointer; + } + + > .standardtitle .action-kebab { + position: relative; + top: 8px; + cursor: pointer; + color: $color-black-46-7; + } + + > .standardtitle .action-menu, .standarditem .action-menu { + position: absolute; + top: -1px; + left: 8px; + width: 220px; + z-index: 10; + + ul { + background: white; + border: 1px solid $color-black-60-8; + border-radius: 8px; + list-style-type: none; + margin: 0; + padding: 0; + line-height: 56px; + + li { + padding: 0px 16px; + box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.05); + + a { + font-size: 16px; + font-weight: 500; + line-height: 24px; + letter-spacing: 0px; + color: $color-black; + text-decoration: none; + text-transform: none; + } + } + + li:last-of-type { + border-bottom: 0px solid transparent; + } + } + } + .standarditem .action-menu { + top: -9px; + } + + > .standardtitle > .iconwrapper.kebab { + position: relative; + } + + > .standardtitle > .iconwrapper.arrow { + transform: rotate(-90deg); + color: inherit; + cursor: pointer; + } + + .standardtitle.-open > .iconwrapper.arrow { + transform: rotate(0); + color: $color-cyan; + } + + > .standardtitle > .title { + flex: 1; + height: 100%; + padding: 0 16px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + > .standarditem { + position: relative; + + &:not(:last-of-type) { + border-bottom: 2px solid $color-black-83-1; + } + + &.-open > .itemheading > .iconwrapper.arrow { + transform: rotate(0); + color: $color-cyan; + } + + &.checkpoint { + border-bottom: 20px solid $color-black-84-7; + } + } + + > .standarditem .kebab { + position: absolute; + right: 0; + top: 15px; + cursor: pointer; + color: $color-black-46-7; + } + + > .standarditem > .itemheading { + color: $color-dark-blue-gray; + background: $color-black-97-3; + position: relative; + display: flex; + flex-flow: column; + justify-content: center; + height: $submissions-cell-height; + + &:hover { + cursor: pointer; + color: $color-cyan; + } + } + + > .standarditem > .itemheading > .iconwrapper { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: auto; + margin: auto; + margin-left: 8px; + height: 24px; + width: 24px; + } + + > .standarditem > .itemheading > .iconwrapper { + &.arrow { + transform: rotate(-90deg); + color: inherit; + } + &.star { + color: $color-galvanize-orange + } + } + + > .standarditem > .itemheading > .challenge-table-label { + text-transform: uppercase; + color: $color-black-60-8; + font-size: 10px; + letter-spacing: 2px; + line-height: 16px; + margin-left: 40px; + } + + > .standarditem > .itemheading > .title { + //color: $dark-blue-gray; + color: inherit; + font-size: 16px; + line-height: 24px; + margin-left: 40px; + padding-right: 16px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + > .standarditem > .itemheading > .title > a { + text-decoration: none; + color: inherit; + } + + > .standarditem > .itembody { + position: relative; + height: $submissions-cell-height; + background: $color-black-99-3; + border-left: 4px solid $color-cyan; + padding-left: 32px; + } + + > .standarditem > .itembody > .short-border-box { + display: flex; + flex-flow: column; + justify-content: center; + border-top: 1px solid $color-black-94-3; + height: 100%; + } + + > .standarditem > .itembody > .short-border-box > .challenge-table-label { + color: $color-black-60-8; + font-size: 10px; + letter-spacing: 2px; + line-height: 16px; + text-transform: uppercase; + margin-left: 16px; + } + + > .standarditem > .itembody > .short-border-box > .title { + color: $color-dark-blue-gray; + font-size: 16px; + line-height: 24px; + margin-left: 16px; + margin-right: 8px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + } + + .submissions-dashboard-table-wrapper { + .flex-row { + > .nameplate { + margin-bottom: 1rem; + } + + > .nameplate > .avatar-wrapper { + width: 40px; + display: inline-block; + line-height: 56px; + margin-right: 10px; + vertical-align: middle; + } + + > .nameplate > span { + display: inline-block; + line-height: 56px; + font-size: 1.1rem; + vertical-align: middle; + color: $color-darker-gray-blue; + } + } + } + + .flex-row { + .sort-dropdown-component { + margin-bottom: 15px; + } + + .expand-collapse { + font-size: 10px; + color: $color-sky-blue; + align-self: center; + } + } + + .manual-score-performance { + width: 188px; + height: 40px; + background-color: white; + border: 1px solid $color-black-90-2; + position: absolute; + z-index: 10; + top: 8px; + left: 107%; + box-shadow: 0px 0px 4px #ccc; + + .scores { + display: flex; + flex-flow: row; + align-items: center; + height: 100%; + } + + &.show-success-criteria { + width: 270px; + height: auto; + + .scores .toggle-success-criteria { + margin-right: 12px; + margin-left: auto; + } + + .scores { + height: 38px; + } + + .success-criteria h1 { + color: #272e39; + font-size: 16px; + font-weight: bold; + letter-spacing: 2px; + margin-bottom: 12px; + } + + .success-criteria h4 { + color: #a8a8a8; + text-transform: uppercase; + font-size: 12px; + font-weight: 600; + margin-bottom: 10px; + } + + .success-criteria ul { + padding-left: 1.2rem; + } + } + + .scores > .actioncircle { + border-radius: 100%; + color: $color-white; + display: flex; + align-items: center; + justify-content: center; + height: 23px; + width: 23px; + font-size: 10px; + line-height: 15px; + font-weight: 200; + background: $color-black-84-7; + margin-left: 12px; + cursor: pointer; + + &.score1 { + &.active { + background-color: $color-tangerine-orange; + } + &:hover { + background-color: $color-tangerine-orange; + } + } + &.score2 { + &.active { + background-color: $color-banana-yellow; + } + &:hover { + background-color: $color-banana-yellow; + } + } + &.score3 { + &.active { + background-color: $color-lime-green; + } + &:hover { + background-color: $color-lime-green; + } + } + } + + .scores > .triangle-thing { + width: 15px; + height: 15px; + z-index: 9; + position: absolute; + background: $color-white; + border-left: 1px solid $color-black-90-2; + border-bottom: 1px solid $color-black-90-2; + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + left: -8px; + } + + .scores > .toggle-success-criteria { + color: $color-black-84-7; + height: 23px; + width: 23px; + display: flex; + align-items: center; + justify-content: center; + margin-left: 12px; + cursor: pointer; + } + + > .success-criteria { + padding: 12px; + width: 100%; + border-top: 1px solid $color-black-90-2; + } + } + + .cohort-submission-legend { + & { + position: relative; + display: flex; + flex-flow: row; + justify-content: flex-end; + } + + > .svg { + opacity: .6; + margin-bottom: .5rem; + cursor: help; + + &:hover + .infomodal { + display: block; + } + } + + > .infomodal { + font-size: 14px; + max-width: 360px; + padding: 1rem 1.5rem; + border-radius: .5rem; + color: $color-white; + background-color: $color-black-10-2; + box-shadow: 0 2px 8px 0 rgba(0,0,0,0.3); + cursor: help; + display: none; + position: absolute; + top: 0; + right: 0; + z-index: 10; + + &:hover { + display: block; + } + } + } + + .challengeindex-table { + & { + position: relative; + display: flex; + flex-flow: row nowrap; + overflow: hidden; + background-color: $color-white; + box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1); + } + + &:after { + content: ""; + position: absolute; + left: 100%; + top: 0; + bottom: 0; + box-shadow: -4px 0 6px 1px rgba(black, 0.1); + background: white; + width: 10px; + } + + &.single-student { + &:after { + box-shadow: none; + } + } + + > .studentspanel { + position: relative; + z-index: 0; + flex: 1 1 100%; + overflow: hidden; + background: #e8e8e8; + } + + > .studentspanel .studentcolumn { + @extend %student-column; + } + + > .curriculumpanel { + position: relative; + z-index: 1; + flex: 0 0 auto; + width: 320px; + padding-top: $submissions-cell-height; + box-shadow: 4px 0 6px 1px rgba(black, 0.1); + } + + > .curriculumpanel > .block-title { + background: $color-black-70-2; + height: 56px; + padding: 0 1rem; + color: $color-dark-blue-gray; + font-size: 12px; + font-weight: bold; + letter-spacing: 2px; + line-height: 56px; + text-transform: uppercase; + user-select: none; + cursor: default; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + > .curriculumpanel > .standard { + @extend %standard-item; + border-bottom: 1px solid $color-black-83-1; + } + + > .curriculumpanel > .standard > .firstcontentfile { + border-top: 2px solid $color-black-83-1; + } + + > .curriculumpanel { + &.single-student { + padding-top: 0; + box-shadow: none; + + > .standard > .standarditem { + border-right: 2px solid $color-black-83-1; + } + } + } + + > .studentspanel { + &.single-student { + overflow-x: auto; + + .studentcolumn { + flex: 1 0 auto; + } + + > .studentcolumn > .standard > .standarditem > .itemheading { + flex-flow: row; + justify-content: flex-end; + } + + > .studentcolumn > .standard > .standarditem > .itembody { + flex-flow: row; + justify-content: flex-end; + } + + > .studentcolumn > .standard > .standarditem > .itemheading svg.donut { + width: 24px; + } + } + } + } + + .columnwrapper { + width: 100%; + overflow: auto; + display: flex; + flex-flow: row nowrap; + } + + .studentnamebar { + position: fixed; + top: 0; + z-index: 999; + width: calc(100% - 32px - 320px); + overflow: auto; + + &.-is-hidden { + visibility: hidden; + pointer-events: none; + } + + > .studentavatars { + display: flex; + flex-flow: row nowrap; + } + + > .studentavatars > .student { + background: $color-white; + flex: 0 0 auto; + display: flex; + flex-flow: column; + align-items: center; + justify-content: center; + height: $submissions-cell-height; + width: 40px; + padding: 8px; + border-bottom: 1px solid $color-black-83-1; + + &:hover { + background: $color-black-97-3; + } + } + } + + .dropdown-component > select { + background-color: $color-white; + } + + .icon-legend { + & { + height: 48px; + background: none; + border: 1px solid $color-black-83-1; + border-radius: 4px; + display: inline-flex; + flex-flow: row nowrap; + vertical-align: bottom; + align-items: center; + margin-bottom: 32px; + user-select: none; + overflow: hidden; + position: relative; + } + + > .item { + flex: 1 0 auto; + display: flex; + flex-flow: row nowrap; + align-items: center; + margin: 0 16px; + } + + > .item > .challenge-table-label { + color: $color-darker-gray-blue; + font-size: 16px; + line-height: 22px; + } + + > .item > .svg { + margin-right: 8px; + } + } + + .flex-row { + & { + position: relative; + display: flex; + flex-flow: row; + } + &.-align-middle { + align-items: center; + } + + > .-flex-alignright { + margin-right: 0; + margin-left: auto; + } + + > .-margin-right { + margin-right: 8px; + } + } + + // other flex-row styles + .flex-row > .pullright { + margin-right: 0; + margin-left: auto; + } +} diff --git a/app/assets/stylesheets/components/_cohort_releases.scss b/app/assets/stylesheets/components/_cohort_releases.scss new file mode 100644 index 0000000..e95a7f4 --- /dev/null +++ b/app/assets/stylesheets/components/_cohort_releases.scss @@ -0,0 +1,205 @@ +.available-blocks { + h2 { + font-weight: bold; + } + + table.block-table { + color: $color-black-46-7; + + tr:nth-of-type(odd) { + background: rgba(0, 0, 0, 0.05); + + td:first-of-type { + border-top-left-radius: 5px; + border-bottom-left-radius: 5px; + } + td:last-of-type { + border-top-right-radius: 5px; + border-bottom-right-radius: 5px; + } + } + + th { + background: white; + } + + th, td { + padding: .5rem; + border-bottom: none; + border-top: none; + } + + .center { + text-align: center; + } + } + + .action-cell { + position: relative; + + .action-menu { + display: none; + position: absolute; + top: 0; + right: 0; + width: 420px; + z-index: 10; + + ul { + background: white; + border: 1px solid $color-black-46-7; + list-style-type: none; + margin: 0; + padding: 0; + + li { + font-size: 14px; + padding: .5rem 1rem; + + a { + svg.svg { + height: 14px; + width: 14px; + margin-left: 4px; + vertical-align: middle; + } + + div { + display: inline; + } + } + } + + li:last-of-type { + border-bottom: 0px solid transparent; + } + } + } + + &:hover { + .action-menu { + display: block; + } + } + } +} + +.cohort-releases-show, .releases-show { + h2 { + padding: 16px 32px; + } + + .pick-version-table { + width: 100%; + } + + .pick-version-table .createdcolumn { + padding-left: 24px; + } + + .pick-version-table > thead { + background-color: #FFFFFF; + border-top: 1px solid $color-black-77; + border-bottom: 1px solid $color-black-77; + height: 40px; + + tr { + font-size: 14px; + line-height: 16px; + text-transform: uppercase; + color: #999999; + } + + tr > th { + font-weight: 500; + padding: 12px; + } + } + + .pick-version-table > tbody { + background-color: #FFFFFF; + + .releaserow { + border-bottom: 1px solid #e7e7e7; + + &.current-release { + background-color: rgba(0,165,181,0.05); + } + } + + .releaserow > td { + padding: 16px; + font-size: 16px; + vertical-align: top; + position: relative; + + &.createdcolumn { + padding-left: 24px; + } + } + + .releaserow > td > h5 { + font-weight: bold; + line-height: 16px; + font-size: 16px; + } + + .releaserow > td > p { + line-height: 16px; + margin-bottom: 8px; + } + + .releaserow > td > a.gitlink { + line-height: 16px; + font-weight: 300; + margin-right: 24px; + } + + .releaserow > td > span.currentlabel { + line-height: 16px; + color: $color-cyan; + text-transform: uppercase; + font-size: 12px; + font-weight: bold; + letter-spacing: 1px; + text-align: center; + padding: 0 24px; + } + } +} + +.cohorts-tooltip { + position: absolute; + top: 14%; + right: 80%; + display: flex; + flex-direction: column; + width: 220px; + border-radius: .5rem; + background-color: $color-black-10-2; + color: $color-white; + overflow: hidden; + box-shadow: 0 2px 8px 0 rgba(0,0,0,0.3); + margin-top: -22px; + margin-left: -10px; +} + +.cohorts-tooltip > .body > div { + padding: 16px; +} + +.cohorts-tooltip > .body > div > p { + margin: 0; +} + +.cohorts-tooltip > .body > div > p > a { + text-decoration: none; + color: white; +} + +.cohorts-tooltip > .body > div > p > a > svg { + height: 14px; + margin-left: 5px; + position: absolute; + margin-top: 5px; +} diff --git a/app/assets/stylesheets/components/_cohorts.scss b/app/assets/stylesheets/components/_cohorts.scss new file mode 100644 index 0000000..5694369 --- /dev/null +++ b/app/assets/stylesheets/components/_cohorts.scss @@ -0,0 +1,957 @@ +.cohorts { + padding: 36px 0; + + .cohortstable { + margin: 20px 0; + } + + .cohortsetuptable .cohorts-list .cohortsetuprow > td, th { + line-height: 1.5rem; + padding: 12px; + vertical-align: middle; + font-weight: normal; + } + + .cohortsetuptable .cohortsetupheader .sortdirection { + position: absolute; + display: inline-flex; + align-items: center; + justify-content: center; + } + + .filters { + margin-bottom: 20px; + } + + a { + font-size: 14px; + margin-top: 7px; + text-decoration: none; + color: $color-sky-blue; + } + + .filterGroup { + margin-bottom: 14px; + } + + .filter-types { + display: -webkit-flex; /* Safari */ + -webkit-flex-wrap: wrap; /* Safari 6.1+ */ + display: flex; + flex-wrap: wrap; + + label { + color: black; + background: linear-gradient(to bottom, #fff 0%, #eceeef 100%); + border-radius: 4px; + margin: 2px 5px 2px 0; + padding: 3px 5px 3px 5px; + border: 1px solid #e6e6e6; + font-size: 12px; + font-family: Arial, sans-serif; + font-weight: lighter; + line-height: 16px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + + i { + padding-right: 5px; + font-size: 10px; + color: black; + cursor: pointer; + font-weight: bold; + } + } + + .new-cohort-btn { + float: right; + + .help-text { + display: none; + } + &.disabled { + a.disabled { + background-color: grey; + border-color: grey; + } + &:hover { + .help-text { + display: block; + font-size: .6rem; + margin-top: 1px; + padding-right: 5px; + } + } + } + } +} + +.cohortinfo { + background-color: $color-black-94-9; + height: 87px; + padding: 0px 36px 0px 36px; + display: flex; + + p { + font-weight: 400; + font-size: 14px; + } + + h6 { + font-weight: bold; + margin-bottom: 4px; + } + + .cohorttitle{ + flex: 1 0 auto; + justify-content: flex-start; + margin-top: 24px; + padding-left: 7px; + } + .cohortdetails{ + display: flex; + justify-content: flex-end; + flex: 0 0 auto; + margin-top: 24px; + } + .cohortdetails > a { + color: $color-cyan; + font-size: 16px; + line-height: 20px; + display: flex; + justify-content: space-between; + } + .cohortdetails > .cohortdetail { + margin-right: 32px; + position: relative; + } +} + +.settingscontainer { + margin: 0px 36px 0px 36px; + + .settingsrow { + display: flex; + border-bottom: 1px solid $color-black-84-7; + } + + .settingsrow > .selectedsettingstab { + flex: 1 0 auto; + justify-content: flex-start; + display: flex; + } + + .settingsrow > .selectedsettingstab > div > p { + font-size: 18px; + line-height: 16px; + font-weight: 500; + padding: 16px 24px 16px 8px; + margin-bottom: 0; + } + .settingsrow > .selectedsettingstab > div > p > a { + text-decoration: none; + color: inherit; + } + + .settingsrow > .selectedsettingstab > .selected { + color: $color-cyan; + border-bottom: 4px solid $color-cyan; + } + + .settingsrow > .managebutton { + flex: 0 0 auto; + align-self: center; + } + + .settingsrow > .managebutton > a { + display: flex; + flex-flow: row nowrap; + justify-content: space-between; + font-weight: 200; + color: white; + } + + .resync-ui { + padding: 1rem 0; + .submit { margin-left: 1rem; } + #resync-url { text-overflow: ellipsis; } + .github-icon { + height: 1.4rem; + position: relative; top: -1px; + } + .non-success-label { padding-right: 0.5rem; } + } + .resync-success-icon { + display: inline-block; + height: 24px; + vertical-align: bottom; + width: 24px; + background: url("data:image/svg+xml;charset=utf-8, %3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20style%3D%22fill%3A%2369A2D7%3B%22%3E%3Cpath%20d%3D%22M19%203H5c-1.11%200-2%20.9-2%202v14c0%201.1.89%202%202%202h14c1.11%200%202-.9%202-2V5c0-1.1-.89-2-2-2zm-9%2014l-5-5%201.41-1.41L10%2014.17l7.59-7.59L19%208l-9%209z%22%2F%3E%3C%2Fsvg%3E"); + } + .successful-resync { + margin-top: 8px; + font-size: 80%; + } + + .import-work { + margin-right: 2rem; + display: flex; + height: 100%; + align-items: center; + + span { + margin: 0 10px; + color: $color-black-60; + } + + svg.success { + color: $color-cyan; + } + + svg.failure { + color: $color-valencia + } + + a { + color: $color-cyan; + text-decoration: none; + } + } +} + +.branch-modal { + position: fixed; + top: 0; + right: 0; + left: 0; + margin: 0 auto; + z-index: 1000000; + box-sizing: border-box; + width: 482px; + height: 202px; + background-color: #FFFFFF; + box-shadow: 0 2px 8px 0 rgba(0,0,0,0.15); + + .modal-header { + padding: 0px; + padding-top: 10px; + padding-left: 24px; + padding-right: 24px; + background-color: #FAFAFA; + } + + .modal-header > h1 { + font-size: 16px; + font-weight: bold; + line-height: 24px; + } + + .modal-header > div > svg { + color: $color-black-60; + cursor: pointer; + } + + .modal-body { + ::-webkit-input-placeholder { /* Chrome/Opera/Safari */ + color: gray; + opacity: .5; + font-weight: italic; + font-style: italic; + padding: 1rem; + border-top: 1px solid #D4D4D4; + } + } + + .modal-body > div > label { + padding-left: 10px; + padding-right: 24px; + } + + .modal-footer { + padding: 6px 0 0 0px; + text-align: right; + width: 100%; + + } + + .modal-footer > .lp-style-button { + margin-right: 22px; + } + + .modal-body > div > label { + font-size: 16px; + font-weight: bold; + line-height: 16px; + } + + .modal-body > div { + margin-top: 8px; + } + + .modal-body > div > span { + margin-left: 67px; + } + + .branch-name { + width: 300px; + height: 32px; + border: 2px solid #D4D4D4; + border-radius: 8px; + background-color: #FFFFFF; + margin-left: 8px; + padding: 8px; + } + +} + +.pick-version-modal .modal-header { + padding: 24px 24px 0 24px; +} + +.settingscontainer > .blocksmodal .modal-header { + padding: 24px 24px 12px 24px; +} + +.pick-version-modal, +.settingscontainer > .blocksmodal, +.cohortinfo > .switch-cohort-mode-modal { + max-width: 1200px; + width: 100%; + position: fixed; + top: 0; + right: 0; + left: 0; + margin: 0 auto; + z-index: 9999999; + box-shadow: 0 2px 8px 0 rgba(0,0,0,0.2); + background-color: $color-black-98-2; + + .actionbar { + left: 0; + bottom: 0; + width: 100%; + height: 80px; + padding: 16px; + background-color: white; + text-align: right; + border-top: 1px solid $color-black-90-2; + } + + .actionbar .lp-style-button { + margin-left: 16px; + } + + .actionbar label { + margin-left: 12px; + } + + .modal-header { + background-color: $color-black-98-2; + flex-wrap: wrap; + } + + .modal-header > h1 { + font-size: 24px; + font-weight: bold; + line-height: 24px; + width: 90%; + } + + .modal-header > .manual-warning { + width: 100%; + padding: 0.5rem 1rem; + margin: 0 0 1rem; + } + + .modal-header > div > svg { + color: $color-black-60; + cursor: pointer; + } + + .loading-spinner { + text-align: center; + padding: 2rem; + } + + .tablewrapper { + overflow-y: auto; + } + + .tablewrapper > .pick-version-table { + width: 100%; + } + + .tablewrapper > .pick-version-table .createdcolumn { + padding-left: 24px; + } + + .tablewrapper > .pick-version-table .checkboxcell { + width: 45px; + } + + .tablewrapper > .pick-version-table > thead { + background-color: #FFFFFF; + border-top: 1px solid $color-black-77; + border-bottom: 1px solid $color-black-77; + height: 40px; + + tr { + font-size: 14px; + line-height: 16px; + text-transform: uppercase; + color: #999999; + } + + tr > th { + font-weight: 500; + padding: 12px; + } + } + + .tablewrapper > .pick-version-table > tbody { + background-color: #FFFFFF; + + .releaserow { + border-bottom: 1px solid #e7e7e7; + + &.current-release { + background-color: rgba(0,165,181,0.05); + } + } + + .releaserow > td { + padding: 16px; + font-size: 16px; + vertical-align: top; + position: relative; + + &.createdcolumn { + padding-left: 24px; + } + } + + .releaserow > td > h5 { + font-weight: bold; + line-height: 16px; + font-size: 16px; + } + + .releaserow > td > p { + line-height: 16px; + margin-bottom: 8px; + } + + .releaserow > td > a.gitlink { + line-height: 16px; + font-weight: 300; + margin-right: 24px; + } + + .releaserow > td > a.gitlink > svg { + width: 16px; + vertical-align: bottom; + margin-left: 0.5rem; + } + + .releaserow > td > span.currentlabel { + line-height: 16px; + color: $color-cyan; + text-transform: uppercase; + font-size: 12px; + font-weight: bold; + letter-spacing: 1px; + text-align: center; + padding: 0 24px; + } + + .releaserow > td .cohorts-tooltip { + z-index: 99999999; + position: absolute; + top: 15%; + right: 80%; + display: flex; + flex-direction: column; + width: 220px; + border-radius: .5rem; + background-color: $color-black-10-2; + color: $color-white; + overflow: hidden; + box-shadow: 0 2px 8px 0 rgba(0,0,0,0.3); + } + + .releaserow > td .cohorts-tooltip > .body > div { + padding: 16px; + } + + .releaserow > td .cohorts-tooltip > .body > div > p { + margin: 0; + } + + .releaserow > td .cohorts-tooltip > .body > div > p > a { + text-decoration: none; + color: white; + } + + .releaserow > td .cohorts-tooltip > .body > div > p > a > svg { + height: 14px; + margin-left: 5px; + position: absolute; + margin-top: 5px; + } + } + + .loadingcontainer { + width: 100%; + height: 15rem; + display: flex; + align-items: center; + justify-content:center; + } + + .loadingcontainer:first-child { + position: relative; + right: 1rem; + } +} + +.course-scoring-info{ + & { + position: absolute; + top: -11px; + left: -38px; + display: flex; + } + + > .svg { + opacity: .6; + margin: .5rem; + cursor: help; + + &:hover + .infomodal { + display: block; + } + } + + > .infomodal { + font-size: 14px; + width: 310px; + margin: .5rem; + padding: 1rem 1.5rem; + border-radius: .5rem; + color: $color-white; + background-color: $color-black-10-2; + box-shadow: 0 2px 8px 0 rgba(0,0,0,0.3); + cursor: help; + display: none; + position: absolute; + top: 0; + right: 0; + z-index: 10; + + &:hover { + display: block; + } + } +} + +.cohortinfo > .switch-cohort-mode-modal { + position: fixed; + top: 0; + right: 0; + left: 0; + margin: 0 auto; + z-index: 1000000; + box-sizing: border-box; + width: 482px; + height: 165px; + background-color: #FFFFFF; + box-shadow: 0 2px 8px 0 rgba(0,0,0,0.15); + + .modal-header { + padding: 0px; + padding-top: 10px; + padding-left: 24px; + padding-right: 24px; + background-color: #FAFAFA; + } + + .modal-header > h1 { + font-size: 16px; + font-weight: bold; + line-height: 24px; + } + + .modal-header > div > svg { + color: $color-black-60; + cursor: pointer; + } + + .modal-body > div > label { + padding-left: 10px; + padding-right: 24px; + } + + .modal-footer { + padding: 6px 0 0 0px; + text-align: right; + width: 100%; + + } + + .modal-footer > .lp-style-button { + margin-right: 22px; + } + + .modal-body > div > label { + font-size: 16px; + font-weight: bold; + line-height: 16px; + } + + .modal-body > div { + margin-top: 8px; + } + + .modal-body > div > span { + margin-left: 67px; + } +} + +.api-documentation { + margin: 2rem auto; + max-width: 800px; +} + +.curriclum-visibility { + + .settingscontainer { + display: flex; + flex-flow: row wrap; + + .settingsrow { + margin-bottom: 2rem; + width: 100%; + } + } + + .visibility { + flex: 0 0 auto; + width: 40%; + margin-right: 1rem; + + .section { + border-bottom: 2px solid $color-black-92-2; + } + + .section-header { + padding: 1rem 0 1rem 2rem; + font-weight: bold; + background: $color-black-94-9; + border-top: 2px solid $color-black-92-2; + } + + .standard { + padding: 1rem 1rem 1rem 1.6rem; + font-weight: 400; + background: white; + border-top: 2px solid $color-black-92-2; + + > .header { + display: flex; + align-items: center; + &.hidden { color: #bfbfbf; } + } + + .chevron { + cursor: pointer; + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + + svg { + color: #ccc; + top: 7px; + position: relative; + margin-right: 0.2rem; + } + } + + .content-file-row { + cursor: pointer; + padding: 0.5rem 0 0.5rem 3rem; + display: flex; + justify-content: space-between; + &.hidden { color: #bfbfbf; } + &.previewed-contentfile { + background: $color-cyan; + color: white; + + svg { + color: white!important; + } + } + } + .content-file-row > p { + font-weight: 400; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 450px; + margin-bottom: 0px; + + &.previewed-contentfile { + background: $color-cyan; + color: white; + + svg { + color: white; + } + } + } + .content-file-row > svg { + position: relative; + cursor: pointer; + } + } + } + + .lesson-preview { + padding: 2rem; + flex: 1 1 auto; + width: 55%; + background: $color-black-88-2; + margin-left: 1rem; + color: #ccc; + + &.has-content { + background: white; + overflow: scroll; + color: #333; + padding: 0; + + div[id^="challenge"] { + height: 200px; + margin-bottom: 2rem; + background: #ccc; + display: flex; + justify-content: center; + align-items: center; + } + } + } + + .lesson-preview h3.placeholder { + margin: 2rem 0; + width: 100%; + text-align: center; + } + + .status-header { + padding: 6px 3rem 0; + display: flex; + background: $color-black-88-2; + color: $color-black-60; + + svg { + color: $color-black-60; + fill: $color-black-60; + } + + .content-file-visibility { + text-transform: uppercase; + } + + .content-file-links { + margin-right: 0; + margin-left: auto; + + .github-icon { + height: 19px; + width: 19px; + position: relative; + top: -9px; + margin-left: 1rem; + } + } + } +} + +.cohortsetuptable { + font-size: 14px; + width: 100%; + + > .cohortsetupheader { + border-bottom: 2px solid $color-black-77; + color: $color-black-60; + text-transform: uppercase; + line-height: 40px; + } + + > .cohortsetupheader > tr > th { + font-weight: 500; + } + + > tbody > .cohortsetuprow > td { + line-height: 48px; + background-color: #FFFFFF; + border-bottom: 1px solid #E7E7E7; + font-size: 16px; + font-weight: 500; + } + + > tbody > .sectiontitleseparator > td { + line-height: 48px; + background-color: $color-black-94-9; + border-bottom: 1px solid #E7E7E7; + font-size: 16px; + font-weight: 600; + padding-left: 16px; + border-top: 2px solid $color-black-77; + } + + td.cohortusername, th.cohortusername { + padding-left: 20px; + } + + > tbody > .cohortsetuprow > td > select { + border: 1px solid #fff; + background-color: transparent; + margin-left: -8px; + } + + .sortcolumn { + padding-left: 24px; + width: 8em; + } + + .sortcolumn > a > svg { + margin-left: -4px; + margin-top: 16px; + cursor: pointer; + } + + > tbody > .cohortsetuprow > td > div > a > .versionlabel { + height: 24px; + background-color: rgba(74,144,226,0.1); + color: $color-sky-blue; + border-radius: 4px; + padding: 4px 10px; + cursor: pointer; + } + + > tbody > .cohortsetuprow > td > div > a > .versionlabel { + > .arrow-svg > svg { + vertical-align: text-bottom; + margin: 0px 8px; + } + } + + > tbody > .cohortsetuprow > td.action-cell { + position: relative; + } + + > tbody > .cohortsetuprow > td.action-cell > div { + display: inline-block; + } + + > tbody > .cohortsetuprow > td.action-cell .action-kebab { + float: right; + color: $color-black-46-7; + + &.active { + color: $color-cyan; + } + + &.disabled { + opacity: 0.25; + + svg { + cursor: not-allowed; + } + } + } + + > tbody > .cohortsetuprow > td.action-cell .user-action { + float: right; + } + > tbody > .cohortsetuprow > td.action-cell .user-action .action-kebab { + padding-top: 7px; + height: 40px; + } + > tbody > .cohortsetuprow > td.action-cell .user-action .action-menu { + margin: 18px 48px 0 0; + } + + > tbody > .cohortsetuprow > td.action-cell > a > svg { + margin: 12px 8px 0 0; + cursor: pointer; + } + + > tbody > .cohortsetuprow > td.updatecolumn > div > svg { + margin-top: 12px; + cursor: pointer; + } + + > tbody > .cohortsetuprow .error-sync { + color: $color-valencia; + } + + > tbody > .cohortsetuprow .error-sync > .errorsyncicon { + cursor:pointer; + } + + > tbody > .cohortsetuprow .error-sync > .errorsyncicon > svg { + vertical-align: middle; + margin-left: 8px; + } + + > tbody > .cohortsetuprow .error-sync > .errors-tooltip { + position: absolute; + display: flex; + flex-direction: column; + width: 400px; + border-radius: 0.5rem; + background-color: #FFFFFF; + color: $color-valencia; + overflow: hidden; + box-shadow: 0 2px 8px 0 rgba(0,0,0,0.3); + padding: 1rem; + margin-top: -8px; + + li { + line-height: 1.5rem; + } + } + + > tbody > .cohortsetuprow .error-sync > a { + //vertical-align: super; + margin-left: 8px; + text-decoration: underline; + color: $color-valencia; + } + + .blockcolumn { + padding-left: 1rem; + } + + > tbody > .cohortsetuprow > td.blockcolumn > svg { + vertical-align: text-bottom; + margin-right: 1rem; + } + + > tbody > .cohortsetuprow > td.blockcolumn > span.managereleases { + font-size: 10px; + background-color: #4e92df; + padding: 1px 8px; + border: none; + border-radius: 12px; + margin-left: 10px; + line-height: 16px; + text-transform: uppercase; + cursor: default; + height: 18px; + } +} diff --git a/app/assets/stylesheets/components/_content-file-show.scss b/app/assets/stylesheets/components/_content-file-show.scss new file mode 100644 index 0000000..29a161e --- /dev/null +++ b/app/assets/stylesheets/components/_content-file-show.scss @@ -0,0 +1,342 @@ + +$sidebar-width: 260px; +$max-content-width: 1280px; +$max-text-content-width: 700px; + +.lesson-layout, #content-file-html { + & { + position: relative; + display: flex; + width: 100%; + height: auto; + min-height: calc(100vh - 104px); + } + + &.-collapsed { + .left-container { + width: 55px; + } + + .content-file-sidebar { + overflow-x: hidden; + width: 55px; + + .toggleaction { + transform: rotate(-90deg); + margin-right: 4px; + } + + .standardtitle, .lessoncel, .blockslink { + display: none; + } + + .standardscore { + margin-left: 0; + } + + .itemrow > svg { + margin-right: 0px; + } + } + } + + .left-container { + position: relative; + flex: 0 0 auto; + width: 0; + background: $color-white; + margin-left: 0; + + @media screen and (min-width: $tablet-breakpoint) { + width: $sidebar-width; + } + } + + .body-container { + flex: 1 1 auto; + display: flex; + flex-flow: column; + justify-content: space-between; + width: 100%; + background: white; + overflow-x: auto; + } + + .body-container .mdown-container { + width: 100%; + margin: 0 auto; + padding: 1rem 50px; + color: $color-tundora; + font-size: 19px; + font-weight: 300; + + @media screen and (min-width: $tablet-breakpoint) { + padding: 2rem 3rem; + } + + pre { + font-size: 14px; + } + + h1 { + @include font-h1; + } + + .checkpoint-info h1 { + margin-bottom: 50px; + margin-top: 30px; + } + + h2 { font-size: 28px; } + h3 { font-size: 22px; } + h4 { font-size: 20px; } + h5 { font-size: 18px; } + h6 { font-size: 18px; } + + h2, h3, h4, h5, h6 { + font-weight: 500; + letter-spacing: -0.3px; + line-height: 1.1; + // margin-bottom: -28px; + } + + h1, h2 { + margin-top: 66px; + } + + h3, h4, h5, h6 { + margin-top: 48px; + } + + h1:first-of-type { + margin-bottom: 60px; + } + + iframe { + display: block; + margin-left: auto; + margin-right: auto; + border: 1px solid #ddd; + margin-top: 42px; + margin-bottom: 6px; + } + + .fluidvids > iframe { + margin-top: 0px; + margin-bottom: 0px; + } + + .fluidvids { + margin-top: 42px; + margin-bottom: 6px; + } + + img { + margin-top: 6px; + margin-bottom: 6px; + } + + pre, table, blockquote, .challenge-block { + margin-top: 42px; + margin-bottom: 6px; + } + + p { + line-height: 1.7; + margin-top: 36px; + margin-bottom: 0px; + } + + blockquote { + font-style: italic; + border-left: 3px solid $color-tundora; + padding-left: 20px; + } + + b, strong { + font-weight: 500; + } + + ul, ol, li { + margin-top: 18px; + margin-bottom: 0px; + } + + h1 + p, h2 + p, h3 + p, h4 + p, h5 + p, h6 + p { + margin-top: 8px; + } + + table, + pre, code, + p, ul, ol, + blockquote, + h1,h2,h3,h4,h5,h6, + .challenge-block, + .checkbox-container, .checkpoint-landing, + .checkpoint-results { + max-width: $max-text-content-width; + margin-left: auto; + margin-right: auto; + } + } + + .body-container .pdf-viewer { + background: $color-black-98-2; + + .react-pdf__Page__canvas { + margin-bottom: 20px; + border: 1px solid #E3E3E3; + } + } + + .body-container .mdown-container img { + max-width: 100%; + } + + .body-container .checkpoint-spacer { + margin-bottom: 72px; + } + + .body-container .content-arrow-container { + display: flex; + flex-direction: column; + border-top: 1px solid $color-black-94-9; + } + + .body-container .content-arrow-container > .content-arrows { + display: flex; + flex-direction: row; + justify-content: space-between; + height: 4rem; + } + + .body-container .content-arrow-container > .content-arrows > .standard-arrow { + flex: 0 1 auto; + max-width: 50%; + padding: 0 1.5rem; + font-weight: 500; + text-decoration: none; + text-transform: uppercase; + + @media screen and (min-width: $tablet-breakpoint) { + padding: 0 3rem; + } + + &.-prev { + margin-right: auto; + } + + &.-next { + margin-left: auto; + } + + &.-prev span { + margin-left: 1rem; + } + + &.-next span { + margin-right: 1rem; + } + } + + .body-container .content-arrow-container > .content-arrows > .standard-arrow > div { + display: flex; + align-items: center; + justify-content: center; + height: 100%; + width: 100%; + color: $color-black-60; + + white-space: nowrap; + } + + .body-container .content-arrow-container > .content-arrows > .standard-arrow > div > span { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + color: $color-cyan; + display: none; + @media screen and (min-width: $tablet-breakpoint) { + display: inline-block; + } + } + + .body-container .content-arrow-container > .content-arrows > .standard-arrow > div > svg { + flex: 0 0 24px; + } + +} + +.react-pdf__Page__canvas { + margin: 0 auto; +} + +.checkpoint-info { + $border-width: 10px; + + .checkpoint-info--header { + background: #666; + color: white; + font-size: 18px; + line-height: 36px; + margin: 0 auto; + max-width: $max-text-content-width; + padding: 2rem 4rem; + + border-top: none; + border-right: none; + border-bottom: none; + border-left: $border-width solid transparent; + + &.-state-complete-all-correct { border-left-color: $color-cyan; } + &.-state-complete-some-incorrect { border-left-color: $color-tangerine-orange; } + + &.-state-incomplete { border-left-color: $color-banana-yellow; } + &.-state-rejected { border-left-color: #E36875; } + &.-state-pending { border-left-color: #AAA; } + + &.-state-score-1 { border-left-color: $color-tangerine-orange; } + &.-state-score-2 { border-left-color: $color-banana-yellow; } + &.-state-score-3 { border-left-color: $color-lime-green; } + + > p:last-child { + margin-bottom: 0; + } + + > ul { + list-style-position: inside; + margin-bottom: 0; + padding-left: 4px; + } + + > .view-results { + background: white; + border-radius: 999px; + border: none; + color: #666666; + display: inline-block; + font-size: 90%; + font-weight: 500; + padding: 6px 35px 4px (35px - $border-width); + text-transform: uppercase; + } + } +} + +ul.task-list { + padding-left: 2em; + + ul { + margin-bottom: 0; + margin-top: 0 + } + + li.task-list-item { + list-style-type: none; + + input.md-task { + margin: 0 0.2em 0.25em -1.2em; + vertical-align: middle; + } + } +} diff --git a/app/assets/stylesheets/components/_content-file-sidebar.scss b/app/assets/stylesheets/components/_content-file-sidebar.scss new file mode 100644 index 0000000..4308332 --- /dev/null +++ b/app/assets/stylesheets/components/_content-file-sidebar.scss @@ -0,0 +1,308 @@ +$sidebar-width: 260px; + +.navigation-move-right { + margin-left: auto; + margin-right: 0; +} + +.content-file-sidebar { + & { + position: fixed; + top: 0; + left: 0; + z-index: 99; + height: 100vh; + width: $sidebar-width; + max-width: calc(100vw - 40px); + transform: translateX(-100%); + transition: transform 200ms ease-out; + flex-shrink: 0; + background: #3D424A; + overflow-x: hidden; + transform: translateX(0); + + &.-is-sticky { + position: fixed; + } + } + + .lesson-layout { + @media screen and (min-width: $tablet-breakpoint) { + transform: translateX(0); + transform: translateX(-100%); + } + } + + .lesson-layout.-is-collapsed & { + transform: translateX(0); + @media screen and (min-width: $tablet-breakpoint) { + transform: translateX(-100%); + } + } + + > .actionsrow { + flex: 0 0 auto; + background: #343940; + padding: 1rem 0.5rem; + display: flex; + flex-flow: row nowrap; + align-items: center; + height: 60px; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); + + .blockslink { + margin-left: 5px; + font-size: 0px; + + svg { + fill: rgba(255, 255, 255, 0.6); + } + } + + .toggleaction { + margin-left: auto; + margin-right: 15px; + transform: rotate(90deg); + cursor: pointer; + + @media screen and (max-width: $tablet-breakpoint) { + display: none; + } + + svg { + fill: rgba(255, 255, 255, 0.6); + } + } + } + + > .standardrow { + flex: 0 0 auto; + background: #343940; + padding: 1rem 1.25rem 1rem 1rem; + display: flex; + flex-flow: row nowrap; + align-items: center; + + &.-status-in-progress.-mode-percentage { + padding-bottom: 0.3rem + } + + > .standardtitle { + font-size: 14px; + font-weight: bold; + color: rgba(255,255,255,0.55); + line-height: 24px; + flex: 1 1 auto; + max-width: 208px; + } + + > .actioncircle { + --actioncircle-size: 24px; + } + > .actioncircle > .svg { + color: $color-cyan; + line-height: 1; + } + > .actioncircle.-awaiting-grade > .svg { + color: #A3A7AE; + line-height: 1; + } + } + + .standardprogressbar { + background: #343940; + padding: 0 1.25rem 1rem 1rem; + > .progressbar { --progressbar-height: 3px } + } + + > .bodyrow { + flex: 1 1 auto; + padding-bottom: 7.25rem; + background: #3D424A; + overflow-y: auto; // Always show scrollbar to avoid alignment issues + scrollbar-width: none; + + &::-webkit-scrollbar { + width: 4px; + } + /* Track */ + &::-webkit-scrollbar-track { + background: $color-medium-blue-gray; + } + /* Handle */ + &::-webkit-scrollbar-thumb { + background: #3D424A; + } + /* Handle on hover */ + &::-webkit-scrollbar-thumb:hover { + background: #3D424A; + } + } + + > .bodyrow > a { + display: block; + color: #3A4551; + text-decoration: none; + } + + > .bodyrow > a.checkpoint svg { + + } + + > .bodyrow > a > .itemrow.-is-active, + > .bodyrow > a:visited > .itemrow.-is-active { + background-color: #3A6371; + + > .iconcel { + color: $color-cyan; + opacity: 1; + } + + > .lessoncel > .lessontitle { + color: rgba(255,255,255,1); + } + } + + .itemrow { + display: flex; + flex-flow: row nowrap; + align-items: center; + height: 60px; + width: 100%; + color: #A3A7AE; + background: #3D424A; + + &:not(.-is-active) { + border-bottom: 1px solid #3b3b3b; + } + } + + .itemrow > .iconcel { + visibility: hidden; + flex: 0 0 auto; + height: 18px; + width: 0; + margin-left: 16px; + margin-right: 0; + opacity: 0.5; + color: $color-black; + } + + .itemrow > .iconcel .svg { + height: 18px; + width: 18px; + color: rgba(255,255,255,0.9); + } + + .itemrow > .lessoncel { + flex: 1 1 auto; + margin-right: 16px; + overflow: hidden; + white-space: nowrap; + } + + .itemrow > .lessoncel > .lessontitle { + color: rgba(255,255,255,0.6); + text-overflow: ellipsis; + overflow: hidden; + font-size: 16px; + line-height: 16px; + } + + .itemrow > svg, .itemrow img { + margin-right: 16px; + flex-shrink: 0; + } + + .itemrow .cant-complete-icon { + position: relative; + + .infomodal { + font-size: 14px; + max-width: 360px; + margin: .5rem; + padding: .5rem 1rem; + border-radius: .5rem; + color: $color-white; + background-color: $color-black-10-2; + box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.3); + cursor: help; + display: none; + position: absolute; + top: -13px; + right: 100%; + z-index: 10; + width: 174px; + } + + &:hover { + .infomodal { + display: block; + } + } + } + + .sidebar-checkpoint-percentage { + margin: 0; + font-weight: 500; + padding-right: 5%; + color: white; + } + + .checkpoint-complete-sidebar-title { + height: 60px; + display: flex; + justify-content: space-between; + align-items: center; + color: rgba(255, 255, 255, 0.6); + font-weight: 500; + padding-left: 16px; + padding-right: 16px; + background-color: #343940; + + p { + margin-bottom: 0; + } + } +} + + +.showhidecircle { + position: fixed; + z-index: 999999; + bottom: 3.5rem; + left: 0; + transform: translateX(-.5rem); + height: 3rem; + width: 3rem; + background: $color-white; + border-radius: 100%; + box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.5); + user-select: none; + cursor: pointer; + + @media screen and (min-width: $tablet-breakpoint) { + height: 2.5rem; + width: 2.5rem; + position: absolute; + top: 1.5rem; + bottom: auto; + transform: translateX( calc(280px - 50%) ); + + .-is-sticky + & { + position: fixed; + transform: translateX(calc(280px - 50%)); + } + .-is-collapsed & { + transform: translateX( 1rem ); + } + } + + > div { + display: flex; + justify-content: center; + align-items: center; + height: inherit; + width: inherit; + } +} diff --git a/app/assets/stylesheets/components/_curriculum-checkpoint-summary.scss b/app/assets/stylesheets/components/_curriculum-checkpoint-summary.scss new file mode 100644 index 0000000..aab88a1 --- /dev/null +++ b/app/assets/stylesheets/components/_curriculum-checkpoint-summary.scss @@ -0,0 +1,46 @@ +.checkpoint-summary-wrapper { + display: flex; + flex-flow: column; + align-items: center; + justify-content: space-between; + margin-right: 1.5rem; + height: 100%; +} + +.checkpoint-summary { + display: flex; + flex-flow: row nowrap; + align-items: center; + line-height: 1rem; + + .avg { + color: $color-cyan; + font-size: 2.75rem; + position: relative; + line-height: 32px; + } + + .indicators { + display: flex; + flex-flow: column nowrap; + margin-left: 1rem; + height: 41px; + + .indicator { + width: 25px; + height: 5px; + margin-top: 3px; + border-radius: 8px; + flex: 0 0 auto; + background-color: $color-black-84-7; + + &:first-of-type { + margin-top: 0px; + } + + &.fill { + background-color: $color-cyan; + } + } + } +} diff --git a/app/assets/stylesheets/components/_curriculum-progress.scss b/app/assets/stylesheets/components/_curriculum-progress.scss new file mode 100644 index 0000000..6bf94b5 --- /dev/null +++ b/app/assets/stylesheets/components/_curriculum-progress.scss @@ -0,0 +1,239 @@ +.curriculumprogress { + & { + display: flex; + flex-flow: column; + align-items: center; + justify-content: space-between; + margin: 64px auto 0px auto; + height: auto; + + @media screen and (min-width: $tablet-breakpoint) { + flex-flow: row nowrap; + padding: 0 4rem; + height: 48px; + } + } + + .progress-indicators { + display: flex; + flex-flow: row nowrap; + align-items: center; + justify-content: space-between; + } + + .curriculumprogressheader { + line-height: 2.5rem; + font-size: 40px; + font-weight: 300; + margin-bottom: 1rem; + letter-spacing: -1px; + + @media screen and (min-width: $tablet-breakpoint) { + font-size: 40px; + margin-bottom: 0; + } + } + + .masterywrapper { + display: flex; + flex-flow: row nowrap; + align-items: center; + + &.-percentage { + flex-flow: column nowrap; + justify-content: space-between; + height: 100%; + + .progressdonut { + width: auto; + height: auto; + } + } + } + + .masterywrapper .masteryaverage { + flex: 0 0 auto; + text-align: center; + } + + .masterywrapper .masteryaverage .masteryaveragevalue { + height: 24px; + color: $black; + font-size: 24px; + font-weight: 500; + line-height: 24px; + } + + .masterywrapper .masteryaverage .masteryaveragelabel { + height: 24px; + color: $color-black-50-2; + font-size: 16px; + font-weight: 500; + } + + .masterywrapper .progressdonut { + position: relative; + flex: 0 0 auto; + height: 96px; + width: 96px; + } + + .masterywrapper .progressdonut.-percentage { + display: flex; + flex-flow: row nowrap; + align-items: center; + justify-content: space-between; + + .donut { + width: 60px; + } + + .donutscore { + position: relative; + color: $color-cyan; + font-size: 2.75rem; + } + } + + .masterywrapper .progressdonut .donutscore { + position: absolute; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + color: $color-lime-green; + font-size: 32px; + line-height: 32px; + + &.-percentage { + color: $color-cyan; + } + } + + .masterywrapper .progressdonut .donutscore .percent { + font-size: 18px; + font-weight: bold; + line-height: 16px; + margin-top: -8px; + } + + .masterywrapper .progressdonut .donut { + width: 100%; + height: 100%; + transform: rotate(90deg); + } + + .masterywrapper .progressdonut .donut .donutring { + stroke: $color-black-84-7; + } + + .masterywrapper .progressdonut .donut .donutsegment { + stroke-linecap: round; + &.-score-3 { + stroke: $color-lime-green; + } + + &.-score-2 { + stroke: $color-banana-yellow; + } + + &.-score-1 { + stroke: $color-tangerine-orange; + } + + &.-completed { + stroke: $color-cyan; + } + + &.-pending { + stroke: $color-black-50-2; + } + } + + .masterywrapper .progresspercentages { + flex: 0 0 auto; + flex-flow: row nowrap; + } + + .masterywrapper .progresspercentages .progresspercentage { + display: flex; + flex-flow: row nowrap; + align-items: center; + flex: 0 0 auto; + } + + .masterywrapper .progresspercentages .progresspercentage .standardbean { + margin-right: 0.75rem; + } + + .masterywrapper .progresspercentages .progresspercentage { + height: 16px; + color: $color-black-20; + font-size: 16px; + font-weight: 500; + line-height: 16px; + margin-bottom: 8px; + } + .masterywrapper .progresspercentages .progresspercentage.percentunscored { + margin-bottom: 0; + } + + .progress-indicators { + position: relative; + height: 60px; + + .infomodal { + font-size: 14px; + padding: .5rem 1rem; + border-radius: .5rem; + color: $color-white; + background-color: $color-black-10-2; + box-shadow: 0 2px 8px 0 rgba(0,0,0,0.3); + cursor: help; + display: none; + position: absolute; + margin-top: -5px; + margin-right: 1rem; + right: 100%; + z-index: 10; + width: 360px; + } + + &:hover { + .infomodal { + display: block; + } + } + } +} + +.curriculum-last-viewed { + width: 100%; + display: flex; + flex-flow: row; + align-items: center; + justify-content: space-between; + padding: 0 4rem; + margin-top: 12px; + + .last-viewed-content { + font-weight: 400; + color: $color-dove-gray; + font-size: 16px; + + a { + color: $color-primary-teal; + } + } +} + +.curriculum-subset-notice.flash-message { + display: block; + position: fixed; top: 0; right: 0; left: 0; + text-align: center; + z-index: $z-primary-navigation + 1; +} +body.-with-curriculum-subset-notice { + padding-top: 50px; +} diff --git a/app/assets/stylesheets/components/_curriculum.scss b/app/assets/stylesheets/components/_curriculum.scss new file mode 100644 index 0000000..b43e20b --- /dev/null +++ b/app/assets/stylesheets/components/_curriculum.scss @@ -0,0 +1,277 @@ +.cohort-curriculum { + > .no-curriculum { + padding: 2.5rem; + } + + > .block-container { + padding: 0; + border-bottom: 6px solid #EAEAEA; + + &:last-of-type { + border-bottom: 0px solid transparent; + } + @media screen and (min-width: 800px) { + padding: 0 2.5rem 0; + } + + &.block-hidden { + .block-info { + margin-bottom: 20px; + } + + .standards-container { + display: none; + } + } + } + + > .block-container > .standards-container { + display: flex; + flex-flow: row wrap; + padding: 16px; + margin-bottom: 26px; + } +} + +.slideshow { + display: flex; + justify-content: center; + padding-top: 25px; +} + +.standardsprogress { + display: flex; + flex-flow: row nowrap; + align-items: center; + margin: 0 0 0 12px; +} + +.standardsprogress > .standardscount { + margin-left: 8px; + + opacity: 0.5; + color: #000000; + + font-size: 14px; + font-weight: 500; + line-height: 16px; + + margin-bottom: -2px; +} + +.block-info { + & { + display: flex; + flex-flow: column; + justify-content: center; + margin: 80px 24px 20px; + } + + > .blocktitle { + line-height: 24px; + font-weight: 500; + font-size: 24px; + display: flex; + align-items: center; + + > span { + margin-left: -5px; + margin-right: 12px; + } + } + + > .blocktitle .svg { + position: relative; + top: 2px; + color: #757575; + cursor: pointer; + } +} + +.non-sidebar-standard-complete { + position: relative; + margin-left: 220px; + margin-bottom: 256px; + + .standard-complete { + width: 21px; + } +} + +.standard-card, a.standard-card{ + .checkpoint-data { + position: absolute; + display: flex; + margin-top: 7.5%; + + .donut { + height: 20px; + width: 20px; + margin-top: 2px; + } + + .checkpoint-complete { + margin-top: 2px; + height: 20px; + } + + .grade-percent { + color: $color-cyan; + font-weight: 600; + padding-left: 5px; + } + } + + & { + position: relative; + display: flex; + flex-flow: column; + flex: 1 1 100%; + height: 180px; + max-width: 274px; + min-width: 274px; + margin: 1rem 0.5rem; + background-color: $color-white; + box-shadow: 0 1px 10px 0 rgba(0,0,0,0.06); + border: 1px solid #E3E3E3; + text-decoration: none; + color: inherit; + border-radius: 4px; + } + + &.-placeholder { + h5, p { + background-color: #333333; + border-radius: 3px; + opacity: 0.1; + } + h5 { width: 50%; } + .action p { + background-color: transparent; + opacity: 1; + } + } + + @media screen and (min-width: 800px) { + flex: 0 0 calc((100% / 4) - 1rem); + max-width: 288px; + } + + &.-completed-standard { + background-color: #f4f4f4; + border: 1px solid #E3E3E3; + box-shadow: none; + + h5, p { + color: #808080; + } + } + + &:hover { + &.-score-3 { + box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.2), 0 0 0 1px $color-lime-green; + } + + &.-score-2 { + box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.2), 0 0 0 1px $color-banana-yellow; + } + + &.-score-1 { + box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.2), 0 0 0 1px $color-tangerine-orange; + } + } + + &.-score-3 > .action .percentage-badge-container > .percentage-badge.actioncircle { + background-color: $color-lime-green; + } + + &.-score-2 > .action .percentage-badge-container > .percentage-badge.actioncircle { + background-color: $color-banana-yellow; + } + + &.-score-1 > .action .percentage-badge-container > .percentage-badge.actioncircle { + background-color: $color-tangerine-orange; + } + + > h5 { + font-size: 18px; + font-weight: 500; + line-height: 26px; + margin: 24px 24px 4px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + color: $color-black-20; + } + + > p { + font-size: 14px; + line-height: 19px; + margin: 0px 24px 32px; + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + color: $color-black-20; + } + + > .action { + font-size: 12px; + font-weight: 600; + line-height: 16px; + height: 40px; + padding: 0 24px; + display: flex; + position: relative; + flex-flow: row nowrap; + align-items: center; + margin-top: auto; + + &.-is-visited { + color: $color-black-20; + } + + .actioncircle { + position: absolute; right: 16px; bottom: 22px; + } + + p { + font-size: 12px; + font-weight: 400; + color: $color-black-50-2; + text-align: right; + margin-top: 4px; + } + + .percentage-badge-container { + p.pending-score { + margin-left: 45px; + text-align: left; + margin-top: -20px; + } + + .percentage-badge.actioncircle { + right: auto; + left: 19px; + background-color: $color-cyan; + + &.-awaiting-grade { + background-color: transparent; + color: $color-black-50-2; + } + } + } + + .full-width { + width: 100%; + } + } + + > span svg { + height: 16px; + width: 16px; + display: inline-block; + margin-right: 6px; + } + +} diff --git a/app/assets/stylesheets/components/_dropdown-component.scss b/app/assets/stylesheets/components/_dropdown-component.scss new file mode 100644 index 0000000..863abf5 --- /dev/null +++ b/app/assets/stylesheets/components/_dropdown-component.scss @@ -0,0 +1,79 @@ +%dropdown-select { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + height: 100%; + min-width: 100%; + margin: 0; + padding: 0 40px 0 16px; + border: 0; + font-size: inherit; + color: inherit; + cursor: inherit; + display: flex; + flex-flow: row; + align-items: center; +} + +.dropdown-component { + & { + display: inline-block; + position: relative; + height: 48px; + border: 1px solid $color-black-92-2; + border-radius: 4px; + background-color: $color-white; + box-shadow: 0 1px 2px 0 rgba(155, 155, 155, 0.2); + color: rgba($color-darkest-blue-gray, 0.8); + cursor: pointer; + user-select: none; + width: auto; + min-width: 200px; + max-width: 400px; + margin-bottom: 32px; + font-size: 18px; + margin-right: 1rem; + } + + &:hover { + color: $color-darkest-blue-gray; + + > .svg { + fill: $color-cyan; + } + } + + > select { + @extend %dropdown-select; + } + + > .svg { + pointer-events: none; + position: absolute; + top: 0; + bottom: 0; + left: auto; + right: 8px; + margin: auto; + fill: $color-black-83-1; + } +} + +.faux-dropdown { + @extend .dropdown-component; + background-color: white; + + > .fauxselect { + @extend %dropdown-select; + } + + &.-is-pressed { + color: $color-dark-blue-gray; + background: $color-black-94-9; + box-shadow: none; + } + + &:hover > .svg { + fill: $color-black-83-1; + } +} diff --git a/app/assets/stylesheets/components/_external-link.scss b/app/assets/stylesheets/components/_external-link.scss new file mode 100644 index 0000000..cc24d52 --- /dev/null +++ b/app/assets/stylesheets/components/_external-link.scss @@ -0,0 +1,13 @@ +a[target="_blank"].external-link { + > svg.svg { + display: inline; + height: 12px; + width: 12px; + margin-left: 4px; + vertical-align: middle; + } + + &.view-in-github { + font-size: 11px; + } +} diff --git a/app/assets/stylesheets/components/_flash-message.scss b/app/assets/stylesheets/components/_flash-message.scss new file mode 100644 index 0000000..b63f831 --- /dev/null +++ b/app/assets/stylesheets/components/_flash-message.scss @@ -0,0 +1,21 @@ +.flash-message { + color: rgba(0, 0, 0, 0.6); + display: flex; + justify-content: space-between; + margin: 0; + border-radius: 0; + line-height: 24px; + font-size: 16px; + font-weight: 400; + strong { + font-weight: 500; + } + + .flash-closebtn { + height: 24px; + } + .flash-closebtn > svg { + color: rgb(153, 153, 153); + cursor: pointer; + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/components/_footer.scss b/app/assets/stylesheets/components/_footer.scss new file mode 100644 index 0000000..6ca2484 --- /dev/null +++ b/app/assets/stylesheets/components/_footer.scss @@ -0,0 +1,66 @@ +body > footer { + & { + display: flex; + flex-flow: column-reverse; + width: 100%; + min-height: 3.5rem; + padding: 0.5rem 2rem; + border-top: 1px solid $color-black-90-2; + font-size: 12px; + text-align: center; + + @media screen and (min-width: $tablet-breakpoint) { + flex-direction: row; + align-items: center; + padding: 0 2rem; + } + } + + > ul { + list-style: none; + padding: 0; + margin: 0 0 0 auto; + text-transform: uppercase; + + @media screen and (min-width: $tablet-breakpoint) { + display: flex; + flex-flow: row nowrap; + } + } + + > ul > li:not(:last-child) { + @media screen and (min-width: $tablet-breakpoint) { + margin-right: 1rem; + } + } + + > ul > li > a { + font-weight: 400; + line-height: 1.5rem; + color: $color-cyan; + text-decoration: none; + + &:hover { + color: $color-navy-blue; + } + } + + > span { + font-weight: 400; + line-height: 1.5rem; + } + + > .logo { + background: none left center no-repeat; + background-image: image-url("svg/mobile-logo.svg"); + background-size: contain; + height: 34px; + margin: 0 1rem 0 0; + min-width: 40px; + @media screen and (min-width: $tablet-breakpoint) { + background-image: image-url("svg/g-learn-lockup.svg"); + margin: 0 1.5rem 0 0; + min-width: 150px; + } + } +} diff --git a/app/assets/stylesheets/components/_grade-buttons.scss b/app/assets/stylesheets/components/_grade-buttons.scss new file mode 100644 index 0000000..12c3318 --- /dev/null +++ b/app/assets/stylesheets/components/_grade-buttons.scss @@ -0,0 +1,12 @@ +.grade-buttons { + & { + right: 0; + position: absolute; + margin-right: 32px; + } + + form { + display: inline-block; + margin-left: 8px; + } +} diff --git a/app/assets/stylesheets/components/_integer_picker.scss b/app/assets/stylesheets/components/_integer_picker.scss new file mode 100644 index 0000000..6af8843 --- /dev/null +++ b/app/assets/stylesheets/components/_integer_picker.scss @@ -0,0 +1,57 @@ +.integer-container { + display: flex; + border-radius: 25px; + border: 2px solid $color-black-93-3; + background-color: $color-white; + height: 45px; + justify-content: center; + align-items: center; + padding: 0 16px 0 16px; + + &.vertical { + flex-direction: column; + height: auto; + position: absolute; + top: 33px; + right: 23px; + border-radius: 10px; + z-index: 1; + width: 70px; + padding: 0; + box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.1); + + .integer { + padding: 5px 0 5px 0; + width: 100%; + } + + .integer:first-child { + border-radius: 8px 8px 0 0; + } + + .integer:last-child { + border-radius: 0 0 8px 8px; + } + + .integer:not(:last-child) { + border-bottom: 1px solid $color-black-93-3; + } + } + + .integer { + color: $color-black-60-8; + text-align: center; + width: 25px; + font-size: 1.2rem; + font-weight: 500; + cursor: pointer; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + + &:hover { + background-color: $color-cyan-very-light; + } + } +} diff --git a/app/assets/stylesheets/components/_lp-style-button.scss b/app/assets/stylesheets/components/_lp-style-button.scss new file mode 100644 index 0000000..ae02900 --- /dev/null +++ b/app/assets/stylesheets/components/_lp-style-button.scss @@ -0,0 +1,127 @@ +%submit-button { + $color-em: 8; + $color-height: ($color-em * 5 + px); + + & { + display: inline-block; + height: $color-height; + width: auto; + min-width: 120px; + padding: 0 ($color-em * 3 + px); + border: none; + border-radius: 100px; + background-color: $color-cyan; + cursor: pointer; + line-height: $color-height; + color: white; + font-size: ($color-em * 1.5 + px); + font-weight: bold; + letter-spacing: 1px; + text-align: center; + text-transform: uppercase; + vertical-align: middle; + + } + + &:focus { + outline: 0; + } + + &:hover { + color: white; + text-decoration: none; + } + + &.-cancel { + background: none; + border: 1px solid rgba(220, 53, 73, 1); + color: rgba(220, 53, 73, 1); + } + + &.-cancel:hover { + background: rgba(220, 53, 73, 1); + border: 1px solid rgba(220, 53, 73, 1); + color: white; + } + + &.-disabled { + opacity: 0.3; + cursor: not-allowed; + } + + &.-outline { + background: none; + border: 1px solid $color-cyan; + color: $color-cyan; + } + + &.-outline:hover { + background: $color-cyan; + border: 1px solid $color-cyan; + color: white; + } + + &.-reject { + background: $color-valencia; + border: 1px solid $color-valencia; + color: $color-white; + } + + &.-white { + background: $color-white; + color: $color-cyan; + + &:hover { + background-color: rgba(255, 255, 255, 0.7); + } + } + + &.-white-grey-border { + background: $color-white; + color: $color-cyan; + font-weight: bold; + border: 1px solid $color-black-90-2; + height: auto; + padding: 2px 18px; + min-width: 80px; + line-height: 24px; + } + + &.-white-alt { + background: $color-white; + color: $color-darkest-blue-gray; + } + + &.-white-outline { + background: none; + border: 1px solid white; + color: white; + } + + &.-red-outline { + background: none; + border: 1px solid red; + color: red; + } + + &.-nowrap { + white-space: nowrap; + } + + &.-small { + font-weight: 200; + height: auto; + padding: 2px; + min-width: 80px; + line-height: 24px; + color: white; + } + + &.max-attempts { + line-height: 1; + } +} + +.lp-style-button { + @extend %submit-button; +} diff --git a/app/assets/stylesheets/components/_mastery-table.scss b/app/assets/stylesheets/components/_mastery-table.scss new file mode 100644 index 0000000..d90fcde --- /dev/null +++ b/app/assets/stylesheets/components/_mastery-table.scss @@ -0,0 +1,382 @@ +.masterytable { + overflow-x: scroll; +} + +.table-performance-grid { + & { + width: 100%; + margin: 0 auto; + background: $color-white; + margin-top: 50px; + } + + th.student-label { + width: 30px; + + &:last-child { + padding-right: 15px; + } + } + + th.vertical-text { + height: 100px; + white-space: nowrap; + font-weight: normal; + } + + th.vertical-text > div { + width: 30px; + transform: translate(19px, 35px) rotate(315deg); + } + + th.vertical-text > div > span { + border-bottom: 1px solid $color-black-80; + } + + th.vertical-text > div > span.selected { + font-weight: bold; + background: yellow; + } + + .tr-summary { + background: $color-light-gray-blue; + } + + .tr-standard > th { + font-weight: normal; + } + + tbody th { + padding: 0 3px; + } + + tbody th, + tbody td { + border: 1px solid $color-black-80; + } + + tbody td.score { + text-align: center; + } + + tbody td.score-0 { + background: white; + } + + tbody td.score-1 { + background: $color-soft-red; + } + + tbody td.score-2 { + background: $color-soft-orange; + } + + tbody td.score-3 { + background: $color-sage; + } + + tbody td.selected { + box-shadow: 0 0 0 2px black inset; + font-weight: bold; + } + + .clear-filters { + position: relative; + } + + .standard-legend { + position: absolute; + bottom: 3rem; + border: 1px solid $color-gray-light; + color: gray; + border-radius: 0.25rem; + padding: 0.5rem 2rem; + margin-right: 0.5rem; + margin-top: 0.5rem; + + &.elective { + left: 80px; + background-color: $color-pale-yellow; + } + } +} + +// print overwrites? +@media print { + table.table-performance-grid { + td { + &.score-selected { + box-shadow: 0 0 0 2px black inset; + } + + &.score-1, + &.score-2, + &.score-3 { + color: $color-black-80 !important; + } + + &.score-0 { + color: white !important; + } + } + } +} + +// used in: +// app/views/instructor/performances/index.html.haml +// app/views/instructor/performances/active_performances.html.haml +.workbook-performance-table { + .student-header { + position: absolute; + width: 100%; + left: 0; + height: 200px; + background: -moz-linear-gradient(top, rgba(0, 0, 0, 0.65) 0%, rgba(0, 0, 0, 0) 100%); + background: -webkit-linear-gradient(top, rgba(0, 0, 0, 0.65) 0%, rgba(0, 0, 0, 0) 100%); + background: linear-gradient(to bottom, rgba(0, 0, 0, 0.65) 0%, rgba(0, 0, 0, 0) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#a6000000", endColorstr="#00000000", GradientType=0); + } + + .student-selected-view { + &.card { + background: rgb(125, 125, 125); + vertical-align: top; + overflow: hidden; + position: fixed; + height: 120px; + width: 300px; + z-index: 2; + + .prop { + text-shadow: 1px 1px 0.5px rgba(65, 65, 65, 0.3); + padding-left: 15px; + display: block; + width: 175px; + float: left; + color: $color-white; + + &.avatar { + height: 119px; + width: 123px; + object-position: center; + object-fit: cover; + } + + &.first-name { + margin: 15px 0 0; + font-weight: 600; + font-size: 20px; + } + + &.last-name { + margin: 2px 0 0; + font-weight: 100; + font-size: 16px; + } + + &.student-performance-gauge { + margin: 20px 0 0; + font-size: 15px; + color: white; + bottom: 10px; + } + } + } + } + + .student-map-wrapper { + background: rgb(255, 255, 255); + position: fixed; + overflow: auto; + height: 120px; + right: 15px; + left: 315px; + z-index: 1; + + .card { + font-size: 0; + padding: 0; + margin: 0; + + li { + box-shadow: inset 0 0 1px rgba(119, 119, 119, 0.75); + transition: ease-in 0.33s; + display: inline-block; + background: white; + width: 20%; + margin: 0; + + .prop { + width: calc(100% - 45px); + padding-left: 5px; + float: left; + + &.avatar { + padding-left: 0; + height: 40px; + width: 40px; + object-position: center; + object-fit: cover; + } + + &.first-name { + padding-top: 4px; + font-size: 16px; + font-weight: 300; + } + + &.last-name { + font-size: 11px; + font-weight: 600; + } + } + + &.active { + box-shadow: inset 0 0 1px $black; + background: $color-galvanize-orange; + } + } + } + } + + .performance-spinner { + position: relative; + text-align: center; + margin: 33% auto; + width: 100%; + } + + .table-performance-grid { + position: relative; + width: 100%; + top: 135px; + + .clear-filters { + vertical-align: bottom; + } + + th.current-name { + vertical-align: bottom; + padding-bottom: 1em; + } + + th.vertical-text { + height: 180px; + white-space: nowrap; + font-weight: normal; + } + + th.vertical-text > div { + transform: translate(19px, 75px) rotate(315deg); + width: 30px; + // hide + display: none; + } + + th.vertical-text > div > span { + border-bottom: 1px solid $color-black-80; + } + + .selected { + background: yellow; + font-weight: bold; + } + + tbody { + tr.tr-summary { + th, + td { + background: $color-black-80; + padding: 10px 0; + + a { + color: $color-black-20; + font-size: 15px; + } + } + } + + th { + padding: 0 3px; + } + + th, + td { + border: 1px solid $color-black-80; + } + + td { + text-align: center; + padding: 8px; + + &.score-0 { + background: white; + } + + &.score-1 { + background: $color-soft-red; + } + + &.score-2 { + background: $color-soft-orange; + } + + &.score-3 { + background: $color-sage; + } + + &.selected { + box-shadow: 0 0 0 2px black inset; + font-weight: bold; + border-bottom: 1px; + border-right: 1px; + } + } + + .tr-success-criterion > th { + font-weight: normal; + max-width: 300px; + background: white; + } + } + } + + table.table { + tr.tr-summary, + tr.tr-standard { + th, + td { + background: $color-light-gray-blue; + } + } + + td { + &.score-selected { + box-shadow: 0 0 0 2px black inset; + } + + &.score-0 { + text-align: center; + vertical-align: middle; + } + + &.score-1 { + background: $color-soft-red; + text-align: center; + vertical-align: middle; + } + + &.score-2 { + background: $color-soft-orange; + text-align: center; + vertical-align: middle; + } + + &.score-3 { + background: $color-sage; + text-align: center; + vertical-align: middle; + } + } + } +} diff --git a/app/assets/stylesheets/components/_modal.scss b/app/assets/stylesheets/components/_modal.scss new file mode 100644 index 0000000..56d47f4 --- /dev/null +++ b/app/assets/stylesheets/components/_modal.scss @@ -0,0 +1,195 @@ +.modal-container { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0,0,0,0.6); + z-index: 1000000; +} + +.modal { + position: fixed; + top: 0; + left: 0; +} + +.modal-main, .mdown-container .modal-container .modal-main { + color: $color-darker-gray-blue; + position: relative; + background: white; + height: auto; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 730px; + border-radius: 5px; + box-shadow: 0 2px 20px 0 rgba(0,0,0,0.07); + overflow: hidden; + + .close-button-wrapper { + display: flex; + justify-content: flex-end; + width: 100%; + padding-top: 5px; + padding-right: 5px; + + svg { + fill: lightgrey; + cursor: pointer; + width: 100%; + height: 100%; + } + + .close-button { + height: 40px; + width: 40px; + + &:hover { + svg { + fill: #AFADAD; + } + } + } + } + + .modal-contents { + padding: 40px 35px 15px; + max-height: 450px; + overflow-y: auto; + + // h1, h3, h4 { + // @include font-h1-settings; + // font-size: 28px; + // font-weight: 400; + // margin-bottom: 25px; + // color: $color-emperor; + // margin-top: 0; + // } + + h4, h1, h3 { + @include font-h1-settings; + display: flex; + font-size: 28px; + font-weight: 400; + margin-bottom: 25px; + color: $color-emperor; + margin-top: 0; + + img { + margin-right: 10px; + } + } + + p, div { + @include font-paragraph; + } + + label { + @include font-paragraph; + margin: 0; + color: $color-silver-chalice; + } + + input[type="checkbox"] { + box-sizing: border-box; + padding: 0; + display: inline-block; + vertical-align: middle; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + cursor: pointer; + height: 24px; + width: 24px; + background: none center no-repeat; + background-size: cover; + margin: 8px; + flex: 0 0 auto; + } + + input[type="checkbox"] { + background-image: url("data:image/svg+xml;charset=utf-8, %3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20style%3D%22fill%3A%23cccccc%3B%22%3E%3Cpath%20d%3D%22M19%205v14H5V5h14m0-2H5c-1.1%200-2%20.9-2%202v14c0%201.1.9%202%202%202h14c1.1%200%202-.9%202-2V5c0-1.1-.9-2-2-2z%22%2F%3E%3C%2Fsvg%3E"); + } + + input[type="checkbox"]:checked { + border-color: $color-cyan; + background: rgba($color-cyan, 0.05); + background-image: url("data:image/svg+xml;charset=utf-8, %3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20style%3D%22fill%3A%234DA9B3%3B%22%3E%3Cpath%20d%3D%22M19%203H5c-1.11%200-2%20.9-2%202v14c0%201.1.89%202%202%202h14c1.11%200%202-.9%202-2V5c0-1.1-.89-2-2-2zm-9%2014l-5-5%201.41-1.41L10%2014.17l7.59-7.59L19%208l-9%209z%22%2F%3E%3C%2Fsvg%3E"); + } + + input[type="text"] { + @include modal-text-input; + } + + textarea { + resize: none; + @extend input[type="text"]; + padding: 8px 16px; + + &.modal__input--large { + height: 180px; + } + } + + .modal__input-wrapper { + margin-bottom: 30px; + } + + .modal__input--error, .new-block__input--error { + border: 1px solid $color-red !important; + } + + .modal__input--error-msg { + color: $color-red; + } + } + + .modal-help-text { + margin-right: 22px; + } + + .modal-actions { + padding: 0 22px 0 0; + border-top: 1px solid #E0E0E0; + width: 100%; + height: 90px; + background-color: #FCFCFC; + display: flex; + align-items: center; + justify-content: flex-end; + } + + .helper-text { + display: flex; + height: 100%; + } + + .helper-text > svg { + margin-right: 10px; + } + + .helper-text > p { + margin: 0 0 2px 0; + } + + // removed this temporarily because it was overriding button hover styles. Leaving it short-term in case it turns out it was needed for something else + // .modal-action { + // &:hover { + // background-color: #F5F3F3; + // } + + // h3 { + // text-transform: uppercase; + // margin-bottom: 0; + // } + // } +} + +.display-block { + display: block; +} + +.display-none { + display: none; +} \ No newline at end of file diff --git a/app/assets/stylesheets/components/_navigation-dropdown.scss b/app/assets/stylesheets/components/_navigation-dropdown.scss new file mode 100644 index 0000000..a0ddcee --- /dev/null +++ b/app/assets/stylesheets/components/_navigation-dropdown.scss @@ -0,0 +1,103 @@ +.navigation-dropdown { + & { + position: relative; + display: flex; + flex-flow: row; + align-items: center; + height: inherit; + user-select: none; + cursor: pointer; + } + + .cohort-label { + max-width: 320px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + &:hover { + background-color: $color-black-97-3; + box-shadow: 0 2px 4px 0 rgba(0,0,0,0.1); + } + + &:hover > .list { + display: block; + } + + &:hover > .label > .sprite-icon { + color: $color-black; + } + + > .label { + display: flex; + flex-flow: row nowrap; + flex: 1 0 auto; + align-items: center; + padding: 0 1rem; + } + + > .label > .user-avatar { + margin-right: 0.5rem; + } + + > .label > .sprite-icon { + color: $color-black-83-1; + margin: 0 0 0 auto; + } + + > .list { + display: none; + position: fixed; + left: 0; + right: 0; + top: 3.5rem; + z-index: 100; + min-width: 100%; + margin: 0; + padding: 0; + background-color: $color-black-97-3; + box-shadow: 0 2px 4px 0 rgba(0,0,0,0.1); + list-style: none; + + @media screen and (min-width: $tablet-breakpoint) { + position: absolute; + top: 100%; + left: auto; + } + } + + > .list > .item { + color: inherit; + border: 0 solid rgba(0,0,0,0.1); + + &:not(:first-child) { + border-top-width: 1px; + } + + &:hover { + background-color: $color-white; + color: $color-black; + } + } + + > .list > .item > a { + color: $color-black-60; + display: block; + line-height: 2.5rem; + padding: 0 1rem; + text-decoration: none; + text-transform: uppercase; + white-space: nowrap; + max-width: 400px; + overflow: hidden; + text-overflow: ellipsis; + } + + .account-email { + padding: 0 1rem; + font-size: 14px; + position: relative; + top: -8px; + } +} diff --git a/app/assets/stylesheets/components/_notifications.scss b/app/assets/stylesheets/components/_notifications.scss new file mode 100644 index 0000000..0497645 --- /dev/null +++ b/app/assets/stylesheets/components/_notifications.scss @@ -0,0 +1,202 @@ +.notifications { + & { + position: relative; + font-size: 12px; + width: 40px; + user-select: none; + } + + > .notificationsicon { + position: relative; + display: flex; + align-items: center; + justify-content: center; + height: 40px; + width: 40px; + cursor: pointer; + } + + > .notificationsicon > svg { + fill: $color-black-80; + } + + &.open > .notificationsicon svg { + fill: $black; + } + + > .notificationsicon > .notificationscount { + top: 8px; + right: 22px; + color: $white; + background-color: $color-valencia; + height: 14px; + min-width: 14px; + font-size: 12px; + font-weight: 500; + position: absolute; + border-radius: 14px; + padding: 0 6px; + display: flex; + align-items: center; + justify-content: center; + } + + > .notificationspanel { + position: fixed; + z-index: 500; + left: 0.5rem; + right: 0.5rem; + top: 3.5rem; + display: flex; + flex-flow: column; + max-height: 448px; + width: auto; + margin: auto; + border: 1px solid $color-black-97-3; + background-color: $white; + box-shadow: 0 2px 16px 0 rgba(0,0,0,0.25); + + @media screen and (min-width: $tablet-breakpoint) { + position: absolute; + top: 100%; + left: -140px; + width: 320px; + } + + &:after { + content: ""; + display: none; + position: absolute; + left: 0; + right: 0; + bottom: 100%; + width: 0; + height: 0; + margin: auto; + border-left: 8px solid transparent; + border-right: 8px solid transparent; + border-bottom: 8px solid $white; + background-color: transparent; + @media screen and (min-width: $tablet-breakpoint) { + display: inherit; + } + } + } + + > .notificationspanel > .headerrow { + background-color: $white; + border-bottom: 1px solid $color-black-90-2; + color: $color-black-50-2; + display: flex; + flex-flow: row nowrap; + font-size: 12px; + font-weight: bold; + align-items: center; + height: 32px; + padding: 0 16px; + flex: 0 0 auto; + text-transform: uppercase; + } + + > .notificationspanel > .bodyrow { + background-color: $color-black-96-1; + display: flex; + flex-flow: column; + flex: 0 1 auto; + overflow-y: auto; + } + + > .notificationspanel > .bodyrow > .notificationitem { + background-color: $white; + border-bottom: 1px solid $color-black-90-2; + text-decoration: none; + padding: 8px 16px 16px 32px; + position: relative; + + &:hover { + > .notificationtitle { + text-decoration: underline; + } + } + + &.unread { + background-color: $color-cyan-opacity-4; + + > .notificationtitle { + font-weight: bold; + } + + &:after { + content: ""; + height: 8px; + width: 8px; + background-color: $color-cyan; + border-radius: 100%; + position: absolute; + top: 12px; + left: 12px; + } + } + } + + > .notificationspanel > .bodyrow > .notificationitem > .notificationheader { + height: 16px; + display: flex; + flex-flow: row nowrap; + justify-content: space-between; + } + + > .notificationspanel > .bodyrow > .notificationitem > .notificationheader > .notificationtagline { + font-size: 12px; + font-weight: bold; + color: $black; + line-height: 16px; + flex: 0 1 auto; + } + + > .notificationspanel > .bodyrow > .notificationitem > .notificationheader > .notificationtimestamp { + font-size: 12px; + font-weight: 500; + color: $color-black-50-2; + line-height: 16px; + text-align: right; + flex: 0 0 auto; + } + + > .notificationspanel > .bodyrow > .notificationitem > .notificationtitle { + font-size: 14px; + color: $color-cyan; + line-height: 16px; + margin-top: 8px; + } + + > .notificationspanel > .bodyrow > .notificationitem > .notificationdescription { + font-size: 14px; + color: $color-black-20; + line-height: 16px; + margin-top: 8px; + } + + > .notificationspanel > .footerrow { + background-color: $white; + border-top: 1px solid $color-black-90-2; + color: $color-cyan; + display: flex; + flex-flow: row nowrap; + font-size: 12px; + font-weight: bold; + align-items: center; + height: 40px; + padding: 0 16px; + flex: 0 0 auto; + text-transform: uppercase; + } + + > .notificationspanel > .footerrow > .markread { + cursor: pointer; + } + + > .notificationspanel > .notificationitem { + margin: 10px 0; + } +} diff --git a/app/assets/stylesheets/components/_pagination.scss b/app/assets/stylesheets/components/_pagination.scss new file mode 100644 index 0000000..4e8ea67 --- /dev/null +++ b/app/assets/stylesheets/components/_pagination.scss @@ -0,0 +1,46 @@ +.react-paginate-container { + margin: 0px 0px 30px 0px; + display: block; + float: left; + list-style: none; + width: 100%; + display: flex; + justify-content: center; + align-items: center; + padding: 0; +} + +.react-paginate-page { + background-color: blue; + display: block; + float: left; + width: 40px; + padding: 5px; + cursor: pointer; + border: 1px solid grey; + background-color: white; + border-radius: 1px; + text-align: center; + padding: 4px; + + &:hover { + background-color: #ffd4a8; + text-decoration: none; + } +} + +.react-paginate-link { + display: block; + width: 100%; + height: 100%; + text-decoration: none !important; + color: black; +} + +.react-paginate-break { + display: none; +} + +.react-paginate-active { + background-color: #ffd4a8; +} \ No newline at end of file diff --git a/app/assets/stylesheets/components/_pill.scss b/app/assets/stylesheets/components/_pill.scss new file mode 100644 index 0000000..e2e88e4 --- /dev/null +++ b/app/assets/stylesheets/components/_pill.scss @@ -0,0 +1,78 @@ +.pill-wrapper { + border-radius: 6px; + display: inline-block; + text-transform: uppercase; + color: #333; + font-weight: 300; + + p { + margin-top: 0px !important; + margin-bottom: 0px !important; + font-family: $font-family-proxima-nova; + } + + &.small { + padding: 2px 10px 2px 10px; + height: 18px; + + .p-text { + font-size: 10px; + line-height: 17px; + + } + + .a-text { + font-size: 10px; + line-height: 17px; + } + } + + &.medium { + padding: 2px 10px 2px 10px; + height: 24px; + + .p-text { + font-size: 12px; + line-height: 20px; + } + + .a-text { + font-size: 12px; + line-height: 20px; + } + } + + &.large { + padding: 5px 20px 5px 20px; + height: 30px; + + .p-text { + font-size: 14px; + line-height: 23px; + } + + .a-text { + font-size: 14px; + line-height: 23px; + } + } + + .p-text { + margin: 0; + text-transform: inherit; + color: inherit; + letter-spacing: 0.1rem; + margin-right: -0.1rem !important; + font-weight: inherit; + } + + .a-text { + margin: 0; + text-transform: inherit; + color: inherit; + letter-spacing: 0.1rem; + margin-right: -0.1rem !important; + font-weight: inherit; + vertical-align: top; + } +} diff --git a/app/assets/stylesheets/components/_point_grade_buttons.scss b/app/assets/stylesheets/components/_point_grade_buttons.scss new file mode 100644 index 0000000..499c4f8 --- /dev/null +++ b/app/assets/stylesheets/components/_point_grade_buttons.scss @@ -0,0 +1,19 @@ +.points-container { + display: flex; + border-radius: 25px; + border: 2px solid $color-black-93-3; + background-color: $color-white; + height: 45px; + justify-content: center; + align-items: center; + padding: 0 10px 0 10px; + + .point { + color: $color-black-60-8; + text-align: center; + width: 25px; + font-size: 1.2rem; + font-weight: 500; + cursor: pointer; + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/components/_primary-header.scss b/app/assets/stylesheets/components/_primary-header.scss new file mode 100644 index 0000000..7ec922d --- /dev/null +++ b/app/assets/stylesheets/components/_primary-header.scss @@ -0,0 +1,100 @@ +.primary-header { + & { + display: flex; + align-items: center; + justify-content: space-between; + padding: 2rem 1.5rem; + } + + &.-blue { + background: $color-darkest-blue-gray; + } + + &.-blue > div > .label { + color: $color-black-60-8; + font-weight: 300; + } + + &.-blue > div > .title { + color: $color-white; + font-size: 1.5rem; + line-height: 1.5rem; + } + + &.-white { + border-bottom: 0.125rem solid $color-black-83-1; + padding: 1.5rem 0; + } + + &.-white > div > .label { + color: $color-black-60; + font-weight: bold; + } + + > .header-left { + max-width: 50%; + } + + > .header-left > .label, + > .header-left > .title { + height: auto; + overflow: hidden; + text-overflow: ellipsis; + } + + > .header-left > .title > span > a { + padding-left: 7px; + color: white; + text-decoration: none; + } + + > .header-left > .title > span > a.disabled { + color: $color-black-50-2; + } + + > .header-left > .title > span > a:hover { + color: $color-black-50-2; + } + + > .header-left > .title > span > a > div { + display: inline; + } + + .header-left > .label > a { + color: $color-black-60-8; + text-decoration: underline; + } + + .header-left > .label > a:hover { + color: $color-black-50-2; + text-decoration: none; + } + + > div > .label { + font-size: 0.75rem; + margin-bottom: 0.5rem; + text-transform: uppercase; + line-height: 1rem; + } + + > div > .title { + line-height: 1.5rem; + font-size: 1.5rem; + } + + > div > .title > .lp-badge { + vertical-align: middle; + } + + > .header-right .lp-badge { + margin-bottom: 0.5rem; + } + + > .header-right a { + text-decoration: none; + } + + > .header-right > .title { + text-align: center; + } +} diff --git a/app/assets/stylesheets/components/_primary-navigation.scss b/app/assets/stylesheets/components/_primary-navigation.scss new file mode 100644 index 0000000..42fc382 --- /dev/null +++ b/app/assets/stylesheets/components/_primary-navigation.scss @@ -0,0 +1,132 @@ +.primary-navigation { + & { + position: relative; + z-index: $z-primary-navigation; + display: flex; + flex-flow: row nowrap; + align-items: center; + height: 3.5rem; + width: 100%; + border-bottom: 1px solid #f2f2f2; + background-color: $color-white; + @media screen and (min-width: $tablet-breakpoint) { + padding-right: 1rem; + } + } + + &.navshadow { + box-shadow: 0 1px 1px 0 rgba(0,0,0, 0.2); + border-bottom: 0; + } + &.checkpoint-navshadow { + box-shadow: 0 2px 20px 0 rgba(0,0,0, 0.07); + border-bottom: 1px solid $color-black-96-1; + } + + > .logo { + background: none left center no-repeat; + background-image: image-url("svg/mobile-logo.svg"); + background-size: contain; + height: 34px; + margin: 0 1rem; + min-width: 40px; + @media screen and (min-width: $tablet-breakpoint) { + background-image: image-url("svg/g-learn-lockup.svg"); + margin: 0 1.5rem; + min-width: 236px; + } + } + + > a .custom-logo { + height: 3rem; + padding: 0.25rem 0.5rem; + } + + > .item { + flex: 0 0 auto; + height: inherit; + margin: 0; + + &:first-of-type { + margin-left: auto; + } + } + + &.checkpoint-navbar { + position: fixed; + justify-content: inherit; + + .checkpoint-navbar-details { + display: flex; + justify-content: right; + white-space: nowrap; + + .checkpoint-timer { + @include font-base; + display: flex; + align-items: center; + margin-right: 4rem; + font-weight: 500; + color: $color-mine-shaft; + min-width: 92px; + + .final-countdown { + } + + svg { + margin-right: 10px; + + &.under-minute { + color: $color-valencia; + } + } + } + .final-countdown > b { + @include font-base; + font-weight: 500; + color: $color-mine-shaft; + display: inline-block; + } + + .final-countdown > .subtext { + margin-right: 10px; + } + + div.its-the.final-countdown > .subtext, div.its-the.final-countdown > b { + color: $color-valencia; + } + + .subtext { + @include font-small; + color: $color-gray; + margin-left: 8px; + } + + .checkpoint-challenges-attempted { + @include font-base; + font-weight: 500; + color: $color-mine-shaft; + display: flex; + align-items: baseline; + margin: auto 4rem auto 0; + white-space: nowrap; + } + + .checkpoint-pair-menu { + margin: auto 0 auto 10px; + display: flex; + position: relative; + + svg { + color: $color-gray; + } + + .pair-menu { + position: absolute; + z-index: 10; + bottom: 0; + } + } + } + } +} diff --git a/app/assets/stylesheets/components/_progress.scss b/app/assets/stylesheets/components/_progress.scss new file mode 100644 index 0000000..7fbb166 --- /dev/null +++ b/app/assets/stylesheets/components/_progress.scss @@ -0,0 +1,59 @@ +// Named this way to avoid conflict with bootstrap's .progress-bar styling +.progressbar { + --progressbar-height: 4px; + width: 100%; + height: var(--progressbar-height); + position: relative; + + &.-theme-light { + background: $color-black-92-2; + } + &.-theme-dark { + background: #4B5157; + } + + .progress-percentage { + height: var(--progressbar-height); + position: absolute; + z-index: 15; + background: $color-cyan; + } + + .progress-pending { + height: var(--progressbar-height); + position: absolute; + z-index: 10; + background: $color-black-50-2; + } +} + +.actioncircle { + --actioncircle-size: 32px; + border-radius: 100%; + color: $color-white; + display: flex; + align-items: center; + justify-content: center; + height: var(--actioncircle-size); + width: var(--actioncircle-size); + font-size: 14px; + line-height: 15px; + font-weight: 200; + flex-shrink: 0; + + svg { + height: var(--actioncircle-size); + width: var(--actioncircle-size); + } + + &.-score-3 { + background-color: $color-lime-green; + } + &.-score-2 { + background-color: $color-banana-yellow; + } + &.-score-1 { + background-color: $color-tangerine-orange; + } +} + diff --git a/app/assets/stylesheets/components/_progress_thresholds_key.scss b/app/assets/stylesheets/components/_progress_thresholds_key.scss new file mode 100644 index 0000000..770e1c3 --- /dev/null +++ b/app/assets/stylesheets/components/_progress_thresholds_key.scss @@ -0,0 +1,35 @@ +.thresholds-key-wrapper { + display: flex; + align-items: center; + + .thresholds-key-square { + width: 15px; + height: 15px; + margin-right: 8px; + border-radius: 2px; + } + + .thresholds-key-content { + margin-top: 1px; + margin-right: 30px; + margin-bottom: 0; + } + + .unscored-key-wrapper { + display: flex; + align-items: center; + + .unscored-key { + height: 10px; + width: 10px; + border-radius: 50%; + background-color: #D23C44; + } + + p { + margin-top: 0; + margin-left: 8px; + margin-right: 30px; + } + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/components/_progress_thresholds_modal.scss b/app/assets/stylesheets/components/_progress_thresholds_modal.scss new file mode 100644 index 0000000..27c7687 --- /dev/null +++ b/app/assets/stylesheets/components/_progress_thresholds_modal.scss @@ -0,0 +1,20 @@ +.progress-thresholds-modal { + .title { + color: #999999; + text-align: center; + margin-bottom: 50px; + } + + .slider-wrapper { + width: 500px; + margin: 0 auto; + } + + .description { + color: #999999; + width: 80%; + margin: 0 auto; + text-align: center; + margin-top: 63px; + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/components/_progress_thresholds_slider.scss b/app/assets/stylesheets/components/_progress_thresholds_slider.scss new file mode 100644 index 0000000..ef1cdc9 --- /dev/null +++ b/app/assets/stylesheets/components/_progress_thresholds_slider.scss @@ -0,0 +1,8 @@ +.ranger-rick { + width: 100%; + position: relative; +} + +.rc-slider-tooltip { + z-index: 1000001; +} \ No newline at end of file diff --git a/app/assets/stylesheets/components/_search-bar.scss b/app/assets/stylesheets/components/_search-bar.scss new file mode 100644 index 0000000..bcd4176 --- /dev/null +++ b/app/assets/stylesheets/components/_search-bar.scss @@ -0,0 +1,44 @@ +.search-bar__wrapper { + display: flex; + width: 100%; + + .search-bar { + display: flex; + padding-left: 5px; + align-items: center; + height: 40px; + transition: flex-grow 0.1s, background-color 0.1s; + + &.search-bar--expanded { + @include input; + border-radius: 40px; + padding-left: 4px; + padding-right: 3px; + background-color: $color-white; + border: 1px solid $color-mercury; + margin: 0; + margin-right: 8px; + flex-grow: 1; + max-width: 400px; + } + + .search-bar__icon { + height: 32px; + padding: 4px 8px; + border-radius: 24px; + &:hover { + background-color: #E8E8E8; + } + } + + input { + border: none; + flex-grow: inherit; + margin-left: 4px; + + &:focus { /* WARNING: accessibility depends on focus outline */ + outline: none; + } + } + } +} diff --git a/app/assets/stylesheets/components/_secondary-navigation.scss b/app/assets/stylesheets/components/_secondary-navigation.scss new file mode 100644 index 0000000..983231b --- /dev/null +++ b/app/assets/stylesheets/components/_secondary-navigation.scss @@ -0,0 +1,58 @@ +.secondary-navigation { + & { + position: relative; + z-index: 9999; + display: flex; + flex-flow: row nowrap; + height: 3rem; + width: 100%; + background-color: $color-white; + box-shadow: 0 1px 1px 0 rgba(0,0,0, 0.2); + overflow-x: scroll; + @media screen and (min-width: $tablet-breakpoint) { + overflow-x: auto; + } + } + + > .item { + flex: 1; + margin: 0; + height: inherit; + border: 0 solid transparent; + border-width: 0 0 2px 0; + color: $color-black-60; + @media screen and (min-width: $tablet-breakpoint) { + flex: 0 0 auto; + } + } + + > .item.-is-active { + color: black; + border-color: $color-cyan; + } + + > .item:hover { + color: black; + background-color: $color-black-97-3; + border-color: $color-black-83-1; + } + + > .item:active { + border-color: $color-dark-cyan; + } + + > .item > a { + position: relative; + display: flex; + flex-flow: row; + align-items: center; + justify-content: center; + height: inherit; + padding: 0 1rem; + text-transform: uppercase; + color: inherit; + text-decoration: none; + user-select: none; + cursor: pointer; + } +} diff --git a/app/assets/stylesheets/components/_slideshow.scss b/app/assets/stylesheets/components/_slideshow.scss new file mode 100644 index 0000000..52e1bcd --- /dev/null +++ b/app/assets/stylesheets/components/_slideshow.scss @@ -0,0 +1,264 @@ +.slideshow-container { + position: absolute; + height: 100%; + width: 100%; + box-shadow: 0 1px 10px 0 rgba(0, 0, 0, 0.2); +} + +.slides { + position: relative; + height: 100%; + padding: 0px; + margin: 0px; + list-style-type: none; + overflow: hidden; +} + +.slide { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + opacity: 0; + z-index: 1; + padding: 0; + margin: 0; + background-repeat: no-repeat; + background-size: cover; + background-position: center; +} + +.showing-none { + opacity: 1; + z-index: 2; +} + +.showing-fade { + opacity: 1; + z-index: 2; + animation-duration: 1s; + animation-name: slide-fade; +} + +@keyframes slide-fade { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +.showing-right { + opacity: 1; + animation-duration: 1s; + animation-name: slide-right; +} + +@keyframes slide-right { + from { + left: -50%; + } + + to { + left: 0; + } +} + +.showing-left { + opacity: 1; + animation-duration: 1s; + animation-name: slide-left; +} + +@keyframes slide-left { + from { + left: 100%; + } + + to { + left: 0; + } +} + +.showing-top { + opacity: 1; + animation-duration: 1s; + animation-name: slide-top; +} + +@keyframes slide-top { + from { + top: 100%; + } + + to { + top: 0; + } +} + +.showing-bottom { + opacity: 1; + animation-duration: 1s; + animation-name: slide-bottom; +} + +@keyframes slide-bottom { + from { + top: -100%; + } + + to { + top: 0; + } +} + +.showing-bounce-left { + opacity: 1; + animation-duration: 1s; + animation-name: slide-bounce-left; +} + +@keyframes slide-bounce-left { + 0% { + left: 100%; + } + 50% { + left: -20%; + } + 100% { + left: 0; + } +} + +.showing-bounce-right { + opacity: 1; + animation-duration: 1s; + animation-name: slide-bounce-right; +} + +@keyframes slide-bounce-right { + 0% { + left: -100%; + } + 50% { + left: 20%; + } + 100% { + left: 0; + } +} + +.show-index.is-text { + color: black; + position: absolute; + bottom: 0; + z-index: 100; + left: 50%; + font-size: 28px; + font-family: 'Slabo 27px', serif; +} + +.show-index.is-dot { + color: black; + position: absolute; + bottom: 0; + z-index: 100; + left: 50%; + font-size: 28px; + font-family: 'Slabo 27px', serif; + display: flex; + transform: translate(-50%); +} + +.show-index.is-dot .dot { + width: 10px; + height: 10px; + margin: 0 3px 3rem 3px; + background-color: black; + border-radius: 50%; + opacity: 0.5; +} + +.show-index.is-dot .dot.is-active { + opacity: 1; +} + +.slideshow-container button:focus { + outline: none; +} + +.btn-arrow { + display: block; + font-size: 5px; + line-height: 0; + -moz-transition: all 0.3s; + -o-transition: all 0.3s; + -webkit-transition: all 0.3s; + transition: all 0.3s; + position: absolute; + top: 50%; + z-index: 10; + cursor: pointer; + height: 50px; + width: 50px; + border-radius: 50%; + padding: 5px; + z-index: 10000; +} + +.btn-arrow:hover, +.btn-arrow:focus { + background: $color-black-92-2; +} + +.btn-arrow:hover::before, +.btn-arrow:hover::after, +.btn-arrow:focus::before, +.btn-arrow:focus::after { + background: rgba(256, 256, 256, 0.5); +} + +.btn-arrow::before { + content: ''; + display: block; + background: rgba(256, 256, 256, 0.6); + position: absolute; + top: 0; + left: 0; + width: 6em; + height: 2em; +} + +.btn-arrow::after { + content: ''; + display: block; + background: rgba(256, 256, 256, 0.6); + position: absolute; + top: 0; + left: 0; + width: 2em; + height: 6em; +} + +.btn-arrow.btn-arrow-left { + left: -75px; +} + +.btn-arrow.btn-arrow-left::before, +.btn-arrow.btn-arrow-left::after { + top: 18px; + left: 18px; +} + +.btn-arrow.btn-arrow-right { + right: -75px; +} + +.btn-arrow.btn-arrow-right::before, +.btn-arrow.btn-arrow-right::after { + top: 18px; + left: 18px; +} \ No newline at end of file diff --git a/app/assets/stylesheets/components/_sort-dropdown-component.scss b/app/assets/stylesheets/components/_sort-dropdown-component.scss new file mode 100644 index 0000000..1912fbd --- /dev/null +++ b/app/assets/stylesheets/components/_sort-dropdown-component.scss @@ -0,0 +1,52 @@ +.sort-dropdown-component { + & { + position: relative; + display: flex; + flex-flow: row nowrap; + align-items: center; + margin-bottom: 32px; + user-select: none; + } + + > .label { + flex: 1 0 auto; + color: $color-black-60-8; + font-size: 18px; + line-height: 24px; + margin-right: 8px; + } + + > .svg { + flex: 0 0 auto; + fill: $color-black-83-1; + position: absolute; + left: auto; + right: 0; + top: 0; + bottom: 0; + margin: auto; + pointer-events: none; + } + + > select { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + flex: 0 0 auto; + border: none; + background: none; + margin: 0; + padding: 0; + width: auto; + color: $color-darkest-blue-gray; + font-size: 18px; + font-weight: bold; + line-height: 24px; + cursor: pointer; + padding-right: (24 + 4 + px); + + &:hover + .svg { + fill: $color-cyan; + } + } +} diff --git a/app/assets/stylesheets/components/_standard-card.scss b/app/assets/stylesheets/components/_standard-card.scss new file mode 100644 index 0000000..08364f4 --- /dev/null +++ b/app/assets/stylesheets/components/_standard-card.scss @@ -0,0 +1,234 @@ +.standardcard { + background-color: $color-white; + margin-bottom: 1.5rem; + border-radius: 5px; + border: 1px solid $color-black-90-2; + display: flex; + flex-flow: row wrap; + align-items: flex-start; + justify-content: space-between; + padding: 20px; + + &.Percentage { + .standard-scoring-block { + border-bottom: 0px solid transparent; + height: auto; + padding: 0; + flex-flow: column; + flex: 0; + } + + .student-details { + width: 50%; + flex: 1; + font-size: 18px; + + span { + min-width: 250px; + } + } + + .info { + color: $color-black-60; + font-size: 14px; + margin-top: 10px; + } + + button { + margin: 25px auto 0; + width: 100%; + } + } + + > .standard-current-score { + background-color: $color-black-92-2; + width: 100%; + padding: 0.3125rem 1.5rem; + font-size: 0.75rem; + font-weight: bold; + letter-spacing: 0.0625rem; + text-transform: uppercase; + } + + > .standard-current-score > .label { + color: $color-black; + opacity: 0.5; + } + + > .standard-description { + padding-top: 1rem; + padding-bottom: 1rem; + width: 100%; + border-top: 1px solid #e6e6e6; + margin-left: 20px; + margin-right: 20px; + } + + > .standard-description > h4 { + margin: 0 0 1.25rem; + font-size: 1.25rem; + font-weight: normal; + line-height: 1.75rem; + color: $color-black; + } + + > .standard-description > .success-criteria { + color: $color-black; + font-size: 1rem; + line-height: 1.5rem; + } + + > .standard-description > .success-criteria > ul { + padding: 0 1rem 0 1.25rem; + margin: 1rem 0 0; + } + + > .standard-description > .success-criteria > ul > li { + padding-left: 0.5rem; + } + + > .standard-description > .toggle-success-criteria { + cursor: pointer; + position: relative; + } + + > .standard-description > .toggle-success-criteria > .label.gray-label { + color: $color-black-60-8; + text-transform: uppercase; + font-size: 0.75rem; + font-weight: bold; + letter-spacing: 0.0625rem; + } + + > .standard-description > .toggle-success-criteria > .svg { + position: absolute; + left: auto; + margin: auto; + pointer-events: none; + right: 0; + color: $color-black-60-8; + top: 0; + bottom: 0; + font-size: 0.875rem; + } + + > .standard-description > .null-success-criteria { + font-style: italic; + color: $color-black-60-8; + } + + > .standard-scoring-block { + display: flex; + height: 4.5rem; + align-items: center; + justify-content: space-between; + padding: 0.3125rem 0; + margin-left: 20px; + margin-right: 20px; + } + + > .standard-scoring-block > .label { + width: 50%; + color: $color-black; + } + + > .standard-scoring-block > .standard-scoring-buttons { + display: flex; + } + + > .standard-scoring-block > .standard-scoring-buttons > .standard-scoring-button { + height: 2.5rem; + width: 2.5rem; + background-color: $color-black-90-2; + color: $color-white; + cursor: pointer; + line-height: 2.5rem; + text-align: center; + margin-left: 0.5rem; + border-radius: 100%; + user-select: none; + font-weight: bolder; + font-size: 1rem; + + &.score-1:hover, + &.score-1.-is-selected { + background-color: $color-valencia; + cursor: default; + } + + &.score-2:hover, + &.score-2.-is-selected { + background-color: $color-banana-yellow; + cursor: default; + } + + &.score-3:hover, + &.score-3.-is-selected { + background-color: $color-lime-green; + cursor: default; + } + + &.-is-suggested:hover, + &.-is-suggested { + border: 0.25rem solid $color-darkest-blue-gray; + background-color: $color-white; + color: $color-darkest-blue-gray; + line-height: 2rem; + } + } + + > .standard-scoring-block > .standard-scoring-buttons > .standard-scoring-button > .suggested-score-tooltip { + background: $color-darkest-blue-gray !important; + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + margin-top: 0.25rem; + + &:after { + display: inline-block !important; + border-left-color: $color-darkest-blue-gray; + height: 0.75rem; + margin-top: -0.375rem; + } + } + + > .standard-scoring-block.-percentage-mode > .percentage-score { + display: flex; + align-items: center; + // padding-right: 20px; + flex-flow: column nowrap; + width: 100px; + + > .overall { + color: #333; + font-size: 24px; + display: flex; + flex-flow: column; + align-items: center; + + .scoring { + padding-top: 5px; + + p { + margin: 0; + padding: 0; + text-align: center; + line-height: 23px; + + &:first-of-type { + font-size: 30px; + font-weight: 400; + } + &:last-of-type { + font-size: 14px; + color: rgb(54,54,54) + } + + } + } + } + .p-text { + color: #DD3D48; + font-weight: 400; + } + } +} diff --git a/app/assets/stylesheets/components/_standard-cards.scss b/app/assets/stylesheets/components/_standard-cards.scss new file mode 100644 index 0000000..5ca5681 --- /dev/null +++ b/app/assets/stylesheets/components/_standard-cards.scss @@ -0,0 +1,159 @@ +.standards-cards { + .standardcard { + & { + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24); + background-color: $color-white; + margin: 24px; + } + + > .standard-current-score { + background-color: $color-black-92-2; + width: 100%; + padding: 5px 24px; + font-size: 12px; + font-weight: bold; + letter-spacing: 1px; + text-transform: uppercase; + + > .label { + color: $color-black; + opacity: 0.5; + } + } + + > .standard-description { + padding: 16px 24px 24px; + + > h4 { + margin: 0 0 20px; + font-size: 24px; + font-weight: normal; + line-height: 28px; + color: $color-black; + } + + > .success-criteria { + color: $color-black; + font-size: 16px; + line-height: 24px; + + > ul { + padding: 0px 16px 0px 20px; + margin: 16px 0px 0px; + + > li { + padding-left: 8px; + } + } + } + + > .toggle-success-criteria { + cursor: pointer; + position: relative; + } + + > .toggle-success-criteria > .label.gray-label { + color: $color-black-60-8; + text-transform: uppercase; + font-size: 12px; + font-weight: bold; + letter-spacing: 1px; + } + + > .toggle-success-criteria > .svg { + position: absolute; + left: auto; + margin: auto; + pointer-events: none; + right: 0; + color: $color-black-60-8; + top: 0px; + bottom: 0px; + font-size: 14px; + } + + > .null-success-criteria { + font-style: italic; + color: $color-black-60-8; + } + } + + > .standard-scoring-block { + display: flex; + height: 72px; + align-items: center; + justify-content: space-between; + border-bottom: 1px solid $color-black-90-2; + padding: 5px 24px; + + > .label { + width: 50%; + color: $color-black; + } + + > .standard-scoring-buttons { + display: flex; + + > .standard-scoring-button { + height: 40px; + width: 40px; + background-color: $color-black-90-2; + color: $color-white; + cursor: pointer; + line-height: 40px; + text-align: center; + margin-left: 8px; + border-radius: 100%; + user-select: none; + font-weight: bolder; + font-size: 16px; + + &.score-1:hover, + &.score-1.-is-selected { + background-color: $color-valencia; + } + + &.score-2:hover, + &.score-2.-is-selected { + background-color: $color-navy-blue; + } + + &.score-3:hover, + &.score-3.-is-selected { + background-color: $color-lime-green; + } + + &.-is-suggested:hover, + &.-is-suggested { + border: 4px solid $color-darkest-blue-gray; + background-color: $color-white; + color: $color-darkest-blue-gray; + line-height: 32px; + } + } + + > .standard-scoring-button > .suggested-score-tooltip { + background: $color-darkest-blue-gray !important; + padding-top: 8px !important; + padding-bottom: 8px !important; + margin-top: 4px; + + &:after { + display: inline-block !important; + border-left-color: $color-darkest-blue-gray; + height: 12px; + margin-top: -6px; + } + } + } + } + } + + .nullstandardcard { + & { + font-size: 16px; + font-style: italic; + padding: 24px; + } + } +} diff --git a/app/assets/stylesheets/components/_standards-mastery-beans.scss b/app/assets/stylesheets/components/_standards-mastery-beans.scss new file mode 100644 index 0000000..5452867 --- /dev/null +++ b/app/assets/stylesheets/components/_standards-mastery-beans.scss @@ -0,0 +1,35 @@ +.standardbeans { + display: flex; + flex-flow: row nowrap; + align-items: center; + margin-right: 16px; +} + +.standardbean { + width: 8px; + height: 8px; + margin-right: 6px; + border-radius: 8px; + flex: 0 0 auto; + + + &.-unscored { + background-color: $color-black-84-7; + } + + &.-is-completed { + background-color: $color-cyan; + } + + &.-score-3 { + background-color: $color-lime-green; + } + + &.-score-2 { + background-color: $color-banana-yellow; + } + + &.-score-1 { + background-color: $color-tangerine-orange; + } +} diff --git a/app/assets/stylesheets/components/_status_picker.scss b/app/assets/stylesheets/components/_status_picker.scss new file mode 100644 index 0000000..c26f154 --- /dev/null +++ b/app/assets/stylesheets/components/_status_picker.scss @@ -0,0 +1,132 @@ +.status-container { + display: flex; + border-radius: 25px; + border: 2px solid $color-black-93-3; + background-color: $color-white; + height: 45px; + justify-content: space-between; + align-items: center; + padding: 0; + width: 120px; + background: linear-gradient( + to right, + transparent 0%, + transparent calc(50% - 0.81px), + $color-black-93-3 calc(50% - 0.8px), + $color-black-93-3 calc(50% + 0.8px), + transparent calc(50% + 0.81px), + transparent 100% + ); + background-color: white; + cursor: pointer; + + .incorrect-status { + height: 100%; + width: 60px; + display: flex; + justify-content: center; + border-radius: 25px 0 0 25px; + + .svg-div { + color: $color-black-60-8; + text-align: center; + font-size: 1.2rem; + font-weight: 500; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + width: 35px; + } + + .incorrect-check { + color: $color-valencia; + width: 40px; + height: 40px; + } + + &:hover { + background-color: $color-cyan-very-light; + } + } + + .correct-status { + height: 100%; + width: 60px; + display: flex; + justify-content: center; + border-radius: 0 25px 25px 0; + + .svg-div { + color: $color-black-60-8; + text-align: center; + font-size: 1.2rem; + font-weight: 500; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + width: 35px; + } + + .correct-check { + color: $color-cyan; + width: 40px; + height: 40px; + } + + &:hover { + background-color: $color-cyan-very-light; + } + } + + &.vertical { + flex-direction: column; + justify-content: center; + height: auto; + position: absolute; + top: 43px; + right: -18px; + border-radius: 10px; + z-index: 1; + width: 80px; + padding: 0; + box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.1); + background: white; + + .status { + width: 100%; + } + + .incorrect-status { + width: 100%; + border-bottom: 1px solid $color-black-93-3; + border-radius: 8px 8px 0 0; + + &:hover { + background-color: $color-cyan-very-light; + } + } + + .correct-status { + width: 100%; + border-radius: 0 0 8px 8px; + + &:hover { + background-color: $color-cyan-very-light; + } + } + + .correct-check { + margin: 0; + } + + .incorrect-check { + margin: 0; + } + + .svg-div { + width: 100%; + } + } +} diff --git a/app/assets/stylesheets/components/_student-mastery-table.scss b/app/assets/stylesheets/components/_student-mastery-table.scss new file mode 100644 index 0000000..c516592 --- /dev/null +++ b/app/assets/stylesheets/components/_student-mastery-table.scss @@ -0,0 +1,156 @@ +.student-performances-table { + & { + background: $color-black-97-3 + } + > .page-header > .container { + > .performance-breadcrumb { + margin: 32px; + padding: 0; + list-style: none; + color: $color-too-gray; + font-size: 16px; + > .item { + color: inherit; + display: inline-block; + } + > .item:not(:first-of-type):before { + content: ""; + display: inline-block; + margin: 0 3px; + height: 18px; + width: 24px; + background: none center no-repeat; + background-image: url("data:image/svg+xml;charset=utf-8, %3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%0A%20%20%3Cpath%20fill%3D%22grey%22%20d%3D%22M10%206L8.59%207.41%2013.17%2012l-4.58%204.59L10%2018l6-6z%22%2F%3E%0A%3C%2Fsvg%3E"); + background-size: contain; + transform: translateY(4px); + } + > .item > a { + font-weight: 300; + text-decoration: none; + outline: 0; + transition: all 300ms ease; + color: inherit; + opacity: 0.5; + } + > .item a:hover { + opacity: 1; + } + } + + > .performance-heading { + margin: 2rem 0 0; + font-size: 48px; + } + } + + .scores > .score > .score-label { + font-size: 12px; + color: $color-white; + position: absolute; + bottom: 1rem; + left: 0.25rem; + right: 0; + text-align: center; + } + + .scores > .score > .value { + font-size: 64px; + font-weight: normal; + color: white; + line-height: 144px; + } + + .scores > .score { + display: inline-block; + position: relative; + background: $color-blue-dark; + border: 1px solid $color-gray-light; + text-align: center; + width: 160px; + height: 160px; + flex: 1 1 auto; + } + + .scores { + position: relative; + padding: 2rem 0; + width: 100%; + display: flex; + margin: 0 auto; + text-align: right; + } + + .performances-container { + & { + padding: 16px; + background: $color-white; + } + + > .legend-div { + display: flex; + margin-bottom: 18px; + align-items: center; + } + + > .legend-div > .standard-legend { + border: 1px solid $color-gray-light; + bottom: 3rem; + border-radius: 0.25rem; + padding: 0.5rem 2rem; + margin-right: 0.5rem; + margin-top: 0.5rem; + } + + > .legend-div > .standard-legend.elective { + background-color: $color-pale-yellow; + } + + > .legend-div > a { + flex-grow: 1; + text-align: right; + } + + .standard-elective { + background-color: $color-pale-yellow; + } + } +} + +table.table { + tr.tr-summary, + tr.tr-standard { + th, + td { + background: $color-light-gray-blue; + } + } + + td { + &.score-selected { + box-shadow: 0 0 0 2px black inset; + } + + &.score-0 { + text-align: center; + vertical-align: middle; + } + + &.score-1 { + background: $color-soft-red; + text-align: center; + vertical-align: middle; + } + + &.score-2 { + background: $color-soft-orange; + text-align: center; + vertical-align: middle; + } + + &.score-3 { + background: $color-sage; + text-align: center; + vertical-align: middle; + } + } +} diff --git a/app/assets/stylesheets/components/_student-name-bar.scss b/app/assets/stylesheets/components/_student-name-bar.scss new file mode 100644 index 0000000..a857e6a --- /dev/null +++ b/app/assets/stylesheets/components/_student-name-bar.scss @@ -0,0 +1,92 @@ +.student-name-bar { + & { + height: 4rem; + background-color: $color-darkester-blue-gray; + position: relative; + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + } + + &.-is-sticky { + position: fixed; + z-index: 9999; + top: 0; + left: 0; + } + + > .avatarname { + color: $color-white; + display: flex; + align-items: center; + font-size: 1.125rem; + } + + > .avatarname > div > .user-avatar, + > .avatarname > .user-avatar { + padding: 0; + margin-right: 10px; + height: 32px; + width: 32px; + } + + > .avatarname > .submit-with-avatars > .user-avatar { + background-color: $color-black-60; + background-size: contain; + border-radius: 100%; + position: relative; + color: $color-white; + margin-right: auto; + border: 2px solid #262A2E; + } + + > .avatarname > .submit-with-avatars.showing-one > .user-avatar { + margin-right: 10px; + } + + > .avatarname > .submit-with-avatars.others .user-avatar { + margin-right: 10px; + } + + > .backtochallengeslink { + margin-left: 2rem; + color: $color-cyan; + font-size: 0.75rem; + cursor: pointer; + text-transform: uppercase; + text-decoration: none; + font-weight: 400; + } + + > .nextsubmissionlink { + margin-right: 2rem; + color: $color-cyan; + font-size: 0.75em; + cursor: pointer; + text-transform: uppercase; + text-decoration: none; + font-weight: 400; + } + + > .allgraded { + display: flex; + align-items: center; + margin-right: 17px; + &:hover { + text-decoration: none; + } + } + + > .avatarname > a { + color: $color-white; + } + + > .avatarname > a.-disabled { + opacity: 0.3; + } + + > .avatarname > a svg { + margin: 1.5625rem 1rem 1rem; + } +} diff --git a/app/assets/stylesheets/components/_submissions-dashboard-table.scss b/app/assets/stylesheets/components/_submissions-dashboard-table.scss new file mode 100644 index 0000000..4af63c3 --- /dev/null +++ b/app/assets/stylesheets/components/_submissions-dashboard-table.scss @@ -0,0 +1,506 @@ +$cell-height: 56px; + +%student-column { + & { + flex: 0 0 auto; + width: 40px; + } + + > .block-title-spacer { + background: $color-black-70-2; + height: 40px; + } + + > .student { + background: $color-white; + display: flex; + flex-flow: column; + align-items: center; + justify-content: center; + height: $cell-height; + padding: 8px; + cursor: pointer; + + &:hover { + background: $color-black-97-3; + } + } + + > .standard > .standarditem { + position: relative; + width: 100%; + border-right: 1px solid $color-black-93-3; + + &:not(:last-of-type) { + border-bottom: 2px solid $color-black-83-1; + } + } + + > .standard > .standarditem > .itemheading { + position: relative; + display: flex; + flex-flow: column; + align-items: center; + justify-content: center; + height: $cell-height; + background: white; + padding: 8px; + } + + > .standard > .standarditem > .itemheading > a { + text-decoration: none; + } + + > .standard > .standarditem > .itemheading > a > .actioncircle { + &{ + border-radius: 100%; + color: $color-white; + display: flex; + align-items: center; + justify-content: center; + height: 23px; + width: 23px; + font-size: 10px; + line-height: 15px; + font-weight: 200; + } + + &.-score-3 { + background-color: $color-lime-green; + } + + &.-score-2 { + background-color: $color-banana-yellow; + } + + &.-score-1 { + background-color: $color-tangerine-orange; + } + } + + > .standard > .standarditem > .itembody { + display: flex; + flex-flow: column; + align-items: center; + justify-content: center; + position: relative; + overflow: hidden; + background: $color-black-97-3; + height: $cell-height; + border-top: 1px solid $color-black-93-3; + } + + > .standard > .standarditem > .itembody > a { + flex: 1 1 100%; + display: inherit; + align-items: inherit; + justify-content: inherit; + padding: 8px; + + &:hover { + background: $color-black-92-2; + } + } + + > .standard > .emptyrow { + height: 40px; + background: $color-black-92-2; + } + + > .standard > .standarditem > .itemheading > svg.donut, + > .standard > .standarditem > .itembody > svg.donut { + height: 100%; + width: 100%; + } +} + +%standard-item { + & { + } + + .standarditem.hidden .itemheading .title { + opacity: 0.4; + } + + > .standardtitle { + display: flex; + flex-flow: row nowrap; + align-items: center; + background: $color-black-92-2; + color: $color-dark-blue-gray; + font-size: 12px; + font-weight: bold; + letter-spacing: 2px; + height: 40px; + line-height: 40px; + text-transform: uppercase; + user-select: none; + cursor: default; + } + + > .standardtitle > .challenge-table-label { + flex: 0 0 auto; + height: 100%; + padding: 0 16px; + background: $color-black-83-1; + } + + > .standardtitle > .title { + flex: 1; + height: 100%; + padding: 0 16px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + > .standarditem { + position: relative; + background: white; + + &:not(:last-of-type) { + border-bottom: 2px solid $color-black-83-1; + } + + &.-is-expanded > .itemheading > .iconwrapper.arrow { + transform: rotate(0); + color: $color-cyan; + } + } + + > .standarditem > .itemheading { + color: $color-dark-blue-gray; + background: white; + position: relative; + display: flex; + flex-flow: column; + justify-content: center; + height: $cell-height; + + &:hover { + cursor: pointer; + color: $color-cyan; + } + } + + > .standarditem > .itemheading > .iconwrapper { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: auto; + margin: auto; + margin-left: 8px; + height: 24px; + width: 24px; + } + + > .standarditem > .itemheading > .iconwrapper { + &.arrow { + transform: rotate(-90deg); + color: inherit; + } + &.star { + color: $color-galvanize-orange + } + } + + > .standarditem > .itemheading > .challenge-table-label { + text-transform: uppercase; + color: $color-black-60-8; + font-size: 10px; + letter-spacing: 2px; + line-height: 16px; + margin-left: 40px; + } + + > .standarditem > .itemheading > .title { + //color: $dark-blue-gray; + color: inherit; + font-size: 16px; + line-height: 24px; + margin-left: 40px; + padding-right: 16px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + > .standarditem > .itemheading > .title > a { + text-decoration: none; + color: inherit; + } + + > .standarditem > .itembody { + position: relative; + height: $cell-height; + background: $color-black-97-3; + border-left: 4px solid $color-cyan; + padding-left: 32px; + } + + > .standarditem > .itembody > .short-border-box { + display: flex; + flex-flow: column; + justify-content: center; + border-top: 1px solid $color-black-93-3; + height: 100%; + } + + > .standarditem > .itembody > .short-border-box > .challenge-table-label { + color: $color-black-60-8; + font-size: 10px; + letter-spacing: 2px; + line-height: 16px; + text-transform: uppercase; + margin-left: 16px; + } + + > .standarditem > .itembody > .short-border-box > .title { + color: $color-dark-blue-gray; + font-size: 16px; + line-height: 24px; + margin-left: 16px; + margin-right: 8px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } +} + +.submissions-dashboard-table-wrapper { + + .flex-row { + > .nameplate { + margin-bottom: 1rem; + } + + > .nameplate > .avatar-wrapper { + width: 40px; + display: inline-block; + line-height: 40px; + margin-right: 10px; + vertical-align: middle; + } + + > .nameplate > span { + display: inline-block; + line-height: 40px; + font-size: 1.1rem; + vertical-align: middle; + color: $color-darker-gray-blue; + } + } +} + +.challengeindex-table { + & { + position: relative; + display: flex; + flex-flow: row nowrap; + overflow: hidden; + background-color: $color-white; + box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1); + } + + &:after { + content: ""; + position: absolute; + left: 100%; + top: 0; + bottom: 0; + box-shadow: -4px 0 6px 1px rgba(black, 0.1); + background: white; + width: 10px; + } + + &.single-student { + &:after { + box-shadow: none; + } + } + + > .studentspanel { + position: relative; + z-index: 0; + flex: 1 1 100%; + overflow: hidden; + background: $color-black-83-1; + } + + > .studentspanel .studentcolumn { + @extend %student-column; + } + + > .curriculumpanel { + position: relative; + z-index: 1; + flex: 0 0 auto; + width: 320px; + padding-top: $cell-height; + box-shadow: 4px 0 6px 1px rgba(black, 0.1); + } + + > .curriculumpanel > .block-title { + background: $color-black-70-2; + height: 40px; + padding: 0 1rem; + color: $color-dark-blue-gray; + font-size: 12px; + font-weight: bold; + letter-spacing: 2px; + line-height: 40px; + text-transform: uppercase; + user-select: none; + cursor: default; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + > .curriculumpanel > .standard { + @extend %standard-item; + } + + > .curriculumpanel { + &.single-student { + padding-top: 0; + box-shadow: none; + + > .standard > .standarditem { + border-right: 2px solid $color-black-83-1; + } + } + } + + > .studentspanel { + &.single-student { + overflow-x: auto; + + .studentcolumn { + flex: 1 0 auto; + } + + > .studentcolumn > .standard > .standarditem > .itemheading { + flex-flow: row; + justify-content: flex-end; + } + + > .studentcolumn > .standard > .standarditem > .itembody { + flex-flow: row; + justify-content: flex-end; + } + + > .studentcolumn > .standard > .standarditem > .itemheading svg.donut { + width: 24px; + } + } + } +} + +.columnwrapper { + width: 100%; + overflow: auto; + display: flex; + flex-flow: row nowrap; +} + +.studentnamebar { + position: fixed; + top: 0; + z-index: 999; + width: calc(100% - 32px - 320px); + overflow: auto; + + &.-is-hidden { + visibility: hidden; + pointer-events: none; + } + + > .studentavatars { + display: flex; + flex-flow: row nowrap; + } + + > .studentavatars > .student { + background: $color-white; + flex: 0 0 auto; + display: flex; + flex-flow: column; + align-items: center; + justify-content: center; + height: $cell-height; + width: 40px; + padding: 8px; + border-bottom: 1px solid $color-black-83-1; + + &:hover { + background: $color-black-97-3; + } + } +} + +.dropdown-component > select { + background-color: $color-white; +} + +.icon-legend { + & { + height: 48px; + background: none; + border: 1px solid $color-black-83-1; + border-radius: 4px; + display: inline-flex; + flex-flow: row nowrap; + vertical-align: bottom; + align-items: center; + margin-bottom: 32px; + user-select: none; + overflow: hidden; + position: relative; + } + + > .item { + flex: 1 0 auto; + display: flex; + flex-flow: row nowrap; + align-items: center; + margin: 0 16px; + } + + > .item > .challenge-table-label { + color: $color-darker-gray-blue; + font-size: 16px; + line-height: 22px; + } + + > .item > .svg { + margin-right: 8px; + } +} + +.flex-row { + & { + position: relative; + display: flex; + flex-flow: row; + } + &.-align-middle { + align-items: center; + } + + > .-flex-alignright { + margin-right: 0; + margin-left: auto; + } + + > .-margin-right { + margin-right: 8px; + } +} + +// other flex-row styles +.flex-row > .pullright { + margin-right: 0; + margin-left: auto; +} diff --git a/app/assets/stylesheets/components/_svg-icon.scss b/app/assets/stylesheets/components/_svg-icon.scss new file mode 100644 index 0000000..203a037 --- /dev/null +++ b/app/assets/stylesheets/components/_svg-icon.scss @@ -0,0 +1,33 @@ +svg.icon { + fill: currentColor; + display: inline-block; + height: 24px; + width: 24px; +} + +svg, +.svg { + fill: currentColor; + width: 24px; + height: 24px; +} + +.svg-24px { + width: 24px; + height: 24px; +} + +.svg-21px { + width: 21px; + height: 21px; +} + +.svg-18px { + width: 18px; + height: 18px; +} + +.svg-15px { + width: 15px; + height: 15px; +} diff --git a/app/assets/stylesheets/components/_thresholds.scss b/app/assets/stylesheets/components/_thresholds.scss new file mode 100644 index 0000000..9ada910 --- /dev/null +++ b/app/assets/stylesheets/components/_thresholds.scss @@ -0,0 +1,33 @@ +.thresholds-key-wrapper-div { + display: flex; + padding-top: 10px; + + .settings-cog { + display: flex; + align-items: center; + cursor: pointer; + height: 25px; + width: 25px; + position: relative; + + svg { + fill: $color-cyan; + } + + &:hover { + svg { + fill: #2D909A; + } + } + } +} + +.lesson-layout .body-container .mdown-container .settings-cog { + top: 4px; +} + +.lesson-layout .body-container .mdown-container p.thresholds-key-content { + margin-top: 1px; + margin-right: 30px; + margin-bottom: 0; +} \ No newline at end of file diff --git a/app/assets/stylesheets/components/_universal-list.scss b/app/assets/stylesheets/components/_universal-list.scss new file mode 100644 index 0000000..11d4568 --- /dev/null +++ b/app/assets/stylesheets/components/_universal-list.scss @@ -0,0 +1,46 @@ +.universal-list-wrapper { + + background-color: $color-alabaster; + + .one-column { + @include one-column; + } + + .list__header { + display: flex; + justify-content: flex-start; + margin-bottom: 20px; + align-items: center; + + h1 { + @include font-h1-settings; + } + + } + + .list__header-bar { + display: flex; + justify-content: flex-end; + align-items: center; + margin-bottom: 12px; + + button { + @include button-theme($color-primary-teal, 'material'); + } + } + + .list-container { + @include list-container; + + a:hover { + text-decoration: none; + } + } + + .back-btn { + height: 24px; + margin-right: 8px; + margin-bottom: 40px; + } + +} diff --git a/app/assets/stylesheets/components/_universal-row.scss b/app/assets/stylesheets/components/_universal-row.scss new file mode 100644 index 0000000..4074033 --- /dev/null +++ b/app/assets/stylesheets/components/_universal-row.scss @@ -0,0 +1,68 @@ +.universal-row { + display: flex; + justify-content: space-between; + padding: 30px 40px; + border-bottom: 2px solid $color-black-94-9; + + h2 { + @include font-h2-settings; + } + + a { + @include link-theme; + } + + p { + @include font-paragraph; + font-size: 15px; + line-height: 20px; + margin-bottom: 15px; + } + + img { + margin-right: 6px; + margin-bottom: 1px !important; + fill: #000; + } + + .gray-text { + color: $color-silver-chalice; + font-weight: 500; + } + + .row__footer { + display: flex; + flex-wrap: wrap; + } + + .pill-wrapper { + margin-right: 5px; + margin-top: 5px; + } + + .row__title-col :last-child { + margin-bottom: 0; + } + + .row__title-col { + flex-grow: 1; + + .row__cat-header { + @include font-caption; + margin-left: 3px; + margin-bottom: 15px; + } + } + + &.hidden { + display: none; + } +} + +.universal-row-click-wrapper { + cursor: pointer; + + &:hover { + box-shadow: $hover-box-shadow; + } +} diff --git a/app/assets/stylesheets/components/_universal-table.scss b/app/assets/stylesheets/components/_universal-table.scss new file mode 100644 index 0000000..d9998c7 --- /dev/null +++ b/app/assets/stylesheets/components/_universal-table.scss @@ -0,0 +1,121 @@ +.universal-table__wrapper { + + .universal-table__table { + font-size: 16px; + width: 100%; + table-layout: fixed; + + tbody { + color: $color-tundora; + border: 1px solid $color-mercury; + font-weight: 500; + background: white; + + &.--box-shadow { + box-shadow: 0 1px 10px 0 rgba(0,0,0,0.06); + } + + tr { + border-bottom: 1px solid $color-black-93-3; + height: 56px; + + &.--highlight:hover { + border-bottom: 1px solid #d0d0d0; + box-shadow: 0 0 10px 0 rgba(0,0,0,0.08); + } + + &.--disabled { + background: $color-alabaster; + color: $color-black-60; + + a, span, div { + color: $color-black-60; + } + } + + &.--selected td { + background: rgba(77, 169, 179, 0.1); + } + + &:last-of-type { + td { + border-bottom: none; + } + } + } + } + + th, td { + white-space: nowrap; + padding: 0 20px; + overflow: hidden; + text-overflow: ellipsis; + + &.checkbox-col { + width: 5%; + text-align: center; + } + + &:first-child { + padding-left: 30px; + } + + &:last-child { + padding-right: 30px; + } + } + + th { + height: 36px; + color: $color-dove-gray; + font-weight: 500; + } + + td { + height: inherit; + + a, span { + color: $color-tundora; + text-decoration: none; + height: 100%; + display: flex; + align-items: center; + display: inline-block; + height: fit-content; + vertical-align: middle; + } + + a:hover { + color: $color-link-blue; + } + + .user-avatar { + margin-right: 10px; + } + + div { + max-width: 170px; + overflow: hidden; + text-overflow: ellipsis; + display: inline-block; + vertical-align: middle; + } + } + + .--empty { + text-align: center; + } + + .universal-table__col { + overflow: visible !important; + } + } + + .universal-table__view-all-btn { + @include font-paragraph; + font-size: 15px; + color: $color-primary-teal; + cursor: pointer; + width: fit-content; + } +} diff --git a/app/assets/stylesheets/components/_user-avatar.scss b/app/assets/stylesheets/components/_user-avatar.scss new file mode 100644 index 0000000..c8d3f38 --- /dev/null +++ b/app/assets/stylesheets/components/_user-avatar.scss @@ -0,0 +1,65 @@ +.user-avatar { + & { + background-color: $color-black-60; + background-size: contain; + border-radius: 100%; + height: 24px; + position: relative; + min-width: 24px; + width: 24px; + color: $color-white; + } + + > svg { + height: 100%; + width: 100%; + position: absolute; + top: 0; + left: 0; + } +} + +.student-details { + display: flex; + flex-flow: row nowrap; + align-items: center; + justify-content: flex-start; + + span { + margin-left: 10px; + } +} + +.submit-with-avatars .user-avatar { + border: 2px solid $color-primary-teal; + background: $color-white; + color: $color-primary-teal; + height: 28px; + width: 28px; + svg text { + font-weight: 500; + } +} + +.submit-with-avatars { + display: flex; + align-items: center; + + &.showing-many { + padding-left: 5px; + + .user-avatar:nth-of-type(1) { + margin-left: 5px; + z-index: 3; + } + .user-avatar:nth-of-type(2) { + z-index: 2; + left: -5px; + } + .user-avatar:nth-of-type(3) { + z-index: 1; + left: -10px; + } + } + +} diff --git a/app/assets/stylesheets/components/_video-player.scss b/app/assets/stylesheets/components/_video-player.scss new file mode 100644 index 0000000..5ffe300 --- /dev/null +++ b/app/assets/stylesheets/components/_video-player.scss @@ -0,0 +1,10 @@ +// just additional styles +.fluidvids-item { + box-shadow: 0 0 0 1px $color-black-96-1; +} + +// width overwrite +.p3sdk-container > .p3sdk-interactive-transcript { + min-width: 100%; + max-width: 100%; +} diff --git a/app/assets/stylesheets/components/badge.scss b/app/assets/stylesheets/components/badge.scss new file mode 100644 index 0000000..2a57f35 --- /dev/null +++ b/app/assets/stylesheets/components/badge.scss @@ -0,0 +1,26 @@ +.lp-badge { + height: 20px; + min-width: 80px; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 4px; + color: $color-white; + font-size: 10px; + font-weight: bold; + letter-spacing: 1px; + padding: 2px 8px; + text-transform: uppercase; + + &.-default { + background-color: $color-black-60-8; + } + + &.-info { + background-color: $color-cyan; + } + + &.-error { + background-color: $color-valencia; + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/components/challenge-detail-comments.scss b/app/assets/stylesheets/components/challenge-detail-comments.scss new file mode 100644 index 0000000..8cc5af6 --- /dev/null +++ b/app/assets/stylesheets/components/challenge-detail-comments.scss @@ -0,0 +1,94 @@ +.challenge-detail-comments-wrapper { + & { + border-top: 1px solid $color-black-94-9; + padding: 24px; + } + + .label.gray-label { + padding-left: 0px; + } + + .challenge-detail-comments { + & { + padding-top: 15px; + margin-top: 8px; + } + + > div > .avatar-name-date { + display: flex; + flex-direction: row; + align-items: center; + } + + > div > .avatar-name-date > .avatar-wrapper { + height: 32px; + width: 32px; + margin-right: 8px; + } + + .comment-content { + background-color: $color-white; + border-radius: 10px; + margin: 10px 0px 16px 40px; + padding: 5px 10px; + } + + .comment-name { + font-weight: bold; + } + + .date { + font-size: 12px; + margin-left: auto; + color: $color-black-60-8; + } + + .item-wrapper { + position: relative; + } + + .item-wrapper:before, + .item-wrapper:after { + content: ""; + position: absolute; + z-index: -1; + top: 0; + left: 15px; + right: auto; + margin: auto 0; + width: 0; + height: calc(100% + 2rem); + border: 1px solid rgb(191, 191, 191); + } + + .item-wrapper:before { + bottom: 0; + } + + .item-wrapper:last-child:before { + top: -1rem; + bottom: auto; + height: calc(44px / 2 + 1rem); + } + + .item-wrapper:last-child:after { + display: block; + top: calc(44px / 2); + bottom: auto; + height: calc(100% + 1rem); + border-color: $color-black-97-3; + } + + .item-wrapper:first-child:before, + .item-wrapper:only-child:before { + top: auto; + bottom: -1rem; + height: 100%; + } + } + + .null-comments-block { + font-size: 16px; + font-style: italic; + } +} diff --git a/app/assets/stylesheets/components/challenge-detail-view.scss b/app/assets/stylesheets/components/challenge-detail-view.scss new file mode 100644 index 0000000..8ae98b3 --- /dev/null +++ b/app/assets/stylesheets/components/challenge-detail-view.scss @@ -0,0 +1,38 @@ +.user-challenge-show { + .challenge { + padding-left: 28px; + } +} + +.comments-standards { + background-color: $color-black-97-3; + z-index: 0; + + .standard-card { + z-index: 2; + } + + .label { + flex: 1 1 100%; + height: 12px; + font-size: 12px; + font-weight: bold; + letter-spacing: 1px; + line-height: 12px; + text-transform: uppercase; + padding-left: 0; + + &.gray-label { + color: $color-black-60-8; + } + + &.cyan-label { + color: $color-cyan; + } + } +} + +[class*="col-"].no-gutter { + padding-right: 0; + padding-left: 0; +} diff --git a/app/assets/stylesheets/components/challenge-timeline.scss b/app/assets/stylesheets/components/challenge-timeline.scss new file mode 100644 index 0000000..d7c3610 --- /dev/null +++ b/app/assets/stylesheets/components/challenge-timeline.scss @@ -0,0 +1,69 @@ +.challenge-timeline { + background-color: $color-dark-cyan; + color: $color-white; + display: flex; + justify-content: center; + align-items: center; + + > .timestamp { + padding: 19px; + background-color: rgba(0,0,0,0.3); + font-size: 12px; + white-space: nowrap; + } + + > ul { + display: flex; + list-style: none; + flex-grow: 1; + height: 100%; + align-items: center; + margin: 0; + padding: 16px 0; + margin-right: 8px; + overflow-x: auto; + } + > ul > div > li { + height: 4px; + width: 4px; + background-color: white; + border-radius: 50%; + } + > ul > div { + display: flex; + justify-content: center; + align-items: center; + border-radius: 50%; + min-height: 14px; + min-width: 14px; + margin: 0 8px; + cursor: pointer; + cursor: hand; + } + > ul > div.highlight { + background-color: rgba(255,255,255,0.3); + } + + > .buttons { + height: 100%; + display: flex; + align-items: center; + padding: 16px; + border-left: 1px solid $color-white; + } + > .buttons > div { + align-items: center; + display: flex; + cursor: pointer; + cursor: hand; + } + > .buttons > div:first-of-type { + margin-right: 12px; + } + > .buttons > div > .svg.primary-color { + color: $color-white; + } + > .buttons > div.disabled > .svg.primary-color { + color: $color-cyan; + } +} diff --git a/app/assets/stylesheets/components/new-comment-form.scss b/app/assets/stylesheets/components/new-comment-form.scss new file mode 100644 index 0000000..2c10aca --- /dev/null +++ b/app/assets/stylesheets/components/new-comment-form.scss @@ -0,0 +1,94 @@ +.new-comment-form { + & { + border-top: 1px solid $color-black-94-9; + padding: 24px; + } + + textarea { + resize: none; + width: 100%; + border: 2px solid $color-black-92-2; + border-radius: 4px; + background-color: $color-white; + outline: none; + padding: 8px; + } + + textarea:focus { + box-shadow: 0 0 3px 0 $color-cyan; + border-color: $color-cyan; + } + + .actions { + & { + display: flex; + } + + a { + flex: 1 1 auto; + color: $color-black-51; + + &:hover { + color: $color-cyan; + text-decoration: none; + } + + > svg { + margin-top: 6px; + } + + > p { + font-size: 10px; + margin-left: 32px; + margin-top: -24px; + } + } + + span { + height: 16px; + width: 187px; + color: $color-black-60-8; + font-size: 12px; + line-height: 16px; + } + + .comment-preview-link { + display: inline-block; + flex: 0 0 auto; + padding: 12px 16px; + border: none; + font-size: 12px; + font-weight: bold; + letter-spacing: 1px; + text-transform: uppercase; + text-decoration: none; + color: $color-cyan; + cursor: pointer; + } + + .lp-style-button { + min-width: 80px; + } + } + + .comment-preview { + background-color: $color-white; + box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1); + padding: 16px; + margin-bottom: 8px; + + p { + margin: 0; + } + } +} + +.comment-and-reject { + background-color: $color-white; + color: $color-black-20; + box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.3); + position: absolute; + min-width: 448px; + right: 6px; + z-index: 10; +} diff --git a/app/assets/stylesheets/components/partnerup.scss b/app/assets/stylesheets/components/partnerup.scss new file mode 100644 index 0000000..1bc5f7f --- /dev/null +++ b/app/assets/stylesheets/components/partnerup.scss @@ -0,0 +1,249 @@ +.partnerup { + .empty-pairs { + margin-top: 1rem; + } + + max-width: 1200px; + display: flex; + justify-content: center; + flex-direction: column; + align-items: center; + margin: 0 auto; + + .actions { + width: 60%; + display: flex; + justify-content: space-around; + text-align: center; + border-bottom: 1px solid #ccc; + } + + .actions > .action-item{ + font-size: 18px; + line-height: 16px; + font-weight: 500; + padding: 16px 0; + width: 50%; + border-bottom: 4px solid transparent; + cursor: pointer; + } + + .actions > .action-item.active { + color: $color-cyan; + border-bottom: 4px solid $color-cyan; + } + + .past-pairings { + &.hide { display: none; } + + .pairing { + &:first-child { + margin-top: 30px; + } + + &:not(:first-child) { + margin-top: 70px; + } + + .pairing-header { + display: flex; + justify-content: space-between; + align-items: center; + width: 447px; + margin: 0 auto; + + .pairing-title { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + } + + .pairing-groups { + display: flex; + flex-flow: column wrap; + + .pairing-edit { + cursor: pointer; + color: $color-cyan; + font-size: 0.9rem; + font-weight: 300; + } + } + + .group { + display: flex; + flex-wrap: wrap; + flex-direction: row; + border-bottom: 1px solid $color-black-83-1; + } + } + + .toggle-history { + display: flex; + justify-content:center; + align-items: center; + margin: 1rem 0; + } + } + + .student { + width: 12rem; + height: 3.5rem; + padding-right: 0.5rem; + display: flex; + flex-grow: 1; + flex-flow: row nowrap; + align-items: center; + + .user-avatar { + margin: 0 0.5rem; + } + + .name { + color: $color-darker-gray-blue; + font-size: 18px; + line-height: 24px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + + .student-actions { + margin-right: 0; + margin-left: auto; + + .fa { + cursor: pointer; + } + } + } + + .pairingform { + margin-top: 30px; + width: 100%; + + &.hide { display: none; } + + h3 { + text-align: center; + } + + input, select { + border: 2px solid #D4D4D4; + border-radius: 5px; + background-color: #FFFFFF; + padding: 8px; + height: 32px; + } + + .form { + display: flex; + flex-flow: column; + width: 600px; + margin: 0 auto; + + .form-inputs { + display: flex; + justify-content: space-around; + flex-flow: row; + } + + .form-group { + margin: 0 1rem; + } + } + + .form-buttons { + display: flex; + justify-content: space-around; + align-items: center; + margin: 1rem 0; + + button { + width: 5rem; + margin: 0 1rem; + + &:disabled { + cursor: not-allowed; + } + } + } + } + + .copy-to-clipboard-container { + display: flex; + align-items: center; + padding-left: 17px; + + .transition-group { + padding-bottom: 20px; + padding-left: 10px; + font-weight: 600; + } + + .copy-text { + position: absolute; + color: $color-galvanize-orange; + } + + .opacity-fade-enter { + opacity: 0.01; + } + + .opacity-fade-enter.opacity-fade-enter-active { + opacity: 1; + transition: opacity 400ms ease-in; + } + + .opacity-fade-leave { + opacity: 1; + } + + .opacity-fade-leave.opacity-fade-leave-active { + opacity: 0.01; + transition: opacity 400ms ease-in; + } + } + + .drag-area { + padding: 0.5rem; + background: $color-black-88-2; + + .student-list-wrapper { + display: flex; + flex-direction: row; + flex-wrap: wrap; + + .inner-student-list-wrapper { + width: 280px; + margin-right: 1rem; + padding: 0.5rem; + + .student { + box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.2); + margin: 1rem 0; + background-color: #ffffff; + width: 100%; + + .fa-exclamation-triangle { + margin-left: 0.5rem; + color: $color-banana-yellow; + cursor: default; + } + } + } + } + } + + .lp-style-button.-outline.-small { + border: 1px solid transparent; + padding: 2px 10px; + color: $color-cyan; + + &:hover { + color: $color-white; + } + } +} + diff --git a/app/assets/stylesheets/components/progress-table.scss b/app/assets/stylesheets/components/progress-table.scss new file mode 100644 index 0000000..015d8e5 --- /dev/null +++ b/app/assets/stylesheets/components/progress-table.scss @@ -0,0 +1,355 @@ +.progress-table { + & { + position: relative; + margin: 10px 32px; + } + + .column-header { + max-width: 78px; + overflow: hidden; + text-overflow: ellipsis + } + + .bold-font { + font-weight: bold; + } + + .export-container { + display: flex; + flex-flow: row nowrap; + position: relative; + padding-top: 10px; + } + + > .export-container > .lp-style-button { + position: relative; + color: white; + } + + > .export-container > .lp-style-button > img { + width: 20px; + height: 20px; + margin-right: 5px; + } + + > .heading { + border-bottom: 2px solid #d4d4d4; + position: relative; + } + + + > .heading > .progress-row { + display: flex; + flex-flow: row nowrap; + overflow: hidden; + margin-top: 25px; + + .cell.threshold.percentage:not(:first-child) { + margin: 0 5px 0 5px; + } + } + + // Disable scroll bar when horizontally scrolling + .heading .progress-row::-webkit-scrollbar { height: 0 !important } + .heading .progress-row { + -ms-overflow-style: none; + overflow: -moz-scrollbars-none; + } + + .progress-body .progress-row:not(:last-child)::-webkit-scrollbar { height: 0 !important } + .progress-body .progress-row:not(:last-child) { + -ms-overflow-style: none; + overflow: -moz-scrollbars-none; + } + + > .heading > .progress-row > .cell { + flex: 0 0 auto; + display: flex; + flex-flow: row nowrap; + align-items: center; + padding: 0 16px; + } + + > .heading > .progress-row > .cell.avg { + justify-content: center; + } + + > .heading > .progress-row > .cell > .label { + color: #9b9b9b; + font-size: 12px; + letter-spacing: 2px; + height: 24px; + line-height: 24px; + text-transform: uppercase; + display: flex; + flex-flow: row nowrap; + align-items: center; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + user-select: none; + + &.-is-sortable { + display: flex !important; + justify-content: center !important; + align-items: center !important; + + cursor: pointer; + + &:hover { + color: #000; + } + } + } + + > .heading > .progress-row > .cell.threshold { + display: flex; + flex-flow: row nowrap; + } + + > .heading > .progress-row > .cell.threshold > .label { + flex: 1 1 auto; + width: calc(100% / 3); + display: flex; + flex-flow: column; + align-items: center; + justify-content: flex-end; + height: 60px; + white-space: normal; + line-height: 1rem; + } + + > .heading > .progress-row > .cell.percentage > .label { + flex-flow: row; + justify-content: center; + align-items: flex-end; + } + + > .heading > .progress-row > .cell.threshold > .label > .score-circle { + margin-bottom: 8px; + } + + > .progress-body { + background: #e7e7e7; + box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1); + } + + > .progress-body > .progress-row { + display: flex; + flex-flow: row nowrap; + overflow: hidden; + height: 60px; + background: white; + border-bottom: 1px solid #e7e7e7; + } + + > .progress-body > .progress-row > .cell { + flex: 0 0 auto; + display: flex; + flex-flow: row nowrap; + align-items: center; + padding: 0 16px; + } + + .progress-body .progress-row .cell:not(:first-child) { + margin: 0 5px 0 5px; + } + + > .progress-body > .progress-row > .cell.avg { + flex: 0 0 auto; + } + + > .progress-body > .progress-row > .cell.mastery-progress, .percentage-progress { + flex: 1 1 auto; + display: flex; + flex-flow: column; + align-items: flex-start; + justify-content: center; + font-weight: 500; + color: #898989; + font-size: 20px; + } + + > .progress-body > .progress-row > .cell.mastery-progress > .label { + height: 16px; + color: #9b9b9b; + font-size: 12px; + line-height: 16px; + margin-top: 8px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + > .progress-body > .progress-row > .cell.threshold { + display: flex; + flex-flow: row nowrap; + } + + > .progress-body > .progress-row > .cell.threshold > .percent-box { + flex: 1 1 100%; + } + + > .progress-body > .progress-row > .cell.student { + display: flex; + flex-flow: row nowrap; + align-items: center; + font-size: 18px; + } + + .heading .progress-row .cell.student:not(:first-child) { + margin: 0 5px 0 5px; + } + + > .progress-body > .progress-row > .cell.student > .user-avatar { + flex: 0 0 auto; + padding-top: 0; + height: 32px; + width: 32px; + } + + a { + color: rgba(0, 165, 181, 1); + margin-left: 16px; + + &:hover { + color: rgba(1, 123, 134, 1); + } + } + + .avg-box { + color: white; + background: $color-black-20; + display: flex; + align-items: center; + justify-content: center; + height: 40px; + width: 100%; + min-width: 40px; + padding: 8px 16px; + font-size: 20px; + font-weight: bolder; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + } + + .percent-box { + $one-color: #dc3549; + $two-color: #4b5259; + $three-color: #9cca68; + color: #898989; + border: 1px solid; + background: white; + display: flex; + align-items: center; + justify-content: center; + height: 45px; + min-width: 56px; + padding: 8px; + font-size: 20px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + border-radius: 5%/15%; + font-weight: 500; + + &:not(:last-of-type) { + margin-right: 8px; + } + + &.-is-one { + color: black; + border-color: rgba($one-color, 0.5); + background-color: white; + } + + &.-is-one.-is-filled { + color: white; + background-color: $one-color; + } + + &.-is-two { + color: black; + border-color: rgba($two-color, 0.5); + background-color: white; + } + + &.-is-two.-is-filled { + color: white; + background-color: $two-color; + } + + &.-is-three { + color: black; + border-color: rgba($three-color, 0.5); + background-color: white; + } + + &.-is-three.-is-filled { + color: white; + background-color: $three-color; + } + } + + .percentage-progressbar { + margin-left: 10px; + .progress-complete { + height: 10px; + background-color: #9A9A9A; + border-radius: 8px; + } + } + + .mastery-progressbar, .percentage-progressbar { + $one-color: #dc3549; + $two-color: #4b5259; + $three-color: #9cca68; + $bg-color: #efefef; + + & { + display: flex; + height: 10px; + width: 100%; + min-width: 100px; + border-radius: 8px; + overflow: hidden; + } + + > .one, + .two, + .three { + height: inherit; + border-right: 1px solid $bg-color; + } + + > .one { + background: $one-color; + } + + > .two { + background: $two-color; + } + + > .three { + background: $three-color; + } + } + + &.Percentage { + a { + color: $color-black-20; + } + + .percent-box { + min-width: 110px; + + &.percentage-mode { + border: 0px; + color: $color-black-30-2; + } + } + } +} diff --git a/app/assets/stylesheets/hopscotch-overrides.scss b/app/assets/stylesheets/hopscotch-overrides.scss new file mode 100644 index 0000000..d9bc5c3 --- /dev/null +++ b/app/assets/stylesheets/hopscotch-overrides.scss @@ -0,0 +1,100 @@ +.hopscotch-bubble-number { + content: ""; + background-image: url(/assets/svg/mobile-logo-d01e8af51b97d9f642d52a826ffe07193b8290e4d1767f6f2b2475bac759e9bc.svg)!important; + background-size: 130%!important; + height: 80px!important; + margin-top: -11px!important; +} + +.hopscotch-bubble { + border: 0px!important; + border-radius: 6px!important; + background-color: #333!important; + box-shadow: 2px 2px 8px rgba(0,0,0,0.4)!important; +} + +.hopscotch-bubble-arrow-border { + visibility: hidden!important; +} + +.hopscotch-bubble-arrow-container.left .hopscotch-bubble-arrow { + border-right: 17px solid #333!important; +} + +.hopscotch-bubble-arrow-container.right .hopscotch-bubble-arrow { + border-left: 17px solid #333!important; +} + +.hopscotch-bubble-arrow-container.up .hopscotch-bubble-arrow { + border-bottom: 17px solid #333!important; +} + +.hopscotch-bubble-arrow-container.down .hopscotch-bubble-arrow { + border-top: 17px solid #333!important; +} + +.hopscotch-bubble-container { + width: 360px!important; + padding: 40px!important; +} + +.hopscotch-title { + font-size: 28px!important; + color: #eee!important; + font-family: "proxima-nova"!important; + line-height: 1!important; + margin-bottom: 20px!important; + margin-left: 15px!important; + letter-spacing: -0.75px!important; +} + +.hopscotch-content { + font-size: 18px!important; + color: #ccc!important; + font-family: "proxima-nova"!important; + font-weight: 300!important; + line-height: 1.3!important; + margin-left: 15px!important; +} + +.hopscotch-actions { + margin-top: 35px!important; + margin-bottom: 10px!important; + text-align: center!important; +} + +.hopscotch-nav-button { + $color-em: 8; + $color-height: ($color-em * 5 + px); + + & { + display: inline-block !important; + height: $color-height !important; + width: auto !important; + min-width: 120px !important; + padding: 0 ($color-em * 3 + px) !important; + border: none !important; + border-radius: 100px !important; + background-color: $color-cyan !important; + background-image: none !important; + cursor: pointer !important; + line-height: $color-height !important; + color: white !important; + font-size: ($color-em * 1.5 + px) !important; + font-weight: bold !important; + letter-spacing: 1px !important; + text-align: center !important; + text-transform: uppercase !important; + vertical-align: middle !important; + } + + &:focus { + outline: 0 !important; + } + + &:hover { + color: white !important; + background-color: #2396a0 !important; + text-decoration: none !important; + } +} diff --git a/app/assets/stylesheets/mixins.scss b/app/assets/stylesheets/mixins.scss new file mode 100644 index 0000000..d06598c --- /dev/null +++ b/app/assets/stylesheets/mixins.scss @@ -0,0 +1,197 @@ +// Fonts +// ===== + +@mixin font-base () { + color: $color-tundora; + font-size: 19px; + font-weight: 300; + line-height: 1.7; + text-align: left; + font-style: normal; +} + +@mixin font-small () { + @include font-base; + font-size: 15px; +} + +@mixin font-h1 () { + font-size: 48px; + font-weight: 300; + letter-spacing: -1px; + line-height: 1.1; +} + +@mixin font-h3 () { + font-size: 32px; + line-height: $font-default-line-height; + text-align: left; + color: $color-emperor; + font-style: normal; + font-weight: 300; + font-family: $font-famiy-system; +} + +@mixin font-h1-settings () { + font-size: 36px; + line-height: $font-default-line-height; + margin-bottom: 40px; + text-align: left; + color: $color-emperor; + font-style: normal; + font-weight: 300; + font-family: $font-famiy-system; +} + +@mixin font-h2-settings () { + font-size: 21px; + font-weight: 500; + color: $color-tundora; + margin-bottom: 15px; + font-family: $font-famiy-system; +} + +@mixin font-paragraph () { + font-size: 16px; + line-height: $font-default-line-height; + text-align: left; + color: $color-tundora; + font-style: normal; + font-weight: 400; + font-family: $font-famiy-system; +} + +@mixin font-caption () { + font-size: 14px; + line-height: $font-default-line-height; + text-align: left; + color: $color-gray; + font-style: normal; + font-weight: 500; + font-family: $font-famiy-system; + letter-spacing: 1.3px; + text-transform: uppercase; +} + +// Components +// =========== + +@mixin input () { + height: $input-height; + border-radius: $round-corners-1; + padding-left: $input-spacing; + padding-right: $input-spacing; + margin: $input-spacing; + background-color: $color-iron; + border: 1px solid $color-athens-gray; + @include font-paragraph; +} + +@mixin input-disabled () { + color: $color-boulder; +} + +@mixin modal-text-input () { + display: block; + width: 100%; + border: 1px solid #E0E0E0; + margin: 3px 0; + padding: 0 16px; + height: 45px; + border-radius: $round-corners-1; + box-shadow: inset 0px 1px 2px $color-inner-shadow; +} + +@mixin button { + display: inline-block; + border-radius: $round-corners-1; + padding: 5px 17px; + font-size: 17px; + font-weight: 400; + margin: 8px; + cursor: pointer; + white-space: nowrap; +}; + +@mixin button-theme ($color, $type: primary) { + @if $type == primary { + background-color: $color; + border: none; + color: $color-white; + } @else if $type == outline { + background-color: unset; + color: $color; + border: 1px solid $color; + } @else if $type == material { + background-color: inherit; + color: $color-primary-teal; + margin: 0; + font-weight: 500; + + &:hover { + background-color: rgba($color-primary-teal, 0.15); + } + + &:active { + background-color: rgba($color-primary-teal, 0.30); + } + } @else { + @error "Unknown button type #{$type}. Must be 'primary' or 'outline' or 'material'." + } +}; + +@mixin link-theme { + color: $color-tundora; + + &:hover { + color: $color-link-blue; + text-decoration: none; + } +} + +@mixin h5-material { + font-size: 20px; + font-weight: 500; + color: $color-tundora; + margin-bottom: 15px; + font-family: $font-famiy-system; +} + +@mixin h6-material { + @include h5-material; + font-size: 14px; + font-weight: 400; + font-family: $font-famiy-system; +} + + + +// Layouts +// ======= + +@mixin one-column () { + max-width: 1084px; + margin: 70px auto 0 auto; + padding: 0 60px; +} + +@mixin container-large () { + background-color: $color-white; + margin: 20px 0; + padding: 5px 30px 40px 30px; + border-radius: $round-corners-1; + box-shadow: $box-shadow-offset-x $box-shadow-offset-y $box-shadow-blur-radius $box-shadow-spread $color-box-shadow; +} + +@mixin list-container { + @include container-large; + padding: 0; + margin: 0; +} + +// styles + +@mixin row-hover () { + border-bottom: 1px solid #d0d0d0; + box-shadow: 0 0 10px 0 rgba(0,0,0,0.08); +} diff --git a/app/assets/stylesheets/mobile.scss b/app/assets/stylesheets/mobile.scss new file mode 100644 index 0000000..5c336bc --- /dev/null +++ b/app/assets/stylesheets/mobile.scss @@ -0,0 +1 @@ +@import "mobile/*"; \ No newline at end of file diff --git a/app/assets/stylesheets/mobile/_submissions-dashboard-table.scss b/app/assets/stylesheets/mobile/_submissions-dashboard-table.scss new file mode 100644 index 0000000..ac9e98f --- /dev/null +++ b/app/assets/stylesheets/mobile/_submissions-dashboard-table.scss @@ -0,0 +1,51 @@ +@media (max-width: 820px) { + .challengeindex-table > .curriculumpanel { + width: 83%; + } + + .challengeindex-table > .studentspanel > .studentcolumn > .standard > .emptyrow { + height: 80px; + background: linear-gradient(top, #d4d4d4 50%,#d4d4d4 50%,#ebebeb 50%) + } + + .challengeindex-table > .curriculumpanel > .standard > .standardtitle { + flex-flow: column nowrap; + height: 80px; + align-items: left; + } + + .challengeindex-table > .curriculumpanel > .standard > .standardtitle > .challenge-table-label, + .challengeindex-table > .curriculumpanel > .standard > .standardtitle > .title { + width: 100%; + height: auto; + padding: 0 2rem; + } + + .challengeindex-table > .studentspanel.single-student > .studentcolumn > .standard > .standarditem > .itemheading, + .challengeindex-table > .studentspanel.single-student > .studentcolumn > .standard > .standarditem > .itembody { + justify-content: center; + } + + .submissions-dashboard-table-wrapper .flex-row { + flex-flow: column !important; // override bootstrap class... + } + + .dropdown-component { + width: 100%; + margin-bottom: 1rem; + } + + .icon-legend { + flex-wrap: wrap; + width: 100%; + margin-bottom: 1rem; + align-items: left; + height: auto; + + .item { + width: 50%; + margin: 0; + padding: .5rem 1rem; + } + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/typography.scss b/app/assets/stylesheets/typography.scss new file mode 100644 index 0000000..5e69baa --- /dev/null +++ b/app/assets/stylesheets/typography.scss @@ -0,0 +1,5 @@ +body { + font-family: "proxima-nova", sans-serif; + font-size: 16px; + font-weight: 300; +} diff --git a/app/assets/stylesheets/variables.scss b/app/assets/stylesheets/variables.scss new file mode 100644 index 0000000..6cfcbbb --- /dev/null +++ b/app/assets/stylesheets/variables.scss @@ -0,0 +1,136 @@ +// Colors (most names from http://chir.ag/projects/name-that-color) +// ================================================================ + +$lighten: 10%; +$darken: 10%; +$more-dark: 20%; +$more-light: 20%; + + +// Brand colors +$color-primary-teal: #4DA9B3; // was #34A8B3 +$color-primary-teal-lighter: lighten( $color-primary-teal, $lighten ); +$color-primary-teal-darker: darken( $color-primary-teal, $darken ); +$color-galvanize-orange-2: #ea8832; +$color-link-blue: #007BFF; + +// Functional colors +$color-white: #ffffff; +$color-black: #000000; +$color-red: #EB574C; +$color-red-lighter: lighten( $color-red, $lighten ); +$color-red-darker: darken( $color-red, $darken ); + +// grays +$color-mine-shaft: #333333; +$color-tundora: #444444; +$color-emperor: #505050; +$color-dove-gray: #666666; +$color-boulder: #777777; +$color-gray: #888888; +$color-silver-chalice: #AAAAAA; +$color-mercury: #E3E3E3; +$color-iron: #E3E4E6; +$color-athens-gray: #F2F3F5; +$color-alabaster: #FAFAFA; +$color-lightened-black: rgba($color-black, 0.6); +$color-light-outline: rgba($color-black, 0.07); +$color-box-shadow: rgba($color-black, 0.04); +$color-inner-shadow: rgba($color-black, 0.1); +$hover-box-shadow: 0 0 10px 0 rgba(0,0,0,0.08); + +// pill colors +$color-pill-light-purple: #E3E3FC; + + +// Fonts +// ===== + +$font-famiy-system: -apple-system, BlinkMacSystemFont, "Segoe UI", + "Roboto", "Oxygen", "Ubuntu", "Helvetica Neue", Arial, sans-serif; +$font-default-line-height: 28px; +$font-family-proxima-nova: "proxima-nova", sans-serif; + +// Layouts +// ======= + +$box-shadow-offset-x: 0; +$box-shadow-offset-y: 4px; +$box-shadow-blur-radius: 20px; +$box-shadow-spread: 0; +$round-corners-1: 4px; +$input-height: 40px; +$input-spacing: 8px; + +// Styles for pages that have not been updated yet +// =============================================== + +$color-dark-gray: #666666; + + +$color-black-10-2: #1A1A1A; +$color-black-14-9: #262626; +$color-black-20: #333333; +$color-black-30-2: #606060; +$color-black-46-7: #777777; +$color-black-50-2: #808080; +$color-black-51: #828282; +$color-black-60-8: #9b9b9b; +$color-black-60-9: #9f9f9f; +$color-black-60: #999999; +$color-black-66-7: #aaaaaa; +$color-black-70-2: #b3b3b3; +$color-black-76-5: #c3c3c3; +$color-black-77: #c6c6c6; +$color-black-80: #cccccc; +$color-black-83-1: #d4d4d4; +$color-black-84-7: #d8d8d8; +$color-black-88-2: #e1e1e1; +$color-black-90-2: #e6e6e6; +$color-black-92-2: #ebebeb; +$color-black-93-3: #eeeeee; // this is gallery "color" from the link above +$color-black-94-2: #efefef; +$color-black-94-3: #e5e5e5; +$color-black-94-9: #f2f2f2; +$color-black-96-1: #f5f5f5; +$color-black-97-3: #f8f8f8; +$color-black-98-2: #fafafa; +$color-black-99-3: #f0f0f0; + +$color-galvanize-orange: #ff901e; +$color-valencia: #dc3549; +$color-med-green: #9cca68; + +$color-sky-blue: #4A90E2; +$color-cyan: #34A8B3; +$color-cyan-opacity-4: #F2FBFB; +$color-dark-cyan: #00737E; +$color-navy-blue: #0C5773; +$color-cyan-very-light: #d2e9ec; + +$color-medium-blue-gray: #3a4352; +$color-dark-blue-gray: #272e39; +$color-darker-gray-blue: #4b5259; +$color-darkest-blue-gray: #3B4248; +$color-darkester-blue-gray: #262A2E; + +// new forge colors +$color-lime-green: #7DCA60; +$color-banana-yellow: #FEC449; +$color-tangerine-orange: #FC7336; + +// old mastery table colors +$color-light-gray-blue: #c6d7f4; +$color-pale-yellow: #f4efd4; +$color-soft-orange: #fce8b2; +$color-soft-red: #f4c7c3; +$color-sage: #b7e1cd; +$color-blue-dark: #33485f; +$color-too-gray: #b6b8ba; +$color-gray-light: #e9eaec; + +// breakpoints +$tablet-breakpoint: 1024px; + +// z-index +$z-primary-navigation: 999999; diff --git a/app/component_props/activity_feed_item_component_props.rb b/app/component_props/activity_feed_item_component_props.rb new file mode 100644 index 0000000..596ab3b --- /dev/null +++ b/app/component_props/activity_feed_item_component_props.rb @@ -0,0 +1,120 @@ +class ActivityFeedItemComponentProps + def self.execute(activity) + { + id: activity.id, + creator: actor_from_activity(activity).full_name, + message: message_from_activity(activity), + created_at: activity.created_at, + label_class: label_class_from_activity(activity), + user_photo: actor_from_activity(activity).profile_image, + user_initials: actor_from_activity(activity).initials + } + end + + private_class_method def self.actor_from_activity(activity) + activity.creator.presence || activity.subject.user + end + + private_class_method def self.label_class_from_activity(activity) + case activity.name + when Activity::NAMES[:checkpoint_submission_evaluated] + performance = Performance.find_by(checkpoint_submission_id: activity.subject_id) + + case performance.score + when 1 + "-score-1" + when 2 + "-score-2" + when 3 + "-score-3" + end + when Activity::NAMES[:checkpoint_submission_created], + Activity::NAMES[:checkpoint_submission_resubmitted] + if activity.subject.submitted_challenge_answers.first.challenge.content_file.autoscore? + "-primary" + else + "-warning" + end + when Activity::NAMES[:comment_created] + "-primary" + when Activity::NAMES[:content_file_viewed] + "-default" + when Activity::NAMES[:submitted_challenge_answer_created], + Activity::NAMES[:submitted_challenge_answer_created_project], + Activity::NAMES[:submitted_challenge_answer_created_code_snippet], + Activity::NAMES[:submitted_challenge_answer_evaluated] + if activity.subject.correct? + "-success" + elsif activity.subject.incorrect? + "-danger" + elsif activity.subject.processing? + "-primary" + else + "-warning" + end + when Activity::NAMES[:video_started] + "-primary" + when Activity::NAMES[:video_ended] + "-success" + end + end + + private_class_method def self.message_from_activity(activity) + case activity.name + when Activity::NAMES[:checkpoint_submission_evaluated] + performance = Performance.find_by(checkpoint_submission_id: activity.subject_id) + content_file = activity.subject.submitted_challenge_answers.first.challenge.content_file + + "scored a #{performance.score} on #{content_file_label(content_file)}." + when Activity::NAMES[:checkpoint_submission_created], + Activity::NAMES[:checkpoint_submission_resubmitted] + + action = activity.name == Activity::NAMES[:checkpoint_submission_resubmitted] ? "resubmitted" : "submitted" + content_file = activity.subject.submitted_challenge_answers.first.challenge.content_file + + suffix = + if content_file.autoscore? + "awaiting automatic evaluation" + else + "awaiting manual scoring" + end + + "#{action} #{content_file_label(content_file)}, #{suffix}." + when Activity::NAMES[:comment_created] + "left a comment." + when Activity::NAMES[:content_file_viewed] + "viewed #{content_file_label(activity.subject)}." + when Activity::NAMES[:submitted_challenge_answer_created], + Activity::NAMES[:submitted_challenge_answer_created_project], + Activity::NAMES[:submitted_challenge_answer_created_code_snippet], + Activity::NAMES[:submitted_challenge_answer_evaluated] + + content_file = activity.subject.challenge.content_file + title = activity.subject.challenge.title + + "answered #{title} - #{content_file_label(content_file)}#{submitted_challenge_answer_suffix(activity.subject)}." + when Activity::NAMES[:video_started] + "started a video." + when Activity::NAMES[:video_ended] + "finished a video." + end + end + + private_class_method def self.content_file_label(content_file) + "#{content_file.standard.release.block.title} - #{content_file.standard.title} - #{content_file.title}" + end + + private_class_method def self.submitted_challenge_answer_suffix(submitted_challenge_answer) + if submitted_challenge_answer.correct? + " correctly" + elsif submitted_challenge_answer.incorrect? + " incorrectly" + elsif submitted_challenge_answer.ungraded? + ", awaiting manual scoring" + elsif submitted_challenge_answer.processing? + ", awaiting automatic evaluation" + else + " but ran into an error: #{submitted_challenge_answer.status}" + end + end +end diff --git a/app/component_props/notifications_component_props.rb b/app/component_props/notifications_component_props.rb new file mode 100644 index 0000000..21dd11c --- /dev/null +++ b/app/component_props/notifications_component_props.rb @@ -0,0 +1,22 @@ +class NotificationsComponentProps + def self.execute(user_id) + notifications = NotificationPolicy::Scope.new(User.find(user_id), Notification).resolve + unread_count = notifications.unread.count + + { + unreadCount: unread_count, + prettyUnreadCount: unread_count > 99 ? "99+" : unread_count, + notifications: notifications.order(read_at: :desc, created_at: :desc).map do |notification| + { + id: notification.id, + tagline: notification.tagline, + title: notification.title, + url: Rails.application.routes.url_helpers.notification_path(notification), + description: notification.description, + read_at: notification.read_at, + created_at: notification.created_at + } + end + } + end +end diff --git a/app/component_props/standard_card_component_props.rb b/app/component_props/standard_card_component_props.rb new file mode 100644 index 0000000..4ab4c68 --- /dev/null +++ b/app/component_props/standard_card_component_props.rb @@ -0,0 +1,9 @@ +class StandardCardComponentProps + attr_reader :standard, + :checkpoint_performance + + def initialize(standard:, latest_performance: nil, checkpoint_performance: nil) + @standard = StandardPresenter::ForCheckpointSubmission.new(standard: standard, latest_performance: latest_performance) + @checkpoint_performance = checkpoint_performance ? PerformancePresenter.new(checkpoint_performance) : nil + end +end diff --git a/app/controllers/api/application_controller.rb b/app/controllers/api/application_controller.rb new file mode 100644 index 0000000..128bcd8 --- /dev/null +++ b/app/controllers/api/application_controller.rb @@ -0,0 +1,114 @@ +class Api::ApplicationController < ActionController::API + include Pundit + include Api::ExceptionHandler + include Api::Response + + before_action :ensure_json_request + before_action :require_authorized_user + + around_action :monitor_api + + rescue_from ActionController::ParameterMissing do |exception| + raise exception if Rails.env.development? + + json_response( + { + "errors": { + "status": "400", + "title": "A parameter is missing to fulfill your request", + "code": "bad_request" + } + }, 400 + ) + end + + def require_authorized_user + unless current_user + json_response( + { + "errors": { + "status": "401", + "title": "You are not authenticated for this request", + "code": "unauthorized" + } + }, :unauthorized + ) + end + end + + def current_user + @current_user ||= if request.headers["Authorization"] + User.find_by(api_token: bearer_token) + else + User.find_by(uid: session[:user_uid]) + end + end + + def current_cohort + @current_cohort ||= if params[:cohort_id].present? + Cohort.find(params[:cohort_id]) + end + end + + def preview_block + @preview_block ||= Block.find_by(title: "preview") + end + + def bearer_token + pattern = /^Bearer / + header = request.headers["Authorization"] + header.gsub(pattern, "") if header&.match(pattern) + end + + def ensure_json_request + return if request.format == :json + + render body: nil, status: 406 + end + + def not_found_or_invalid_version + # does this path exist then 405 + # does this path not exist then 404 + match = request.path.match(/^\/api\/(v(?[1])?)/i) # look for a valid version + error = match && match[:version] ? :not_found : :gone + + json_response( + { + "errors": { + "status": error == :not_found ? 404 : 410, + "title": error == :not_found ? "The requested resource could not be found" : "The requested API version no longer exists", + "code": error == :not_found ? "not_found" : "gone" + } + }, + error + ) + end + + # monitor_api wraps all calls to our Api::ApplicationController and records + # data. Set @api_interaction_metadata anywhere in an api controller action + # to populate additional custom metadata for an api_interaction + def monitor_api + start = Time.now + + yield + + finish = Time.now + duration = duration_in_millseconds(start, finish) + + CreateApiInteractionJob.perform_later( + user_id: current_user&.id, + ip: request.remote_ip, + path: request.path, + method: request.method, + action_name: action_name, + duration: duration, + controller_name: controller_name, + response_code: response.code.to_i, + metadata: @api_interaction_metadata + ) + end + + def duration_in_millseconds(start, finish) + (finish - start) * 1000.0 + end +end diff --git a/app/controllers/api/v1/blocks/releases_controller.rb b/app/controllers/api/v1/blocks/releases_controller.rb new file mode 100644 index 0000000..d3d8171 --- /dev/null +++ b/app/controllers/api/v1/blocks/releases_controller.rb @@ -0,0 +1,28 @@ +class Api::V1::Blocks::ReleasesController < Api::ApplicationController + def create + render_method_not_allowed_response and return unless request.post? + authorize(Release) + + pending_release = Release.create(block_id: current_block.id, + notes: release_notes || "", + github_sha: "pending", + user_id: current_user.id, + state: Release::STATES[:pending]) + + CreateReleaseJob.perform_later(pending_release_id: pending_release.id) if pending_release.id + + json_response({ release_id: pending_release.id }, pending_release.id ? :ok : :bad_request) + end + + private + + def current_block + @current_block ||= Block.find(params[:block_id]) + end + + def release_notes + if params[:release] + params[:release][:notes] + end + end +end diff --git a/app/controllers/api/v1/blocks_controller.rb b/app/controllers/api/v1/blocks_controller.rb new file mode 100644 index 0000000..d35e507 --- /dev/null +++ b/app/controllers/api/v1/blocks_controller.rb @@ -0,0 +1,52 @@ +class Api::V1::BlocksController < Api::ApplicationController + def index + render_method_not_allowed_response and return unless request.get? + authorize(Block) + if params[:repo_name].present? + block = Block.includes(releases: :cohort_releases).where("repo_name ilike ?", params[:repo_name]) + if params[:org].present? && params[:origin].present? + block = block.where("org ilike ? AND origin ilike ?", params[:org], params[:origin]) + end + render json: { blocks: block.empty? ? [] : [block_details(block.first)] } + else + blocks = Block.includes(releases: :cohort_releases).order(title: :asc) + render json: { blocks: blocks.map {|b| block_details(b) } } + end + end + + def create + render_method_not_allowed_response and return unless request.post? + authorize(Block) + + block = Block.new(block_params) + + block.title = block.repo_name if block.title.blank? + + if block.save + json_response({ blocks: [block] }, :ok) + else + json_response( + { errors: { status: 400, title: "errors: #{block.errors.full_messages.join(', ')}" } }, + :bad_request + ) + end + end + + private + + def block_params + params.require(:block).permit(:title, :repo_name, :org, :origin) + end + + def block_details(block) + { + id: block.id, + origin: block.origin, + org: block.org, + repo_name: block.repo_name, + sync_errors: block.sync_errors, + title: block.title, + cohorts_using: block.releases.reduce([]) { |m, r| m + r.cohort_releases.map(&:cohort_id) }.compact + } + end +end diff --git a/app/controllers/api/v1/cohorts/blocks/content_files_controller.rb b/app/controllers/api/v1/cohorts/blocks/content_files_controller.rb new file mode 100644 index 0000000..33d9791 --- /dev/null +++ b/app/controllers/api/v1/cohorts/blocks/content_files_controller.rb @@ -0,0 +1,218 @@ +class Api::V1::Cohorts::Blocks::ContentFilesController < Api::ApplicationController + include Api::ContentVisibilityCrud + + def update + render_method_not_allowed_response and return unless request.patch? + + authorize(Cohort.find(params[:cohort_id]), :toggle_content_visibility?) + + result = handle_param_logic("ContentFile", visibility_type_params) + + json_response({ status: result.to_s }, result) + end + + def take_assessment + render_method_not_allowed_response and return unless request.post? + authorize(current_cohort, :take_assessment?) + + unless current_content_file.checkpoint? + json_response({ error: "only checkpoints can be assessed" }, 403) and return + end + + submission = CheckpointSubmissionFinder.latest_for_checkpoint_content_file_for_user_in_cohort( + cohort_id: current_cohort.id, + content_file: current_content_file, + user_id: current_user.id, + with_started: true + ) + + if submission.nil? || submission.state != CheckpointSubmission::STATES[:started] + # if the state was started, we don't need to check for limit reach + if user_reached_attempt_limit? + json_response(limit_reached_response, :ok) and return + end + + submission = CheckpointSubmission.create!( + cohort_id: current_cohort.id, + content_file_uid: current_content_file.uid, + content_file_block_id: params[:block_id], + user_id: current_user.id, + state: CheckpointSubmission::STATES[:started] + ) + if current_content_file.time_limit.present? + GradeTimedCheckpointJob.set(wait: current_content_file.time_limit.minutes).perform_later(current_content_file.id, submission.id) + end + end + + json_response({ + content_file_html: newer_current_content_file.html, + submission_id: submission&.id, + challenges_with_answers: challenges_with_answers, + created_at: submission&.created_at, + limit_reached: false, + time_limit: newer_current_content_file.time_limit + }, :ok) + end + + def student_scores + render_method_not_allowed_response and return unless request.get? + authorize(current_cohort, :student_scores?) + if current_cohort.students.count < 1000 + students = current_cohort.students + + checkpoint_submissions_for_students = CheckpointSubmissionFinder.lastest_by_state_for_students_in_cohort( + cohort_id: current_cohort.id, + block_id: params[:block_id], + content_file_uid: current_content_file.uid, + student_ids: students.map(&:id) + ).includes(submitted_challenge_answers: :challenge).group_by(&:user_id) + + resp = formatted_student_scores(students, checkpoint_submissions_for_students) + + json_response(resp, :ok) + else + json_response({ student_limit_reached: true }, :ok) + end + end + + private + + def formatted_student_scores(students, submissions) + students.map do |student| + { + id: student.id, + auth_edit_url: student.auth_edit_url, + email: student.email, + initials: student.initials, + first_name: student.first_name, + last_name: student.last_name, + profile_image: student.profile_image, + has_signed_in: student.signed_in?, + submissions: submissions[student.id].nil? ? {} : format_submissions(submissions[student.id]) + } + end + end + + def format_submissions(submissions) + started = submissions.find { |s| s.state == "started"} + needs_review = submissions.find { |s| s.state == "needs_review"} + done = submissions.find { |s| s.state == "done"} + retry_sub = submissions.find { |s| s.state == "retry"} + + ultimate_done = [done, retry_sub].compact.sort {|a, b| b.created_at <=> a.created_at}&.first + submissions = [ultimate_done, needs_review].compact.sort {|a, b| b.created_at <=> a.created_at} + + # Original implementation when 'started' was present in set + # May revisit this when add time feature is built + # [] => nil, nil + # [done] => done score, done state + # [needs_review] => needs review suggest?, needs review state + # [started, needs_review] => needs review suggest?, started state + # [needs_review, done] => done score, scored-pending state + # [done, needs_review] => done score, done state + # [started, done] => done score, started state + # [started, needs_review, done] => done score, started state + # + # Changed to: + # [] => nil, nil + # [done] => done score, done state + # [needs_review] => needs review suggest?, needs review state + # [done, needs_review] => done score, done state + # [needs_review, done] => done score, needs review and done state + + score = nil + if ultimate_done + score = ultimate_done.percent_score + elsif needs_review # no done or retry, see if score is suggested + # if any submitted challenge answer has nil points, we cannot suggest a score + all_points = needs_review.submitted_challenge_answers.map(&:points) + unless all_points.include?(nil) + suggested_points = all_points.reduce(:+) + total_points = needs_review.submitted_challenge_answers.map(&:challenge).map(&:points).reduce(:+) + score = suggested_points && total_points ? ((suggested_points.to_f / total_points.to_f) * 100).to_i : 0 + end + end + + { + needs_review_id: needs_review&.id, + done_id: ultimate_done&.id, + started_id: started&.id, + score: score, + state: submssion_state(started, submissions), + created_at: (submissions[0] || started)&.created_at + } + end + + def submssion_state(started, submissions) + if submissions.length == 2 && submissions[0].state == "needs_review" && submissions[1].state == "done" + "needs_review_and_done" + elsif submissions.empty? && started + "started" + else + submissions[0]&.state + end + end + + def user_reached_attempt_limit? + return false if current_content_file.max_checkpoint_submissions.nil? + + user_attempts = current_user.checkpoint_submissions_count( + current_cohort.id, + current_content_file.standard.release.block_id, + current_content_file.uid + ) + + if user_attempts >= current_content_file.max_checkpoint_submissions + return true + end + + false + end + + def limit_reached_response + { + content_file_html: current_content_file.html, + submission_id: nil, + challenges_with_answers: challenges_with_answers, + limit_reached: true + } + end + + def current_content_file + @current_content_file ||= ContentFile.find(params[:id]) + end + + def newer_current_content_file + @newer_current_content_file ||= ContentFileFinder.from_cohort_block_content_file_path(cohort_id: current_cohort.id, + block_id: params[:block_id], + content_file_path: current_content_file.path) + end + + def challenges_with_answers + challenges = Challenge.where(content_file: current_content_file).order(position: :desc) + all_submitted_challenge_answers = SubmittedChallengeAnswerFinder.latest_for_user_id_content_file_for_cohort( + current_user.id, + current_content_file, + current_cohort.id + ) + challenges.map do |challenge| + submitted_challenge_answers = all_submitted_challenge_answers.select do |sca| + sca.challenge.uid == challenge.uid && sca.answered? + end.flatten.compact + ChallengeWithSubmittedChallengeAnswersPresenter.new( + current_cohort, + challenge, + submitted_challenge_answers, + current_user.instructor_or_admin?(current_cohort.id), + user_context: current_user, + is_checkpoint: true, + can_view_status: false, + can_view_explanation: false + ) + end + end + + def visibility_type_params + params.permit(:visible, :optional) + end +end diff --git a/app/controllers/api/v1/cohorts/blocks/units_controller.rb b/app/controllers/api/v1/cohorts/blocks/units_controller.rb new file mode 100644 index 0000000..68c45a0 --- /dev/null +++ b/app/controllers/api/v1/cohorts/blocks/units_controller.rb @@ -0,0 +1,19 @@ +class Api::V1::Cohorts::Blocks::UnitsController < Api::ApplicationController + include Api::ContentVisibilityCrud + + def update + render_method_not_allowed_response and return unless request.patch? + + authorize(Cohort.find(params[:cohort_id]), :toggle_content_visibility?) + + result = handle_param_logic("Standard", visibility_type_params) + + json_response({ status: result.to_s }, result) + end + + private + + def visibility_type_params + params.permit(:visible, :optional) + end +end diff --git a/app/controllers/api/v1/cohorts/cohorts_controller.rb b/app/controllers/api/v1/cohorts/cohorts_controller.rb new file mode 100644 index 0000000..1d6a393 --- /dev/null +++ b/app/controllers/api/v1/cohorts/cohorts_controller.rb @@ -0,0 +1,118 @@ +class Api::V1::Cohorts::CohortsController < Api::ApplicationController + def create + render_method_not_allowed_response and return unless request.post? + authorize(current_user, :onboarder?) + + if param_errors.any? + json_response({ error: "Validation Error: #{param_errors.join(', ')}" }, 400) and return + end + + client = AuthApi::Client.new("product.write") + + resp = client.create_product(formatted_cohort) + AuthResolverService.resolve(resp) if resp&.uid + + json_response({ status: "ok", uid: resp&.uid }, :ok) and return + rescue AuthApi::RequestFailed => e + json_response({ error: JSON.parse(e.message) }, 400) and return + end + + def curriculum + render_method_not_allowed_response and return unless request.get? + + authorize(current_cohort, :api_documentation?) + + @cohort_releases_by_sections, @visibilities = current_cohort.current_curriculum + + json_response({ + cohort_title: current_cohort.name, + cohort_id: current_cohort.id, + course_yaml_url: ResyncJobResult.find_latest(current_cohort.id)&.data&.dig("course_config_url"), + sections: build_sections + }, :ok) + end + + private + + def formatted_cohort + { + product: { + uid: SecureRandom.hex[0...18], + name: params[:name], + product_type: params[:product_type], + label: params[:label], + campus_name: params[:campus_name], + opt_out_for_marketing: params[:opt_out_for_marketing].nil? ? false : params[:opt_out_for_marketing], + starts_on: params[:starts_on], + ends_on: params[:ends_on] + } + } + end + + def param_errors + validation_response = [] + + if params[:name].blank? + validation_response.push "name can't be blank" + end + if params[:starts_on].blank? + validation_response.push "starts_on can't be blank" + elsif /[0-9]{4}-[0-9]{2}-[0-9]{2}/.match(params[:starts_on]).nil? + validation_response.push "starts_on must be in format yyyy-mm-dd" + end + if params[:product_type].blank? + validation_response.push "product_type can't be blank" + end + if params[:opt_out_for_marketing] && !([true, false].include? params[:opt_out_for_marketing]) + validation_response.push "opt_out_for_marketing must be true or false" + end + validation_response + end + + def build_sections + @cohort_releases_by_sections.map do |section, _v| + { + title: section.title, + units: build_units(section) + } + end + end + + def build_units(section) + @cohort_releases_by_sections[section].map do |r| + StandardFinder.for_cohort_release(cohort_id: current_cohort.id, release_id: r.release_id) + end.flatten.map do |standard| + { + uid: standard.uid, + title: standard.title, + description: standard.description, + visible: @visibilities["Standard"][standard.uid].nil? ? true : !@visibilities["Standard"][standard.uid].hidden?, + block_id: standard.release.block_id, + api_endpoint: api_v1_cohort_block_units_url(current_cohort.id, standard.release.block_id, standard.uid), + content_files: standard.content_files.unscoped.where(standard_id: standard.id).in_default_order.map do |cf| + { + uid: cf.uid, + title: cf.title, + path: content_file_path(current_cohort.id, standard.release.block_id, cf.path), + visible: @visibilities["ContentFile"][cf.uid].nil? ? true : !@visibilities["ContentFile"][cf.uid].hidden?, + git_url: git_url(cf), + type: cf.content_file_type, + api_endpoint: api_v1_cohort_block_content_files_url(current_cohort.id, standard.release.block_id, cf.uid) + } + end + } + end + end + + def git_url(content_file) + release = content_file.standard.release + block = release.block + base_url = block.git_url + branch = release.branch_name + "#{base_url}/blob/#{branch}/#{content_file.path}" + end + + def current_cohort + @current_cohort ||= Cohort.find(params[:cohort_id]) + end +end diff --git a/app/controllers/api/v1/cohorts/users_controller.rb b/app/controllers/api/v1/cohorts/users_controller.rb new file mode 100644 index 0000000..83b9f19 --- /dev/null +++ b/app/controllers/api/v1/cohorts/users_controller.rb @@ -0,0 +1,163 @@ +class Api::V1::Cohorts::UsersController < Api::ApplicationController + def index + render_method_not_allowed_response and return unless request.get? + authorize(current_cohort, :api_documentation?) + + json_response(formatted_cohort_users, :ok) + end + + def create + render_method_not_allowed_response and return unless request.post? + authorize(current_cohort, :enroll?) + + if param_errors.any? + json_response({ error: "Validation Error: #{param_errors.join(', ')}" }, 400) and return + end + + if user_from_email + json_response({ status: "already-exists", uid: user_from_email.uid }, :ok) and return if user_enrolled_in_cohort? + uid = enroll_existing_user(user_from_email) + else + uid = invite_user + end + json_response({ status: "ok", uid: uid }, :ok) and return + rescue AuthApi::RequestFailed => e + json_response({ error: e.message }, 400) and return + end + + def update + render_method_not_allowed_response and return unless request.patch? + authorize(current_cohort, :enroll?) + + if target_user&.student_or_instructor_of?(current_cohort.id) + enroll_existing_user(target_user) + json_response({ status: "ok" }, :ok) + else + json_response({ status: "404" }, 404) + end + rescue AuthApi::RequestFailed => e + json_response({ error: e.message }, 400) and return + end + + def destroy + render_method_not_allowed_response and return unless request.delete? + authorize(current_cohort, :enroll?) + + if target_user&.student_or_instructor_of?(current_cohort.id) + unenroll_existing_user + json_response({ status: "ok" }, :ok) + else + json_response({ status: "404" }, 404) + end + rescue AuthApi::RequestFailed => e + json_response({ error: e.message }, 400) and return + end + + private + + def current_cohort + @current_cohort ||= Cohort.find(params[:cohort_id]) + end + + def target_user + @target_user ||= User.find(params[:id]) + end + + def user_from_email + @user_from_email ||= User.find_by(email: params[:email]) + end + + def user_enrolled_in_cohort? + user_from_email.student_or_instructor_of?(current_cohort.id) + end + + def formatted_cohort_users + User.select("users.id, users.uid, users.first_name, users.last_name, users.email, cohort_users.roles"). + joins(:cohort_users). + where("cohort_users.cohort_id = ?", current_cohort.id). + order("cohort_users.created_at DESC").map do |user| + { + id: user.id, + uid: user.uid, + first_name: user.first_name, + last_name: user.last_name, + email: user.email, + roles: user.roles + } + end + end + + def invite_user + client = AuthApi::Client.new("user.invite user.write user.product_roles") + options = { + user: { + first_name: params[:first_name], + last_name: params[:last_name], + email: params[:email], + registrations: [{ + product_uid: current_cohort.uid, + roles: enroll_roles + }] + } + } + + resp = client.invite_user(options) + AuthResolverService.resolve(resp) if resp&.uid + resp&.uid + end + + def enroll_roles + [ + params[:instructor] == true ? "instructor" : nil, + params[:onboard] == true ? "auth.product_admin" : nil + ].compact + end + + def enroll_existing_user(user) + client = AuthApi::Client.new("user.write user.product_roles") + options = { + id: user.uid, + user: { + registrations: [{ + product_uid: current_cohort.uid, + roles: enroll_roles + }] + } + } + + resp = client.update_user(options) + AuthResolverService.resolve(resp) if resp&.uid + resp&.uid + end + + def unenroll_existing_user + client = AuthApi::Client.new("user.write user.unregister") + options = { + id: target_user.uid, + user: { + registrations: [{ + product_uid: current_cohort.uid, + _destroy: true + }] + } + } + + resp = client.update_user(options) + AuthResolverService.resolve(resp) if resp&.uid + end + + def param_errors + validation_response = [] + + if params[:first_name].blank? + validation_response.push "first_name can't be blank" + end + if params[:last_name].blank? + validation_response.push "last_name can't be blank" + end + if params[:email].blank? + validation_response.push "email can't be blank" + end + validation_response + end +end diff --git a/app/controllers/api/v1/content_files_controller.rb b/app/controllers/api/v1/content_files_controller.rb new file mode 100644 index 0000000..7fe82d5 --- /dev/null +++ b/app/controllers/api/v1/content_files_controller.rb @@ -0,0 +1,34 @@ +class Api::V1::ContentFilesController < Api::ApplicationController + skip_around_action :monitor_api, only: [:show] + + def show + authorize(current_user, :content_file_api?) + + content_file = ContentFile.unscoped.find(params[:id]) + + render json: content_file + end + + def create + render_method_not_allowed_response and return unless request.post? + + authorize(current_user, :content_file_api?) + + outcome = PreviewContentFileService.new(sandbox_id: current_user.sandbox.id, + s3_key: create_params[:s3_key]).execute + + if outcome[:content_file] + render json: { preview_url: content_file_url(current_user.sandbox.id, + preview_block.id, + outcome[:content_file].path) }, status: :ok + elsif outcome[:errors] + render json: { errors: outcome[:errors].join(", ") }, status: :unprocessable_entity + end + end + + private + + def create_params + params.permit(:s3_key) + end +end diff --git a/app/controllers/api/v1/pineapple_controller.rb b/app/controllers/api/v1/pineapple_controller.rb new file mode 100644 index 0000000..4ae3969 --- /dev/null +++ b/app/controllers/api/v1/pineapple_controller.rb @@ -0,0 +1,6 @@ +class Api::V1::PineappleController < Api::ApplicationController + def pineapple + render_method_not_allowed_response and return unless request.get? + json_response(this_is_for_you: "\u{1f34d}") + end +end diff --git a/app/controllers/api/v1/releases_controller.rb b/app/controllers/api/v1/releases_controller.rb new file mode 100644 index 0000000..2e62d2b --- /dev/null +++ b/app/controllers/api/v1/releases_controller.rb @@ -0,0 +1,70 @@ +class Api::V1::ReleasesController < Api::ApplicationController + def create + authorize(current_user, :regenerate_api_token?) + + release = Release.new( + s3_key: release_params[:s3_key], + github_sha: "preview", + branch_name: "preview", + block_id: Block.find_or_create_by(title: "preview").id, + preview_cohort_id: current_user.sandbox.id, + state: Release::STATES[:pending] + ) + + if release.save + render json: { release_id: release.id }, status: :ok + else + render json: { errors: release.errors.full_messages.join(", ") }, status: :internal_server_error + end + end + + def release_polling + authorize(current_user, :release_polling?) + + release = Release.find_by(id: release_params[:release_id]) + + if release.nil? + render json: { errors: "Could not find the release requested", sync_warnings: "" }, status: :unprocessable_entity + elsif release.state == Release::STATES[:success] + preview_url = nil + + if release.preview_cohort_id.present? + cf_count = ContentFileFinder.all_from_cohort_block(cohort_id: current_user.sandbox.id, + block_id: Block.find_by(title: "preview").id) + + preview_url = if cf_count.size == 1 + release.update(sync_warnings: release.sync_warnings.reject { |warning| warning.include?("link") }.compact) + cf_no_link_warnings = cf_count.first.dup + cf_no_link_warnings.warnings = cf_no_link_warnings.warnings.reject { |warning| warning.include?("link") }.compact + cf_no_link_warnings.uid = cf_no_link_warnings.uid.reverse + + if cf_no_link_warnings.save + new_challenges = cf_count.first.challenges.map(&:dup) + new_challenges.each { |c| c.content_file_id = cf_no_link_warnings.id } + cf_count.first.challenges.map(&:delete) + new_challenges.map(&:save) + cf_count.first.delete + end + + content_file_url(current_user.sandbox.id, + preview_block.id, + cf_no_link_warnings.path) + else + Rails.application.routes.url_helpers.cohort_url(current_user.sandbox.id) + end + end + + render json: { status: release.state, preview_url: preview_url, sync_warnings: release.sync_warnings }, status: :ok + elsif release.state == Release::STATES[:pending] || release.state == Release::STATES[:processing] + render json: { status: release.state, sync_warnings: release.sync_warnings }, status: :ok + else + render json: { errors: release.sync_errors.join(", "), sync_warnings: release.sync_warnings }, status: :unprocessable_entity + end + end + + private + + def release_params + params.permit(:release_id, :s3_key) + end +end diff --git a/app/controllers/api/v1/users_controller.rb b/app/controllers/api/v1/users_controller.rb new file mode 100644 index 0000000..245729e --- /dev/null +++ b/app/controllers/api/v1/users_controller.rb @@ -0,0 +1,55 @@ +class Api::V1::UsersController < Api::ApplicationController + def regenerate_token + authorize(current_user, :regenerate_api_token?) + + current_user.regenerate_api_token + current_user.sandbox + + render json: { token: current_user.api_token } + end + + def learn_cli_credentials + render_method_not_allowed_response and return unless request.get? + + authorize(current_user, :learn_cli_credentials?) + + render json: { + user_id: current_user.id.to_s, + user_email: current_user.email, + s3: { + access_key_id: Rails.application.secrets.glearn_access_key_id, + secret_access_key: Rails.application.secrets.glearn_secret_access_key, + key_prefix: Rails.application.secrets.glearn_key_prefix, + bucket_name: Rails.application.secrets.glearn_bucket_name + }, + slack: { + dev_notify_url: Rails.application.secrets.dev_notify_slack_url + } + } + end + + def learn_cli_metadata + render_method_not_allowed_response and return unless request.post? + + authorize(current_user, :learn_cli_metadata?) + + @api_interaction_metadata = { + cli_benchmark: user_params.as_json + } + + render json: { message: "Success" }, status: :ok + end + + private + + def user_params + params.require(:cli_benchmark).permit( + :time_to_compress, + :time_to_build_on_learn, + :time_to_upload_to_s3, + :master_release_and_build, + :total_cmd_time, + :command_name + ) + end +end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb new file mode 100644 index 0000000..a633613 --- /dev/null +++ b/app/controllers/application_controller.rb @@ -0,0 +1,147 @@ +class ApplicationController < ActionController::Base + include Pundit + include JsonHelper + include Pagy::Backend + + protect_from_forgery with: :exception + before_action :require_signed_in_user + before_action :is_mobile? + before_action :miniprofiler + after_action :set_last_viewed_cohort_id + after_action :verify_authorized + before_action :can_access_api? + before_action :warn_browser_compatibility + + rescue_from StandardError do |exception| + raise exception if Rails.env.development? + + if exception.is_a?(Pundit::NotAuthorizedError) + if request.format.json? + render_error_response(status: 403, text: exception.message, backtrace: exception.backtrace) + else + redirect_to root_path, alert: "You do not have permission to access that page." + end + elsif exception.is_a?(ActiveRecord::RecordNotFound) + error_404 + elsif request.format.json? + Honeybadger.notify(exception, context: { referer: request.referer }) + render_error_response(status: 500, text: exception.message, backtrace: exception.backtrace) + else + Honeybadger.notify(exception, context: { referer: request.referer }) + error_500 + end + end + + def require_signed_in_user + if current_user.blank? + session[:requested_path] = request.fullpath unless request.fullpath == "/" + redirect_to auth_api.new_session_path + end + end + + def error_500 + skip_authorization + render template: "error_500", status: :service_unavailable, format: :html + end + + def error_404 + skip_authorization + if request.format.json? + render_error_response(status: 404, text: "not found", backtrace: nil) + else + render template: "error_404", status: :not_found, format: :html + end + end + + def api_token + authorize(current_user, :regenerate_api_token?) + render template: "api_token", format: :html + end + + def api_interactions + authorize(current_user, :view_api_interactions?) + + begin + @pagy, @records = pagy( + ApiInteraction.order(created_at: :desc), + page: params[:page] || 1 + ) + # Main reason for this rescue is for if someone types page=not_a_valid_page_number + # into the URL bar so nothing breaks we send to page 1 + rescue StandardError + @pagy, @records = pagy(ApiInteraction.order(created_at: :desc), page: 1) + + render template: "api_interactions", locals: { + api_interactions: @records, + page: @pagy.vars[:page], + per_page: @pagy.vars[:items], + total_count: @pagy.vars[:count] + }, format: :html and return + end + + render template: "api_interactions", locals: { + api_interactions: @records, + page: @pagy.vars[:page], + per_page: @pagy.vars[:items], + total_count: @pagy.vars[:count] + }, format: :html + end + + private + + def warn_browser_compatibility + return if Rails.env.test? + + @unsupported_browser = false + uagent = request.env["HTTP_USER_AGENT"] + if uagent =~ /Edge/ || uagent =~ /MSIE/ || uagent =~ /Opera/ || uagent =~ /OPR/ || uagent =~ /Trident/ + @unsupported_browser = true + end + end + + def can_access_api? + @authorized_api_access ||= current_user.admin? || CohortUser.instructor.where(user_id: current_user.id).any? + end + + def render_error_response(status:, text:, backtrace:) + json_response = { errors: [message: "#{status} #{text}"] } + json_response[:backtrace] = backtrace unless Rails.env.production? + render json: json_response, status: status + end + + def set_last_viewed_cohort_id + return unless current_user + return unless @current_cohort + + current_user.update(last_viewed_cohort_id: @current_cohort.id) + end + + def is_mobile? + @is_mobile_device = browser.mobile? + end + + def segment_identify + return if Rails.env.test? + return unless current_user + + @current_user_uid = current_user.uid + @identify_properties = { + firstName: current_user.first_name, + lastName: current_user.last_name, + email: current_user.email, + githubUsername: current_user.github_username, + createdAt: current_user.created_at, + learnId: current_user.id, + roleName: current_user.admin? ? "admin" : "student" + } + Analytics.identify( + user_id: @current_user_uid, + traits: @identify_properties + ) + end + + def miniprofiler + emails = ["chad.lillquist@galvanize.com", "brad.lamson@galvanize.com", "grunde@galvanize.com"] + Rack::MiniProfiler.authorize_request if emails.include?(current_user&.email) + end +end diff --git a/app/controllers/blocks/releases_controller.rb b/app/controllers/blocks/releases_controller.rb new file mode 100644 index 0000000..75e3079 --- /dev/null +++ b/app/controllers/blocks/releases_controller.rb @@ -0,0 +1,69 @@ +module Blocks + class ReleasesController < ApplicationController + before_action :set_html_title + + def index + authorize(current_cohort, :create_cohort_release?) + + releases = ReleaseFinder.for_block(params[:block_id]) + release_presenters = BlockPresenter::ForCohortReleases.releases_for_cohort( + releases: releases, + cohort: current_cohort, + block_id: params[:block_id] + ) + + render json: { releases: release_presenters } + end + + def new + authorize(Release) + render(locals: { block: current_block, release: Release.new }) + end + + def create + authorize(Release) + + pending_release = Release.create(block_id: current_block.id, + notes: release_params[:notes], + github_sha: "pending", + user_id: current_user.id, + state: Release::STATES[:pending]) + + CreateReleaseJob.perform_later(pending_release_id: pending_release.id) + + flash[:notice] = "Release creation queued." + redirect_to block_url(current_block) + end + + private + + def set_html_title + @html_title = "Blocks" + end + + def current_cohort + @current_cohort ||= Cohort.find(params[:cohort_id]) + end + + def current_block + @current_block ||= Block.find(params[:block_id]) + end + + def release_params + params.require(:release).permit(:notes) + end + + def set_segment_page_properties + @track_properties = { + productId: nil, + pageType: @html_title, + cohortId: nil, + cohortName: nil, + blockId: current_block&.id, + blockName: current_block&.title, + unitId: nil, + unitName: nil + }.to_json + end + end +end diff --git a/app/controllers/blocks_controller.rb b/app/controllers/blocks_controller.rb new file mode 100644 index 0000000..18c8d39 --- /dev/null +++ b/app/controllers/blocks_controller.rb @@ -0,0 +1,77 @@ +class BlocksController < ApplicationController + before_action :set_html_title + + def index + authorize(Block) + relations = { releases: { cohort_releases: { cohort: :cohort_users } } } + blocks = Block.all.active.without_preview.includes(relations).order(title: :asc) + render( + locals: { + blocks: blocks.map { |b| BlockPresenter::ForBlock.new(block: b) } + } + ) + end + + def show + authorize(current_block) + releases = Release.where(block_id: current_block.id, branch_name: "master").order(id: :desc).map do |r| + BlockPresenter::ForReleases.new(release: r) + end + SetBlockCachesJob.perform_later(block_id: current_block.id) + render(locals: { block: current_block, url: current_block.repo_url, releases: releases }) + end + + def blockpagev2 + authorize(current_block) + releases = Release.where(block_id: current_block.id, branch_name: "master").order(id: :desc).map do |r| + BlockPresenter::ForReleases.new(release: r) + end + render( + locals: { + block: BlockPresenter::ForBlock.new(block: current_block), + github_url: current_block.git_url, + releases: releases + } + ) + end + + def release_polling + authorize(current_block) + releases = Release.where(block_id: current_block.id, branch_name: "master").order(id: :desc).map do |r| + BlockPresenter::ForReleases.new(release: r) + end + render json: { block: current_block, releases: releases } + end + + def new + authorize(Block) + render(locals: { block: Block.new }) + end + + private + + def set_html_title + @html_title = "Blocks" + end + + def current_block + @current_block ||= Block.find(params[:id]) + end + + def block_params + params.require(:block).permit(:title, :repo_name, :org, :origin) + end + + def set_segment_page_properties + @track_properties = { + productId: nil, + pageType: @html_title, + cohortId: nil, + cohortName: nil, + blockId: params[:id].present? ? current_block&.id : nil, + blockName: params[:id].present? ? current_block&.title : nil, + unitId: nil, + unitName: nil + }.to_json + end +end diff --git a/app/controllers/cohorts/blocks/content_files_controller.rb b/app/controllers/cohorts/blocks/content_files_controller.rb new file mode 100644 index 0000000..98a6b2c --- /dev/null +++ b/app/controllers/cohorts/blocks/content_files_controller.rb @@ -0,0 +1,306 @@ +module Cohorts + module Blocks + class ContentFilesController < ApplicationController + def show + skip_authorization and render template: "error_404" and return if current_content_file.nil? + authorize(current_content_file, :show?, visible_for_cohort: current_cohort) + @html_title = current_content_file.title + @page_type = current_content_file.content_file_type.titleize + @current_category = "curriculum" + @force_navigation_hide = current_content_file.content_file_type == ContentFile::TYPES[:resource] + + run_content_file_visit + + render( + locals: current_content_file.checkpoint? ? checkpoint_locals : lesson_locals + ) + end + + def lesson_locals + curriculum_warning_count = current_user.instructor_or_admin?(current_cohort.id) ? current_content_file.warnings.length : 0 + { + repo_details: current_block.repo_details, + visited_lesson_uids: lesson_visits.map(&:content_file_uid) | [current_content_file.uid], # SideBar + standard: standard_presenter, # SideBar + cohort_path: cohort_path(current_cohort), # SideBar, SubmissionRenderer + checkpoint_info: checkpoint_info, # SideBar, SubmissionRenderer + content_files_submissions: single_standard_submissions, # Lesson, SideBar + user_id: current_user.id, # ChallengeBlock, SideBar + content_file: content_file_locals, # ChallengeBlock, SubmissionRenderer + cohort_mode: current_cohort.mode, # ChallengeBlock, SubmissionRenderer + content_file_presenter: content_file_presenter, # ChallengeBlock, SubmissionRenderer + is_instructor_or_admin: instructor_or_admin, # ChallengeBlock, SubmissionRenderer + content_file_submission_path: content_file_submission_path, # ChallengeBlock + is_ipynb_file: current_content_file.path.include?(".ipynb"), # SubmissionRenderer, html + content_file_hidden: content_visisbility.include?(current_content_file.uid), # SubmissionRenderer + standard_hidden: content_visisbility.include?(current_standard.uid), # SubmissionRenderer + visibility_path: instructor_or_admin ? content_cohort_path(current_cohort) : nil, # SubmissionRenderer + cohort_id: current_cohort.id, # SubmissionRenderer + is_sandbox_cohort: current_cohort.sandbox, # SubmissionRenderer + curriculum_warning_count: curriculum_warning_count, # SubmissionRenderer + checkpoint_is_autoscored: current_content_file.autoscore, # SubmissionRenderer + is_enrolled_student: current_user.student_of?(current_cohort.id), # SubmissionRenderer + content_file_footer_presenter: ContentFilePresenter::ForFooter.new( + cohort: current_cohort, + content_file: current_content_file + ) # Lesson, SubmissionRenderer + } + end + + # sidebar attributes are used for both checkpoint and lesson, should be extracted + # pull out links from any locals, refactor to use routes.tsx + # checkpoint landing page locals should be from a separate method, will cleanup lesson locals + def checkpoint_locals + checkpoint_attempts_remaining = nil + checkpoint_submissions_count = current_user.checkpoint_submissions_count( + current_cohort.id, + current_block.id, + current_content_file.uid + ) + if current_content_file.max_checkpoint_submissions.present? + checkpoint_attempts_remaining = current_content_file.max_checkpoint_submissions - checkpoint_submissions_count + checkpoint_attempts_remaining = checkpoint_attempts_remaining < 0 ? 0 : checkpoint_attempts_remaining + end + + { + load_student_scores: current_cohort.students.size < 1000, + repo_details: current_block.repo_details, + is_ipynb_file: current_content_file.path.include?(".ipynb"), + checkpoint_title: current_content_file.title, # SideBar + visited_lesson_uids: lesson_visits.map(&:content_file_uid) | [current_content_file.uid], # SideBar + standard: standard_presenter, # SideBar + cohort_path: cohort_path(current_cohort), # SideBar, SubmissionRenderer + cohort_id: current_cohort.id, + checkpoint_info: checkpoint_info, # SideBar, SubmissionRenderer + content_files_submissions: single_standard_submissions, # Lesson, SideBar + user_id: current_user.id, # ChallengeBlock, SideBar + cohort_mode: current_cohort.mode, # ChallengeBlock, SubmissionRenderer + checkpoint_attempts_remaining: checkpoint_attempts_remaining, + time_limit: current_content_file.time_limit, + challenge_types: current_content_file.challenges.map(&:challenge_type).uniq, + progress_thresholds: current_cohort.settings["progress_thresholds"], + content_file: content_file_locals, # ChallengeBlock, SubmissionRenderer + is_instructor_or_admin: instructor_or_admin, # Checkpoint and children + is_preview_sandbox: current_cohort.sandbox, + student_scores_endpoint: api_v1_cohort_block_student_scores_path(current_cohort.id, + current_block.id, + current_content_file.id), + github_url: content_file_github_url, + take_assessment_path: api_v1_cohort_block_take_assessment_path(current_cohort, + current_block, + current_content_file), + storage_key: "viewed_new_assessment", + is_enrolled_student: current_user.student_of?(current_cohort.id), + cohort_allow_paired_submissions: current_cohort.allow_paired_submissions + } + end + + def content_file_locals + { + id: current_content_file.id, + github_url: content_file_github_url, + html: current_content_file.html.html_safe, + is_checkpoint: current_content_file.checkpoint?, + is_resource: current_content_file.resource?, + title: current_content_file.title, + path: current_content_file.path, + permalink: permalink_url(current_block.repo_name, current_content_file.path), + type: current_content_file.content_file_type, + students_in_cohort: current_cohort.students.map do |s| + { id: s.id, full_name: s.full_name, initials: s.initials, profile_image: s.profile_image } + end + } + end + + def track_activity_event + render nothing: true, status: 404 and return if current_cohort.nil? || current_content_file.nil? + + authorize(current_cohort, :show?) + + Activity.create( + cohort: current_cohort, + creator: current_user, + name: params[:event], + subject: current_content_file, + content: params[:content] + ) + + respond_to do |format| + format.json do + render json: { ack: :ok } + end + end + end + + private + + def current_cohort + @current_cohort ||= Cohort.find(params[:cohort_id]) + end + + def current_content_file + @content_file ||= ContentFileFinder.from_cohort_block_content_file_path( + cohort_id: current_cohort.id, + block_id: params[:block_id], + content_file_path: params[:path] + ) + end + + def content_file_github_url + release = current_content_file.standard.release + block = release.block + base_url = block.git_url + branch = release.branch_name + "#{base_url}/blob/#{branch}/#{current_content_file.path}" + end + + def current_standard + @current_standard ||= current_content_file.standard + end + + def current_block + @current_block ||= current_standard.release.block + end + + def content_visisbility + @content_visisbility ||= ContentVisibility.where( + cohort_id: current_cohort.id, + content_uid: [current_standard.uid, current_content_file.uid] + ).map(&:content_uid) + end + + def all_checkpoints + @all_checkpoints ||= CheckpointSubmission.where( + content_file_uid: current_content_file.uid, + cohort_id: current_cohort.id, + content_file_block_id: current_block.id, + user_id: current_user.id + ).order(created_at: :desc) + end + + def checkpoints_by_state + @checkpoints_by_state ||= { + done: all_checkpoints.find { |chs| chs.state == CheckpointSubmission::STATES[:done] }, + retry: all_checkpoints.find { |chs| chs.state == CheckpointSubmission::STATES[:retry] }, + started: all_checkpoints.find { |chs| chs.state == CheckpointSubmission::STATES[:started] }, + needs_review: all_checkpoints.find { |chs| chs.state == CheckpointSubmission::STATES[:needs_review] } + } + end + + def single_standard_submissions + @single_standard_submissions ||= StandardSubmissionsService.new( + standard: current_standard, + cohort: current_cohort, + student_ids: [current_user.id], + all_checkpoints: all_checkpoints, + instructor_or_admin: current_user.instructor_or_admin?(current_cohort.id) + ).single + end + + def lesson_visits + @lesson_visits ||= LessonVisit.where( + user_id: current_user.id, + standard_uid: current_standard.uid, + cohort_id: current_cohort.id, + block_id: current_block.id + ) + end + + def content_file_presenter + @content_file_presenter ||= ContentFilePresenter::ForShow.new( + current_content_file, + current_cohort, + current_user + ) + end + + def standard_presenter + @standard_presenter ||= StandardPresenter::ForStandardCard.new( + standard: current_standard, + cohort: current_cohort, + current_user_id: current_user.id, + user_performances: + if current_cohort.mode == Cohort::MODES[:mastery] + PerformanceFinder.latest_for_standards_in_cohort( + standard_uids: [current_standard.uid], + user_ids: [current_user.id], + cohort_id: current_cohort.id + ).to_a + else + [] + end, + cohort_standard_progress_data: single_standard_submissions, + instructor_or_admin: instructor_or_admin, + lesson_visits: lesson_visits + ) + end + + def mastery_score + @mastery_score ||= Performance.where( + user_id: current_user.id, standard_uid: current_standard.uid, block_id: current_block.id + ).last&.score || nil + end + + def instructor_or_admin + @instructor_or_admin ||= current_user.instructor_or_admin?(current_cohort.id) + end + + def checkpoint_info + @checkpoint_info ||= { + cohortId: current_cohort.id, + cohortMode: current_cohort.mode, + checkpointsByState: checkpoints_by_state, + challengeTotal: content_file_presenter.challenges_with_answers.length, + contentFilesSubmission: + single_standard_submissions.find do |cfs| + cfs[:content_file_type] == ContentFile::TYPES[:checkpoint] + end. + try(:dig, :checkpoint_submissions, current_user.id) + + }.merge( + if current_cohort.mode == Cohort::MODES[:mastery] + { + masteryScore: mastery_score + } + else + { + challengeCorrect: content_file_presenter.challenges_with_answers.count do |ch| + ch.submitted_challenge_answer_presenters[0]&.status == "correct" + end + } + end + ) + end + + def run_content_file_visit + return if current_content_file.content_file_type == ContentFile::TYPES[:resource] || + current_content_file.content_file_type == ContentFile::TYPES[:instructor] + + ContentFileVisitJob.perform_later( + current_user.id, + current_block.id, + current_cohort.id, + current_content_file.id, + current_standard.uid + ) + end + + def content_file_submission_path + cohort_content_file_submitted_challenge_answers_path(current_cohort, current_content_file) + end + + def set_segment_page_properties + @track_properties = { + productId: current_cohort.uid, + pageType: @page_type, + cohortId: current_cohort.id, + cohortName: current_cohort.name, + blockId: current_block.id, + blockName: current_block.title, + unitId: current_content_file.standard.id, + unitName: current_content_file.standard.title + }.to_json + end + end + end +end diff --git a/app/controllers/cohorts/checkpoint_submissions/activities_controller.rb b/app/controllers/cohorts/checkpoint_submissions/activities_controller.rb new file mode 100644 index 0000000..cc83f67 --- /dev/null +++ b/app/controllers/cohorts/checkpoint_submissions/activities_controller.rb @@ -0,0 +1,80 @@ +module Cohorts + module CheckpointSubmissions + class ActivitiesController < ApplicationController + before_action :current_cohort + + def create + authorize(checkpoint_submission, :comment?) + + activity = Activity.new( + content: activity_params[:content], + subject: checkpoint_submission, + creator: current_user, + name: Activity::NAMES[:comment_created], + cohort: current_cohort + ) + + if activity.save + first_sca = checkpoint_submission.submitted_challenge_answers.first + content_file = first_sca.challenge.content_file + checkpoint_submission_url = cohort_checkpoint_submission_url(current_cohort, checkpoint_submission) + + if activity_params[:notify] == "true" + notification = { + tagline: "Comment Left", + title: + "#{current_user.full_name} commented on #{content_file.standard.release.block.title}" \ + " - #{content_file.standard.title} - Checkpoint", + url: checkpoint_submission_url, + description: "\"#{activity_params[:content]}\"" + } + + if checkpoint_submission.user_id == current_user.id + current_cohort.instructors.each { |instructor| instructor.notify(notification) } + + slack_users(CohortUser.instructor.where(cohort: current_cohort)&.map(&:user), checkpoint_submission_url, content_file.title) + else + checkpoint_submission.user.notify(notification) + + slack_users([first_sca.user], checkpoint_submission_url, content_file.title) + end + end + + render json: ActivityPresenter.new(activity), status: 200 + else + render json: { error: activity.errors.full_messages }, status: 400 + end + end + + private + + def activity_params + params.require(:activity).permit(:content, :notify) + end + + def current_cohort + @cohort ||= CohortPolicy::Scope.new(current_user, Cohort).resolve.find_by!(id: params[:cohort_id]) + end + + def checkpoint_submission + @checkpoint_submission ||= CheckpointSubmission.find(params[:checkpoint_submission_id]) + end + + def slack_users(users, checkpoint_submission_url, content_file_title) + users.each do |user| + user.send_slack_message( + slack_message_content( + commentor: current_user, + url: checkpoint_submission_url, + content_file_title: content_file_title + ) + ) + end + end + + def slack_message_content(commentor:, content_file_title:, url:) + "#{commentor.full_name} left a comment on #{content_file_title}. Read it here: #{url}." + end + end + end +end diff --git a/app/controllers/cohorts/cohort_releases_controller.rb b/app/controllers/cohorts/cohort_releases_controller.rb new file mode 100644 index 0000000..99a2210 --- /dev/null +++ b/app/controllers/cohorts/cohort_releases_controller.rb @@ -0,0 +1,156 @@ +module Cohorts + class CohortReleasesController < ApplicationController + def index + authorize(current_cohort, :create_cohort_release?) + + @current_category = "setup" + render json: { cohort_releases: cohort_release_presenters } + end + + def resync + authorize(current_cohort, :create_cohort_release?) + + ResyncCourseJob.perform_later( + cohort_id: current_cohort.id, + course_url: params[:course_config_url] + ) + + render json: {} + end + + def resync_status + authorize(current_cohort, :create_cohort_release?) + latest = ResyncJobResult.find_latest(current_cohort.id) + latest.timeout_latest! if latest&.older_than_one_minute? + render json: latest + end + + def archive_resync_error + authorize(current_cohort, :create_cohort_release?) + if params[:cancel] + ResyncJobResult.cancel_latest!(current_cohort.id) + else + ResyncJobResult.archive_latest_failure!(current_cohort.id) + end + render json: ResyncJobResult.find_latest(current_cohort.id) + end + + def create + authorize(current_cohort, :create_cohort_release?) + + CohortRelease.create!(cohort: current_cohort, release_id: cohort_release_params[:release_id]) + + redirect_to(setup_cohort_path(current_cohort), flash: { success: "Block attached." }) + end + + def update + authorize(current_cohort_release) + + if cohort_release_params[:use_latest_release] == true + latest_release_id = Release.where(block_id: current_cohort_release.release.block_id, branch_name: "master").order(:id).last.id + cohort_release_params[:release_id] = latest_release_id + elsif cohort_release_params[:release_id].present? && cohort_release_params[:use_latest_release].blank? + cohort_release_params[:use_latest_release] = false + end + + current_cohort_release.update!(cohort_release_params.merge(pending_release_id: nil)) + + respond_to do |format| + format.html do |_f| + redirect_to(setup_cohort_path(current_cohort), flash: { success: "Block release updated." }) + end + format.json do |_f| + render json: { release: CohortReleasePresenter::ForCohortSetup.new(cohort_release: current_cohort_release) } + end + end + end + + def switch_to_branch + authorize(current_cohort, :create_cohort_release?) + block = Block.find(params[:block_id]) + repo_name = block.repo_name + github_sha = branch_sha(params[:block_id], params[:branch_name]) + flash_info = if !github_sha + { type: "danger", + msg: "Error. The provided branch '#{params[:branch_name]}' does not exist on repo: #{block.repo_url}." } + else + resolve_branch_release(github_sha) + end + + render json: { + cohort_release: CohortReleasePresenter::ForCohortSetup.new(cohort_release: current_cohort_release), + flash_info: flash_info.merge(title: repo_name.titleize) + } + end + + def branch_polling + authorize(current_cohort, :create_cohort_release?) + render json: { + cohort_release: CohortReleasePresenter::ForCohortSetup.new(cohort_release: current_cohort_release), + cohort_releases: cohort_release_presenters + } + end + + private + + def resolve_branch_release(github_sha) + release_at_sha = Release.find_by(github_sha: github_sha, block_id: params[:block_id], branch_name: params[:branch_name]) + if release_at_sha.present? && release_at_sha.successfully_synced? + msg = if current_cohort_release.release_id == release_at_sha.id + "Nothing to publish, block is already up-to-date with the latest commit on '#{params[:branch_name]}'." + else + "Attached existing and previously synced branch '#{params[:branch_name]}'" + end + current_cohort_release.update(release_id: release_at_sha.id, pending_release_id: nil, use_latest_release: false) + flash_info = { type: "success", msg: msg } + elsif release_at_sha.present? && !release_at_sha.successfully_synced? + release_at_sha.update_attributes( + state: Release::STATES[:pending], + sync_errors: [] + ) + flash_info = queue_job_with_publish_flash(release_at_sha) + else + new_release = Release.create( + block_id: params[:block_id], + github_sha: branch_sha(params[:block_id], params[:branch_name]), + state: Release::STATES[:pending], + branch_name: params[:branch_name] + ) + flash_info = queue_job_with_publish_flash(new_release) + end + flash_info + end + + def branch_sha(block_id, branch_name) + return @github_sha if @github_sha + + git_type = Block.find(block_id).git_type + git_klass = git_type == "github" ? DownloadGithubRepositoryService : DownloadGitlabRepositoryService + @github_sha = git_klass.new(release: nil, tmp_path: "").branch_sha(block_id, branch_name) + end + + def queue_job_with_publish_flash(release) + current_cohort_release.update(pending_release_id: release.id, use_latest_release: false) + SwitchToBranchJob.perform_later(pending_release_id: release.id, cohort_release_id: current_cohort_release.id) + { type: "warning", msg: "Publishing branch '#{params[:branch_name]}'" } + end + + def current_cohort + @current_cohort ||= Cohort.find(params[:cohort_id]) + end + + def current_cohort_release + @current_cohort_release ||= CohortRelease.includes(:release).find(params[:id]) + end + + def cohort_release_params + @cohort_release_params ||= params.require(:cohort_release).permit(:release_id, :use_latest_release) + end + + def cohort_release_presenters + CohortRelease.attached_to_cohort(current_cohort.id).map do |cohort_release| + CohortReleasePresenter::ForCohortSetup.new(cohort_release: cohort_release) + end + end + end +end diff --git a/app/controllers/cohorts/content_files/checkpoint_submissions_controller.rb b/app/controllers/cohorts/content_files/checkpoint_submissions_controller.rb new file mode 100644 index 0000000..491b2be --- /dev/null +++ b/app/controllers/cohorts/content_files/checkpoint_submissions_controller.rb @@ -0,0 +1,338 @@ +module Cohorts + module ContentFiles + class CheckpointSubmissionsController < ApplicationController + def show + authorize(current_checkpoint_submission, :show?) + + if current_checkpoint_submission.state == CheckpointSubmission::STATES[:started] + redirect_back fallback_location: cohorts_path(current_cohort), + flash: { alert: "Cannot view a Checkpoint that has not yet been submitted." } and return + end + + @html_title = "#{loaded_student.full_name}: #{current_content_file.title}" + activities = + Activity.where( + subject_type: CheckpointSubmission.to_s, + subject_id: CheckpointSubmissionFinder.all_for_user_id_content_file_in_cohort(loaded_student.id, + current_content_file, + current_cohort.id)&.map(&:id), + name: Activity::NAMES[:comment_created] + ).order(created_at: :asc) + is_instructor_or_admin = current_user.instructor_or_admin?(current_cohort.id) + + render locals: { + current_checkpoint_submission: current_checkpoint_submission_presenter, + loaded_student: loaded_student, + loaded_pairs: loaded_pairs, + pair_submissions: pair_submissions, + challenges: challenge_presenters, + standard_card_props: standard_card_props, + cohort_id: current_cohort.id, + cohort_mode: current_cohort.mode, + has_scored: standard_card_props.checkpoint_performance.present?, + current_user_id: current_user.id, + is_instructor_or_admin: is_instructor_or_admin, + resubmit_url: content_file_path(current_cohort, current_content_file.standard.release.block, current_content_file.path), + next_ungraded_submission_url: next_ungraded_submission_url(current_checkpoint_submission), + performance_path: cohort_user_performances_path( + current_cohort, + current_checkpoint_submission.submitted_challenge_answers.first.user + ), + previous_challenge_path: previous_challenge(current_checkpoint_submission), + next_challenge_path: next_challenge(current_checkpoint_submission), + progress_thresholds: current_cohort.settings["progress_thresholds"], + activities: activities.order(created_at: :asc).map { |activity| ActivityPresenter.new(activity) }, + track_event_path: track_activity_event_path( + current_cohort, + current_content_file.standard.release.block_id, + current_content_file.path + ) + } + end + + def update + authorize(current_checkpoint_submission) + + current_answers = current_checkpoint_submission.submitted_challenge_answers.includes(:challenge) + + current_checkpoint_submission.update!(checkpoint_submission_params.merge(grader_id: current_user.id)) + + if checkpoint_submission_params[:state] == CheckpointSubmission::STATES[:done] + total_points = current_answers.map(&:challenge).map(&:points).compact.reduce(:+) + correct_points = current_answers.map(&:points).compact.reduce(:+) + current_checkpoint_submission.update!(total_points: total_points, correct_points: correct_points) + end + + if current_checkpoint_submission.cohort.mode == Cohort::MODES[:percentage] && + checkpoint_submission_params[:state] != CheckpointSubmission::STATES[:retry] + Performance.create( + user_id: loaded_student.id, + updator: current_user, + score: 0, + standard_id: current_standard.id, + cohort_id: current_checkpoint_submission.cohort.id, + checkpoint_submission_id: current_checkpoint_submission.id + ) + end + + student = current_answers.first.user + student.send_slack_message(slack_message_content) + + NotificationService.checkpoint_submission_graded( + user: student, + grader: current_user, + cohort: current_checkpoint_submission.cohort, + content_file: current_content_file, + checkpoint_submission: current_checkpoint_submission.reload + ) + render json: { + current_checkpoint_submission: current_checkpoint_submission_presenter + } + end + + private + + def checkpoint_submission_params + params.require(:checkpoint_submission).permit(:state) + end + + def current_cohort + @current_cohort ||= CohortPolicy::Scope.new(current_user, Cohort).resolve.find(params[:cohort_id]) + end + + def current_content_file + @current_content_file ||= current_checkpoint_submission.submitted_challenge_answers.first.challenge.content_file + end + + def current_block + @current_block ||= current_standard.release.block + end + + def current_standard + @current_standard ||= current_content_file.standard + end + + def current_cohort_release + @current_cohort_release ||= CohortRelease.joins(release: :standards). + where("cohort_releases.cohort_id = ? AND standards.uid = ?", current_cohort.id, current_standard.uid). + first + end + + def current_checkpoint_submission + CheckpointSubmission.find(params[:id]) + end + + def current_checkpoint_submission_presenter + CheckpointSubmissionPresenter.new( + checkpoint_submission: current_checkpoint_submission, + content_file: current_content_file, + url_cohort_id: current_cohort.id + ) + end + + def student + @student ||= current_checkpoint_submission.user + end + + def loaded_student + return @loaded_student if @loaded_student.present? + + @loaded_student ||= UserPresenter::ForAvatar.new(student) + end + + def loaded_pairs + return @loaded_pairs if @loaded_pairs.present? + return [loaded_student] if current_checkpoint_submission.pair_submission_ids.empty? || + current_cohort.mode == Cohort::MODES[:mastery] || + current_user.instructor_or_admin?(current_cohort) == false + + students = User.select(:first_name, :last_name, :id, :profile_image).where(id: pair_submissions.map(&:user_id)).order(id: :desc) + @loaded_pairs ||= students.map { |student| UserPresenter::ForAvatar.new(student) }.unshift(loaded_student) + end + + def pair_submissions + return [] if current_cohort.mode == Cohort::MODES[:mastery] || current_user.student_of?(current_cohort) + return @pair_submissions if @pair_submissions.present? + + @pair_submissions ||= CheckpointSubmission.where(id: current_checkpoint_submission.pair_submission_ids).filter do |cs| + CheckpointSubmission.where( + user_id: cs.user_id, + cohort_id: cs.cohort_id, + content_file_block_id: cs.content_file_block_id, + content_file_uid: cs.content_file_uid + ).where.not(state: CheckpointSubmission::STATES[:started]). + where("created_at > ?", cs.created_at).empty? + end.map do |sub| + CheckpointSubmissionPresenter.new( + checkpoint_submission: sub, + content_file: current_content_file, + url_cohort_id: current_cohort.id + ) + end + end + + def next_ungraded_submission_url(checkpoint_submission) + user_ids = CohortUser.where(cohort_id: checkpoint_submission.cohort_id).student.map(&:user_id) + not_in_ids = [checkpoint_submission.id, checkpoint_submission.pair_submission_ids].compact.flatten + pair_user_ids = CheckpointSubmission.select(:user_id).where(id: not_in_ids).map(&:user_id) + + previous_submission_ids_by_users = CheckpointSubmission.select(:id). + where("created_at < ?", checkpoint_submission.created_at). + where( + user_id: pair_user_ids, + content_file_block_id: checkpoint_submission.content_file_block_id, + content_file_uid: checkpoint_submission.content_file_uid + ).map(&:id) + + oldest_ungraded_submission = CheckpointSubmission. + where(content_file_uid: current_content_file.uid, + content_file_block_id: current_content_file.standard.release.block_id, + user_id: user_ids, + cohort_id: checkpoint_submission.cohort_id). + where.not(id: not_in_ids + previous_submission_ids_by_users, state: CheckpointSubmission::STATES[:started]). + select("DISTINCT ON (checkpoint_submissions.user_id) checkpoint_submissions.id, checkpoint_submissions.state"). + order("checkpoint_submissions.user_id, created_at DESC").to_a.select {|cs| cs.state == "needs_review"}.last + if oldest_ungraded_submission + Rails.application.routes.url_helpers.cohort_checkpoint_submission_path( + current_cohort.id, oldest_ungraded_submission.id + ) + else + Rails.application.routes.url_helpers.unit_progress_cohort_path(current_cohort.id) + end + end + + def challenge_presenters + is_instructor_or_admin = current_user.instructor_or_admin?(current_cohort.id) + challenge_ids = current_checkpoint_submission.submitted_challenge_answers.pluck(:challenge_id).uniq + challenges = Challenge.where(id: challenge_ids).order(position: :asc) + + all_submissions = SubmittedChallengeAnswer.where( + user_id: loaded_pairs.map(&:id), + challenge_uid: challenges.map(&:uid).uniq, + block_id: current_checkpoint_submission.content_file_block_id # select only for submissions in block + ).where( + "status <> 'draft'" + ).order(created_at: :desc) + + challenges.map do |challenge| + ChallengeWithSubmittedChallengeAnswersPresenter.new( + current_cohort, + challenge, + all_submissions.select {|sca| sca.challenge_uid == challenge.uid }, + is_instructor_or_admin, + user_context: loaded_pairs, + is_checkpoint: true, + can_view_status: is_instructor_or_admin || current_checkpoint_submission.done?, + can_view_explanation: current_checkpoint_submission.done? + ) + end + end + + def standard_card_props + standard = current_content_file.standard + @standard_card_props ||= StandardCardComponentProps.new( + standard: standard, + latest_performance: Performance.order(created_at: :desc). + find_by(user_id: loaded_student.id, standard_id: standard.id), + checkpoint_performance: Performance.order(created_at: :desc). + find_by(user_id: loaded_student.id, standard_id: standard.id, checkpoint_submission_id: params[:id]) + ) + end + + def next_checkpoint_submission_url(all_needs_review_checkpoint_submissions, current_checkpoint_submission) + sorted_oldest_first_submissions = all_needs_review_checkpoint_submissions.sort_by(&:updated_at) + + next_index = sorted_oldest_first_submissions.map(&:id).index(current_checkpoint_submission.id) + # next_index = next_index.nil? ? 0 : next_index + 1 + + if next_index.nil? + next_needs_review_checkpoint_submission = sorted_oldest_first_submissions.first + else + next_needs_review_checkpoint_submission = sorted_oldest_first_submissions[next_index + 1] + if next_needs_review_checkpoint_submission.nil? && sorted_oldest_first_submissions.length > 1 + next_needs_review_checkpoint_submission = sorted_oldest_first_submissions.first + end + end + + if next_needs_review_checkpoint_submission + cohort_checkpoint_submission_url( + params[:cohort_id], + next_needs_review_checkpoint_submission.id + ) + else + unit_progress_cohort_path(params[:cohort_id]) + end + end + + def slack_message_content + action = case current_checkpoint_submission.reload.state + when CheckpointSubmission::STATES[:done] + "finished scoring" + when CheckpointSubmission::STATES[:rejected] + "rejected" + end + standard_title = current_content_file.standard.title + checkpoint_name = current_content_file.title + url = cohort_checkpoint_submission_url( + params[:cohort_id], + current_checkpoint_submission.id + ) + + "#{current_user.full_name} #{action} your submission to #{standard_title} Checkpoint: #{checkpoint_name}. Review it here: #{url}." + end + + NO_ORPHANS = "NOT (content_files.content_file_type = 'checkpoint' AND submitted_challenge_answers.checkpoint_submission_id IS NULL)" + + def previous_challenge(checkpoint_submission) + # check for previous within block, not necessarily in standard + previous_sca_in_block = SubmittedChallengeAnswer.joins(challenge: [content_file: [standard: :release]]). + where("submitted_challenge_answers.user_id = ?", loaded_student.id). + where("submitted_challenge_answers.cohort_id = ?", current_cohort.id). + where("standards.position <= ?", current_standard.position). + where("releases.block_id = ?", checkpoint_submission.content_file_block_id). + where("challenges.id NOT IN (?)", current_content_file.challenges.map(&:id)). + where(NO_ORPHANS). + order("standards.position DESC, content_files.position DESC, challenges.position DESC").first + return previous_sca_in_block.review_path(cohort_id: current_cohort.id, user_id: loaded_student.id) if previous_sca_in_block.present? + + # check within previous blocks + previous_sca_blocks = SubmittedChallengeAnswer.joins(challenge: [content_file: [standard: [release: :cohort_releases]]]). + where("submitted_challenge_answers.user_id = ?", loaded_student.id). + where("submitted_challenge_answers.cohort_id = ?", current_cohort.id). + where("cohort_releases.position < ?", current_cohort_release.position). + where(NO_ORPHANS). + order("cohort_releases.position DESC"). + order("standards.position DESC"). + order("content_files.position DESC"). + order("challenges.position DESC").first + + return previous_sca_blocks.review_path(cohort_id: current_cohort.id, user_id: loaded_student.id) if previous_sca_blocks.present? + end + + def next_challenge(checkpoint_submission) + # check within block with standard position greater than submission's standard position + next_sca = SubmittedChallengeAnswer.joins(challenge: [content_file: [standard: :release]]). + where("submitted_challenge_answers.user_id = ?", loaded_student.id). + where("submitted_challenge_answers.cohort_id = ?", current_cohort.id). + where("standards.position > ?", current_standard.position). + where("releases.block_id = ?", checkpoint_submission.content_file_block_id). + where("challenges.id NOT IN (?)", current_content_file.challenges.map(&:id)). + where(NO_ORPHANS). + order("standards.position ASC, content_files.position ASC, challenges.position ASC").first + return next_sca.review_path(cohort_id: current_cohort.id, user_id: loaded_student.id) if next_sca.present? + + # check in blocks later in the cohort + next_sca_blocks = SubmittedChallengeAnswer.joins(challenge: [content_file: [standard: [release: :cohort_releases]]]). + where("submitted_challenge_answers.user_id = ?", loaded_student.id). + where("submitted_challenge_answers.cohort_id = ?", current_cohort.id). + where("cohort_releases.position > ?", current_cohort_release.position). + where(NO_ORPHANS). + order("cohort_releases.position DESC"). + order("standards.position DESC"). + order("content_files.position DESC"). + order("challenges.position DESC").first + return next_sca_blocks.review_path(cohort_id: current_cohort.id, user_id: loaded_student.id) if next_sca_blocks.present? + end + end + end +end diff --git a/app/controllers/cohorts/content_files/submitted_challenge_answers_controller.rb b/app/controllers/cohorts/content_files/submitted_challenge_answers_controller.rb new file mode 100644 index 0000000..968e4d8 --- /dev/null +++ b/app/controllers/cohorts/content_files/submitted_challenge_answers_controller.rb @@ -0,0 +1,346 @@ +module Cohorts + module ContentFiles + class SubmittedChallengeAnswersController < ApplicationController + include CreateSubmittedChallengeAnswerService + + before_action :current_cohort # no route should function unless the cohort exists + + def update_local + sca = SubmittedChallengeAnswer.includes(:challenge).find(params[:id]) + + authorize(sca, :update_local_challenge_answer?) + + if params["m"] == true # See ChallengeBlock.tsx + sca.update(status: SubmittedChallengeAnswer::STATUSES[:correct]) + else + sca.update(status: SubmittedChallengeAnswer::STATUSES[:incorrect]) + end + + render json: { + submittedChallengeAnswer: SubmittedChallengeAnswerPresenter.new( + sca, + instructor_or_admin + ) + } + end + + def create + start_time = DateTime.current + authorize(current_cohort, :submit_challenge_answer?) + + challenge = Challenge.find(params[:challenge_id]) + submitted_challenge_answer = if params[:draft] + create_submitted_challenge_answer_draft(challenge, params[:answer]) + else + create_submitted_challenge_answer( + current_cohort, + current_user, + challenge, + params[:answer], + params[:checkpoint_submission_id] + ) + end + + end_time = DateTime.current + if ["checkbox", "local-snippet", "multiple-choice", "number", "poll", "short-answer"].include?(challenge.challenge_type) + # Challenges that dont need callouts to assessment-service should not take longer than 2 secs, alert us + length_of_scoring = end_time.to_i - start_time.to_i + if length_of_scoring > 10 + SlackChallengePerformanceJob.perform_later(submitted_challenge_answer.id, request.referer, length_of_scoring) + end + end + + render json: { + submittedChallengeAnswer: SubmittedChallengeAnswerPresenter.new( + submitted_challenge_answer, + instructor_or_admin + ) + } + end + + def batch_create + authorize(current_cohort, :submit_challenge_answer?) + + unless current_content_file.max_checkpoint_submissions.nil? + user_attempts = current_user.checkpoint_submissions_count( + current_cohort.id, + current_content_file.standard.release.block_id, + current_content_file.uid + ) + + if user_attempts >= current_content_file.max_checkpoint_submissions + render json: { + message: "Sorry, you have already submitted this checkpoint the max amount of times." + } and return + end + end + + checkpoint_submission = params[:draft] == true ? nil : find_or_create_checkpoint_submission(current_user.id) + + challenge_ids = params[:submitted_challenge_answers].map {|s| s[:challenge_id]} + challenges = Challenge.where(id: challenge_ids.compact).to_a + params[:submitted_challenge_answers]&.each do |submission| + challenge = challenges.find { |c| c.id == submission[:challenge_id].to_i } + if checkpoint_submission + create_submitted_challenge_answer( + current_cohort, + current_user, + challenge, + submission[:answer], + checkpoint_submission&.id + ) + else + create_submitted_challenge_answer_draft(challenge, submission[:answer]) + end + end + + if checkpoint_submission + checkpoint_submission.update(submitted_at: DateTime.current) + name = if previous_checkpoint_submission?(checkpoint_submission.id) + Activity::NAMES[:checkpoint_submission_resubmitted] + else + Activity::NAMES[:checkpoint_submission_created] + end + + Activity.create( + cohort: current_cohort, + creator: current_user, + name: name, + subject: checkpoint_submission + ) + end + + checkpoint_submission_presenter = if checkpoint_submission + CheckpointSubmissionPresenter.new( + checkpoint_submission: checkpoint_submission, + content_file: current_content_file + ) + end + + submitted_date = checkpoint_submission&.created_at + + if checkpoint_submission + CheckpointSubmissionService.new( + checkpoint_submission, + current_content_file, + current_cohort, + current_user + ).attempt_autoscore + + if params[:pairs].present? + create_pair_submissions(checkpoint_submission) + CheckpointPairedSubmissionJob.perform_later(checkpoint_submission.id, current_content_file.autoscore) + end + end + + render json: { + submittedDate: submitted_date, + checkpointSubmission: checkpoint_submission_presenter + } + end + + def checkpoint_submission_results + authorize(current_cohort, :submit_challenge_answer?) + + results = {} + + latest_checkpoint_submission = CheckpointSubmissionFinder.latest_for_checkpoint_content_file_for_user_in_cohort( + cohort_id: current_cohort.id, + content_file: current_content_file, + user_id: current_user.id + ) + + if current_content_file.autoscore + scas = SubmittedChallengeAnswer.includes(:challenge).where( + checkpoint_submission_id: latest_checkpoint_submission.id, + user: current_user, + cohort: current_cohort + ) + + failed_scas = scas.where(status: SubmittedChallengeAnswer::FAILURE_STATUSES.values) + + if failed_scas.any? + results["errors"] = failed_scas.map do |sca| + { + challenge_num: sca.challenge.position, + challenge_err: sca.test_results.empty? ? sca.status.gsub("_", " ").titleize : sca.test_results + } + end + + scas.update_all(checkpoint_submission_id: nil) + Performance.where(checkpoint_submission_id: latest_checkpoint_submission.id).delete_all + latest_checkpoint_submission.destroy + + render json: results and return + end + + if scas.where(status: SubmittedChallengeAnswer::UNGRADED_STATUSES[:processing]).empty? + results = assign_checkpoint_results(latest_checkpoint_submission, scas) + end + else + results["url"] = cohort_checkpoint_submission_path(current_cohort, latest_checkpoint_submission) + end + + render json: results + end + + def update + authorize(current_submitted_challenge_answer) + + new_attributes = submitted_challenge_answer_params + new_attributes[:manual_grader_id] = current_user.id if SubmittedChallengeAnswer.new(new_attributes).graded? + + if current_submitted_challenge_answer.update(new_attributes) && current_submitted_challenge_answer.checkpoint_submission + current_submitted_challenge_answer.checkpoint_submission.update_points + if current_submitted_challenge_answer.checkpoint_submission.done? + NotificationService.checkpoint_challenge_graded( + user: current_submitted_challenge_answer.user, + cohort: current_submitted_challenge_answer.cohort, + content_file: current_content_file, + checkpoint_submission: current_submitted_challenge_answer.checkpoint_submission, + challenge: current_submitted_challenge_answer.challenge + ) + end + end + + render json: { + submitted_challenge_answer_presenter: SubmittedChallengeAnswerPresenter.new( + current_submitted_challenge_answer, + true + ) + }, status: 200 + end + + def cancel + authorize(current_submitted_challenge_answer) + + if current_submitted_challenge_answer.processing? + current_submitted_challenge_answer.update_attributes( + status: SubmittedChallengeAnswer::STATUSES[:canceled], + test_results: "Tests canceled by student." + ) + end + + render json: { submittedChallengeAnswer: + SubmittedChallengeAnswerPresenter.new(current_submitted_challenge_answer, instructor_or_admin) } + end + + def show + authorize(current_submitted_challenge_answer) + + render json: SubmittedChallengeAnswerPresenter.new(current_submitted_challenge_answer, instructor_or_admin) + end + + private + + def assign_checkpoint_results(latest_checkpoint_submission, scas) + results = { + "url": cohort_checkpoint_submission_path(current_cohort, latest_checkpoint_submission), + "created_at": latest_checkpoint_submission.created_at, + "state": latest_checkpoint_submission.state, + "cohort_mode": current_cohort.mode, + "correct_challenges": scas.select {|sca| sca.status == SubmittedChallengeAnswer::GRADED_STATUSES[:correct] }.count, + "total_challenges": scas.count, + "total_points": scas.map { |sa| sa.challenge.points }.flatten.reduce(:+), + "correct_points": scas.find_all do |sa| + sa.points if sa.status == SubmittedChallengeAnswer::STATUSES[:correct] || sa.challenge.can_assign_partial_credit + end.map(&:points).reduce(:+) || 0 + } + + perf = latest_checkpoint_submission.performances.order("created_at DESC").last + results["mastery_score"] = perf.score if perf.present? + + results + end + + def previous_checkpoint_submission?(submission_id) + challenge_ids = params[:submitted_challenge_answers]&.map { |sca| sca[:challenge_id] } + return false if challenge_ids.blank? + + SubmittedChallengeAnswer.where(user: current_user, challenge_id: challenge_ids). + where("checkpoint_submission_id != ?", submission_id). + map(&:checkpoint_submission_id).compact.any? + end + + def create_submitted_challenge_answer_draft(challenge, answer) + submitted_challenge_answer = SubmittedChallengeAnswer.new( + cohort: current_cohort, + answer: answer.nil? ? "" : answer, + challenge_id: challenge.id, + checkpoint_submission_id: nil, + user: current_user, + status: SubmittedChallengeAnswer::UNGRADED_STATUSES[:draft], + hints_shown: 0, + test_results: "" + ) + submitted_challenge_answer.save! + submitted_challenge_answer + end + + def instructor_or_admin + current_user.instructor_or_admin?(current_cohort.id) + end + + def current_cohort + @cohort ||= CohortPolicy::Scope.new(current_user, Cohort).resolve.find_by!(id: params[:cohort_id]) + end + + def current_content_file + @current_content_file ||= ContentFile.unscoped.find(params[:content_file_id]) + end + + def current_submitted_challenge_answer + @submitted_challenge_answer ||= SubmittedChallengeAnswer.find(params[:id]) + end + + def find_or_create_checkpoint_submission(user_id) + checkpoint_submission = CheckpointSubmission.find_by( + cohort_id: params[:cohort_id], + user_id: user_id, + content_file_block_id: current_content_file.standard.release.block_id, + content_file_uid: current_content_file.uid, + state: CheckpointSubmission::STATES[:started] + ) + if checkpoint_submission.nil? + checkpoint_submission = CheckpointSubmission.create!( + cohort_id: params[:cohort_id], + user_id: user_id, + content_file_block_id: current_content_file.standard.release.block_id, + content_file_uid: current_content_file.uid, + state: CheckpointSubmission::STATES[:needs_review] + ) + else + # TODO: save on a db transaction by waiting until later? + checkpoint_submission.update(state: CheckpointSubmission::STATES[:needs_review]) + end + checkpoint_submission + end + + def create_pair_submissions(checkpoint_submission) + student_pair_ids = params[:pairs].keys.map(&:to_i).delete_if { |id| id == current_user.id } + submissions = student_pair_ids.map do |user_id| + unless current_content_file.max_checkpoint_submissions.nil? + user = User.find(user_id) + user_attempts = user.checkpoint_submissions_count( + current_cohort.id, + current_content_file.standard.release.block_id, + current_content_file.uid + ) + next if user_attempts >= current_content_file.max_checkpoint_submissions + end + + find_or_create_checkpoint_submission(user_id) + end.compact + checkpoint_submission.update(pair_submission_ids: submissions.map(&:id)) unless submissions.empty? + submissions.each do |sub| + ids = [checkpoint_submission.id, submissions.map(&:id).reject { |id| id == sub.id}].flatten + sub.update(pair_submission_ids: ids) + end + end + + def submitted_challenge_answer_params + params.require(:submitted_challenge_answer).permit(:status, :points) + end + end + end +end diff --git a/app/controllers/cohorts/content_files_controller.rb b/app/controllers/cohorts/content_files_controller.rb new file mode 100644 index 0000000..8302e25 --- /dev/null +++ b/app/controllers/cohorts/content_files_controller.rb @@ -0,0 +1,260 @@ +module Cohorts + class ContentFilesController < ApplicationController + def visibility + authorize(current_cohort, :submissions_dashboard?) + query = ContentVisibility.where( + cohort_id: current_cohort.id, + content_type: "ContentFile", + content_uid: current_content_file.uid, + visibility_type: params[:visibility_type] + ) + if request.method == "PUT" + query.first_or_create! + elsif request.method == "DELETE" + query.delete_all + end + render json: { success: true } + end + + def student_summary_csv + authorize(current_cohort, :submissions_dashboard?) + data = ActiveRecord::Base.connection.exec_query( + student_summary_sql, + "SQL", + [[nil, current_cohort.id], [nil, current_content_file.uid], [nil, current_block_id]] + ) + head :no_content and return if data.empty? + data = add_topics(data) + respond_to do |format| + format.html { redirect_to cohort_path(current_cohort) } + format.csv do + csv_headers("student_summary") + self.response_body = build_csv_enumerator(data[0].map {|k, _| k }, data) + end + end + end + + def challenge_data_csv + authorize(current_cohort, :submissions_dashboard?) + sql_query_params = [[nil, current_cohort.id], [nil, current_content_file.uid], [nil, current_block_id]] + data = ActiveRecord::Base.connection.exec_query(challenge_data_sql, + "SQL", + sql_query_params) + head :no_content and return if data.empty? + respond_to do |format| + format.html { redirect_to cohort_path(current_cohort) } + format.csv do + csv_headers("challenge_data") + self.response_body = build_csv_enumerator(data[0].map {|k, _| k }, data) + end + end + end + + private + + def add_topics(data) + group_checkpoint_submissions = CheckpointSubmission.includes(submitted_challenge_answers: :challenge). + where(id: data.map { |r| r["checkpoint_submission_id"] }). + group_by(&:id) + + data.map do |r| + if r["checkpoint_submission_id"] + submission = group_checkpoint_submissions[r["checkpoint_submission_id"]][0] + ungraded = submission.state == CheckpointSubmission::STATES[:needs_review] && + submission.submitted_challenge_answers.map(&:points).include?(nil) + + topic_hash = parse_checkpoint_topics(submission, ungraded) + if ungraded + topic_hash.merge!("points_earned" => nil, "score_percentage" => nil) + end + r.to_hash.merge(topic_hash) + else + r.to_hash.merge(parse_checkpoint_topics(nil, false)) + end + end + end + + def parse_checkpoint_topics(submission, ungraded) + topic_hash = content_file_topics.each_with_object({}) do |topic, hash| + pts_earned = checkpoint_submission_pts_earned(submission, topic, ungraded) + pts_avail = content_file_pts_avail[topic] + + if submission && pts_avail && pts_earned + percent = (((pts_earned).to_f / (pts_avail).to_f) * 100).to_i + end + hash["topic:#{topic}_pts_earned"] = pts_earned + hash["topic:#{topic}_pts_avail"] = pts_avail + hash["topic:#{topic}_percent"] = percent + end + topic_hash + end + + def content_file_pts_avail + @content_file_pts_avail ||= content_file_topics.each_with_object({}) do |topic, hash| + hash[topic] = current_content_file.challenges.select {|c| c.topics&.include?(topic)}.map(&:points).compact.reduce(:+) + end + end + + def checkpoint_submission_pts_earned(submission, topic, ungraded) + return nil if submission.nil? || ungraded + + matching_scas = submission.submitted_challenge_answers.select { |sca| sca.challenge.topics&.include?(topic)} + matching_scas.map(&:points).compact.reduce(:+) + end + + def content_file_topics + @content_file_topics ||= current_content_file.challenges.map(&:topics).flatten.compact.uniq + @content_file_topics + end + + def current_content_file + @current_content_file ||= ContentFile.unscoped.find(params[:id]) + end + + def current_cohort + @current_cohort ||= CohortPolicy::Scope.new(current_user, Cohort).resolve.find(params[:cohort_id]) + end + + def current_block_id + @current_block ||= current_content_file.standard.release.block_id + end + + def csv_filename(type) + "#{type}-#{current_content_file.title}-cohort#{current_cohort.id}-#{Time.zone.now.to_date.to_s(:default)}.csv" + end + + def csv_headers(filename) + headers["X-Accel-Buffering"] = "no" + headers["Cache-Control"] = "no-cache" + headers["Content-Type"] = "text/csv; charset=utf-8" + headers["Content-Disposition"] = + %(attachment; filename="#{csv_filename(filename)}") + headers["Last-Modified"] = Time.zone.now.ctime.to_s + end + + def build_csv_enumerator(header, data) + Enumerator.new do |y| + CsvBuilder.new(header, data, y).build + end + end + + class CsvBuilder + attr_accessor :output, :header, :data + + def initialize(header, data, output = "") + @output = output + @header = header + @data = data + end + + def build + output << CSV.generate_line(header) + data.each do |row| + output << CSV.generate_line(row.map {|_, v| v}) + end + output + end + end + + def challenge_data_sql + <<~SQL + WITH checkpoint_attempts AS ( + SELECT DISTINCT id, user_id FROM checkpoint_submissions AS cs + WHERE cs.cohort_id = $1 AND cs.content_file_uid = $2 AND cs.content_file_block_id = $3 + ), + checkpoint_user_attempts AS ( + SELECT id, ROW_NUMBER () OVER (PARTITION BY user_id ORDER BY id) from checkpoint_attempts + ) + SELECT u.first_name, + u.last_name, + u.email, + c.challenge_type, + c.position, + c.title, + c.topics, + c.question, + c.answer AS correct_answer, + sca.answer AS student_answer, + c.points AS possible_points, + sca.points AS student_points, + sca.created_at AS submitted_at, + cs.content_file_uid, + cs.state AS checkpoint_state, + cs.id AS checkpoint_id, + c.uid AS challenge_uid, + cua.row_number AS attempt_number + FROM submitted_challenge_answers AS sca + JOIN users AS u + ON sca.user_id = u.id + JOIN cohort_users AS cu + ON cu.user_id = u.id + JOIN checkpoint_submissions AS cs + ON cs.id = sca.checkpoint_submission_id + JOIN challenges AS c + ON c.id = sca.challenge_id + JOIN checkpoint_user_attempts AS cua + ON cua.id = cs.id + WHERE sca.cohort_id = $1 + AND cu.roles = '{}' + AND cu.cohort_id = $1 + AND sca.checkpoint_submission_id IS NOT NULL + AND cs.content_file_uid = $2 + AND cs.content_file_block_id = $3 + AND sca.status <> 'draft' + AND cs.state <> 'started' + ORDER BY u.last_name, + c.position, + cs.created_at + SQL + end + + def student_summary_sql + <<~SQL + SELECT u.first_name, + u.last_name, + u.email, + CASE + WHEN u.last_viewed_cohort_id IS NOT NULL THEN 'y' + ELSE 'n' + END AS has_logged_in, + CASE + WHEN cs.id IS NULL THEN NULL + ELSE Row_number() + OVER( + partition BY u.id + ORDER BY cs.id ) + END AS attempt_number, + cs.id AS checkpoint_submission_id, + cs.state AS submission_state, + cs.created_at AS attempt_started, + cs.submitted_at AS attempt_submitted, + Sum(sca.points) AS points_earned, + Sum(c.points) AS total_points, + 100 * Sum(sca.points) / Sum(c.points) AS score_percentage + FROM users AS u + JOIN cohort_users AS cu + ON cu.user_id = u.id + LEFT JOIN checkpoint_submissions AS cs + ON cs.user_id = u.id + AND cs.cohort_id = cu.cohort_id + AND (cs.content_file_uid = $2 OR cs.content_file_uid IS NULL) + AND cs.content_file_block_id = $3 + LEFT JOIN submitted_challenge_answers AS sca + ON sca.checkpoint_submission_id = cs.id + LEFT JOIN challenges AS c + ON c.id = sca.challenge_id + WHERE cu.cohort_id = $1 + AND cu.roles = '{}' + GROUP BY u.id, + u.first_name, + u.last_name, + u.email, + u.last_viewed_cohort_id, + cs.id + ORDER BY has_logged_in DESC, + u.last_name, + attempt_number + SQL + end + end +end diff --git a/app/controllers/cohorts/pairings_controller.rb b/app/controllers/cohorts/pairings_controller.rb new file mode 100644 index 0000000..c4f872b --- /dev/null +++ b/app/controllers/cohorts/pairings_controller.rb @@ -0,0 +1,49 @@ +module Cohorts + class PairingsController < ApplicationController + def index + authorize(current_cohort, :partnerup?) + + pairings = Pairing.where(cohort_id: current_cohort.id).order(created_at: :desc) + + render json: pairings + end + + def create + authorize(current_cohort, :partnerup?) + + pairing = Pairing.create!(pairing_params.merge(cohort_id: current_cohort.id)) + + render json: pairing + end + + def update + authorize(current_cohort, :partnerup?) + + loaded_pairing.update!(pairing_params) + + render json: loaded_pairing + end + + def destroy + authorize(current_cohort, :partnerup?) + + loaded_pairing.destroy! + + render json: { ack: "ok" } + end + + protected + + def pairing_params + @pairing_params ||= params.require(:pairing).permit(:size, :title, :groups) + end + + def loaded_pairing + @loaded_pairing ||= Pairing.find(params[:id]) + end + + def current_cohort + @current_cohort ||= CohortPolicy::Scope.new(current_user, Cohort).resolve.find(params[:cohort_id]) + end + end +end diff --git a/app/controllers/cohorts/standards_controller.rb b/app/controllers/cohorts/standards_controller.rb new file mode 100644 index 0000000..4a3ce64 --- /dev/null +++ b/app/controllers/cohorts/standards_controller.rb @@ -0,0 +1,43 @@ +module Cohorts + class StandardsController < ApplicationController + def show + authorize(current_cohort, :submissions_dashboard?) + all_checkpoints = CheckpointSubmission.where(content_file_block_id: current_cohort.block_ids, + cohort_id: current_cohort.id). + where.not(state: CheckpointSubmission::STATES[:started]). + order(created_at: :desc) + result = StandardSubmissionsService. + new(standard: current_standard, cohort: current_cohort, + all_checkpoints: all_checkpoints, + instructor_or_admin: false).single(show_hidden: true) + + render json: result + end + + def visibility + authorize(current_cohort, :submissions_dashboard?) + query = ContentVisibility.where( + cohort_id: current_cohort.id, + content_type: "Standard", + content_uid: current_standard.uid, + visibility_type: params["visibility_type"] + ) + if request.method == "PUT" + query.first_or_create! + elsif request.method == "DELETE" + query.delete_all + end + render json: { success: true } + end + + private + + def current_standard + @current_standard ||= Standard.find(params[:id]) + end + + def current_cohort + @current_cohort ||= CohortPolicy::Scope.new(current_user, Cohort).resolve.find(params[:cohort_id]) + end + end +end diff --git a/app/controllers/cohorts/submitted_challenge_answers/activities_controller.rb b/app/controllers/cohorts/submitted_challenge_answers/activities_controller.rb new file mode 100644 index 0000000..0df2ebd --- /dev/null +++ b/app/controllers/cohorts/submitted_challenge_answers/activities_controller.rb @@ -0,0 +1,84 @@ +module Cohorts + module SubmittedChallengeAnswers + class ActivitiesController < ApplicationController + before_action :current_cohort + + def create + activity = Activity.new( + content: activity_content[:content], + subject: current_submitted_challenge_answer, + creator: current_user, + name: Activity::NAMES[:comment_created], + cohort: current_cohort + ) + + authorize(activity, :create_for_submitted_challenge_answer?) + + if activity.save + challenge = current_submitted_challenge_answer.challenge + content_file = challenge.content_file + standard = content_file.standard + block = standard.release.block + + url = cohort_user_challenge_url( + current_cohort, + current_submitted_challenge_answer.user, + current_submitted_challenge_answer.challenge + ) + if current_submitted_challenge_answer.user_id == current_user.id + current_cohort.instructors.each do |instructor| + instructor.send_slack_message( + slack_message_content( + commentor: current_user, + challenge: current_submitted_challenge_answer.challenge, + url: url + ) + ) + + instructor.notify( + tagline: "Comment Left", + title: + "#{current_user.full_name} commented on #{block.title} - #{standard.title} - #{content_file.title} - #{challenge.title}", + url: cohort_user_challenge_url(current_cohort, current_submitted_challenge_answer.user, challenge), + description: "\"#{activity_content[:content]}\"" + ) + end + else + current_submitted_challenge_answer.user.send_slack_message( + slack_message_content(commentor: current_user, challenge: current_submitted_challenge_answer.challenge, url: url) + ) + + current_submitted_challenge_answer.user.notify( + tagline: "Comment Left", + title: + "#{current_user.full_name} commented on #{block.title} - #{standard.title} - #{content_file.title} - #{challenge.title}", + url: cohort_user_challenge_url(current_cohort, current_submitted_challenge_answer.user, challenge), + description: "\"#{activity_content[:content]}\"" + ) + end + render json: ActivityPresenter.new(activity), status: 200 + else + render json: { error: activity.errors.full_messages }, status: 400 + end + end + + private + + def activity_content + params.require(:activity).permit(:content) + end + + def current_cohort + @current_cohort ||= CohortPolicy::Scope.new(current_user, Cohort).resolve.find_by!(id: params[:cohort_id]) + end + + def current_submitted_challenge_answer + @submitted_challenge_answer ||= SubmittedChallengeAnswer.find(params[:submitted_challenge_answer_id]) + end + + def slack_message_content(commentor:, challenge:, url:) + "#{commentor.full_name} left a comment on #{challenge.title}. Read it here: #{url}." + end + end + end +end diff --git a/app/controllers/cohorts/users/challenges_controller.rb b/app/controllers/cohorts/users/challenges_controller.rb new file mode 100644 index 0000000..ca13285 --- /dev/null +++ b/app/controllers/cohorts/users/challenges_controller.rb @@ -0,0 +1,182 @@ +module Cohorts + module Users + class ChallengesController < ApplicationController + def show + current_user.admin? ? skip_authorization : authorize(loaded_cohort_user, :view_user_challenges?) + + @html_title = "#{loaded_user.full_name}: #{current_challenge.title}" + + is_instructor_or_admin = current_user.instructor_or_admin?(current_cohort.id) + submitted_challenge_answers = SubmittedChallengeAnswerFinder.all_for_user_id_challenge_in_cohort(loaded_user.id, + current_challenge, + current_cohort.id). + where.not(status: SubmittedChallengeAnswer::UNGRADED_STATUSES[:draft]) + + activities = Activity.where( + subject_type: SubmittedChallengeAnswer.to_s, + name: Activity::NAMES[:comment_created], + subject_id: submitted_challenge_answers&.map(&:id) + ).order(created_at: :asc) + + render( + locals: { + challenge: ChallengeWithSubmittedChallengeAnswersPresenter.new( + current_cohort, + current_challenge, + submitted_challenge_answers, + is_instructor_or_admin, + user_context: loaded_user, + is_checkpoint: false + ), + block_id: current_release.block_id, + content_file_path: current_challenge.content_file.path, + content_file_position: current_challenge.content_file.position, + content_file_type: current_challenge.content_file.content_file_type, + activities: activities.order(created_at: :asc).map { |activity| ActivityPresenter.new(activity) }, + standard: StandardCardComponentProps.new(standard: current_challenge.standard), + loaded_user: loaded_user_details, + is_instructor_or_admin: is_instructor_or_admin, + cohort_id: current_cohort.id, + cohort_mode: current_cohort.mode, + previous_challenge_path: previous_challenge, + next_challenge_path: next_challenge + } + ) + end + + private + + def loaded_user_details + { id: loaded_user.id, profile_image: loaded_user.profile_image, full_name: loaded_user.full_name, initials: loaded_user.initials } + end + + def loaded_cohort_user + @loaded_cohort_user ||= CohortUser.find_by!(user_id: user_params[:user_id], cohort_id: cohort_params[:cohort_id]) + end + + def loaded_user + @loaded_user ||= UserPolicy::Scope.new(current_user, User).resolve.find(user_params[:user_id]) + end + + def current_cohort + @current_cohort ||= CohortPolicy::Scope.new(current_user, Cohort).resolve.find(cohort_params[:cohort_id]) + end + + def current_challenge + @current_challenge ||= Challenge.find(challenge_params[:id]) + end + + def current_standard + @current_standard ||= current_challenge.content_file.standard + end + + def current_release + @current_release ||= current_standard.release + end + + def current_cohort_release + @current_cohort_release ||= CohortRelease.joins(release: :standards). + where("cohort_releases.cohort_id = ? AND standards.uid = ?", current_cohort.id, current_standard.uid). + first + end + + def user_params + params.permit(:user_id) + end + + def cohort_params + params.permit(:cohort_id) + end + + def challenge_params + params.permit(:id) + end + + def previous_challenge + # first check in content file + previous_in_cf = SubmittedChallengeAnswerFinder.latest_for_user_id_content_file_for_cohort( + loaded_user.id, current_challenge.content_file, current_cohort.id + ).joins(:challenge). + where("challenges.position < ?", current_challenge.position). + order("challenges.position DESC").first + return previous_in_cf.review_path(cohort_id: current_cohort.id, user_id: loaded_user.id) if previous_in_cf.present? + + # check in previous content files in standard + previous_in_standard = SubmittedChallengeAnswer.joins(challenge: [content_file: [standard: :release]]). + where("submitted_challenge_answers.user_id = ?", loaded_user.id). + where("content_files.position < ?", current_challenge.content_file.position). + where("standards.uid = ?", current_standard.uid). + where("releases.block_id = ?", current_release.block_id). + where("submitted_challenge_answers.cohort_id = ?", current_cohort.id). + no_orphans. + order("content_files.position DESC, challenges.position DESC").first + return previous_in_standard.review_path(cohort_id: current_cohort.id, user_id: loaded_user.id) if previous_in_standard.present? + + # check in previous standards in block + previous_in_block = SubmittedChallengeAnswer.joins(challenge: [content_file: [standard: :release]]). + where("submitted_challenge_answers.user_id = ?", loaded_user.id). + where("standards.position < ?", current_standard.position). + where("releases.block_id = ?", current_release.block_id). + where("submitted_challenge_answers.cohort_id = ?", current_cohort.id). + no_orphans. + order("standards.position DESC, content_files.position DESC, challenges.position DESC").first + return previous_in_block.review_path(cohort_id: current_cohort.id, user_id: loaded_user.id) if previous_in_block.present? + + # check in previous blocks + previous_out_block = SubmittedChallengeAnswer.joins(challenge: [content_file: [standard: [release: :cohort_releases]]]). + where("submitted_challenge_answers.user_id = ?", loaded_user.id). + where("cohort_releases.position < ?", current_cohort_release.position). + where("submitted_challenge_answers.cohort_id = ?", current_cohort.id). + no_orphans. + order("cohort_releases.position DESC"). + order("standards.position DESC"). + order("content_files.position DESC"). + order("challenges.position DESC").first + return previous_out_block.review_path(cohort_id: current_cohort.id, user_id: loaded_user.id) if previous_out_block.present? + end + + def next_challenge + # first check in content file + next_in_cf = SubmittedChallengeAnswerFinder.latest_for_user_id_content_file_for_cohort( + loaded_user.id, current_challenge.content_file, current_cohort.id + ).joins(:challenge). + where("challenges.position > ?", current_challenge.position). + order("challenges.position ASC").first + return next_in_cf.review_path(cohort_id: current_cohort.id, user_id: loaded_user.id) if next_in_cf.present? + + # check in next content files in standard + next_in_standard = SubmittedChallengeAnswer.joins(challenge: [content_file: [standard: :release]]). + where("submitted_challenge_answers.user_id = ?", loaded_user.id). + where("content_files.position > ?", current_challenge.content_file.position). + where("standards.uid = ?", current_standard.uid). + where("releases.block_id = ?", current_release.block_id). + where("submitted_challenge_answers.cohort_id = ?", current_cohort.id). + no_orphans. + order("content_files.position ASC, challenges.position ASC").first + return next_in_standard.review_path(cohort_id: current_cohort.id, user_id: loaded_user.id) if next_in_standard.present? + + # check in next standards in block + next_in_block = SubmittedChallengeAnswer.joins(challenge: [content_file: [standard: :release]]). + where("submitted_challenge_answers.user_id = ?", loaded_user.id). + where("standards.position > ?", current_standard.position). + where("releases.block_id = ?", current_release.block_id). + where("submitted_challenge_answers.cohort_id = ?", current_cohort.id). + no_orphans. + order("standards.position ASC, content_files.position ASC, challenges.position ASC").first + return next_in_block.review_path(cohort_id: current_cohort.id, user_id: loaded_user.id) if next_in_block.present? + + # check in next blocks + next_out_block = SubmittedChallengeAnswer.joins(challenge: [content_file: [standard: [release: :cohort_releases]]]). + where("submitted_challenge_answers.user_id = ?", loaded_user.id). + where("cohort_releases.position > ?", current_cohort_release.position). + where("submitted_challenge_answers.cohort_id = ?", current_cohort.id). + no_orphans. + order("cohort_releases.position ASC"). + order("standards.position ASC"). + order("content_files.position ASC"). + order("challenges.position ASC").first + return next_out_block.review_path(cohort_id: current_cohort.id, user_id: loaded_user.id) if next_out_block.present? + end + end + end +end diff --git a/app/controllers/cohorts/users/performances_controller.rb b/app/controllers/cohorts/users/performances_controller.rb new file mode 100644 index 0000000..e5e34df --- /dev/null +++ b/app/controllers/cohorts/users/performances_controller.rb @@ -0,0 +1,41 @@ +module Cohorts + module Users + class PerformancesController < ApplicationController + def create + performances = [] + + performance_params["standard_ids"].each do |standard_id| + performance = Performance.new( + user: loaded_user, + updator: current_user, + score: performance_params["score"], + standard_id: standard_id, + cohort_id: current_cohort.id, + checkpoint_submission_id: performance_params["checkpoint_submission_id"] + ) + + authorize(performance) + + next unless performance.save + + performances << PerformancePresenter.new(performance) + end + render json: performances + end + + private + + def performance_params + params.require(:performance).permit(:checkpoint_submission_id, :score, standard_ids: []) + end + + def current_cohort + @current_cohort ||= Cohort.find(params[:cohort_id]) + end + + def loaded_user + @loaded_user ||= User.find(params[:user_id]) + end + end + end +end diff --git a/app/controllers/cohorts/users_controller.rb b/app/controllers/cohorts/users_controller.rb new file mode 100644 index 0000000..034a676 --- /dev/null +++ b/app/controllers/cohorts/users_controller.rb @@ -0,0 +1,154 @@ +module Cohorts + class UsersController < ApplicationController + def submissions_dashboard + authorize(loaded_cohort_user, :view_user_challenges?) + + @current_category = "submissions" + students = [{ + id: loaded_user.id, + avatar: loaded_user.profile_image, + name: loaded_user.full_name, + initials: loaded_user.initials, + challenges_path: submissions_dashboard_cohort_user_path(current_cohort, loaded_user.id) + }] + + submission_data = SubmissionsDashboardPresenter.submission_data( + cohort: current_cohort, + cohort_mode: current_cohort.mode, + student_ids: [loaded_user.id] + ) + + render( + locals: { + cohort_id: current_cohort.id, + students: students, + submission_data: submission_data, + progress_thresholds: current_cohort.settings["progress_thresholds"] + } + ) + end + + def curriculum_progress + authorize(current_cohort) + + cohort_releases = ReleaseFinder.for_cohort(current_cohort.id).includes(standards: [{ content_files: :challenges }]).to_a + + hidden_uids = ContentVisibility.where(cohort_id: current_cohort.id, content_type: "Standard").pluck(:content_uid) + all_standards = cohort_releases.flat_map(&:standards).reject {|s| hidden_uids.include?(s.uid) }.sort_by(&:position) + + all_checkpoints = CheckpointSubmission.where( + content_file_block_id: cohort_releases.map(&:block_id), + user_id: current_user.id, + cohort_id: current_cohort.id + ).where.not(state: CheckpointSubmission::STATES[:started]). + order(created_at: :desc).group_by(&:content_file_block_id) + + completion_data = StandardSubmissionsService.new(standard: nil, + cohort: current_cohort, + cohort_releases: cohort_releases, + standard_uids: all_standards.map(&:uid), + student_ids: [current_user.id], + all_checkpoints: all_checkpoints.values.flatten, + instructor_or_admin: current_user.instructor_or_admin?(current_cohort.id)).all_standards + + progress = {} + user_performances = PerformanceFinder.latest_for_standards_in_cohort(standard_uids: all_standards.map(&:uid), + user_ids: [current_user.id], + cohort_id: current_cohort.id). + includes(:checkpoint_submission). + to_a + + if current_cohort.mode == Cohort::MODES[:mastery] + progress = calc_progress(Cohort::MODES[:mastery], cohort_releases, user_performances, nil, current_user.id, nil, all_standards) + progress[:mastery_average] = MasteryAverageService.execute(user_performances&.select { |p| p.score > 0 }&.map(&:score)) + elsif current_cohort.mode == Cohort::MODES[:percentage] + lesson_visits = LessonVisit.visible_for(current_cohort.id). + where(user_id: current_user.id, block_id: cohort_releases.map(&:block_id)). + order(updated_at: :desc) + progress = calc_progress(Cohort::MODES[:percentage], + cohort_releases, nil, + completion_data, + current_user.id, + lesson_visits, + all_standards) + end + + cohort_has_checkpoints, user_has_checkpoints, user_has_scored_submission = checkpoint_presence(completion_data) + render json: { + checkpoint_average: user_has_scored_submission ? progress[:checkpoint_average] : nil, + user_has_checkpoints: user_has_checkpoints, + cohort_uses_checkpoints: cohort_has_checkpoints, + progress: progress.to_json + } + end + + private + + # checkpoint_presence returns three booleans + # the first is the presence of a checkpoint + # the second is the presence of a user's checkpoint + # the third is the presence of a done checkpoint + def checkpoint_presence(completion_data) + cohort_has_checkpoint = false + user_has_checkpoint_submission = false + user_has_scored_submission = false + + completion_data.each_key do |release_id| + completion_data[release_id].each_key do |standard_id| + checkpoint = completion_data[release_id][standard_id].find {|cf| cf[:content_file_type] == ContentFile::TYPES[:checkpoint] } + + if checkpoint + cohort_has_checkpoint = true + user_submission = checkpoint[:checkpoint_submissions][current_user.id] + + user_has_checkpoint_submission = true if user_submission.present? + user_has_scored_submission = true if user_submission && user_submission[:state] == CheckpointSubmission::STATES[:done] + end + end + end + [cohort_has_checkpoint, user_has_checkpoint_submission, user_has_scored_submission] + end + + def calc_progress(cohort_mode, _cohort_releases, performances, completion_data, user_id, lesson_visits, standards) + if cohort_mode == Cohort::MODES[:mastery] + return nil unless current_user.student_of?(current_cohort) && !performances.nil? + + CurriculumProgressService.new(performances: performances, user_id: user_id, standards: standards).execute_mastery + elsif cohort_mode == Cohort::MODES[:percentage] + return nil unless current_user.student_of?(current_cohort) && !completion_data.nil? + + CurriculumProgressService.new( + completion_data: completion_data, + user_id: user_id, + lesson_visits: lesson_visits, + standards: standards + ).execute_completion + end + end + + def set_segment_page_properties + @track_properties = { + productId: current_cohort.uid, + pageType: "Submissions", + cohortId: current_cohort.id, + cohortName: current_cohort.name, + blockId: nil, + blockName: nil, + unitId: nil, + unitName: nil + }.to_json + end + + def loaded_cohort_user + @loaded_cohort_user ||= CohortUser.find_by!(user_id: params[:id], cohort_id: params[:cohort_id]) + end + + def loaded_user + @loaded_user ||= UserPolicy::Scope.new(current_user, User).resolve.find(params[:id]) + end + + def current_cohort + @current_cohort ||= CohortPolicy::Scope.new(current_user, Cohort).resolve.find(params[:cohort_id]) + end + end +end diff --git a/app/controllers/cohorts_controller.rb b/app/controllers/cohorts_controller.rb new file mode 100644 index 0000000..9fce5da --- /dev/null +++ b/app/controllers/cohorts_controller.rb @@ -0,0 +1,463 @@ +class CohortsController < ApplicationController + before_action :handle_last_setup_visit, only: %i[setup users content partnerup] + + def index + authorize(Cohort) + @html_title = "Cohorts" + @page_type = "Cohorts" + + own_cohorts = current_user.cohorts.without_sandboxes.order(name: :asc) + all_other_cohorts = Cohort.all.without_sandboxes.where.not(id: own_cohorts.pluck(:id)).order(name: :asc) + cohort_types = own_cohorts.map(&:product_type).concat(all_other_cohorts.map(&:product_type)).uniq.compact.reject(&:blank?) + cohort_campuses = own_cohorts.map(&:campus_name).concat(all_other_cohorts.map(&:campus_name)).uniq.compact.reject(&:blank?) + cohort_id_counts = Hash[CohortUser.all.pluck(:cohort_id).group_by { |x| x }.map { |k, v| [k, v.count] }] + + render( + locals: { + all_other_cohorts: all_other_cohorts, + own_cohorts: own_cohorts, + cohort_id_counts: cohort_id_counts, + learn_base_url: ENV["LEARN_BASE_URL"], + cohort_types: cohort_types, + cohort_campuses: cohort_campuses, + new_auth_product_url: Rails.application.secrets.auth_url + "/admin/products/new" + } + ) + end + + def update + authorize(current_cohort) + + current_cohort.mode = update_cohort_params[:mode] if update_cohort_params[:mode] + if update_cohort_params.dig("settings", "progress_thresholds") + current_cohort.settings["progress_thresholds"] = update_cohort_params[:settings]["progress_thresholds"] + end + + flash = if current_cohort.save + { type: "success", msg: "successfully updated #{current_cohort.name}." } + else + { type: "error", msg: "could not update #{current_cohort.name}." } + end + + respond_to do |format| + format.json do |_f| + render json: { cohort: current_cohort, flash: flash } + end + end + end + + def users + authorize(current_cohort) + redirect_to content_cohort_path(current_cohort) and return if current_cohort.sandbox + @html_title = "Setup" + @page_type = "Setup" + @current_category = "setup" + release_count = CohortRelease.attached_to_cohort(current_cohort.id).count + + render( + locals: { + cohort: current_cohort, + release_count: release_count, + auth_product_url: Rails.application.secrets.auth_url + "/admin/products/#{current_cohort.uid}" + } + ) + end + + def content + authorize(current_cohort) + @html_title = "Setup" + @page_type = "Setup" + @current_category = "setup" + + cohort_releases_by_sections, visibilities = current_cohort.current_curriculum + + render( + locals: { + cohort: current_cohort, + release_count: cohort_releases_by_sections.values.flatten.count, + sections: cohort_releases_by_sections.map do |k, releases| + CohortSetup::Visibility.new( + section: k, + releases_in_sections: releases, + cohort_id: current_cohort.id, + visibilities: visibilities + ) + end, + auth_product_url: Rails.application.secrets.auth_url + "/admin/products/#{current_cohort.uid}" + } + ) + end + + def show + authorize(current_cohort) + @html_title = current_cohort.name + @page_type = "Curriculum Overview" + @current_category = "curriculum" + @titles_filter = params[:'standard-names']&.split("|") + @body_class = "-with-curriculum-subset-notice" if @titles_filter + + cohort_cohort_releases = CohortRelease.attached_to_cohort(current_cohort.id) + cohort_releases = Release.where(id: cohort_cohort_releases.map(&:release_id)). + includes(standards: [{ content_files: :challenges }]).to_a + + all_standards = cohort_releases.map do |cohort_release| + cohort_release.standards.visible_for(current_cohort.id) + end.flatten.sort_by(&:position) + + visible_content_files = ContentFile.unscoped.where(standard_id: all_standards.map(&:id)) + hidden_content_files = ContentVisibility.where( + cohort: current_cohort, + content_type: "ContentFile", + content_uid: visible_content_files.pluck(:uid) + ) + hidden_content_file_count = hidden_content_files.count + content_file_count = visible_content_files.count + + sections = cohort_cohort_releases. + group_by {|cr| cr.section}. + reject {|section, _crs| section.nil?}. # Legacy data might not have a section + to_a. + sort_by {|section, _crs| section.position}. + map do |section, crs| + release_ids = crs.sort_by(&:position).map(&:release_id) + standards_in_section = all_standards.select { |s| release_ids.include?(s.release_id) } + standards = standards_in_section.reject do |standard| + cfs = visible_content_files.select { |cf| cf.standard_id == standard.id } + cf_count = (cfs.map(&:uid) - hidden_content_files.map(&:content_uid)).count + cf_count == 0 + end + section.as_json.merge( + release_ids: release_ids, + standard_count: standards.count, + standardsForSectionPath: cohort_standards_for_section_path(current_cohort, section.id) + ) + end + + warning_message = no_curriculum_warning( + sections.empty?, + all_standards.empty?, + hidden_content_file_count, + content_file_count + ) + + welcome_to_learn = welcome_to_learn( + sections.empty?, + all_standards.empty?, + hidden_content_file_count, + content_file_count + ) + + last_viewed_presenter = nil + last_viewed_lesson_visit = LessonVisit.visible_for(current_cohort.id). + where(user_id: current_user.id, block_id: cohort_releases.map(&:block_id)). + order(updated_at: :desc).first + unless all_standards.empty? || warning_message != "" || welcome_to_learn + last_viewed_presenter = ContentFilePresenter::ForCurriculumLastViewed.new( + cohort: current_cohort, + standards: all_standards, + last_viewed_lesson_visit: last_viewed_lesson_visit + ) + end + + render( + locals: { + curriculum_progress_path: curriculum_progress_cohort_user_path(current_cohort, current_user), + current_cohort: current_cohort, + content_view: last_viewed_presenter, + sections: sections, + warning_message: warning_message, + warning_count: current_user.instructor_or_admin?(current_cohort.id) ? cohort_releases.flat_map(&:sync_warnings).length : 0, + welcome_to_learn: welcome_to_learn + } + ) + end + + def error + authorize(current_cohort) + + cohort_cohort_releases = CohortRelease.attached_to_cohort(current_cohort.id) + cohort_releases = Release.where(id: cohort_cohort_releases.map(&:release_id)).to_a + + render( + locals: { + warnings: cohort_releases.flat_map(&:sync_warnings).map do |warning| + { warning: warning, anchor: warning.split(":").first } + end + } + ) + end + + def standards_for_section + authorize(current_cohort) + + cohort_cohort_releases = CohortRelease. + attached_to_cohort(current_cohort.id). + where(section_id: params[:section_id]). + includes(release: [standards: [{ content_files: :challenges }]]). + to_a + + cohort_releases = cohort_cohort_releases.map(&:release) + hidden_uids = ContentVisibility.where(cohort_id: current_cohort.id, content_type: "Standard").pluck(:content_uid) + all_standards = cohort_releases.flat_map do |cohort_release| + cohort_release.standards + end.reject {|s| hidden_uids.include?(s.uid) }.sort_by(&:position) + + user_performances = nil + if current_cohort.mode == Cohort::MODES[:mastery] + user_performances = PerformanceFinder.latest_for_standards_in_cohort(standard_uids: all_standards.map(&:uid), + user_ids: [current_user.id], + cohort_id: current_cohort.id).to_a + end + lesson_visits = LessonVisit.visible_for(current_cohort.id). + where(user_id: current_user.id, block_id: cohort_releases.map(&:block_id)). + order(updated_at: :desc) + + all_checkpoints = CheckpointSubmission.includes(submitted_challenge_answers: :challenge).where( + content_file_block_id: cohort_releases.map(&:block_id), + user_id: current_user.id, + cohort_id: current_cohort.id + ).where.not(state: CheckpointSubmission::STATES[:started]). + order(created_at: :desc) + + instructor_or_admin = current_user.instructor_or_admin?(current_cohort.id) + + progress_data = StandardSubmissionsService.new(standard: nil, + cohort: current_cohort, + cohort_releases: cohort_releases, + standard_uids: all_standards.map(&:uid), + student_ids: [current_user.id], + all_checkpoints: all_checkpoints, + instructor_or_admin: instructor_or_admin).all_standards + + cohort_releases = cohort_releases.map do |release| + standards = all_standards.select { |s| s.release_id == release.id } + standards.map do |standard| + cohort_standard_progress_data = progress_data[release.id][standard.id] if progress_data + StandardPresenter::ForStandardCard.new( + standard: standard, + cohort: current_cohort, + user_performances: user_performances, + cohort_standard_progress_data: cohort_standard_progress_data || [], + current_user_id: current_user.id, + instructor_or_admin: instructor_or_admin, + lesson_visits: lesson_visits, + checkpoint_submissions: all_checkpoints + ) + end + end + render json: cohort_releases.to_json + end + + def setup + authorize(current_cohort) + redirect_to content_cohort_path(current_cohort) and return if current_cohort.sandbox + @html_title = "Setup" + @page_type = "Setup" + @current_category = "setup" + + available_blocks = BlockFinder.available_blocks_for(current_cohort.id). + includes(releases: { cohort_releases: :cohort }). + uniq + + render( + locals: { + resync_job: ResyncJobResult.find_latest(current_cohort.id), + successful_resync_job: ResyncJobResult.find_latest_successful(current_cohort.id), + all_available_blocks: available_blocks.map { |block| BlockPresenter::ForBlock.new(block: block) }, + cohort: current_cohort, + cohort_releases: + CohortRelease.attached_to_cohort(current_cohort.id).map do |cohort_release| + CohortReleasePresenter::ForCohortSetup.new(cohort_release: cohort_release) + end, + unattached_block_release_options: + ReleaseFinder.latest_for_all_blocks_not_attached_to_cohort(current_cohort.id), + auth_product_url: Rails.application.secrets.auth_url + "/admin/products/#{current_cohort.uid}" + } + ) + end + + def partnerup + authorize(current_cohort) + redirect_to content_cohort_path(current_cohort) and return if current_cohort.sandbox + if current_cohort.students.count > 500 + flash[:error] = "Partnerup disabled for cohorts over 500." + redirect_to content_cohort_path(current_cohort) and return + end + + @html_title = "Setup" + @page_type = "Setup" + @current_category = "setup" + release_count = CohortRelease.attached_to_cohort(current_cohort.id).count + + render( + locals: { + cohort: current_cohort, + students: current_cohort.cohort_users.student.map { |s| { uid: s.user.uid, name: s.user.full_name, profile_image: s.user.profile_image }}, + release_count: release_count, + pairings: Pairing.where(cohort_id: current_cohort.id).order(created_at: :desc), + auth_product_url: "#{Rails.application.secrets.auth_url}/admin/products/#{current_cohort.uid}" + } + ) + end + + def unit_progress + authorize(current_cohort, :submissions_dashboard?) + redirect_to cohort_path(current_cohort) and return if current_cohort.sandbox + @html_title = "Unit Progress" + @page_type = "Unit Progress" + @current_category = "submissions" + + students = nil + submission_data = nil + if current_cohort.students.length < 500 + student_ids = [] + students = current_cohort.students.order(:first_name).map do |student| + student_ids.push(student.id) + { + id: student.id, + avatar: student.profile_image, + name: student.full_name, + initials: student.initials, + cohort_reg_date: student.cohort_users.where(cohort_id: current_cohort.id).first&.created_at, + challenges_path: submissions_dashboard_cohort_user_path(current_cohort, student.id) + } + end + + submission_data = SubmissionsDashboardPresenter.submission_data( + cohort: current_cohort, + cohort_mode: current_cohort.mode, + student_ids: student_ids + ) + end + + render( + locals: { + cohort_mode: current_cohort.mode, + cohort_id: current_cohort.id, + students: students, + submission_data: submission_data, + progress_thresholds: current_cohort.settings["progress_thresholds"] + } + ) + end + + def activity_dashboard + authorize(current_cohort) + redirect_to cohort_path(current_cohort) and return if current_cohort.sandbox + @html_title = "Activity Dashboard" + @page_type = "Activity" + @current_category = "activity" + + respond_to do |format| + format.html do + render locals: { + url: activity_dashboard_cohort_path(current_cohort, format: :json), + student_count: current_cohort.students.count + } + end + format.json do + render json: ActivityAggregatorService.new(current_cohort, params[:offset], current_user.timezone).execute + end + end + end + + def course_stats + authorize(current_cohort, :progress?) + redirect_to cohort_path(current_cohort) and return if current_cohort.sandbox + @html_title = "Course Stats" + @page_type = "Course Stats" + @current_category = "progress" + + students = nil + if current_cohort.id == 1974 || current_cohort.students.length < 100 + students = CohortStudentProgressService.new(current_cohort).students + end + + render( + locals: { + students: students, + cohort_mode: current_cohort.mode, + progress_thresholds: current_cohort.settings["progress_thresholds"], + cohort_id: current_cohort.id + } + ) + end + + def course_stats_csv + authorize(current_cohort, :progress?) + if current_cohort.id == 1974 + ProgressCsvJob.perform_later(current_cohort.id, current_user.id, false) + else + ProgressCsvJob.perform_later(current_cohort.id, current_user.id, current_cohort.students.length > 100) + end + render json: { ack: "ok" } + end + + def import_users_work + authorize(current_cohort) + ImportStudentWorkJob.perform_later(current_cohort.id, current_user.email) + render json: { ack: "ok" } + end + + def import_users_work_status + authorize(current_cohort) + render json: { student_import_state: current_cohort.student_import_state, + student_import_completed_at: current_cohort.student_import_completed_at } + end + + def feed + authorize(current_cohort) + + render( + locals: { + activities: Activity. + where(cohort: current_cohort). + order(created_at: :desc). + first(50). + map { |activity| ActivityFeedItemComponentProps.execute(activity) }, + current_cohort: current_cohort + } + ) + end + + private + + def current_cohort + @current_cohort ||= params[:cohort_id].present? ? Cohort.find(params[:cohort_id]) : Cohort.find(params[:id]) + end + + def update_cohort_params + params.require(:cohort).permit(:mode, settings: [progress_thresholds: []]) + end + + def handle_last_setup_visit + cohort_user = CohortUser.where(cohort_id: current_cohort.id, user_id: current_user.id).first + return unless cohort_user + + unless cohort_user.last_setup_visit == request.original_fullpath + cohort_user.update(last_setup_visit: request.original_fullpath) + end + end + + def no_curriculum_warning(no_sections, no_standards, hidden_content_file_count, content_file_count) + if current_user.instructor_or_admin?(current_cohort.id) + if no_sections + "It looks like you don't have any curriculum yet. To fix this you can add your Curriculum #{view_context.link_to 'here', setup_cohort_path(current_cohort)}." + elsif no_standards || hidden_content_file_count == content_file_count + "It looks the curriculum is not visible yet. To fix this you can #{view_context.link_to 'change visibility here', content_cohort_path(current_cohort)}." + else + "" + end + else + "" + end + end + + def welcome_to_learn(no_sections, no_standards, hidden_content_file_count, content_file_count) + no_content = no_sections || no_standards || hidden_content_file_count == content_file_count + + return true if !current_user.instructor_or_admin?(current_cohort.id) && no_content + + false + end +end diff --git a/app/controllers/concerns/api/content_visibility_crud.rb b/app/controllers/concerns/api/content_visibility_crud.rb new file mode 100644 index 0000000..ec247f8 --- /dev/null +++ b/app/controllers/concerns/api/content_visibility_crud.rb @@ -0,0 +1,58 @@ +module Api::ContentVisibilityCrud + extend ActiveSupport::Concern + + included do + def handle_param_logic(content_type, the_params) + result = :error + + return :not_found if content_type.constantize.where(uid: params[:id]).empty? + return :not_found unless exists_in_requested_cohort?(content_type) + + if the_params.key?(:visible) + result = create_content_visibility(content_type, "hidden") if the_params[:visible].to_s == "false" + result = destroy_content_visibility(content_type, "hidden") if the_params[:visible].to_s == "true" + end + + if the_params.key?(:optional) + result = create_content_visibility(content_type, "optional") if the_params[:optional].to_s == "false" + result = destroy_content_visibility(content_type, "optional") if the_params[:optional].to_s == "true" + end + + result + end + + def exists_in_requested_cohort?(content_type) + if content_type == "Standard" + StandardFinder.all_for_cohort(cohort_id: params[:cohort_id]).map(&:uid) + elsif content_type == "ContentFile" + ContentFileFinder.all_from_cohort_block(cohort_id: params[:cohort_id], + block_id: params[:block_id]).map(&:uid) + end.include?(params[:id]) + end + + def create_content_visibility(content_type, visibility_type) + cv = ContentVisibility.new(cohort_id: params[:cohort_id], + content_uid: params[:id], + content_type: content_type, + visibility_type: visibility_type) + if cv.save + :ok + else + :error + end + rescue ActiveRecord::RecordNotUnique + :ok + end + + def destroy_content_visibility(content_type, visibility_type) + cv = ContentVisibility.find_by(cohort_id: params[:cohort_id], + content_uid: params[:id], + content_type: content_type, + visibility_type: visibility_type) + + cv&.destroy + + :ok + end + end +end diff --git a/app/controllers/concerns/api/exception_handler.rb b/app/controllers/concerns/api/exception_handler.rb new file mode 100644 index 0000000..0cfa71b --- /dev/null +++ b/app/controllers/concerns/api/exception_handler.rb @@ -0,0 +1,75 @@ +module Api::ExceptionHandler + extend ActiveSupport::Concern + + CODES = { + # routing layer + not_allowed: { status: 405, title: "Method not allowed" }, + invalid_version: { status: 410, title: "The requested API version no longer exists" }, + + # controller layer + unauthorized: { status: 401, title: "You do not have access to the requested resource" }, + unauthenticated: { status: 403, title: "You are not authenticated for this request" }, + not_found: { status: 404, title: "The requested resource could not be found" }, + malformed_params: { status: 422, title: "The params provided are malformed" }, + missing_param: { status: 422, title: "A required param was not provided" }, + invalid_resource: { status: 422, title: "The current resource was invalid", messages: [], attrs: {} }, + server_error: { status: 500, title: "An unknown error has occurred" } + } + + included do + rescue_from ActiveRecord::RecordNotFound, with: :not_found_response + rescue_from Aws::S3::Errors::NoSuchKey, with: :not_found_response + + rescue_from BlockParser::ConvertMdToJson::MdParseError, with: :unprocessable_entity_response + rescue_from BlockParser::BuildHtmlFromMdJson::InvalidMdError, with: :unprocessable_entity_response + rescue_from ActiveRecord::RecordInvalid, with: :unprocessable_entity_response + + rescue_from Pundit::NotAuthorizedError do |_e| + json_response( + { + "errors": { + "status": "401", + "title": "You are not authenticated for this request", + "code": "unauthorized" + } + }, :unauthorized + ) + end + + def not_found_response + json_response({ message: "The requested resource could not be found" }, :not_found) + end + + def unprocessable_entity_response + json_response({ message: "The current resource was invalid" }, :unprocessable_entity) + end + + def render_method_not_allowed_response + json_response( + { + "errors": { + "status": "405", + "title": "Method not allowed", + "code": "not_allowed" + } + }, :method_not_allowed + ) + end + end + + class_methods do + def rack_response(code, options = {}) + status, json = error_options(code, options) + [status, { "Content-Type" => "application/json" }, [json.to_json]] + end + + def error_options(code, options = {}) + hash = (CODES[code] || CODES[:server_error]).merge(options) + hash[:code] ||= code + hash[:status] ||= 500 + status = hash[:status] + hash[:status] = hash[:status].to_s + [status, { errors: hash }] + end + end +end diff --git a/app/controllers/concerns/api/response.rb b/app/controllers/concerns/api/response.rb new file mode 100644 index 0000000..acac2d2 --- /dev/null +++ b/app/controllers/concerns/api/response.rb @@ -0,0 +1,5 @@ +module Api::Response + def json_response(object, status = :ok) + render json: object, status: status + end +end diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb new file mode 100644 index 0000000..8bcebc6 --- /dev/null +++ b/app/controllers/home_controller.rb @@ -0,0 +1,28 @@ +class HomeController < ApplicationController + skip_before_action :require_signed_in_user, only: :hello + + def hello + skip_authorization + render plain: "Hello!" + end + + def index + authorize(current_user, :show?) + last_viewed_cohort_id = current_user.last_viewed_cohort_id + + path = if session[:requested_path].present? + requested_path = session[:requested_path] + session[:requested_path] = nil + requested_path + elsif last_viewed_cohort_id && current_user.student_instructor_or_admin_of?(last_viewed_cohort_id) + current_user.update(last_viewed_cohort_id: nil) + cohort_path(last_viewed_cohort_id) + elsif current_user.cohorts.any? + cohort_path(CohortUser.where(user: current_user).order(:created_at).last.cohort_id) + elsif current_user.admin? + cohorts_path + end + + redirect_to path if path.present? + end +end diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb new file mode 100644 index 0000000..37896e7 --- /dev/null +++ b/app/controllers/notifications_controller.rb @@ -0,0 +1,32 @@ +class NotificationsController < ApplicationController + def index + authorize(Notification) + + render_notifications_json + end + + def show + authorize(current_notification) + + current_notification.update(read_at: DateTime.current) unless current_notification.read_at? + + redirect_to(current_notification.url) + end + + def mark_all_read + authorize(Notification) + policy_scope(Notification).unread.update_all(read_at: DateTime.current) + + render_notifications_json + end + + private + + def render_notifications_json + render json: NotificationsComponentProps.execute(current_user.id) + end + + def current_notification + @current_notification ||= policy_scope(Notification).find(params[:id]) + end +end diff --git a/app/controllers/permalinks_controller.rb b/app/controllers/permalinks_controller.rb new file mode 100644 index 0000000..6001e7e --- /dev/null +++ b/app/controllers/permalinks_controller.rb @@ -0,0 +1,85 @@ +class PermalinksController < ApplicationController + def permalink + authorize(current_user, :show?) + + block = Block.find_by(repo_name: params[:repo_name]) + error_404 and return if block.nil? + + if referer_cohort && referer_cohort_contains_content? + redirect_to content_file_path(referer_cohort, block.id, params[:path]) and return + end + + if all_content_file_paths.count == 1 && !referer_cohort + redirect_to all_content_file_paths.first[:path] and return + end + return error_404 if all_content_file_paths.count == 0 + + cohort_count = all_content_file_paths.length + render(locals: { + fullpath: "#{request.protocol}#{request.host_with_port}#{request.fullpath}", + header: cohort_count == 1 ? "Switch cohorts" : "Choose a Cohort", + paragraph: if cohort_count == 1 + " a different cohort. Click the link below to go where it is located." + + else + " multiple cohorts. Select the cohort where you'd like to open it." + end, + all_content_file_paths: all_content_file_paths + }) + end + + private + + def referer_cohort_contains_content? + @referer_cohort_contains_content ||= !content_file_paths_for_cohorts([referer_cohort.id]).empty? + end + + def referer_cohort + @referer_cohort ||= if request.referer && referer_is_from_learn + path = request.referer[root_url.length..-1] + path = path[1..path.length - 1] if path[0] == "/" + path.start_with?("cohorts/") ? Cohort.find(path.split("/")[1].to_i) : nil + end + end + + def referer_is_from_learn + return false if request.referer.nil? + + request_url = request.referer[0..root_url.length - 1] + request_url == root_url + end + + def block + @block ||= Block.find_by(repo_name: params[:repo_name]) + end + + def cohorts_using_block + @cohorts_using_block ||= Cohort.joins(cohort_releases: :release).where("releases.block_id = ?", block.id) + end + + def users_cohorts_using_block + @users_cohorts_that_have_block ||= cohorts_using_block.where(id: current_user.cohort_users.map(&:cohort_id)) + end + + def cohorts + @cohorts ||= current_user.admin? ? cohorts_using_block : users_cohorts_using_block + end + + def all_content_file_paths + return @all_content_files if @all_content_files + + all_content_files = content_file_paths_for_cohorts(cohorts.map(&:id)) + + @all_content_files = all_content_files.map do |cf| + { name: cohorts.find { |c| c.id == cf.cohort_id }.name, path: content_file_path(cf.cohort_id, block.id, cf.path) } + end.uniq.sort { |a, b| a[:name] <=> b[:name] } + end + + def content_file_paths_for_cohorts(cohort_ids) + ContentFile.unscoped.select("cohort_releases.cohort_id AS cohort_id, path"). + joins(standard: { release: :cohort_releases }). + where("releases.block_id = ?", block.id). + where("cohort_id IN (?)", cohort_ids). + where("path = ?", params[:path]) + end +end diff --git a/app/controllers/webhooks/assessments_service/submitted_challenge_answers_controller.rb b/app/controllers/webhooks/assessments_service/submitted_challenge_answers_controller.rb new file mode 100644 index 0000000..8eedbb0 --- /dev/null +++ b/app/controllers/webhooks/assessments_service/submitted_challenge_answers_controller.rb @@ -0,0 +1,120 @@ +module Webhooks + module AssessmentsService + class SubmittedChallengeAnswersController < ActionController::Base + class InvalidChallengeTypeEvaluation < StandardError + end + + def update + if params[:token] == Rails.application.secrets.assessments_callback_token + submitted_challenge_answer = SubmittedChallengeAnswer.find(params[:id]) + + if params[:status_only] + submitted_challenge_answer.update(status: params[:status]) + head :ok, content_type: "application/json" and return + end + + if submitted_challenge_answer.challenge.code_snippet? || + submitted_challenge_answer.challenge.testable_project? || + submitted_challenge_answer.challenge.custom_snippet? + unless submitted_challenge_answer.status == "canceled" + results = params[:results] + status = params[:status] + correct = status == SubmittedChallengeAnswer::STATUSES[:correct] + points = correct ? submitted_challenge_answer.challenge.points : 0 + submitted_challenge_answer.update_attributes( + status: status, + test_results: results, + points: points, + assessment_ran_at: params[:assessment_ran_at] + ) + cohort = Cohort.find_by(id: params[:cohort_id]) + + checkpoint_submission = submitted_challenge_answer.checkpoint_submission + if checkpoint_submission.present? + CheckpointSubmissionService.new(checkpoint_submission, + submitted_challenge_answer.challenge.content_file, + cohort, + submitted_challenge_answer.user).attempt_autoscore + else + # Alert when challenge takes a while + slack_performance_delays(submitted_challenge_answer) + + Activity.create( + cohort_id: params[:cohort_id], + subject: submitted_challenge_answer, + name: Activity::NAMES[:submitted_challenge_answer_evaluated] + ) + end + end + else + Honeybadger.notify( + InvalidChallengeTypeEvaluation.new("An invalid challenge type was submitted to the assessments service for evaluation.") + ) + end + + head :ok, content_type: "application/json" + else + head :unauthorized, content_type: "application/json" + end + rescue ActiveRecord::RecordNotFound + head :not_found, content_type: "application/json" + end + + private + + def slack_performance_delays(submitted_challenge_answer) + length_of_scoring = submitted_challenge_answer.updated_at.to_i - submitted_challenge_answer.created_at.to_i + content_file_url = content_file_url(submitted_challenge_answer.cohort_id, + submitted_challenge_answer.block_id, + submitted_challenge_answer.challenge.content_file.path) + + if submitted_challenge_answer.challenge.code_snippet? + if length_of_scoring > 10 && submitted_challenge_answer.challenge.language != "java" + SlackChallengePerformanceJob.perform_later(submitted_challenge_answer.id, content_file_url, length_of_scoring) + elsif length_of_scoring > 20 && submitted_challenge_answer.challenge.language == "java" + SlackChallengePerformanceJob.perform_later(submitted_challenge_answer.id, content_file_url, length_of_scoring) + end + + elsif submitted_challenge_answer.challenge.testable_project? + if length_of_scoring > 80 + SlackChallengePerformanceJob.perform_later(submitted_challenge_answer.id, content_file_url, length_of_scoring) + end + + elsif submitted_challenge_answer.challenge.custom_snippet? + if length_of_scoring > 60 + SlackChallengePerformanceJob.perform_later(submitted_challenge_answer.id, content_file_url, length_of_scoring) + end + end + end + + def segment_track_challenge_submitted(sca, cohort) + return if Rails.env.test? + + standard = sca.challenge.content_file.standard + block = standard.release.block + Analytics.track( + user_id: sca.user.uid, + event: "Challenge Submitted", + properties: { + pageType: sca.challenge.content_file.content_file_type.titleize, + path: Rails.application.routes.url_helpers.content_file_path(cohort, block, sca.challenge.content_file.path), + title: sca.challenge.content_file.title, + productId: cohort.uid, + cohortId: cohort.id, + cohortName: cohort.name, + blockId: block.id, + blockName: block.title, + unitId: standard.id, + unitUId: standard.uid, + unitName: standard.title, + challengeID: sca.challenge.id, + challengeUID: sca.challenge.uid, + challengeName: sca.challenge.title, + challengeType: sca.challenge.challenge_type, + challengeStatus: sca.status + } + ) + end + end + end +end diff --git a/app/controllers/webhooks/auth/cohorts_controller.rb b/app/controllers/webhooks/auth/cohorts_controller.rb new file mode 100644 index 0000000..c51cc92 --- /dev/null +++ b/app/controllers/webhooks/auth/cohorts_controller.rb @@ -0,0 +1,34 @@ +module Webhooks + module Auth + class CohortsController < ActionController::Base + def update + cohort = AuthResolverService.resolve(request.env[:resolved_resource]) + + if cohort.nil? + error_message = "Provided cohort is not compatible with Learn V2" + results = { cohort: cohort_params, errors: [error_message] } + + Honeybadger.notify( + error_message, + context: { auth_resource: request.env[:resolved_resource] } + ) + + render json: { errors: results }, status: 400 + elsif cohort.errors.empty? + render json: {}, status: 200 + else + results = { cohort: cohort_params, errors: cohort.errors.full_messages } + + Honeybadger.notify("Invalid cohort payload", context: results) + render json: { errors: results }, status: 400 + end + end + + private + + def cohort_params + params.require(:data).permit! + end + end + end +end diff --git a/app/controllers/webhooks/auth/users_controller.rb b/app/controllers/webhooks/auth/users_controller.rb new file mode 100644 index 0000000..866f006 --- /dev/null +++ b/app/controllers/webhooks/auth/users_controller.rb @@ -0,0 +1,24 @@ +module Webhooks + module Auth + class UsersController < ActionController::Base + def update + user = AuthResolverService.resolve(request.env[:resolved_resource]) + + if user.errors.empty? + render json: {}, status: 200 + else + results = { user: user_params, errors: user.errors.full_messages } + + Honeybadger.notify("Invalid user payload", context: results) + render json: { errors: results }, status: 400 + end + end + + private + + def user_params + params.require(:data).permit! + end + end + end +end diff --git a/app/exporters/performance_exporter.rb b/app/exporters/performance_exporter.rb new file mode 100644 index 0000000..548dc80 --- /dev/null +++ b/app/exporters/performance_exporter.rb @@ -0,0 +1,55 @@ +require "csv" + +class PerformanceExporter + def initialize(cohort) + @cohort = cohort + end + + def to_csv + headers = [ + "Cohort Title", + "Cohort Label", + "Block Title", + "Standard" + ] + + users = User.where(id: [@cohort.student_ids]).sort_by(&:full_name) + headers += users.map(&:full_name) + + standards = [] + performances = {} + + ReleaseFinder.for_cohort(@cohort.id).includes(%i[block standards]).each do |release| + standards.concat(release.standards) + + release_performances = PerformanceFinder.latest_for_cohort_release(cohort_id: @cohort.id, release: release) + + release.standards.each do |standard| + release_performances.where("standards.uid = ?", standard.uid).each do |performance| + performances[standard.id] ||= {} + performances[standard.id][performance.user_id] = performance.score + end + end + end + + CSV.generate do |csv| + csv << headers + standards.each do |standard| + block = standard.release.block + + row = [ + @cohort.name, + @cohort.label, + block.title, + standard.description + ] + + row += users.map do |user| + performances.fetch(standard.id) { {} }.fetch(user.id) { 0 } + end + + csv << row + end + end + end +end diff --git a/app/exporters/progress_exporter.rb b/app/exporters/progress_exporter.rb new file mode 100644 index 0000000..54c92e4 --- /dev/null +++ b/app/exporters/progress_exporter.rb @@ -0,0 +1,107 @@ +require "csv" + +# ProgressExporter is coupled to the data format form StudentProgressPresenter +class ProgressExporter + def initialize(students_data, cohort_mode, cohort_id) + @students_data = students_data + @cohort_mode = cohort_mode + @cohort_id = cohort_id + end + + def topics + @topics ||= @students_data.map(&:progress_percentages).map { |pp| pp[:topic_averages] }.map(&:keys).flatten.uniq + end + + def topic_headers + topics.map { |t| ["topic:#{t}_pts_earned", "topic:#{t}_pts_avail", "topic:#{t}_percent"]}.flatten + end + + def student_topics(student) + student_topics = topics.map do |t| + topic_avg = student.progress_percentages[:topic_averages][t] + if topic_avg + [topic_avg[:earned], topic_avg[:possible], topic_avg[:average]] + else + [nil, nil, nil] + end + end.flatten + student_totals = student.progress_percentages[:totals] + [student_totals[:total_earned], student_totals[:total_possible], student_totals[:percent]] + student_topics + end + + def headers + if @cohort_mode == Cohort::MODES[:percentage] + [ + "student", + "email", + "link to student submission page in Learn", + "link to student contact in sfdc", + "preferred campus", + "timestamp of last activity", + "sign up date", + "checkpoint avg", + "% complete", + "course_points_earned", + "course_points_avail", + "course_points_percent" + ] + topic_headers + elsif @cohort_mode == Cohort::MODES[:mastery] + [ + "student", + "email", + "link to student submission page in Learn", + "link to student contact in sfdc", + "preferred campus", + "timestamp of last activity", + "sign up date", + "% 3s", + "% 2s", + "% 1s", + "% complete", + "avg" + ] + end + end + + def to_csv + sfdc_url = if Rails.env != "production" + "https://test.salesforce.com/" + else + "https://login.salesforce.com/" + end + CSV.generate do |csv| + csv << headers + @students_data.each do |s| + row = if @cohort_mode == Cohort::MODES[:percentage] + [ + s.full_name, + s.email, + "https://learn-2.galvanize.com#{s.performances_url}", + "#{sfdc_url}#{s.uid}", + s.preferred_campus.to_s, + s.latest_activity, + s.registration_date, + "#{s.progress_percentages[:checkpoint_average]} %", + "#{s.progress_percentages[:percent_completed]} %" + ] + student_topics(s) + elsif @cohort_mode == Cohort::MODES[:mastery] + [ + s.full_name, + s.email, + "https://learn-2.galvanize.com#{s.performances_url}", + "#{sfdc_url}#{s.uid}", + s.preferred_campus.to_s, + s.latest_activity, + s.registration_date, + "#{s.score_percentages[:three]} %", + "#{s.score_percentages[:two]} %", + "#{s.score_percentages[:one]} %", + "#{s.progress_percentages[:three]} %", + s.average + ] + end + csv << row + end + end + end +end diff --git a/app/finders/block_finder.rb b/app/finders/block_finder.rb new file mode 100644 index 0000000..31ead2a --- /dev/null +++ b/app/finders/block_finder.rb @@ -0,0 +1,7 @@ +class BlockFinder + def self.available_blocks_for(cohort_id) + attached_release_ids = CohortRelease.where(cohort_id: cohort_id).pluck(:release_id) + block_ids = Release.where.not(id: attached_release_ids).pluck(:block_id).uniq + Block.where(id: block_ids).order(:title) + end +end diff --git a/app/finders/checkpoint_submission_finder.rb b/app/finders/checkpoint_submission_finder.rb new file mode 100644 index 0000000..e4ab94b --- /dev/null +++ b/app/finders/checkpoint_submission_finder.rb @@ -0,0 +1,74 @@ +class CheckpointSubmissionFinder + # rubocop:disable Metrics/LineLength + def self.latest_two_by_state_by_standards(cohort_id:, student_ids:, standard_uids:, block_ids:) + firsts = CheckpointSubmission.includes(submitted_challenge_answers: :challenge). + select("DISTINCT ON (checkpoint_submissions.user_id, checkpoint_submissions.state, standards.uid) checkpoint_submissions.*, standards.uid"). + joins(submitted_challenge_answers: { challenge: { content_file: :standard } }). + where("checkpoint_submissions.cohort_id = ? AND content_file_block_id IN (?) AND standards.uid IN (?) AND checkpoint_submissions.user_id IN (?)", + cohort_id, + block_ids, + standard_uids, + student_ids). + where.not(state: "started"). + order("checkpoint_submissions.user_id, checkpoint_submissions.state, standards.uid, created_at DESC") + seconds = CheckpointSubmission.includes(submitted_challenge_answers: :challenge). + select("DISTINCT ON (checkpoint_submissions.user_id, checkpoint_submissions.state, standards.uid) checkpoint_submissions.*, standards.uid"). + joins(submitted_challenge_answers: { challenge: { content_file: :standard } }). + where("checkpoint_submissions.cohort_id = ? AND content_file_block_id IN (?) AND standards.uid IN (?) AND checkpoint_submissions.user_id IN (?) AND checkpoint_submissions.id NOT IN (?)", + cohort_id, + block_ids, + standard_uids, + student_ids, + firsts.map(&:id)). + where.not(state: "started"). + order("checkpoint_submissions.user_id, checkpoint_submissions.state, standards.uid, created_at DESC") + firsts + seconds + end + # rubocop:enable Metrics/LineLength + + def self.lastest_by_state_for_students_in_cohort(cohort_id:, block_id:, content_file_uid:, student_ids:) + CheckpointSubmission. + select("DISTINCT ON (user_id, state) checkpoint_submissions.*"). + where("cohort_id = ? AND content_file_block_id = ? AND content_file_uid = ? AND user_id IN (?)", + cohort_id, + block_id, + content_file_uid, + student_ids). + order("user_id, state, created_at DESC") + end + + def self.latest_for_checkpoint_content_file_for_user_in_cohort(cohort_id:, content_file:, user_id:, with_started: false) + submissions = CheckpointSubmission.where( + content_file_uid: content_file.uid, + content_file_block_id: content_file.standard.release.block_id, + user_id: user_id, + cohort_id: cohort_id + ) + + unless with_started + submissions = submissions.where.not(state: CheckpointSubmission::STATES[:started]) + end + + submissions.order("created_at DESC").first + end + + def self.all_for_user_id_content_file_in_cohort(user_id, content_file, cohort_id) + CheckpointSubmission. + where(user_id: user_id, + cohort_id: cohort_id, + content_file_uid: content_file.uid, + content_file_block_id: content_file.standard.release.block_id). + where("state != 'retry'"). + order(created_at: :desc) + end + + # all_for_user_standards yields the checkpoints a user has submitted for a set of standards + # it includes the uid of the standard for that checkpoint submission + def self.all_for_user_standards(user_id, standard_uids) + CheckpointSubmission.joins(submitted_challenge_answers: [challenge: [content_file: :standard]]). + select("DISTINCT ON (checkpoint_submissions.id) checkpoint_submissions.*, standards.uid as standard_uid"). + where("checkpoint_submissions.user_id = ? AND standards.uid IN (?)", user_id, standard_uids). + group("checkpoint_submissions.id, standards.uid"). + order("checkpoint_submissions.id") + end +end diff --git a/app/finders/cohort_user_finder.rb b/app/finders/cohort_user_finder.rb new file mode 100644 index 0000000..2c5f806 --- /dev/null +++ b/app/finders/cohort_user_finder.rb @@ -0,0 +1,9 @@ +class CohortUserFinder + def self.instructors_for_cohorts_using_different_version_of_release_block(release) + CohortUser. + instructor. + joins(cohort: [cohort_releases: :release]). + where("releases.block_id = ? AND cohort_releases.release_id != ?", release.block_id, release.id). + order(:id) + end +end diff --git a/app/finders/content_file_finder.rb b/app/finders/content_file_finder.rb new file mode 100644 index 0000000..96a2eae --- /dev/null +++ b/app/finders/content_file_finder.rb @@ -0,0 +1,20 @@ +class ContentFileFinder + def self.from_cohort_block_content_file_path(cohort_id:, block_id:, content_file_path:) + ContentFile.unscoped. + joins(standard: :release). + joins("INNER JOIN cohort_releases ON releases.id = cohort_releases.release_id"). + where("releases.block_id = ? AND cohort_releases.cohort_id = ? AND path = ?", block_id, cohort_id, content_file_path). + first + end + + def self.all_from_cohort_block(cohort_id:, block_id:) + ContentFile.unscoped. + joins(standard: :release). + joins("INNER JOIN cohort_releases ON releases.id = cohort_releases.release_id"). + where("releases.block_id = ? AND cohort_releases.cohort_id = ?", block_id, cohort_id) + end + + def self.first_for_standard(standard_id) + ContentFile.where(standard_id: standard_id).order(position: :asc).first + end +end diff --git a/app/finders/performance_finder.rb b/app/finders/performance_finder.rb new file mode 100644 index 0000000..b18c98e --- /dev/null +++ b/app/finders/performance_finder.rb @@ -0,0 +1,71 @@ +class PerformanceFinder + def self.latest_for_cohort_release(cohort_id:, release:) + Performance. + joins(standard: :release). + where("releases.block_id = ? AND performances.cohort_id = ?", release.block_id, cohort_id). + joins("INNER JOIN cohort_users ON cohort_users.user_id = performances.user_id"). + where("cohort_users.cohort_id = ?", cohort_id). + merge(CohortUser.student). + where("standards.uid in (SELECT uid FROM standards WHERE standards.release_id=?)", release.id). + select("DISTINCT ON (performances.user_id, standards.uid) performances.*"). + order("performances.user_id, standards.uid, performances.created_at DESC") + end + + def self.latest_for_standards_in_cohort(standard_uids:, user_ids:, cohort_id:) + Performance. + joins(:standard). + where("cohort_id = ?", cohort_id). + where("standards.uid in (?)", standard_uids). + where("performances.user_id in (?)", user_ids). + where("performances.cohort_id = ?", cohort_id). + select("DISTINCT ON (performances.user_id, standards.uid, performances.block_id) performances.*"). + order("performances.user_id, standards.uid, performances.block_id, performances.created_at DESC") + end + + def self.latest_for_cohort_student_release(cohort_id:, release:, user_id:) + latest_for_cohort_release(cohort_id: cohort_id, release: release).where("cohort_users.user_id = ?", user_id) + end + + def self.latest_for_cohort_user(cohort_id:, user_id:) + Performance. + where("performances.cohort_id = ? AND performances.user_id = ?", cohort_id, user_id). + select("DISTINCT ON (performances.user_id, performances.standard_uid) performances.*"). + order("performances.user_id, performances.standard_uid, performances.created_at DESC") + end + + def self.latest_standard_scores_for_cohort(user_ids: [], content_file_uids: nil, cohort_id:) + return {} if user_ids.empty? + + performances = Performance.joins( + "LEFT OUTER JOIN checkpoint_submissions ON checkpoint_submissions.id = performances.checkpoint_submission_id" + ).select( + "performances.user_id, performances.score, performances.standard_uid, performances.block_id, " \ + "performances.checkpoint_submission_id, checkpoint_submissions.state, checkpoint_submissions.created_at AS checkpoint_created_at, " \ + "checkpoint_submissions.total_points AS checkpoint_total_points, checkpoint_submissions.correct_points AS checkpoint_correct_points" + ).where( + "performances.cohort_id = ? AND performances.user_id IN (?)", cohort_id, user_ids + ).order("performances.created_at DESC") + + if content_file_uids + performances = performances.where("checkpoint_submissions.content_file_uid in (?)", content_file_uids) + end + + grouped_performances = performances.to_a.group_by(&:user_id) + result = Hash[user_ids.map { |key, _value| [key, {}] }] + grouped_performances.each do |key, value| + result[key] = value.each_with_object({}) do |perf, hash| + hash[perf.block_id] ||= {} + hash[perf.block_id][perf.standard_uid] ||= { + score: perf.score, + checkpoint_submission_id: perf.checkpoint_submission_id, + checkpoint_created_at: perf.checkpoint_created_at, + standard_uid: perf.standard_uid, + checkpoint_state: perf.state, + total_points: perf.checkpoint_total_points, + correct_points: perf.checkpoint_correct_points + } + end || {} + end + result + end +end diff --git a/app/finders/release_finder.rb b/app/finders/release_finder.rb new file mode 100644 index 0000000..4dad71f --- /dev/null +++ b/app/finders/release_finder.rb @@ -0,0 +1,24 @@ +class ReleaseFinder + def self.latest_for_all_blocks_not_attached_to_cohort(cohort_id) + Release. + where( + "releases.block_id NOT IN (SELECT releases.block_id FROM cohort_releases INNER " \ + " JOIN releases ON cohort_releases.release_id = releases.id WHERE cohort_releases.cohort_id = ?)", + cohort_id + ). + select("DISTINCT ON (releases.block_id) releases.*"). + order("releases.block_id, releases.created_at DESC") + end + + def self.for_cohort(cohort_id) + Release.joins(:cohort_releases).where("cohort_releases.cohort_id = ?", cohort_id).order("cohort_releases.position ASC") + end + + def self.for_block(block_id) + Release.where("block_id = ? AND branch_name = 'master'", block_id).order("releases.created_at DESC") + end + + def self.available_update_count_for(release) + Release.where("id > ? AND block_id = ? AND branch_name = 'master'", release.id, release.block_id).count + end +end diff --git a/app/finders/standard_finder.rb b/app/finders/standard_finder.rb new file mode 100644 index 0000000..ddd5d44 --- /dev/null +++ b/app/finders/standard_finder.rb @@ -0,0 +1,10 @@ +class StandardFinder + def self.all_for_cohort(cohort_id:) + Standard.joins(release: :cohort_releases).where("cohort_releases.cohort_id = ?", cohort_id) + end + + def self.for_cohort_release(cohort_id:, release_id:) + Standard.joins(release: :cohort_releases).where(release_id: release_id). + where("cohort_releases.cohort_id = ?", cohort_id).in_default_order + end +end diff --git a/app/finders/submitted_challenge_answer_finder.rb b/app/finders/submitted_challenge_answer_finder.rb new file mode 100644 index 0000000..05f7403 --- /dev/null +++ b/app/finders/submitted_challenge_answer_finder.rb @@ -0,0 +1,28 @@ +class SubmittedChallengeAnswerFinder + def self.latest_for_user_id_content_file_for_cohort(user_id, content_file, cohort_id) + challenge_uids = Challenge.where(content_file_id: content_file.id).pluck(:uid) + + SubmittedChallengeAnswer. + where(user_id: user_id, block_id: content_file.standard.release.block_id, + challenge_uid: challenge_uids, cohort_id: cohort_id). + latest_for_user_id_challenge_uid + end + + def self.all_for_user_id_challenge_in_cohort(user_id, challenge, cohort_id) + content_file = ContentFile.unscoped.find(challenge.content_file_id) + SubmittedChallengeAnswer. + where(user_id: user_id, block_id: content_file.standard.release.block_id, + challenge_uid: challenge.uid, cohort_id: cohort_id). + order(created_at: :desc) + end + + # only used in ChallengeWithSubmittedChallengeAnswersPresenter + def self.all_for_challenge_in_cohort(cohort, challenge, users_id = nil) + content_file = ContentFile.unscoped.find(challenge.content_file_id) + SubmittedChallengeAnswer.includes(:user). + where(user_id: users_id || cohort.students.map(&:id), block_id: content_file.standard.release.block_id, challenge_uid: challenge.uid). + select("DISTINCT ON (submitted_challenge_answers.user_id) submitted_challenge_answers.*"). + order("submitted_challenge_answers.user_id, created_at DESC"). + sort { |a, b| a.user.first_name <=> b.user.first_name } + end +end diff --git a/app/finders/user_finder.rb b/app/finders/user_finder.rb new file mode 100644 index 0000000..ac5d5b1 --- /dev/null +++ b/app/finders/user_finder.rb @@ -0,0 +1,8 @@ +class UserFinder + def self.students_joined_cohort_yesterday(cohort_id) + User.joins(:cohort_users). + where("cohort_users.cohort_id = ?", cohort_id). + where("cohort_users.created_at > ?", Time.current - 1.day). + merge(CohortUser.student) + end +end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb new file mode 100644 index 0000000..d9a1585 --- /dev/null +++ b/app/helpers/application_helper.rb @@ -0,0 +1,34 @@ +module ApplicationHelper + def sprite_navigation(name) + content_tag( + :svg, + content_tag( + :use, + "", + "xlink:href" => "/assets/images/svg/svg-sprite-navigation-symbol.svg#{name}" + ), + class: "icon" + ) + end + + def flash_class(level) + case level.to_sym + when :notice then "alert alert-info" + when :success then "alert alert-success" + when :error then "alert alert-danger" + when :alert then "alert alert-danger" + end + end + + def errors_for?(model, attribute) + model.errors[attribute].any? + end + + def errors_for(model, attribute) + return unless errors_for?(model, attribute) + + content_tag :small, class: "text-danger" do + model.errors[attribute].map(&:humanize).join(", ") + end + end +end diff --git a/app/helpers/json_helper.rb b/app/helpers/json_helper.rb new file mode 100644 index 0000000..45516ad --- /dev/null +++ b/app/helpers/json_helper.rb @@ -0,0 +1,9 @@ +module JsonHelper + def true?(obj) + obj.to_s == "true" + end + + def false?(obj) + obj.to_s == "false" + end +end diff --git a/app/helpers/secondary_navigation_helper.rb b/app/helpers/secondary_navigation_helper.rb new file mode 100644 index 0000000..fe79992 --- /dev/null +++ b/app/helpers/secondary_navigation_helper.rb @@ -0,0 +1,10 @@ +module SecondaryNavigationHelper + def setup_href(cohort) + return content_cohort_path(cohort.id) if cohort.sandbox + + cohort_user = current_user.cohort_users.where(cohort_id: cohort.id).first + return content_cohort_path(cohort.id) if cohort_user.nil? || cohort_user.last_setup_visit.nil? + + cohort_user.last_setup_visit + end +end diff --git a/app/helpers/standard_navigation_helper.rb b/app/helpers/standard_navigation_helper.rb new file mode 100644 index 0000000..6019a28 --- /dev/null +++ b/app/helpers/standard_navigation_helper.rb @@ -0,0 +1,165 @@ +module StandardNavigationHelper + delegate :url_helpers, to: "Rails.application.routes" + + def get_previous_standard_link(current_standard:, cohort:, content_file_id:) + @cohort = cohort + @current_content_file_id = content_file_id + @current_standard = current_standard + + if current_content_file_position.zero? # current file is first standard file + if previous_standard&.content_files&.any? + standard_link(@previous_standard, @previous_standard.content_files.order(position: :asc).last) + end + elsif current_content_file_position > 0 # current file is not first standard file + previous_content_file = current_content_files.where("position < ?", current_content_file_position).last + previous_content_file ? standard_link(@current_standard, previous_content_file) : nil + end + end + + def get_next_standard_link(current_standard:, cohort:, content_file_id:) + @cohort = cohort + @current_content_file_id = content_file_id + @current_standard = current_standard + + if current_content_file_position == current_content_files.length - 1 # current file is last standard file + return nil unless next_standard + + standard_link(next_standard, ContentFileFinder.first_for_standard(next_standard.id)) + else + next_content_file = current_content_files.where("position > ?", current_content_file_position).first + standard_link(@current_standard, next_content_file) + end + end + + def get_previous_content_file_link(current_standard:, cohort:, content_file_id:) + @cohort = cohort + @current_content_file_id = content_file_id + @current_standard = current_standard + + previous_content_file_id = current_content_files. + where("position < ?", current_content_file_position). + last&.id + + if previous_content_file_id.nil? + if previous_standard.present? && !previous_standard_visible_files.empty? + content_file_link( + previous_standard, + previous_standard_visible_files.order(position: :asc).last.id + ) + else + return nil unless current_standard_cohort_release_position + + previous_release = current_cohorts_releases. + where("position = ?", current_standard_cohort_release_position - 1). + last&.release + + return nil unless previous_release + + previous_release_standard = previous_release&.standards&.last + previous_content_file_id = previous_release_standard&.content_files&.last&.id + + content_file_link(previous_release_standard, previous_content_file_id) + end + else + content_file_link(@current_standard, previous_content_file_id) + end + end + + def get_next_content_file_link(current_standard:, cohort:, content_file_id:) + @cohort = cohort + @current_content_file_id = content_file_id + @current_standard = current_standard + + next_content_file_id = current_content_files. + where("position > ?", current_content_file_position). + first&. + id + + if next_content_file_id.nil? + next_standards_content_files = + next_standard.present? ? next_standard.content_files.order(position: :asc).visible_for(@cohort.id) : [] + + if !next_standards_content_files.empty? + content_file_link( + next_standard, + next_standards_content_files.first.id + ) + else + return nil unless current_standard_cohort_release_position + + next_release = current_cohorts_releases. + where("position = ?", current_standard_cohort_release_position + 1). + first&. + release + + return nil unless next_release + + next_release_standard = next_release&.standards&.visible_for(@cohort.id)&.first + next_content_file_id = next_release_standard&.content_files&.visible_for(@cohort.id)&.first&.id + + content_file_link(next_release_standard, next_content_file_id) + end + else + content_file_link(@current_standard, next_content_file_id) + end + end + + private + + def current_standard_position + @current_standard_position ||= @current_standard.position + end + + def current_content_file_position + @current_content_file_position ||= current_content_files.unscoped.find(@current_content_file_id).position + end + + def current_content_files + @current_content_files ||= ContentFile.where(standard: @current_standard). + visible_for(@cohort.id). + order(position: :asc) + end + + def current_standard_cohort_release_position + @current_standard_cohort_release_position ||= current_cohorts_releases. + select { |cohort_release| cohort_release.release == @current_standard.release }. + first&.position + end + + def current_cohorts_releases + @current_cohorts_releases ||= CohortRelease.where(cohort: @cohort).in_default_order + end + + def standard_link(standard, content_file) + return nil if content_file.blank? || standard.blank? + + { title: content_file.title, url: url_helpers.content_file_path(@cohort, standard.release.block, content_file.path) } + end + + def content_file_link(standard, content_file_id) + return nil if content_file_id.blank? + + content_file = standard.content_files.find_by(id: content_file_id) + block = standard.release.block + + { title: content_file.title, url: url_helpers.content_file_path(@cohort, block, content_file.path) } + end + + def cohort_standards + @cohort_standards ||= StandardFinder. + for_cohort_release(cohort_id: @cohort.id, release_id: @current_standard.release_id). + visible_for(@cohort.id) + end + + def previous_standard + @previous_standard ||= cohort_standards.where("standards.position < ?", current_standard_position).last + end + + def previous_standard_visible_files + @previous_standard_visible_files ||= previous_standard.content_files.visible_for(@cohort.id) + end + + def next_standard + @next_standard ||= cohort_standards.where("standards.position > ?", current_standard_position).first + end +end diff --git a/app/javascript/api.d.ts b/app/javascript/api.d.ts new file mode 100644 index 0000000..51881ec --- /dev/null +++ b/app/javascript/api.d.ts @@ -0,0 +1,550 @@ +declare namespace Api { + type rails_path = string + type user_id = number + + type Score = null | 1 | 2 | 3 + + type Activity = { + id: number + // formatted_created_at: number + name: string + content: string + created_at: string + user_photo: string + user_initials: string + } + + type Standard = { + id: number + success_criteria: string + current_score: Api.Score + description: string + } + + type Student = { + id: number, + full_name: string, + initials: string, + profile_image: string + } + + type ContentFile = { + id: number + uid: string + title: string + hidden: boolean + content_file_path: string + content_file_type: 'lesson' | 'checkpoint' | 'instructor' | 'resource' + challenges: ChallengeWithSubmissions[] + checkpoint_submissions?: Record + type_relative_position: number, + max_checkpoint_submissions: number + } + + type CheckpointStudentScore = { + email: string + first_name: string + has_signed_in: boolean + id: number + auth_edit_url: string + initials: string + last_name: string + profile_image: string + submissions: CheckpointStudentScoreSubmission + } + + type CheckpointStudentScoreSubmission = { + created_at: string + done_id: number + needs_review_id: number + score: number + started_id: number + state: string + } + + type CheckpointSubmission = { + id: number + cohort_id: number + state: CheckpointSubmissionState + created_at: string + updated_at: string + last_performance_percent: number + total_possible_points: number + points_earned: number + challenge_total: number + path: string + } + + type CheckpointSubmissionState = 'needs_review' | 'rejected' | 'done' | 'retry' | 'started' + + type CheckpointDataBase = { + cohortId: number + challengeTotal: number + contentFilesSubmission: Api.CheckpointSubmission | null + checkpointsByState: { + done: Api.CheckpointSubmission | null + retry: Api.CheckpointSubmission | null + needs_review: Api.CheckpointSubmission | null + started: Api.CheckpointSubmission | null + } + } + + type CheckpointInfo + = CheckpointDataBase & { + cohortMode: Api.CohortModeMastery | Api.CohortModePercentage + masteryScore: number + challengeCorrect: number + } + + type ContentFileType = 'checkpoint' | 'lesson' | 'resource' | 'instructor' | undefined + + type ChallengeWithSubmissions = { + id: number + title: string + student_submissions: Record> + } + + type Notification = { + id: number + created_at: Date + description: null | string + read_at: null | Date + tagline: string + title: string + updated_at: Date + url: string + user_id: number + } + + type Challenge = { + id: number + uid: string + answer: null | string + content_file_id: number + created_at: Date + docker_directory_path: null | string + explanation: null | string + hints: string[] + language: null | string + position: number + max_attemps: number + raw_json: any + setup: string + tests: null | string + title: string + updated_at: Date + upstream_repo_path: null | string + validate_fork: boolean + } + + type ChallengeWithSubmittedChallengeAnswersPresenterBase = { + id: number + uid: string + title: string + autoscorable: boolean + hints: string[] + index: number // Where does this come from?? + next_student: rails_path + number_of_hints: number + previous_student: rails_path + points: number + topics: string[] + + show_tests: boolean + tests?: string // Present if show_tests is true + + can_view_status: boolean + can_check_answer: boolean + can_view_explanation: boolean + submitted_challenge_answer_presenters: SubmittedChallengeAnswerPresenter[] + submitted_challenge_answer_presenter: SubmittedChallengeAnswerPresenter + } + + type ChallengeType + = 'checkbox' | 'code-snippet' | 'custom-snippet' + | 'multiple-choice' | 'number' | 'poll' + | 'short-answer' | 'testable-project' + | 'paragraph' | 'project' | 'local-snippet' + + type ChallengeWithSubmittedChallengeAnswersPresenter + = ChallengeWithSubmittedChallengeAnswersPresenterBase & + { + challenge_type: Exclude + + // explanation: any + placeholder: null | string + decimal: null | number + question: null | string + language: null | string + options: null | Array<{ + rendered_option: string, + option: any + }> + // grader_label: any + } + | LocalJsChallenge + + type LocalJsChallenge + = ChallengeWithSubmittedChallengeAnswersPresenterBase & + { + challenge_type: 'local-snippet' + tests: string + helpers: string[] + language: 'javascript' + question: string + placeholder: string + options: null | Array<{ + rendered_option: string, + option: any + }> + } + + type SubmittedChallengeAnswerPresenter = { + status: SubmitedChallengeAnswerStatus + overall_status: SubmittedChallengeAnswerOverallStatus + answer: null | string + last_graded_at: null | Date + challenge_id: number + student_comment_url: null | rails_path + test_results: string + cancel_url: null | string + submitted_challenge_answer_id: number + submitted_challenge_answer_url: null | rails_path + // increment_challenge_answer_url: any + attempted_on: null | string + challenge_explanation: null | string + rubric: null | string + incorrect_attempts: number + hints: string[] + grader_label: null | string + permissions: { update: boolean } + created_at: null | Date + increment_hints_shown_submitted_challenge_answer_url: null | rails_path + points: null | number + max_points: null | number + checkpoint_submission_id: null | number + } + + type SubmitedChallengeAnswerStatus + = 'correct' | 'incorrect' + | 'ungraded' | 'processing' | 'failed' | 'invalid_repo' + | 'canceled' | 'invalid_fork' | 'timeout' | 'missing_file' | 'unknown' | 'retry' | 'building' + + type SubmittedChallengeAnswerOverallStatus + = 'none' | 'graded' | 'ungraded' + + type CohortModeMastery = 'Mastery' + type CohortModePercentage = 'Percentage' + type CohortMode = CohortModePercentage | CohortModeMastery + + type UserForAvatar = { + id: number + initials: string + full_name: string + profile_image: null | string + } + + type StandardPresenter_ForCardBase = { + id: number + block_id: number + cohort_id: number + cohort_standard_progress: { + percent_done: number + percent_pending: number + remaining: number + total_completed: number + total_pending: number + } + cohort_standard_progress_data: any[] + title: string + description: string + has_progress: boolean + progress_complete: number + progress_percentage: number + } + + type StandardPresenter_ForCard + = StandardPresenter_ForCardBase & { + cohort_mode: 'Percentage' + progress_pending: number + remaining_to_completion: number + is_completed: boolean + has_progress: boolean + } + | StandardPresenter_ForCardBase & { + cohort_mode: 'Mastery' + mastery_score: number + // These exist but we shouldn't use them + // last_visited_by_user: '-is-current' | '-is-visited' | '-is-unvisited' + // mastery_class: '-score-1' | '-score-2' | '-score-3' | '-unscored' + } + + type LessonVisit = { + id: number + user_id: number + block_id: number + cohort_id: number + standard_uid: string + content_file_path: string + content_file_uid: null | string + + visit_count: number + } + + namespace CurriculumPage { + type release_id = number + type Section = { + id: number + title: string + release_ids: release_id[] + standard_count: number + standardsForSectionPath: string | null + } + } + + namespace CheckpointSubmissionShow { + type t = { + id: number + user_id: number + url: string + title: string + autoscorable: boolean + block_id: number + max_checkpoint_submissions: number + submission_count: number + content_file_url: string + grader: any + submitted_on: string + state: CheckpointSubmissionState + } + + type StandardCardProps = { + checkpoint_performance: null | CheckpointPerformance + standard: Standard + } + type CheckpointPerformance = { + score: number + // checkpoint_submission_id: number + created_at: string + standard_id: number + // updator_id: number + // user_id: number + updator_full_name: string + // updator_full_name: performance.updator.nil ? "Autoscored" : performance.updator.full_name + } + } + + namespace Submissions { + type block_id = number + type standard_uid = string + + type SubmissionData + = { + cohort_mode: 'Mastery' | 'Percentage' + blocks: Block[] + sections: Block[] + completion_progress: Record + > + > + } + + type Student = { + id: user_id + initials: string + name: string + avatar: null | string + challenges_path: rails_path + cohort_reg_date: string + } + + type Block = { + id: number + title: string + standards: Standard[] + } + + type Standard = { + id: number + uid: string + title: string + description: string + success_criteria?: string // Only present in mastery mode + student_performances: Record + content_files: ContentFile[] + submissions_path: rails_path + } + + type StudentPerformance = { + score?: number + student_id: number + standard_uid?: string + checkpoint_created_at?: null | string + checkpoint_state?: null | CheckpointSubmissionState + checkpoint_submission_id?: null | number + ungraded_submission_id?: number + ungraded_submission_state?: CheckpointSubmissionState + total_points: number + correct_points: number + } + } + + namespace Setup { + type Flash = { + title: string + msg: string | any + type: string + } + type ResyncJobBase = { + id: number + cohort_id: number + course_config_url: string + } + type SuccessfulResyncJob = ResyncJobBase & { + status: 'success' + synced_at: string + } + type CanceledResyncJob = ResyncJobBase & { + status: 'canceled' + } + type FailureResyncJob = ResyncJobBase & { + status: 'failure' + archived: boolean + error_type: string + error_data: any + } + type TimeoutResyncJob = ResyncJobBase & { + status: 'timeout' + archived: boolean + error_type: string + error_data: any + } + type PendingResyncJob = ResyncJobBase & { + status: 'pending' + } + type ResyncJob = SuccessfulResyncJob | FailureResyncJob | PendingResyncJob | CanceledResyncJob | TimeoutResyncJob + + type VisibilitySection = { + id: number + title: string + standards_with_lessons: VisibilityStandard[] + } + type VisibilityStandard = { + id: number + title: number + hidden: boolean + content_file_count: number + content_files: Array + } + type VisibilityContentFile = { + id: number, + uid: string, + title: string, + hidden: boolean, + path: string, + github_url: string, + visible: boolean, + } + } + + type BlockPresenter_ForReleases = { + cohorts_using_release: Cohort[] + last_update: string + name: string + release_id: number + version: string + repo_name: string + notes: string + repo_url: string + commit_url: string + github_sha: string + diff_url: string + block_id: number + user_avatar: UserForAvatar + } + + type BlockPresenter_ForBlocks = { + submission_count: number, + cohorts_using_this_block: object[], + cohort_count: number, + id: number, + last_update: string, + latest_release_id: number, + name: string, + readme_link: string, + readme_text: string, + release_count: number, + repo_description?: string, + repo_name: string, + repo_tags?: string[], + repo_url: string, + student_count: number, + sync_errors?: string[], + user_avatar: UserForAvatar + } + + type Cohort = { + id: number + uid: string + name: string + product_type: string + label: string + gcode: string + campus_name: string + slack_channel: string + starts_on: string + ends_on: string + created_at: string + updated_at: string + deleted_at: string + mode: string + } + + namespace Pairs { + type Student = { + uid: string + name: string + profile_image: string + } + + type Pairing = { + size: number + groups: Api.Pairs.Student[][] | string + id: number | null + title: string + } + } + + type ApiInteraction = { + id: number + user_id: number + ip: string + path: string + method: string + action_name: string + duration: number + controller_name: string + response_code: string + } + + type RepoDetails = { + repo_name: string + org: string + origin: string + } +} + +declare module 'objectify-array/*'{ + var _a: any; + export = _a; +} + +interface Array { + flat(): Array; + flatMap(func: (x: T) => T): Array; +} diff --git a/app/javascript/components/AceEditor.tsx b/app/javascript/components/AceEditor.tsx new file mode 100644 index 0000000..525be56 --- /dev/null +++ b/app/javascript/components/AceEditor.tsx @@ -0,0 +1,133 @@ +import * as React from 'react' +import ace from './lib/ace' + +type Props = { + mode: string + theme: string + name: string + width: string + height: string + fontSize: number + showGutter: boolean + + value: string + defaultValue: string + + maxLines?: number + readOnly: boolean + wrapEnabled: boolean + selectFirstLine: boolean + showPrintMargin: boolean + behavioursEnabled: boolean + highlightActiveLine: boolean + wrapBehavioursEnabled: boolean + + onLoad: (e: React.SyntheticEvent) => void + onChange: (input: string) => void + onFocus: (e: React.SyntheticEvent) => void + handleCodeSubmit: (e: React.SyntheticEvent) => void + + setShowPrintMargin: any // Not used? + editorProps: any // Not used? +} + +export default class AceEditor extends React.Component { + editor: any + + public static defaultProps: Partial = { + name: 'ace-editor', + mode: '', + theme: '', + height: '100%', + width: '100%', + defaultValue: '', + value: '', + fontSize: 14, + showGutter: true, + readOnly: false, + highlightActiveLine: true, + showPrintMargin: true, + selectFirstLine: false, + wrapEnabled: true, + behavioursEnabled: true, + } + + componentDidMount() { + this.editor = ace.edit(this.props.name); + this.editor.getSession().$useWorker = false; + this.editor.$blockScrolling = Infinity; + this.editor.getSession().setMode('ace/mode/' + this.props.mode); + this.editor.setTheme('ace/theme/' + this.props.theme); + this.editor.setFontSize(this.props.fontSize); + this.editor.on('change', this.onChange); + this.editor.on('focus', this.props.onFocus); + this.editor.setValue(this.props.defaultValue || this.props.value, (this.props.selectFirstLine === true ? -1 : null)); + this.editor.setOption('maxLines', this.props.maxLines); + this.editor.setOption('readOnly', this.props.readOnly); + this.editor.setOption('highlightActiveLine', this.props.highlightActiveLine); + this.editor.setOption('behavioursEnabled', this.props.behavioursEnabled); + this.editor.setOption('wrapBehavioursEnabled', this.props.wrapBehavioursEnabled); + this.editor.setShowPrintMargin(this.props.setShowPrintMargin); + this.editor.renderer.setShowGutter(this.props.showGutter); + this.editor.commands.addCommand({ + name: 'submit-code', + exec: this.props.handleCodeSubmit, + bindKey: { mac: 'cmd-enter', win: 'ctrl-enter' } + }); + + if (this.props.onLoad) this.props.onLoad(this.editor); + } + + componentWillReceiveProps(nextProps: Props) { + let currentRange = this.editor.selection.getRange(); + + // only update props if they are changed + if (nextProps.mode !== this.props.mode) { + this.editor.getSession().setMode('ace/mode/' + nextProps.mode); + } + if (nextProps.theme !== this.props.theme) { + this.editor.setTheme('ace/theme/' + nextProps.theme); + } + if (nextProps.fontSize !== this.props.fontSize) { + this.editor.setFontSize(nextProps.fontSize); + } + if (nextProps.maxLines !== this.props.maxLines) { + this.editor.setOption('maxLines', nextProps.maxLines); + } + if (nextProps.readOnly !== this.props.readOnly) { + this.editor.setOption('readOnly', nextProps.readOnly); + } + if (nextProps.highlightActiveLine !== this.props.highlightActiveLine) { + this.editor.setOption('highlightActiveLine', nextProps.highlightActiveLine); + } + if (nextProps.setShowPrintMargin !== this.props.setShowPrintMargin) { + this.editor.setShowPrintMargin(nextProps.setShowPrintMargin); + } + if (nextProps.wrapEnabled !== this.props.wrapEnabled) { + this.editor.getSession().setUseWrapMode(nextProps.wrapEnabled); + } + if (nextProps.value && this.editor.getValue() !== nextProps.value) { + this.editor.setValue(nextProps.value, (this.props.selectFirstLine === true ? -1 : null)); + if (currentRange && typeof currentRange === 'object') { + this.editor.getSession().getSelection().setSelectionRange(currentRange); + } + } + if (nextProps.showGutter !== this.props.showGutter) { + this.editor.renderer.setShowGutter(nextProps.showGutter); + } + } + + onChange = () => { + if (this.props.onChange) { + const value = this.editor.getValue(); + + this.props.onChange(value); + } + } + + render() { + const divStyle = { width: this.props.width, height: this.props.height }; + + return

+ } +} diff --git a/app/javascript/components/Badge.tsx b/app/javascript/components/Badge.tsx new file mode 100644 index 0000000..3512874 --- /dev/null +++ b/app/javascript/components/Badge.tsx @@ -0,0 +1,18 @@ +import * as React from 'react' + +type Props = { + id?: string + text: string + className?: string +} + +export default (props: Props) => { + let classes = `lp-badge ${(props.className ? props.className : '')}`; + let badgeText = props.text.replace('_', ' '); + + return ( + + {badgeText} + + ); +}; diff --git a/app/javascript/components/Button.tsx b/app/javascript/components/Button.tsx new file mode 100644 index 0000000..2323ff9 --- /dev/null +++ b/app/javascript/components/Button.tsx @@ -0,0 +1,26 @@ +import * as React from 'react' + +type Props = { + className?: string + id?: string + type?: any + onClick?: any + children?: React.ReactNode + disabled?: boolean +} + +export default (props: Props) => { + let classes = `lp-style-button ${(props.className ? props.className : '')}`; + + return ( + + ); +}; diff --git a/app/javascript/components/ButtonTo.tsx b/app/javascript/components/ButtonTo.tsx new file mode 100644 index 0000000..f8efe0e --- /dev/null +++ b/app/javascript/components/ButtonTo.tsx @@ -0,0 +1,75 @@ +import * as React from 'react' + +type Props = { + buttonText: string + method: string + paramName: string + url: string + disabled?: boolean + parentId?: string + paramVal: string + buttonClass: string +} + +export default (props: Props) => { + let formMethod = props.method; + let methodInput; + let csrfToken = $_('meta[name=csrf-token]', el => el.getAttribute('content')) || undefined; + let inputClass = props.buttonClass; + let hasMadeComment = false; + + if (props.disabled) { + inputClass = inputClass.concat(' -disabled'); + } + + if (props.method === 'patch') { + formMethod = 'post'; + methodInput = ( + + ); + } + + const submit = (e: any) => { + if (props.buttonText === 'Reject' && !hasMadeComment) { + e.preventDefault(); + $_('#comment-and-reject', el => el.style.display = 'block'); + } + }; + + const newCommentHandler = (e: any) => { + if (props.buttonText === 'Reject') { + e.preventDefault(); + console.error('Route does not exist: api_v1_checkpoint_submission_checkpoint_submission_comments_path') + // $.post(Routes.api_v1_checkpoint_submission_checkpoint_submission_comments_path(props.parentId), { + // comment: { + // content: $('.comment-and-reject textarea').text() + // } + // }).then((data) => { + // $(`#${props.buttonText}Form`).first().trigger('submit', { hasMadeComment: true }); + // }); + } + }; + + const injectCommentFormForReject = () => { + if (props.buttonText === 'Reject' && props.parentId !== null) { + console.error('NewCommentForm does not exist') + // return
; + } + }; + + return ( + + {injectCommentFormForReject()} +
+ {methodInput} + + + +
+
+ ); +}; diff --git a/app/javascript/components/Dropdown.tsx b/app/javascript/components/Dropdown.tsx new file mode 100644 index 0000000..6f659f1 --- /dev/null +++ b/app/javascript/components/Dropdown.tsx @@ -0,0 +1,40 @@ +import * as React from 'react' +import {isEmpty} from 'lodash-es' +import Icon from './Icon' + +type Props = { + placeholder?: string + selectedStandard?: string + options: { + id: string + savedValue?: null | string + items: Array<{ id: number | string, title: string }> + } + onChange: any +} + +export default (props: Props) => { + let placeholder; + let uniqueId = props.options.id; + let selected = props.options.savedValue || undefined; + let options = props.options.items.map((option) => { + return ( + + ); + }); + + if (!isEmpty(props.placeholder)) { + placeholder = ; + } + + return ( +
+ + +
+ ); +}; + diff --git a/app/javascript/components/Icon.tsx b/app/javascript/components/Icon.tsx new file mode 100644 index 0000000..b8b61fb --- /dev/null +++ b/app/javascript/components/Icon.tsx @@ -0,0 +1,20 @@ +import * as React from 'react' + +type Props = { + id: string + sprite: string + color?: string + viewBox?: string +} + +export default (props: Props) => { + let url = `/assets/images/svg/svg-sprite-${props.sprite}-symbol.svg${props.id}`; + let classes = `svg svg-24px ${props.color || ''}`; + let viewBox = props.viewBox || '0 0 24 24'; + + return ( + + + + ); +}; diff --git a/app/javascript/components/Loading.tsx b/app/javascript/components/Loading.tsx new file mode 100644 index 0000000..d3acbe5 --- /dev/null +++ b/app/javascript/components/Loading.tsx @@ -0,0 +1,59 @@ +import * as React from 'react' + +export default class LoadingLogo extends React.Component { + + componentDidMount() { + var {TimelineMax, Sine} = window + let bubbleAnimation1 = new TimelineMax({ paused: false }); + let bubbleAnimation2 = new TimelineMax({ paused: false }); + let bubbleAnimation3 = new TimelineMax({ repeat: -1, paused: false }); + + bubbleAnimation1 + .to('#bubble-1', 1.25, { scaleX: 0.74, scaleY: 0.74, ease: Sine.easeOut }) + .to('#bubble-1', 1.25, { x: -30, y: -20, transformOrigin: '50% 50%', ease: Sine.easeOut }, '-=1.25') + .to('#bubble-1', 1.25, { rotation: -100, transformOrigin: '50% 50%', ease: Sine.easeOut }, '-=1.25') + .to('#bubble-1', 1.25, { scaleX: 0.45, scaleY: 0.45, ease: Sine.easeOut }) + .to('#bubble-1', 1.25, { x: -10, y: -53, transformOrigin: '50% 50%', ease: Sine.easeOut }, '-=1.25') + .to('#bubble-1', 1.25, { rotation: 0, transformOrigin: '50% 50%', ease: Sine.easeOut }, '-=1.25') + .to('#bubble-1', 1.25, { scaleX: 0.0, scaleY: 0.0, transformOrigin: '50% 50%', ease: Sine.easeOut }); + + bubbleAnimation2 + .to('#bubble-2', 1.25, { scaleX: 0.69, scaleY: 0.69, ease: Sine.easeOut }) + .to('#bubble-2', 1.25, { x: 20, y: -31, transformOrigin: '50% 50%', ease: Sine.easeOut }, '-=1.25') + .to('#bubble-2', 1.25, { rotation: 100, transformOrigin: '50% 50%', ease: Sine.easeOut }, '-=1.25') + .to('#bubble-2', 1.25, { scaleX: 0.0, scaleY: 0.0, transformOrigin: '50% 50%', ease: Sine.easeOut }); + + bubbleAnimation3 + .to('#bubble-3', 1.25, { scaleX: 0.0, scaleY: 0.0, transformOrigin: '50% 50%', ease: Sine.easeOut }) + .to('#bubble-3', 0, { x: 10, y: 52, transformOrigin: '50% 50%' }) + .to('#bubble-3', 1.25, { scaleX: 2.25, scaleY: 2.25, transformOrigin: '50% 50%', ease: Sine.easeOut }) + .to('#bubble-3', 1.25, { scaleX: 1.58, scaleY: 1.58, ease: Sine.easeOut }) + .to('#bubble-3', 1.25, { x: -19, y: 31, transformOrigin: '50% 50%', ease: Sine.easeOut }, '-=1.25') + .to('#bubble-3', 1.25, { rotation: -92, transformOrigin: '50% 50%', ease: Sine.easeOut }, '-=1.25') + .to('#bubble-3', 1.25, { scaleX: 1.1, scaleY: 1.1, ease: Sine.easeOut }) + .to('#bubble-3', 1.25, { x: 0, y: 1, transformOrigin: '50% 50%', ease: Sine.easeOut }, '-=1.25') + .to('#bubble-3', 1.25, { rotation: 5, transformOrigin: '50% 50%', ease: Sine.easeOut }, '-=1.25'); + } + + render() { + return ( +
+ +
+ ); + } +} diff --git a/app/javascript/components/Marked.tsx b/app/javascript/components/Marked.tsx new file mode 100644 index 0000000..c5e9a99 --- /dev/null +++ b/app/javascript/components/Marked.tsx @@ -0,0 +1,25 @@ +import * as React from 'react' +const marked = require('marked') + +type Props = { + source: null | string + className?: string +} + +export default class Marked extends React.Component { + + rawMarkup() { + if (this.props.source !== null) { + let rawMarkup = marked(this.props.source.toString()); + + rawMarkup = rawMarkup + .replace(//g, '
'); + + return { __html: rawMarkup }; + } + } + + render() { + return
; + } +} diff --git a/app/javascript/components/Menu.tsx b/app/javascript/components/Menu.tsx new file mode 100644 index 0000000..43833cd --- /dev/null +++ b/app/javascript/components/Menu.tsx @@ -0,0 +1,45 @@ +import * as React from 'react' + +type Props = { + items: Array<{ url: string, text: string }> + unmountMe: () => void +} + +export default class Menu extends React.Component { + + private nodeRef: any + + componentWillMount() { + document.addEventListener('click', this.handleClickOff, false); + } + + componentWillUnmount() { + document.removeEventListener('click', this.handleClickOff, false); + } + + handleClickOff = (e: MouseEvent | TouchEvent) => { + if (! this.nodeRef.contains(e.target)) { + this.props.unmountMe(); + } + } + + listItems() { + const listItems = this.props.items.map((item, i) => +
  • + {item.text} +
  • + ); + + return ( +
      { listItems }
    + ); + } + + render() { + return ( +
    this.nodeRef = node}> + { this.listItems() } +
    + ); + } +} diff --git a/app/javascript/components/Notifications.tsx b/app/javascript/components/Notifications.tsx new file mode 100644 index 0000000..55f3967 --- /dev/null +++ b/app/javascript/components/Notifications.tsx @@ -0,0 +1,116 @@ +import * as React from 'react' +import * as Routes from '../generated/routes' +import NotificationsIcon from './notifications/NotificationsIcon' +import http from '../lib/http' + + +type Props = {} +type State = { + loading: boolean + open: boolean + unreadCount: number + notifications: Api.Notification[] +} + +export default class Notifications extends React.Component { + private node: any + + constructor(props: Props) { + super(props); + + this.handleOutsideClick = this.handleOutsideClick.bind(this); + + this.state = { + loading: true, + open: false, + unreadCount: 0, + notifications: [] + }; + } + + componentDidMount() { + this.bootstrap(); + } + + async bootstrap() { + var data = await http('GET', Routes.notificationsPath()); + this.updateFromPayload(data); + } + + updateFromPayload(data: any) { + this.setState({ + notifications: data.notifications, + unreadCount: data.unreadCount, + loading: false + }); + } + + togglePanel() { + if (!this.state.open) { + document.addEventListener('touchmove', this.handleOutsideClick, false); + document.addEventListener('click', this.handleOutsideClick, false); + } else { + document.removeEventListener('touchmove', this.handleOutsideClick, false); + document.removeEventListener('click', this.handleOutsideClick, false); + } + + this.setState({ open: !this.state.open }); + } + + handleOutsideClick(e: any) { + if (this.node.contains(e.target)) { + return; + } + + this.togglePanel(); + } + + async markAllRead() { + var data = await http('POST', Routes.markAllReadNotificationsPath()); + this.updateFromPayload(data); + } + + render() { + let panel; + + if (!this.state.loading && this.state.open) { + let footerRow; + + if (this.state.unreadCount > 0) { + footerRow = (
    Mark all read
    ); + } + + let notifications = this.state.notifications.map((notification) => { + let klass = notification.read_at ? 'read' : 'unread'; + + return ( + +
    +
    {notification.tagline}
    +
    {window.moment(notification.created_at).tz(window.moment.tz.guess()).fromNow()}
    +
    +
    {notification.title}
    +
    {notification.description}
    +
    + ); + }); + + panel = ( +
    +
    Notifications
    +
    {notifications}
    + { footerRow } +
    + ); + } + + let openClass = this.state.open ? 'open' : ''; + + return ( +
    { this.node = node; }}> + + { panel } +
    + ); + } +} diff --git a/app/javascript/components/ProcessingIcon.tsx b/app/javascript/components/ProcessingIcon.tsx new file mode 100644 index 0000000..f2d1db4 --- /dev/null +++ b/app/javascript/components/ProcessingIcon.tsx @@ -0,0 +1,31 @@ +import * as React from 'react' + +export default () => ( + + + + + +); diff --git a/app/javascript/components/RowKebab.tsx b/app/javascript/components/RowKebab.tsx new file mode 100644 index 0000000..313fc02 --- /dev/null +++ b/app/javascript/components/RowKebab.tsx @@ -0,0 +1,36 @@ +import * as React from 'react' +import SvgRenderer from './SvgRenderer' + +type Props = { + active: boolean + toggleAction:() => void +} + +type State = { + kebabClass: string +} + +export default class RowKebab extends React.Component { + constructor(props: Props) { + super(props) + this.state = { + kebabClass: this.props.active ? 'action-kebab active' : 'action-kebab' + } + } + + static getDerivedStateFromProps(nextProps: Props, prevState: State): State { + let kb:string = 'action-kebab' + if (nextProps.active) { + kb = kb + ' active' + } + return { kebabClass: kb } + } + + render() { + return ( + + + + ) + } +} diff --git a/app/javascript/components/ScoreCircle.tsx b/app/javascript/components/ScoreCircle.tsx new file mode 100644 index 0000000..dc2baed --- /dev/null +++ b/app/javascript/components/ScoreCircle.tsx @@ -0,0 +1,23 @@ +import * as React from 'react' + +export default (n: number) => { + let circleClass = function(n: number) { + switch (n) { + case 1: + return ' -is-one'; + case 2: + return ' -is-two'; + case 3: + return ' -is-three'; + default: + return ''; + } + }; + + return ( +
    + {n} +
    + ); +}; + diff --git a/app/javascript/components/SidebarProgress.tsx b/app/javascript/components/SidebarProgress.tsx new file mode 100644 index 0000000..bed2c83 --- /dev/null +++ b/app/javascript/components/SidebarProgress.tsx @@ -0,0 +1,28 @@ +import * as React from 'react' + +type Props = { + masteryCohort: boolean +} +type State = {} + +export default class SidebarProgress extends React.Component { + constructor(props: Props) { + super(props); + } + + render() { + if (this.props.masteryCohort) { + return ( +
    +
    + ); + } else { + return ( +
    +
    +
    +
    + ); + } + } + } diff --git a/app/javascript/components/SortDropdown.tsx b/app/javascript/components/SortDropdown.tsx new file mode 100644 index 0000000..6b9a463 --- /dev/null +++ b/app/javascript/components/SortDropdown.tsx @@ -0,0 +1,36 @@ +import * as React from 'react' +import Icon from './Icon' + +type Props = { + className: string, + selectedSort?: string, + options: { + id: any, + savedValue: string, + sorts: Array<{ + id: any, + title: string + }> + } + onChange: (e: any) => void +} + +export default (props: Props) => { + let uniqueId = props.options.id; + let selected = props.options.savedValue || props.selectedSort || ''; + let options = props.options.sorts.map((option) => { + return ( + + ); + }); + + return ( +
    +
    Sort by:
    + + +
    + ); +}; diff --git a/app/javascript/components/StandardBean.tsx b/app/javascript/components/StandardBean.tsx new file mode 100644 index 0000000..1f918cc --- /dev/null +++ b/app/javascript/components/StandardBean.tsx @@ -0,0 +1,36 @@ +import * as React from 'react' + +type Props = { + score: number, + isCompleted: boolean +} + +export default class StandardBean extends React.Component { + render() { + let className; + + if (this.props.score) { + switch (this.props.score) { + case 1: + className = '-score-1'; + break; + case 2: + className = '-score-2'; + break; + case 3: + className = '-score-3'; + break; + default: + className = '-unscored'; + } + } else if(this.props.isCompleted) { + className = '-is-completed'; + } else { + className = '-unscored'; + } + + return ( +
    + ); + } +} diff --git a/app/javascript/components/SvgRenderer.tsx b/app/javascript/components/SvgRenderer.tsx new file mode 100644 index 0000000..f0e65b2 --- /dev/null +++ b/app/javascript/components/SvgRenderer.tsx @@ -0,0 +1,26 @@ +import * as React from 'react' + +type Props = { + viewBox?: string + url?: string + style?: object + onClick?: (e: any) => void + className?: string + dataAttrs?: any +} + +export default class SvgRenderer extends React.Component { + render() { + return ( + + + + ); + } +} diff --git a/app/javascript/components/Timestamp.tsx b/app/javascript/components/Timestamp.tsx new file mode 100644 index 0000000..c321777 --- /dev/null +++ b/app/javascript/components/Timestamp.tsx @@ -0,0 +1,16 @@ +import * as React from 'react' + +type Props = { + timestamp: any +} + +export default (props: Props) => ( +
    + {stampFromString(props.timestamp)} +
    +); + +export function stampFromString (date: string) { + const timezone = window.moment.tz.guess() + return `${window.moment(date).tz(timezone).calendar()} ${window.moment.tz(timezone).zoneAbbr()}` +} diff --git a/app/javascript/components/UserAvatar.tsx b/app/javascript/components/UserAvatar.tsx new file mode 100644 index 0000000..3071827 --- /dev/null +++ b/app/javascript/components/UserAvatar.tsx @@ -0,0 +1,29 @@ +import * as React from 'react' + +type Props = { + src: null | string + initials: string +} + +export default (props: Props) => { + if (props.src) { + return ( +
    + ); + } else { + return ( +
    + + + + {props.initials} + + + +
    + ); + } +}; diff --git a/app/javascript/components/activities/NewActivityForm.tsx b/app/javascript/components/activities/NewActivityForm.tsx new file mode 100644 index 0000000..a7d567e --- /dev/null +++ b/app/javascript/components/activities/NewActivityForm.tsx @@ -0,0 +1,138 @@ +import * as React from 'react' +import Textarea from 'react-textarea-autosize' +import Marked from '../Marked' +import http from '../../lib/http' + +type Props = { + afterActivityHandler: (activity: Api.Activity) => void + buttonType: string + maxRows: number + minRows: number + createActivityUrl: string + notify: boolean +} +type State = { + newActivity: string + showPreview: boolean +} + +export default class NewActivityForm extends React.Component { + constructor(props: Props) { + super(props); + } + + state = { + newActivity: '', + showPreview: false + } + + static get defaultProps() { + return { + afterActivityHandler: null, + buttonType: 'comment', + maxRows: 5, + minRows: 1 + }; + } + + createActivity = () => { + http('POST', this.props.createActivityUrl, { + body: { + activity: { + content: this.state.newActivity, + notify: this.props.notify + } + } + }) + .then((data: any) => { + if (this.props.afterActivityHandler) this.props.afterActivityHandler(data); + this.setState({ + newActivity: '', + showPreview: false + }); + }); + } + + get ActivityButton() { + let buttonClass = '', buttonText = ''; + let disabled = this.state.newActivity === ''; + + if (this.props.buttonType === 'comment') { + buttonClass = ''; + buttonText = 'Send'; + } else if (this.props.buttonType === 'reject') { + buttonClass = '-reject'; + buttonText = 'Comment & Reject'; + } + + if (disabled) { + buttonClass = buttonClass.concat(' -disabled'); + } + + return ( + + ); + } + + get PreviewButton() { + if (this.state.newActivity == '') { return null; } + + let buttonText = this.state.showPreview ? 'Edit' : 'Preview'; + + return ( + + {buttonText} + + ); + } + + toggleActivityPreview = () => { + this.setState({ showPreview: !this.state.showPreview }); + } + + setActivityState = (e: any) => { + this.setState({ newActivity: e.target.value }); + } + + getTextarea() { + let textArea = ( + + ); + + if (this.state.showPreview) { + textArea = ; + } + + return textArea; + } + + render() { + let commentFormClass = this.props.buttonType === 'reject' ? ' comment-and-reject' : ''; + + return ( +
    +
    + {this.getTextarea()} +
    +
    + + + + {this.PreviewButton} + {this.ActivityButton} +
    +
    + ); + } +} diff --git a/app/javascript/components/api/ApiInteractions.tsx b/app/javascript/components/api/ApiInteractions.tsx new file mode 100644 index 0000000..903cf17 --- /dev/null +++ b/app/javascript/components/api/ApiInteractions.tsx @@ -0,0 +1,142 @@ +import React, { Component, Fragment } from 'react'; +import JSONPretty from 'react-json-pretty'; +import StatusCircle from '../shared/Icons/StatusCircle'; +import Done from '../shared/Icons/Done'; +import Clear from '../shared/Icons/Clear'; +import Pagination from '../shared/Pagination/Pagination'; + +require('react-json-pretty/themes/1337.css'); + +type Props = { + apiInteractions: Api.ApiInteraction[] + page: string + perPage: number + totalCount: number +} + +type State = { + openDrawers: any +} + +export default class ApiInteractions extends Component { + state: State = { + openDrawers: {}, + }; + + toggleMetadataDrawer = (drawerIndex: number) => { + this.setState(prevState => ({ + openDrawers: { + ...prevState.openDrawers, + [drawerIndex]: !prevState.openDrawers[drawerIndex], + } + })); + } + + goToPage = (pageObj: any) => { + window.location.href = + `${window.location.href.split('?')[0]}?page=${pageObj.selected + 1}` + } + + render() { + const { apiInteractions, perPage, totalCount } = this.props; + const page = Number(this.props.page); + const totalPages = Math.ceil(totalCount / perPage); + + return ( +
    +
    +

    API Interactions

    +
    +
    + + + + + + + + + + + + + + {apiInteractions.map((interaction: any, i: number) => { + const anyMetadata = interaction.metadata ? Object.keys(interaction.metadata).length > 0 : false; + + return ( + + this.toggleMetadataDrawer(i)} + className="tr" + > + + + + + + + + + + {this.state.openDrawers[i] && ( + + + + )} + + )} + )} + +
    RESPONSE CODEMETHODPATHDURATIONUSER IDIP ADDRRECORD IDMETADATA
    +
    + +
    +
    + {interaction.response_code} +
    +
    {interaction.method}{interaction.path}{`${interaction.duration}ms`}{interaction.user_id}{interaction.ip}{interaction.id} + {anyMetadata ? ( +
    + +
    + ) : ( +
    + +
    + )} +
    +
    + {anyMetadata ? ( + + ) : ( +

    No metadata on this call

    + )} +
    +
    + + + {totalPages > 0 && ( + + )} + + ); + } +} + +const statusCodeColor = (responseCode: number) => { + const code = responseCode.toString(); + return code.startsWith('1') || code.startsWith('2') || code.startsWith('3') ? 'green' : 'red'; +} \ No newline at end of file diff --git a/app/javascript/components/api/ApiToken.tsx b/app/javascript/components/api/ApiToken.tsx new file mode 100644 index 0000000..0810733 --- /dev/null +++ b/app/javascript/components/api/ApiToken.tsx @@ -0,0 +1,86 @@ +import React, { Component } from 'react' +import CopyToClipboard from 'react-copy-to-clipboard'; +import http from '../../lib/http' +import {apiV1RegenerateTokenPath} from '../../generated/routes' +import Button from '../shared/Button/Button' + +type Props = { + apiToken: string + regeneratePath: string +} + +type State = { + apiToken: string + copyButtonText: string +} + +export default class ApiToken extends Component { + state: State = { + apiToken: this.props.apiToken, + copyButtonText: 'Copy Token', + } + + regenerateApiToken = () => { + http('GET', apiV1RegenerateTokenPath()).then((resp: any) => { + this.setState({ + apiToken: resp["token"], + copyButtonText: 'Copy Token', + }) + }) + } + + onCopyClick = () => { + this.setState({ + copyButtonText: 'Copied!' + }); +} + + render() { + const { apiToken } = this.state + + return ( +
    +
    +

    Learn API

    +
    +

    Docs

    +

    + + API Documentation is auto-generated and contains samples that can be used for mocking tests. +

    +

    Token

    +

    + This token allows your app to authenticate requests to the Learn API. + Please don't share it with anyone, include it in any code repositories, or store it in an insecure way. + It will not expire unless you generate a new token. +

    +
    + + {apiToken !== "" && + +
    +
    +
    +
    + ) + } +} diff --git a/app/javascript/components/blocks/BlockPage-v2.tsx b/app/javascript/components/blocks/BlockPage-v2.tsx new file mode 100644 index 0000000..a8a749e --- /dev/null +++ b/app/javascript/components/blocks/BlockPage-v2.tsx @@ -0,0 +1,331 @@ +import * as React from 'react'; +import { debounce } from 'lodash'; +import * as Routes from '../../generated/routes' +import Avatar from '../UserAvatar'; +import UniversalList from '../shared/UniversalList/UniversalList'; +import UniversalRow from '../shared/UniversalRow/UniversalRow'; +import Button from '../shared/Button/Button'; +import UniversalTable from '../shared/UniversalTable/UniversalTable'; +import BlocksStats from './BlocksStats'; +import Icon from '../Icon'; +import Pill from '../shared/Pill/Pill'; +import ProcessingIcon from '../ProcessingIcon'; +import FlashAlert from '../shared/FlashAlert/FlashAlert'; +import http from '../../lib/http'; +import ErrorMessagesTable from '../shared/ErrorMessagesTable/ErrorMessagesTable'; +import BlocksNewRelease from './BlocksNewRelease'; + +const timezone = window.moment.tz.guess(); + +const ALERT_STATES = { + success: 'success', + queued: 'queued', + error: 'error' +} + +const pollingThrottleDelay = 2000; + +type Props = { + block: Api.BlockPresenter_ForBlocks, + releases: Api.BlockPresenter_ForReleases[], + github_url: string +} + +type State = { + alertState: string, + newReleaseModalVisible: boolean, + releases: Api.BlockPresenter_ForReleases[], + syncErrors: string[] +} + +class BlockPage extends React.Component { + releasePollingThrottled: any; + + constructor(props: Props) { + super(props) + + this.state = { + alertState: '', + newReleaseModalVisible: false, + releases: this.props.releases || [], + syncErrors: this.props.block.sync_errors || [] + } + + this.releasePollingThrottled = debounce(this.releasePolling.bind(this), pollingThrottleDelay); + } + + componentDidMount() { + if (this.state.releases[0] && this.state.releases[0].github_sha === 'pending') { + this.releasePollingThrottled(this.props.block.id); + } + } + + // TODO: call (debounced) after creating a new modal + releasePolling = () => { + http('GET', Routes.releasePollingBlockPath(this.props.block.id)) + .then((data: any) => { + if (data.block.sync_errors.length > 0) { + this.setState({ + releases: data.releases, + syncErrors: data.block.sync_errors, + alertState: ALERT_STATES.error + }); + } else if (data.releases[0] && data.releases[0].github_sha === 'pending') { + this.setState({ alertState: ALERT_STATES.queued }) + this.releasePollingThrottled(); + } else if (data.releases.length > 0) { + this.setState({ + releases: data.releases, + syncErrors: [], + alertState: ALERT_STATES.success + }); + } + }); + } + + generateAlert = (block: string) => ({ + success: { type: 'success', message: 'Release created.' }, + queued: { type: 'notice', message: 'Release creation queued.' }, + error: { type: 'error', message: <>{block}:{' Error. Unable to build release.'} }, + }) + + generateBody = () => { + const infoRow = this.generateInfoRow(); + const statsRow = this.generateStatsRow(); + const releasesRow = this.generateReleasesRow(); + const cohortsRow = this.generateCohortsRow(); + + return [infoRow, statsRow, releasesRow, cohortsRow] + } + + generateButtons = () => { + // TODO: implement other addt'l buttons + // TODO: implement modal work + const newReleaseBtn = ( + {this.renderResults()} -- GitLab From 81bc1da0f9fa97393679f0c8ec05a56e07d1a697 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Mon, 14 Sep 2020 17:29:26 -1000 Subject: [PATCH 032/283] Add alert styling to add users to cohorts form results --- app/javascript/components/cohorts/UsersNew.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/javascript/components/cohorts/UsersNew.tsx b/app/javascript/components/cohorts/UsersNew.tsx index c7af1b5..e80f1d8 100644 --- a/app/javascript/components/cohorts/UsersNew.tsx +++ b/app/javascript/components/cohorts/UsersNew.tsx @@ -32,12 +32,12 @@ export default class UsersNew extends Component { const body = { email: value }; const data = await http('POST', Routes.apiV1CohortUsersPath(this.props.cohortId), { body }); if (data.error) { - results.push(`${value} - ERROR: ${data.error}`); + results.push({ success: false, message: `${value} - ERROR: ${data.error}`}); } else { - results.push(`${value} - Added to cohort`); + results.push({ success: true, message: `${value} - Added to cohort`}); } } - this.setState({ results : results }); + this.setState({value: '', results : results }); } renderResults = () => { @@ -50,7 +50,7 @@ export default class UsersNew extends Component {
    Results
    { this.state.results.map(result => { return ( -

    {result}

    +
    {result.message}
    ) })} -- GitLab From 03391d452f780ead7e6c1e2ae3d3dedde92fef45 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 14 Sep 2020 17:38:24 -1000 Subject: [PATCH 033/283] removing error from message --- app/javascript/components/cohorts/UsersNew.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/javascript/components/cohorts/UsersNew.tsx b/app/javascript/components/cohorts/UsersNew.tsx index e80f1d8..ca91b95 100644 --- a/app/javascript/components/cohorts/UsersNew.tsx +++ b/app/javascript/components/cohorts/UsersNew.tsx @@ -32,12 +32,12 @@ export default class UsersNew extends Component { const body = { email: value }; const data = await http('POST', Routes.apiV1CohortUsersPath(this.props.cohortId), { body }); if (data.error) { - results.push({ success: false, message: `${value} - ERROR: ${data.error}`}); + results.push({ success: false, message: `${value} - ${data.error}`}); } else { - results.push({ success: true, message: `${value} - Added to cohort`}); + results.push({ success: true, message: `${value} - Added to cohort.`}); } } - this.setState({value: '', results : results }); + this.setState({ value: '', results: results }); } renderResults = () => { -- GitLab From 8e6eb2e06febaa2afb0bd7720ddb196727dd50cc Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 14 Sep 2020 17:41:48 -1000 Subject: [PATCH 034/283] fixing type error --- app/javascript/components/cohorts/UsersNew.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/javascript/components/cohorts/UsersNew.tsx b/app/javascript/components/cohorts/UsersNew.tsx index ca91b95..1447fda 100644 --- a/app/javascript/components/cohorts/UsersNew.tsx +++ b/app/javascript/components/cohorts/UsersNew.tsx @@ -2,12 +2,17 @@ import React, { Component } from 'react' import * as Routes from '../../generated/routes' import http from '../../lib/http' +interface ResultObj { + success: boolean, + message: string +} + type Props = { cohortId: number } type State = { value: string, - results: string[] + results: ResultObj[] } export default class UsersNew extends Component { @@ -26,7 +31,7 @@ export default class UsersNew extends Component { let values:string[] = this.state.value.split('\n').map(value => value.trim()); values = values.filter(value => value !== ''); - let results = []; + let results:ResultObj[] = []; for (let i = 0; i < values.length; i++) { let value = values[i]; const body = { email: value }; -- GitLab From 82b9d1e16cbd2f0c192f62a4bf0328d3a6fc8b88 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 14 Sep 2020 17:50:50 -1000 Subject: [PATCH 035/283] fixing type issues. fixing all warnings from IDE. --- app/javascript/components/cohorts/UsersNew.tsx | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/app/javascript/components/cohorts/UsersNew.tsx b/app/javascript/components/cohorts/UsersNew.tsx index 1447fda..ef41550 100644 --- a/app/javascript/components/cohorts/UsersNew.tsx +++ b/app/javascript/components/cohorts/UsersNew.tsx @@ -12,20 +12,21 @@ type Props = { } type State = { value: string, - results: ResultObj[] + results: ResultObj[], + textAreaDisplayRows: number } export default class UsersNew extends Component { - constructor(props) { + constructor(props: Props) { super(props); - this.state = { value: '', results: [] }; + this.state = { value: '', results: [], textAreaDisplayRows: 10 }; } - handleChange = event => { - this.setState({value: event.target.value}); + handleChange = (event:any) => { + this.setState({ value: event.target.value }); } - handleSubmit = async event => { + handleSubmit = async (event:any) => { event.preventDefault(); let values:string[] = this.state.value.split('\n').map(value => value.trim()); @@ -76,7 +77,7 @@ export default class UsersNew extends Component {

    - +
    -- GitLab From 83a0f5f227063f358dbae7bf126ed5d52b032468 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 15 Sep 2020 10:20:49 -1000 Subject: [PATCH 036/283] styling the new and edit cohort form. --- app/assets/stylesheets/cohorts.scss | 5 ++++ app/controllers/cohorts_controller.rb | 4 ++- app/views/cohorts/_cohort_edit_form.html.haml | 27 ++++++++++++------- app/views/cohorts/edit.html.haml | 4 ++- app/views/cohorts/new.html.haml | 4 ++- 5 files changed, 31 insertions(+), 13 deletions(-) diff --git a/app/assets/stylesheets/cohorts.scss b/app/assets/stylesheets/cohorts.scss index aaf876c..18fbca1 100644 --- a/app/assets/stylesheets/cohorts.scss +++ b/app/assets/stylesheets/cohorts.scss @@ -7,3 +7,8 @@ color: $color-lightened-black; } } + +.form-group.required .control-label:after { + content:"*"; + color:red; +} \ No newline at end of file diff --git a/app/controllers/cohorts_controller.rb b/app/controllers/cohorts_controller.rb index 4668e3e..ded9086 100644 --- a/app/controllers/cohorts_controller.rb +++ b/app/controllers/cohorts_controller.rb @@ -6,6 +6,7 @@ class CohortsController < ApplicationController @cohort = Cohort.new() @controller_action = 'create' + @button_text = 'Create Cohort' end def create @@ -28,6 +29,7 @@ class CohortsController < ApplicationController @cohort = current_cohort @controller_action = 'update_cohort' + @button_text = 'Update Cohort' end def update_cohort @@ -470,7 +472,7 @@ class CohortsController < ApplicationController # Cohort Create and Update Admin Views. def cohort_params - params.require(:cohort).permit(:name, :product_type, :starts_on) + params.require(:cohort).permit(:name, :product_type, :starts_on, :ends_on) end def update_cohort_params diff --git a/app/views/cohorts/_cohort_edit_form.html.haml b/app/views/cohorts/_cohort_edit_form.html.haml index aa09598..b96ee78 100644 --- a/app/views/cohorts/_cohort_edit_form.html.haml +++ b/app/views/cohorts/_cohort_edit_form.html.haml @@ -1,11 +1,18 @@ = form_for @cohort, :url => { :controller => 'cohorts', :action => @controller_action } do |f| - = f.label :name, "Name", :class => '' - = f.text_field :name - - = f.label :product_type, "Product Type", :class => '' - = f.text_field :product_type - - = f.label :starts_on, "Start Date", :class => '' - = f.date_field :starts_on - - = f.submit \ No newline at end of file + .form-group.required + .control-label + = f.label :name, "Name", required: true + = f.text_field :name + .form-group.required + .control-label + = f.label :product_type, "Product Type" + = f.text_field :product_type + .form-group.required + .control-label + = f.label :starts_on, "Start Date" + = f.date_field :starts_on + .form-group + = f.label :ends_on, "End Date" + %br + = f.date_field :ends_on + = f.submit @button_text, class: "btn btn-sm btn-primary" \ No newline at end of file diff --git a/app/views/cohorts/edit.html.haml b/app/views/cohorts/edit.html.haml index 1dfdac6..669f3ab 100644 --- a/app/views/cohorts/edit.html.haml +++ b/app/views/cohorts/edit.html.haml @@ -1 +1,3 @@ -= render 'cohort_edit_form' \ No newline at end of file +.with-margins + %h1 Update Cohort + = render 'cohort_edit_form' \ No newline at end of file diff --git a/app/views/cohorts/new.html.haml b/app/views/cohorts/new.html.haml index 1dfdac6..30b08aa 100644 --- a/app/views/cohorts/new.html.haml +++ b/app/views/cohorts/new.html.haml @@ -1 +1,3 @@ -= render 'cohort_edit_form' \ No newline at end of file +.with-margins + %h1 New Cohort + = render 'cohort_edit_form' \ No newline at end of file -- GitLab From c8d9997fba46a96cb74fa54862eec14dbd29b060 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 15 Sep 2020 11:29:40 -1000 Subject: [PATCH 037/283] removing unused property --- app/views/cohorts/_cohort_edit_form.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/cohorts/_cohort_edit_form.html.haml b/app/views/cohorts/_cohort_edit_form.html.haml index b96ee78..abbd806 100644 --- a/app/views/cohorts/_cohort_edit_form.html.haml +++ b/app/views/cohorts/_cohort_edit_form.html.haml @@ -1,7 +1,7 @@ = form_for @cohort, :url => { :controller => 'cohorts', :action => @controller_action } do |f| .form-group.required .control-label - = f.label :name, "Name", required: true + = f.label :name, "Name" = f.text_field :name .form-group.required .control-label -- GitLab From 91409b687a56f02b09e59e54e788561f50d01093 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Tue, 15 Sep 2020 12:48:56 -1000 Subject: [PATCH 038/283] Add ability to edit cohort users settings --- app/controllers/cohorts_controller.rb | 2 +- app/controllers/users_controller.rb | 27 ++++ .../components/cohorts/UsersNew.tsx | 138 +++++++++--------- .../cohorts/settings/UserCohortKebab.tsx | 73 +++++++++ app/policies/cohort_policy.rb | 4 + app/views/cohorts/_cohort_edit_form.html.haml | 6 +- app/views/cohorts/users.html.haml | 22 ++- app/views/users/edit.html.haml | 9 ++ config/routes.rb | 2 +- .../api/v1/cohorts/users_controller_spec.rb | 106 +++++++------- 10 files changed, 255 insertions(+), 134 deletions(-) create mode 100644 app/javascript/components/cohorts/settings/UserCohortKebab.tsx create mode 100644 app/views/users/edit.html.haml diff --git a/app/controllers/cohorts_controller.rb b/app/controllers/cohorts_controller.rb index ded9086..374df2b 100644 --- a/app/controllers/cohorts_controller.rb +++ b/app/controllers/cohorts_controller.rb @@ -472,7 +472,7 @@ class CohortsController < ApplicationController # Cohort Create and Update Admin Views. def cohort_params - params.require(:cohort).permit(:name, :product_type, :starts_on, :ends_on) + params.require(:cohort).permit(:name, :product_type, :campus_name, :starts_on, :ends_on) end def update_cohort_params diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 9ef84ba..53d6131 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -3,4 +3,31 @@ class UsersController < ApplicationController authorize(Cohort) @cohort_id = params[:cohort_id] end + + def edit + authorize(current_cohort) + current_cohort_user + end + + def update + authorize(current_cohort) + current_cohort_user.update(roles: [params[:instructor]].compact) + redirect_to users_cohort_path(current_cohort) + end + + def destroy + authorize(current_cohort) + current_cohort_user.destroy + redirect_to users_cohort_path(current_cohort) + end + + private + + def current_cohort + @current_cohort ||= Cohort.find(params[:cohort_id]) + end + + def current_cohort_user + @cohort_user ||= CohortUser.find_by(cohort_id: params[:cohort_id], user_id: params[:id]) + end end diff --git a/app/javascript/components/cohorts/UsersNew.tsx b/app/javascript/components/cohorts/UsersNew.tsx index ef41550..6cf86b2 100644 --- a/app/javascript/components/cohorts/UsersNew.tsx +++ b/app/javascript/components/cohorts/UsersNew.tsx @@ -1,89 +1,91 @@ -import React, { Component } from 'react' +import React, {Component} from 'react' import * as Routes from '../../generated/routes' import http from '../../lib/http' interface ResultObj { - success: boolean, - message: string + success: boolean, + message: string } type Props = { - cohortId: number + cohortId: number } type State = { - value: string, - results: ResultObj[], - textAreaDisplayRows: number + value: string, + results: ResultObj[], + textAreaDisplayRows: number } export default class UsersNew extends Component { - constructor(props: Props) { - super(props); - this.state = { value: '', results: [], textAreaDisplayRows: 10 }; - } + constructor(props: Props) { + super(props); + this.state = {value: '', results: [], textAreaDisplayRows: 10}; + } - handleChange = (event:any) => { - this.setState({ value: event.target.value }); - } + handleChange = (event: any) => { + this.setState({value: event.target.value}); + } - handleSubmit = async (event:any) => { - event.preventDefault(); + handleSubmit = async (event: any) => { + event.preventDefault(); - let values:string[] = this.state.value.split('\n').map(value => value.trim()); - values = values.filter(value => value !== ''); + let values: string[] = this.state.value.split('\n').map(value => value.trim()); + values = values.filter(value => value !== ''); - let results:ResultObj[] = []; - for (let i = 0; i < values.length; i++) { - let value = values[i]; - const body = { email: value }; - const data = await http('POST', Routes.apiV1CohortUsersPath(this.props.cohortId), { body }); - if (data.error) { - results.push({ success: false, message: `${value} - ${data.error}`}); - } else { - results.push({ success: true, message: `${value} - Added to cohort.`}); - } - } - this.setState({ value: '', results: results }); + let results: ResultObj[] = []; + for (let i = 0; i < values.length; i++) { + let value = values[i]; + const body = {email: value}; + const data = await http('POST', Routes.apiV1CohortUsersPath(this.props.cohortId), {body}); + if (data.error) { + results.push({success: false, message: `${value} - ${data.error}`}); + } else { + results.push({success: true, message: `${value} - Added to cohort.`}); + } } + this.setState({value: '', results: results}); + } - renderResults = () => { - if (!this.state.results.length) return null; - return ( -
    -
    -
    -
    -
    Results
    - { this.state.results.map(result => { - return ( -
    {result.message}
    - ) - })} -
    -
    -
    + renderResults = () => { + if (!this.state.results.length) return null; + return ( +
    +
    +
    +
    +
    Results
    + {this.state.results.map(result => { + return ( +
    {result.message}
    + ) + })}
    - ); - } +
    +
    +
    + ); + } - render() { - return ( -
    -

    Add Users to Cohort

    -
    -

    Enter email addresses of the users you wish to add to this cohort. - These users need to exist in KeyCloak in the proper realm. - You can enter multiple email addresses by separating them with new lines. -

    -
    - - -
    -
    - -
    - {this.renderResults()} -
    - ); - } + render() { + return ( +
    +

    Add Users to Cohort

    +
    +

    Enter email addresses of the users you wish to add to this cohort. + These users need to exist in KeyCloak in the proper realm. + You can enter multiple email addresses by separating them with new lines. +

    +
    + + +
    +
    + +
    + {this.renderResults()} +
    + ); + } } diff --git a/app/javascript/components/cohorts/settings/UserCohortKebab.tsx b/app/javascript/components/cohorts/settings/UserCohortKebab.tsx new file mode 100644 index 0000000..beb3fdc --- /dev/null +++ b/app/javascript/components/cohorts/settings/UserCohortKebab.tsx @@ -0,0 +1,73 @@ +import * as React from 'react' +import * as Routes from '../../../generated/routes' +import RowKebab from '../../RowKebab' + +type Props = { + studentId: number + studentUid: string + authUrl: string + cohortId: number +} + +type State = { + showActionMenu: boolean +} + +export default class UserKebab extends React.Component { + constructor(props: Props) { + super(props) + this.state = { + showActionMenu: false + } + } + + toggleActionMenu = () => { + this.setState({showActionMenu: !this.state.showActionMenu}); + } + + handleMenuOutsideClick = (e: any) => { + if ($_('#action-menu', el => el.contains(e.target))) { + return; + } + + this.toggleActionMenu(); + } + + addClickListeners(handler: any) { + document.addEventListener('touchmove', handler, false); + document.addEventListener('click', handler, false); + } + + removeClickListeners(handler: any) { + document.removeEventListener('touchmove', handler, false); + document.removeEventListener('click', handler, false); + } + + get actionMenu() { + if (this.state.showActionMenu) { + this.addClickListeners(this.handleMenuOutsideClick); + + return ( + + ); + } else { + this.removeClickListeners(this.handleMenuOutsideClick); + } + } + + render() { + return ( + <> + + {this.actionMenu} + + ) + } +} diff --git a/app/policies/cohort_policy.rb b/app/policies/cohort_policy.rb index 02fe526..bd9d955 100644 --- a/app/policies/cohort_policy.rb +++ b/app/policies/cohort_policy.rb @@ -16,6 +16,10 @@ class CohortPolicy < ApplicationPolicy user.instructor_or_admin?(record.id) end + def destroy? + user.instructor_or_admin?(record.id) + end + def update? user.instructor_or_admin?(record.id) end diff --git a/app/views/cohorts/_cohort_edit_form.html.haml b/app/views/cohorts/_cohort_edit_form.html.haml index b96ee78..9027241 100644 --- a/app/views/cohorts/_cohort_edit_form.html.haml +++ b/app/views/cohorts/_cohort_edit_form.html.haml @@ -7,6 +7,10 @@ .control-label = f.label :product_type, "Product Type" = f.text_field :product_type + .form-group + = f.label :campus_name, "Campus Name" + %br + = f.text_field :campus_name .form-group.required .control-label = f.label :starts_on, "Start Date" @@ -15,4 +19,4 @@ = f.label :ends_on, "End Date" %br = f.date_field :ends_on - = f.submit @button_text, class: "btn btn-sm btn-primary" \ No newline at end of file + = f.submit @button_text, class: "btn btn-sm btn-primary" diff --git a/app/views/cohorts/users.html.haml b/app/views/cohorts/users.html.haml index 4a1dc15..c3e505a 100644 --- a/app/views/cohorts/users.html.haml +++ b/app/views/cohorts/users.html.haml @@ -17,18 +17,13 @@ %div %p= link_to("Partnerup", partnerup_cohort_path(cohort), class: "") - if cohort.mode == "Percentage" - = react_component "cohorts/settings/UserImport", - cohortName: cohort.name, - importState: cohort.student_import_state, - importCompletedAt: cohort.student_import_completed_at, - userEmail: current_user.email, + = react_component "cohorts/settings/UserImport", + cohortName: cohort.name, + importState: cohort.student_import_state, + importCompletedAt: cohort.student_import_completed_at, + userEmail: current_user.email, importPath: import_users_work_cohort_path(cohort), importStatusPath: import_users_work_status_cohort_path(cohort) - .managebutton - - if current_user.role?(User::ROLES[:product_admin]) || current_user.product_admin_of?(cohort.id) - = link_to auth_product_url, class: "lp-style-button", target: "_blank" do - Manage Users in Auth - = react_component "SvgRenderer", viewBox: "-8 -8 10 24", style: {fill: "white"}, url: path_to_image("svg/svg-sprite-action-symbol.svg#ic_launch_24px") %table.cohortsetuptable %thead.cohortsetupheader %tr @@ -42,7 +37,10 @@ %td.cohortusername= instructor.full_name %td= instructor.github_username %td= instructor.email - %td yes + %td.action-cell + yes + %div.user-action + = react_component "cohorts/settings/UserCohortKebab", studentId: instructor.id, studentUid: instructor.uid, cohortId: cohort.id, authUrl: Rails.application.secrets.auth_url - cohort.students.order(first_name: :asc).each do |student| %tr.cohortsetuprow %td.cohortusername= student.full_name @@ -51,4 +49,4 @@ %td.action-cell no %div.user-action - = react_component "cohorts/settings/UserKebab", studentId: student.id, studentUid: student.uid, cohortId: cohort.id, authUrl: Rails.application.secrets.auth_url + = react_component "cohorts/settings/UserCohortKebab", studentId: student.id, studentUid: student.uid, cohortId: cohort.id, authUrl: Rails.application.secrets.auth_url diff --git a/app/views/users/edit.html.haml b/app/views/users/edit.html.haml new file mode 100644 index 0000000..1093e93 --- /dev/null +++ b/app/views/users/edit.html.haml @@ -0,0 +1,9 @@ +.container + = @cohort_user.user.full_name + = @cohort_user.cohort.name + = form_for @cohort_user, :url => { :controller => 'users', :action => :update } do |f| + .form-group + = label :instructor, "Instructor" + = check_box_tag :instructor, "forge.instructor", @cohort_user.roles.include?("forge.instructor") + = f.submit "Update Cohort User Settings", class: "btn btn-sm btn-primary" + = link_to "Delete", cohort_user_path(@cohort_user.cohort_id, @cohort_user.user_id), method: :delete, data: { confirm: "Really?" } diff --git a/config/routes.rb b/config/routes.rb index e575ff9..60296a1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -57,7 +57,7 @@ Rails.application.routes.draw do get "/blocks-v2/:id" => "blocks#blockpagev2", as: "blockpage", format: false resources :cohorts, only: %i[new create index edit show update] do - resources :users, only: %i[new] + resources :users, only: %i[new edit update destroy] get "standards_for_section/:section_id" => :standards_for_section, as: "standards_for_section" member do diff --git a/spec/controllers/api/v1/cohorts/users_controller_spec.rb b/spec/controllers/api/v1/cohorts/users_controller_spec.rb index 40f2d52..44611c0 100644 --- a/spec/controllers/api/v1/cohorts/users_controller_spec.rb +++ b/spec/controllers/api/v1/cohorts/users_controller_spec.rb @@ -80,96 +80,100 @@ resource "Enrollments" do Invite new users or enroll existing users to a cohort. A user is invited only if they do not exist. Enrolling a user who is already enrolled changes nothing about their enrollment- their roles will not be modified to match the body parameters, and instead must be changed via a PATCH. MARKDOWN header "Authorization", "Bearer #{user.api_token}" - dbl = double(Keycloak::Internal) - #expect(KeycloakResolverService).to receive(:find_or_create_user) - - # expect(dbl).to receive(:get_user_info).with( - # email, - # false, - # Rails.application.secrets.keycloak_client_id, - # Rails.application.secrets.keycloak_client_secret - # ).and_return([{ id: "4b58555dbbc93c9016f7325ead84667d", - # firstName: first_name, - # lastName: last_name, - # email: email - # }]) - - # allow_any_instance_of(Keycloak::Internal).to receive(:get_user_info).and_return( - allow(Keycloak::Internal).to receive(:get_user_info).and_return( - [{ id: "4b58555dbbc93c9016f7325ead84667d", - firstName: first_name, - lastName: last_name, - email: email - }] - ) - # allow(Keycloak::Internal).to receive(:new).and_return(dbl) + # Using double for Keyclaok::Internal does not seem to work + # dbl = double(Keycloak::Internal) + + expect(Keycloak::Internal).to receive(:get_user_info).with( + email, + true, + Rails.application.secrets.keycloak_client_id, + Rails.application.secrets.keycloak_client_secret + ).and_return(OpenStruct.new({ id: "4b58555dbbc93c9016f7325ead84667d", + firstName: first_name, + lastName: last_name, + email: email + })) + expect { do_request }.to have_enqueued_job(CreateApiInteractionJob) - puts "RESPONSE_JSON = #{response_json}" + new_user = User.find_by(email: email) + expect(new_user.first_name).to eq(first_name) + expect(new_user.last_name).to eq(last_name) + expect(new_user.email).to eq(email) + expect(status).to eq 200 expect(response_json["status"]).to eq("ok") - expect(response_json["uid"]).to eq("4b58555dbbc93c9016f7325ead84667d") end it "finds the user by email in the system" do - existing_user = create(:user, email: email) + existing_user = create(:user, email: email, first_name: first_name, last_name: last_name) header "Authorization", "Bearer #{user.api_token}" - expect(KeycloakResolverService).to receive(:find_or_create_user) - dbl = double(AuthApi::Client) - expect(dbl).to receive(:update_user).with( - { - id: existing_user.uid, - user: { - registrations: [{ - product_uid: cohort.uid, - roles: [ - "instructor", - "auth.product_admin" - ] - }] - } - } - ).and_return(OpenStruct.new({uid: "abc123"})) - allow(AuthApi::Client).to receive(:new).and_return(dbl) + + allow(Keycloak::Internal).to receive(:get_user_info).and_return(OpenStruct.new({ id: "test", + firstName: first_name, + lastName: last_name, + email: email + })) + expect { do_request }.to have_enqueued_job(CreateApiInteractionJob) + expect(existing_user.first_name).to eq(first_name) + expect(existing_user.last_name).to eq(last_name) + expect(existing_user.email).to eq(email) + expect(status).to eq 200 expect(response_json["status"]).to eq("ok") end - it "does not make a request to auth if the user exists and is enrolled" do + it "makes a request to KeyCloak even if the user exists and is enrolled" do header "Authorization", "Bearer #{user.api_token}" - existing_user = create(:user, email: email) + existing_user = create(:user, email: email, first_name: first_name, last_name: last_name) create(:cohort_user, user: existing_user, cohort: cohort) + expect(Keycloak::Internal).to receive(:get_user_info).with( + email, + true, + Rails.application.secrets.keycloak_client_id, + Rails.application.secrets.keycloak_client_secret + ).and_return(OpenStruct.new({ id: "test", + firstName: first_name, + lastName: last_name, + email: email + })) + expect { do_request }.to have_enqueued_job(CreateApiInteractionJob) + expect(existing_user.first_name).to eq(first_name) + expect(existing_user.last_name).to eq(last_name) + expect(existing_user.email).to eq(email) + expect(status).to eq 200 - expect(response_json["status"]).to eq("already-exists") + expect(response_json["status"]).to eq("ok") end - it "responds with a 400 when the auth API request fails" do + it "responds with a 400 when the KeyCloak request fails" do header "Authorization", "Bearer #{user.api_token}" - dbl = double(AuthApi::Client) - expect(dbl).to receive(:invite_user).and_raise(AuthApi::RequestFailed) - allow(AuthApi::Client).to receive(:new).and_return(dbl) + + expect(Keycloak::Internal).to receive(:get_user_info).and_raise(Keycloak::UserLoginNotFound) + expect { do_request }.to have_enqueued_job(CreateApiInteractionJob) + puts "RESPONSE_JSON = " + response_json.to_s expect(status).to eq 400 - expect(response_json["error"]).to eq("AuthApi::RequestFailed") + expect(response_json["error"]).to eq("User does not exist in KeyCloak.") end context "malformed body" do -- GitLab From a2111970853e3a165e442f18e86b5526d3b93b64 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 15 Sep 2020 13:31:33 -1000 Subject: [PATCH 039/283] styling the cohort edit forms --- app/views/cohorts/_cohort_edit_form.html.haml | 12 ++++++------ app/views/cohorts/edit.html.haml | 2 +- app/views/cohorts/new.html.haml | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/views/cohorts/_cohort_edit_form.html.haml b/app/views/cohorts/_cohort_edit_form.html.haml index 9c48666..87a34c2 100644 --- a/app/views/cohorts/_cohort_edit_form.html.haml +++ b/app/views/cohorts/_cohort_edit_form.html.haml @@ -2,21 +2,21 @@ .form-group.required .control-label = f.label :name, "Name" - = f.text_field :name + = f.text_field :name, class: "form-control" .form-group.required .control-label = f.label :product_type, "Product Type" - = f.text_field :product_type + = f.text_field :product_type, class: "form-control" .form-group = f.label :campus_name, "Campus Name" %br - = f.text_field :campus_name + = f.text_field :campus_name, class: "form-control" .form-group.required .control-label = f.label :starts_on, "Start Date" - = f.date_field :starts_on + = f.date_field :starts_on, class: "form-control" .form-group = f.label :ends_on, "End Date" %br - = f.date_field :ends_on - = f.submit @button_text, class: "btn btn-sm btn-primary" + = f.date_field :ends_on, class: "form-control" + = f.submit @button_text, class: "btn btn-primary" diff --git a/app/views/cohorts/edit.html.haml b/app/views/cohorts/edit.html.haml index 669f3ab..f2c0744 100644 --- a/app/views/cohorts/edit.html.haml +++ b/app/views/cohorts/edit.html.haml @@ -1,3 +1,3 @@ -.with-margins +.container %h1 Update Cohort = render 'cohort_edit_form' \ No newline at end of file diff --git a/app/views/cohorts/new.html.haml b/app/views/cohorts/new.html.haml index 30b08aa..1a3ad0f 100644 --- a/app/views/cohorts/new.html.haml +++ b/app/views/cohorts/new.html.haml @@ -1,3 +1,3 @@ -.with-margins +.container %h1 New Cohort = render 'cohort_edit_form' \ No newline at end of file -- GitLab From 5e2190c53825049860c64ecb0777e83196c2e371 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 15 Sep 2020 17:29:21 -1000 Subject: [PATCH 040/283] styling the cohort user edit screen --- app/views/users/edit.html.haml | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/app/views/users/edit.html.haml b/app/views/users/edit.html.haml index 1093e93..30c53cf 100644 --- a/app/views/users/edit.html.haml +++ b/app/views/users/edit.html.haml @@ -1,9 +1,20 @@ .container - = @cohort_user.user.full_name - = @cohort_user.cohort.name + %h1 Update Cohort User +%br +.container = form_for @cohort_user, :url => { :controller => 'users', :action => :update } do |f| + %h5 Basic Info: + .form-group + = label :cohort_name, :title, "Cohort Name" + = text_field_tag :cohort_name, @cohort_user.cohort.name, class: "form-control", readonly: true + .form-group + = label :user_name, :title, "Full Name" + = text_field_tag :user_name, @cohort_user.user.full_name, class: "form-control", readonly: true + %h5 Roles: .form-group - = label :instructor, "Instructor" - = check_box_tag :instructor, "forge.instructor", @cohort_user.roles.include?("forge.instructor") - = f.submit "Update Cohort User Settings", class: "btn btn-sm btn-primary" - = link_to "Delete", cohort_user_path(@cohort_user.cohort_id, @cohort_user.user_id), method: :delete, data: { confirm: "Really?" } + .form-check + = check_box_tag :instructor, "forge.instructor", @cohort_user.roles.include?("forge.instructor"), class: "form-check-input" + = label :instructor, "Instructor" + = f.submit "Update Cohort User", class: "btn btn-primary" + %br + = link_to "Remove User From Cohort", cohort_user_path(@cohort_user.cohort_id, @cohort_user.user_id), method: :delete, data: { confirm: "Really?" }, class: "btn btn-danger" -- GitLab From c0dd7120ef697df2bcc1796cf939c512cc54fc12 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 15 Sep 2020 17:48:10 -1000 Subject: [PATCH 041/283] fixing links --- app/controllers/cohorts_controller.rb | 2 +- app/javascript/components/cohorts/settings/CohortInfo.tsx | 3 +-- app/views/cohorts/setup.html.haml | 2 +- app/views/cohorts/users.html.haml | 5 +++++ 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/controllers/cohorts_controller.rb b/app/controllers/cohorts_controller.rb index 374df2b..159fdd6 100644 --- a/app/controllers/cohorts_controller.rb +++ b/app/controllers/cohorts_controller.rb @@ -38,7 +38,7 @@ class CohortsController < ApplicationController @cohort = current_cohort if @cohort.update(cohort_params) - redirect_to cohort_path + redirect_to setup_cohort_path(@cohort) else flash[:error] = @cohort.errors.full_messages.join(", ") render :edit diff --git a/app/javascript/components/cohorts/settings/CohortInfo.tsx b/app/javascript/components/cohorts/settings/CohortInfo.tsx index 1bedfc5..03dcabf 100644 --- a/app/javascript/components/cohorts/settings/CohortInfo.tsx +++ b/app/javascript/components/cohorts/settings/CohortInfo.tsx @@ -28,9 +28,8 @@ export default class CohortInfo extends React.Component {

    {cohortStartDateFormatted}

    { editUrl && !sandboxCohort && - + Edit - } diff --git a/app/views/cohorts/setup.html.haml b/app/views/cohorts/setup.html.haml index d528196..0ae17ab 100644 --- a/app/views/cohorts/setup.html.haml +++ b/app/views/cohorts/setup.html.haml @@ -1,7 +1,7 @@ = react_component "cohorts/settings/CohortInfo", cohort: cohort, cohortStartDateFormatted: cohort.starts_on.strftime("%b %e, %Y"), - editUrl: current_user.role?(User::ROLES[:product_admin]) || current_user.product_admin_of?(cohort.id) ? edit_cohort_path : nil, + editUrl: current_user.role?(User::ROLES[:product_admin]) || current_user.product_admin_of?(cohort.id) ? edit_cohort_path(cohort.id) : nil, targetBlankIconSrc: path_to_image("svg/svg-sprite-action-symbol.svg#ic_launch_24px") = react_component "cohorts/settings/CohortSettingsTabs", diff --git a/app/views/cohorts/users.html.haml b/app/views/cohorts/users.html.haml index c3e505a..9d63cf7 100644 --- a/app/views/cohorts/users.html.haml +++ b/app/views/cohorts/users.html.haml @@ -24,6 +24,11 @@ userEmail: current_user.email, importPath: import_users_work_cohort_path(cohort), importStatusPath: import_users_work_status_cohort_path(cohort) + .managebutton + - if current_user.role?(User::ROLES[:product_admin]) || current_user.product_admin_of?(cohort.id) + = link_to new_cohort_user_path(cohort.id), class: "lp-style-button", target: "_blank" do + Add Users + = react_component "SvgRenderer", viewBox: "-8 -8 10 24", style: {fill: "white"}, url: path_to_image("svg/svg-sprite-action-symbol.svg#ic_launch_24px") %table.cohortsetuptable %thead.cohortsetupheader %tr -- GitLab From 0de0f7ecd0529a0785143b566003d2275a1795ff Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 15 Sep 2020 17:50:19 -1000 Subject: [PATCH 042/283] removing manager users in auth button from partnerup tab --- app/views/cohorts/partnerup.html.haml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/views/cohorts/partnerup.html.haml b/app/views/cohorts/partnerup.html.haml index 1986a41..f692e28 100644 --- a/app/views/cohorts/partnerup.html.haml +++ b/app/views/cohorts/partnerup.html.haml @@ -15,11 +15,6 @@ %p= link_to("Users (#{cohort.cohort_users.length})", users_cohort_path(cohort), class: "") .selected %p= link_to("Partnerup", partnerup_cohort_path(cohort), class: "") - .managebutton - - if current_user.role?(User::ROLES[:product_admin]) || current_user.product_admin_of?(cohort.id) - = link_to auth_product_url, class: "lp-style-button", target: "_blank" do - Manage Users in Auth - = react_component "SvgRenderer", viewBox: "-8 -8 10 24", style: {fill: "white"}, url: path_to_image("svg/svg-sprite-action-symbol.svg#ic_launch_24px") = react_component "cohorts/pairing/GroupPairs", cohort_id: cohort.id, -- GitLab From 1486a3c02e9fb3b5677e708a4e2814dc11169705 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Tue, 15 Sep 2020 18:22:32 -1000 Subject: [PATCH 043/283] Some changes to regression testing --- .../api/v1/cohorts/cohorts_controller_spec.rb | 93 +++++------ .../api/v1/cohorts/users_controller_spec.rb | 121 +------------- spec/controllers/users_controller_spec.rb | 150 ++++++++++++++++++ .../keycloak_resolver_service_spec.rb | 43 ++--- 4 files changed, 210 insertions(+), 197 deletions(-) create mode 100644 spec/controllers/users_controller_spec.rb diff --git a/spec/controllers/api/v1/cohorts/cohorts_controller_spec.rb b/spec/controllers/api/v1/cohorts/cohorts_controller_spec.rb index b0454cc..8671ef4 100644 --- a/spec/controllers/api/v1/cohorts/cohorts_controller_spec.rb +++ b/spec/controllers/api/v1/cohorts/cohorts_controller_spec.rb @@ -9,7 +9,7 @@ resource "Cohorts" do header "Accept", "application/json" describe "a admin can create a cohort" do - parameter :name, "[Body Parameter]\nThe name of the Cohort.", required: true, example: "Web Development with scripting language ArnoldC" + parameter :name, "[Body Parameter]\nThe name of the Cohort.", required: true, example: "Web Development with scripting language ArnoldC" parameter :product_type, "[Body Parameter]\nThe type or structure of the cohort.", required: true, example: "Workshop" parameter :label, "[Body Parameter]\nThe label of this cohort.", required: false, example: "17-01-WD-GT" parameter :campus_name, "[Body Parameter]\nThe campus of this cohort.", required: false, example: "Seattle-Pioneer Square" @@ -24,39 +24,40 @@ resource "Cohorts" do let(:opt_out_for_marketing) { true } let(:starts_on) { "2020-10-10" } let(:ends_on) { "2021-01-10" } - + post "/api/v1/cohorts" do example "Creating a new cohort" do explanation <<-MARKDOWN.strip_heredoc Allow users to easily create a cohort. MARKDOWN header "Authorization", "Bearer #{user.api_token}" - dbl = double(AuthApi::Client) - expect(AuthResolverService).to receive(:resolve) - expect(SecureRandom).to receive(:hex).and_return("4b58555dbbc93c9016") - expect(dbl).to receive(:create_product).with( - { - product: { - uid: "4b58555dbbc93c9016", - name: name, - product_type: product_type, - label: label, - campus_name: campus_name, - opt_out_for_marketing: true, - starts_on: starts_on, - ends_on: ends_on - } - } - ).and_return(OpenStruct.new({uid: "4b58555dbbc93c9016"})) - - allow(AuthApi::Client).to receive(:new).and_return(dbl) + # Commented out since AuthApi has been removed + # dbl = double(AuthApi::Client) + # expect(AuthResolverService).to receive(:resolve) + # expect(SecureRandom).to receive(:hex).and_return("4b58555dbbc93c9016") + # expect(dbl).to receive(:create_product).with( + # { + # product: { + # uid: "4b58555dbbc93c9016", + # name: name, + # product_type: product_type, + # label: label, + # campus_name: campus_name, + # opt_out_for_marketing: true, + # starts_on: starts_on, + # ends_on: ends_on + # } + # } + # ).and_return(OpenStruct.new({uid: "4b58555dbbc93c9016"})) + # + # allow(AuthApi::Client).to receive(:new).and_return(dbl) expect { do_request }.to have_enqueued_job(CreateApiInteractionJob) expect(status).to eq 200 - expect(response_json["uid"]).to eq("4b58555dbbc93c9016") - + #expect(response_json["uid"]).to eq("4b58555dbbc93c9016") + end context "when cohorts aren't created" do let(:name) { "" } @@ -65,42 +66,44 @@ resource "Cohorts" do let(:opt_out_for_marketing) {"hampster"} example "required params are missing", document:false do explanation <<-MARKDOWN.strip_heredoc - Responds with a 400 when Required Params: name, product_type, or starts_on are missing. opt_out_for_marketing must be true or false. + Responds with a 400 when Required Params: name, product_type, or starts_on are missing. opt_out_for_marketing must be true or false. MARKDOWN header "Authorization", "Bearer #{user.api_token}" expect { do_request }.to have_enqueued_job(CreateApiInteractionJob) - expect(status).to eq 400 + expect(status).to eq 400 expect(response_json["error"]).to eq("Validation Error: name can't be blank, starts_on can't be blank, product_type can't be blank, opt_out_for_marketing must be true or false") - end - end - context "responds with a 400 when auth API request fails" do - example "auth API fails", document:false do - explanation <<-MARKDOWN.strip_heredoc - Responds with a 400 when auth API request fails. - MARKDOWN - header "Authorization", "Bearer #{user.api_token}" - dbl = double(AuthApi::Client) - expect(dbl).to receive(:create_product).and_raise(AuthApi::RequestFailed, "{}") - allow(AuthApi::Client).to receive(:new).and_return(dbl) - expect { + end + end + context "responds with a 401 when for unauthorized call" do + example "auth API fails", document:false do + explanation <<-MARKDOWN.strip_heredoc + Responds with a 400 when auth API request fails. + MARKDOWN + header "Authorization", "Bearer 'wrong'" + # Commented out since AuthApi has been removed + # dbl = double(AuthApi::Client) + # expect(dbl).to receive(:create_product).and_raise(AuthApi::RequestFailed, "{}") + # allow(AuthApi::Client).to receive(:new).and_return(dbl) + # expect { do_request - }.to have_enqueued_job(CreateApiInteractionJob) + # }.to have_enqueued_job(CreateApiInteractionJob) + + puts "RESPONSE_JSON = " + response_json.to_s + expect(status).to eq 401 - expect(status).to eq 400 - - expect(response_json["error"]).to eq({}) - end - end + expect(response_json["errors"]["code"]).to eq("unauthorized") + end + end end end end context "when an admin" do ActiveJob::Base.queue_adapter = :test - + let(:user) { create(:user, :admin, api_token: "token") } let!(:cohort) { create(:cohort) } let!(:release) { create(:release, branch_name: "master") } @@ -111,7 +114,7 @@ resource "Cohorts" do let!(:hidden_content_file) { create(:content_file, uid: "bcd456", title: "Java Mocking Exit Ticket", position: 2, content_file_type: "lesson", standard: standard, path: "03-exit-ticket.md") } let!(:content_visibility) { create(:content_visibility, content_uid: "bcd456", content_type: "ContentFile", visibility_type: "hidden", cohort_id: cohort.id) } let!(:resync_job_result) { create(:resync_job_result, edges: { cohort_id: cohort.id }, data: { course_config_url: 'https://github.com/gSchool/learn-course-files/blob/master/test/test.yaml' }) } - + header "Content-Type", "application/json" header "Accept", "application/json" diff --git a/spec/controllers/api/v1/cohorts/users_controller_spec.rb b/spec/controllers/api/v1/cohorts/users_controller_spec.rb index 44611c0..456be4a 100644 --- a/spec/controllers/api/v1/cohorts/users_controller_spec.rb +++ b/spec/controllers/api/v1/cohorts/users_controller_spec.rb @@ -170,7 +170,6 @@ resource "Enrollments" do do_request }.to have_enqueued_job(CreateApiInteractionJob) - puts "RESPONSE_JSON = " + response_json.to_s expect(status).to eq 400 expect(response_json["error"]).to eq("User does not exist in KeyCloak.") @@ -188,128 +187,10 @@ resource "Enrollments" do }.to have_enqueued_job(CreateApiInteractionJob) expect(status).to eq 400 - expect(response_json["error"]).to eq("Validation Error: first_name can't be blank, last_name can't be blank, email can't be blank") + expect(response_json["error"]).to eq("Validation Error: email can't be blank") end end end end - - describe "Updating an enrollment" do - - parameter ":cohort_id", "[Path Parameter]\nThe ID of the cohort. Matches the ID from the URL when viewing any cohort in Learn", required: true, example: "1500" - parameter ":id", "[Path Parameter]\nThe ID of the user.", required: true, example: "456" - parameter :instructor, "[Body Parameter]\nThe boolean that sets the forge.instructor role for enrollment.", required: true, example: "true = has instructor role\nfalse = has student role" - parameter :onboard, "[Body Parameter]\nThe boolean that sets the auth.product_admin role for enrollment.", required: true, example: "true = user can enroll others in the cohort\nfalse = no onboarding ability" - - let(:cohort_id) { cohort.id } - let(:id) { enrolled_student.id } - let(:instructor) { true } - let(:onboard) { true } - - patch "/api/v1/cohorts/:cohort_id/users/:id" do - example "Updating a user's enrollment roles" do - explanation <<-MARKDOWN.strip_heredoc - Update the roles for the user enrolled in the specified cohort. Can modify the forge.instructor and auth.product_admin roles for that enrollment only. The user will have only the roles specified after the action is taken. - MARKDOWN - header "Authorization", "Bearer #{user.api_token}" - dbl = double(AuthApi::Client) - expect(dbl).to receive(:update_user).with( - { - id: enrolled_student.uid, - user: { - registrations: [{ - product_uid: cohort.uid, - roles: [ - "instructor", - "auth.product_admin" - ] - }] - } - } - ) - allow(AuthApi::Client).to receive(:new).and_return(dbl) - expect { - do_request - }.to have_enqueued_job(CreateApiInteractionJob) - - expect(status).to eq 200 - expect(response_json["status"]).to eq("ok") - end - - it "returns 404 status if there is no enrollment for that cohort and user" do - header "Authorization", "Bearer #{user.api_token}" - dbl = double(AuthApi::Client) - CohortUser.destroy_all - expect(dbl).to_not receive(:update_user).with( - { - id: enrolled_student.uid, - user: { - registrations: [{ - product_uid: cohort.uid, - roles: [] - }] - } - } - ) - allow(AuthApi::Client).to receive(:new).and_return(dbl) - expect { - do_request - }.to have_enqueued_job(CreateApiInteractionJob) - expect(status).to eq 404 - expect(response_json["status"]).to eq("404") - end - - it "responds with a 400 when the auth API request fails" do - header "Authorization", "Bearer #{user.api_token}" - dbl = double(AuthApi::Client) - expect(dbl).to receive(:update_user).and_raise(AuthApi::RequestFailed) - allow(AuthApi::Client).to receive(:new).and_return(dbl) - expect { - do_request - }.to have_enqueued_job(CreateApiInteractionJob) - - expect(status).to eq 400 - - expect(response_json["error"]).to eq("AuthApi::RequestFailed") - end - end - end - - describe "Deleting an enrollment" do - - parameter ":cohort_id", "[Path Parameter]\nThe ID of the cohort. Matches the ID from the URL when viewing any cohort in Learn", required: true, example: "1500" - parameter ":id", "[Path Parameter]\nThe ID of the user.", required: true, example: "456" - - let(:cohort_id) { cohort.id } - let(:id) { enrolled_student.uid } - - delete "/api/v1/cohorts/:cohort_id/users/:id" do - example "Unenrolling a user from a cohort" do - explanation <<-MARKDOWN.strip_heredoc - Delete the enrollment for a specified cohort and user. - MARKDOWN - header "Authorization", "Bearer #{user.api_token}" - dbl = double(AuthApi::Client) - expect(dbl).to receive(:update_user).with( - { - id: enrolled_student.uid, - user: { - registrations: [{ - product_uid: cohort.uid, - _destroy: true - }] - } - } - ) - allow(AuthApi::Client).to receive(:new).and_return(dbl) - expect { - do_request - }.to have_enqueued_job(CreateApiInteractionJob) - - expect(status).to eq 200 - expect(response_json["status"]).to eq("ok") - end - end - end end end diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb new file mode 100644 index 0000000..c7bf525 --- /dev/null +++ b/spec/controllers/users_controller_spec.rb @@ -0,0 +1,150 @@ +require "integration_helper" + +describe UsersController do + + let(:user) { create(:user, :admin, api_token: "token") } + let(:student_to_enroll) { create(:user) } + let!(:cohort) { create(:cohort) } + let!(:enrolled_student) { create(:user, first_name: "Eric", last_name: "Ericson", email: "eric@example.com") } + let!(:cohort_user) { create(:cohort_user, created_at: 3.days.ago, cohort: cohort, user: enrolled_student) } + + describe "GET #new" do + context "create a new user" do + # get "/cohorts/:cohort_id/users/:id" do + # + # end + end + end + + describe "Updating an enrollment" do + + # parameter ":cohort_id", "[Path Parameter]\nThe ID of the cohort. Matches the ID from the URL when viewing any cohort in Learn", required: true, example: "1500" + # parameter ":id", "[Path Parameter]\nThe ID of the user.", required: true, example: "456" + # parameter :instructor, "[Body Parameter]\nThe boolean that sets the forge.instructor role for enrollment.", required: true, example: "true = has instructor role\nfalse = has student role" + # parameter :onboard, "[Body Parameter]\nThe boolean that sets the auth.product_admin role for enrollment.", required: true, example: "true = user can enroll others in the cohort\nfalse = no onboarding ability" + # + # let(:cohort_id) { cohort.id } + # let(:id) { enrolled_student.id } + # let(:instructor) { true } + # let(:onboard) { true } + # + # patch "/cohorts/:cohort_id/users/:id" do + # example "Updating a user's enrollment roles" do + # explanation <<-MARKDOWN.strip_heredoc + # Update the roles for the user enrolled in the specified cohort. Can modify the forge.instructor and auth.product_admin roles for that enrollment only. The user will have only the roles specified after the action is taken. + # MARKDOWN + # header "Authorization", "Bearer #{user.api_token}" + # + # expect(Keycloak::Internal).to receive(:get_user_info).with( + # email, + # true, + # Rails.application.secrets.keycloak_client_id, + # Rails.application.secrets.keycloak_client_secret + # ).and_return(OpenStruct.new({ id: "test", + # firstName: first_name, + # lastName: last_name, + # email: email, + # roles: [ + # "forge.instructor" + # ] + # })) + # + # # dbl = double(AuthApi::Client) + # # expect(dbl).to receive(:update_user).with( + # # { + # # id: enrolled_student.uid, + # # user: { + # # registrations: [{ + # # product_uid: cohort.uid, + # # }] + # # } + # # } + # # ) + # # allow(AuthApi::Client).to receive(:new).and_return(dbl) + # + # expect { + # do_request + # }.to have_enqueued_job(CreateApiInteractionJob) + # + # puts "RESPONSE_JSON = " + response_json.to_s + # expect(status).to eq 200 + # expect(response_json["status"]).to eq("ok") + # end + # + # it "returns 404 status if there is no enrollment for that cohort and user" do + # header "Authorization", "Bearer #{user.api_token}" + # dbl = double(AuthApi::Client) + # CohortUser.destroy_all + # expect(dbl).to_not receive(:update_user).with( + # { + # id: enrolled_student.uid, + # user: { + # registrations: [{ + # product_uid: cohort.uid, + # roles: [] + # }] + # } + # } + # ) + # allow(AuthApi::Client).to receive(:new).and_return(dbl) + # expect { + # do_request + # }.to have_enqueued_job(CreateApiInteractionJob) + # expect(status).to eq 404 + # expect(response_json["status"]).to eq("404") + # end + # + # it "responds with a 400 when the auth API request fails" do + # header "Authorization", "Bearer #{user.api_token}" + # dbl = double(AuthApi::Client) + # expect(dbl).to receive(:update_user).and_raise(AuthApi::RequestFailed) + # allow(AuthApi::Client).to receive(:new).and_return(dbl) + # expect { + # do_request + # }.to have_enqueued_job(CreateApiInteractionJob) + # + # expect(status).to eq 400 + # + # expect(response_json["error"]).to eq("AuthApi::RequestFailed") + # end + # end + end + + describe "Deleting an enrollment" do + + # parameter ":cohort_id", "[Path Parameter]\nThe ID of the cohort. Matches the ID from the URL when viewing any cohort in Learn", required: true, example: "1500" + # parameter ":id", "[Path Parameter]\nThe ID of the user.", required: true, example: "456" + # + # let(:cohort_id) { cohort.id } + # let(:id) { enrolled_student.uid } + # + # delete "/cohorts/:cohort_id/users/:id" do + # example "Unenrolling a user from a cohort" do + # explanation <<-MARKDOWN.strip_heredoc + # Delete the enrollment for a specified cohort and user. + # MARKDOWN + # header "Authorization", "Bearer #{user.api_token}" + # dbl = double(AuthApi::Client) + # expect(dbl).to receive(:update_user).with( + # { + # id: enrolled_student.uid, + # user: { + # registrations: [{ + # product_uid: cohort.uid, + # _destroy: true + # }] + # } + # } + # ) + # allow(AuthApi::Client).to receive(:new).and_return(dbl) + # expect { + # do_request + # }.to have_enqueued_job(CreateApiInteractionJob) + # + # expect(status).to eq 200 + # expect(response_json["status"]).to eq("ok") + # end + # end + end + +end diff --git a/spec/services/keycloak_resolver_service_spec.rb b/spec/services/keycloak_resolver_service_spec.rb index 58ad92a..9407824 100644 --- a/spec/services/keycloak_resolver_service_spec.rb +++ b/spec/services/keycloak_resolver_service_spec.rb @@ -87,46 +87,25 @@ describe KeycloakResolverService do expect(auth_user.roles).to eq [] end - it "allows users with the admin role, saving other roles" do + it "creates a unique user with the admin role, saving other roles" do auth_user.roles = [User::ROLES[:admin], "futzy.butzy"] user = nil expect { user = subject.find_or_create_user }.to change { User.count }.by(1) expect(user.admin?).to be true expect(user.first_name).to eq "Inigo" + expect(user.last_name).to eq "Montoya" expect(user.roles).to eq([User::ROLES[:admin], "futzy.butzy"]) - end - - context "when a user has a course product in auth" do - context "when the user does not have a role for the product" do - xit "creates the user with an enrollment cohort_user" do - user = nil - expect { user = subject.resolve_user(auth_user) }.to change { User.count }.by(1) - expect(user.cohorts.length).to eq 1 - expect(user.cohorts.first.uid).to eq "abc123" - expect(user.cohort_users.first.roles).to eq([]) - end - end - context "when the user has an instructor role for the product in auth" do - before { auth_user.registrations.first.roles << CohortUser::ROLES[:instructor] } - - xit "creates the user with an instructor cohort_user" do - user = nil - expect { user = subject.resolve_user(auth_user) }.to change { User.count }.by(1) - expect(user.cohorts.length).to eq 1 - expect(user.cohorts.first.uid).to eq "abc123" - expect(user.cohort_users.first.roles).to eq([CohortUser::ROLES[:instructor]]) - end - end - end - - xit "lazily creates cohorts for products that it doesn't already know about" do - auth_user.registrations << auth_product_registration - - user = nil - expect { user = subject.resolve_user(auth_user) }.to change { Cohort.count }.by(1) - expect(user.cohorts.count).to eq 2 + # It doesn't add a new user if the user already exists + new_user = nil + user_count = User.count + new_user = subject.find_or_create_user + expect(User.count).to eq user_count + expect(new_user.admin?).to be true + expect(new_user.first_name).to eq "Inigo" + expect(new_user.last_name).to eq "Montoya" + expect(new_user.roles).to eq([User::ROLES[:admin], "futzy.butzy"]) end end -- GitLab From ab2b24493b3ec22427ae8f97afbe7be31fa56997 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Wed, 16 Sep 2020 20:32:09 -1000 Subject: [PATCH 044/283] fixing remove confirmation message. changing the link to edit a cohort user to not open in a new tab. --- app/javascript/components/cohorts/settings/UserCohortKebab.tsx | 2 +- app/views/users/edit.html.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/javascript/components/cohorts/settings/UserCohortKebab.tsx b/app/javascript/components/cohorts/settings/UserCohortKebab.tsx index beb3fdc..7db7964 100644 --- a/app/javascript/components/cohorts/settings/UserCohortKebab.tsx +++ b/app/javascript/components/cohorts/settings/UserCohortKebab.tsx @@ -52,7 +52,7 @@ export default class UserKebab extends React.Component { diff --git a/app/views/users/edit.html.haml b/app/views/users/edit.html.haml index 30c53cf..3513485 100644 --- a/app/views/users/edit.html.haml +++ b/app/views/users/edit.html.haml @@ -17,4 +17,4 @@ = label :instructor, "Instructor" = f.submit "Update Cohort User", class: "btn btn-primary" %br - = link_to "Remove User From Cohort", cohort_user_path(@cohort_user.cohort_id, @cohort_user.user_id), method: :delete, data: { confirm: "Really?" }, class: "btn btn-danger" + = link_to "Remove User From Cohort", cohort_user_path(@cohort_user.cohort_id, @cohort_user.user_id), method: :delete, data: { confirm: "Are you sure you want to remove #{@cohort_user.user.full_name} from this cohort?" }, class: "btn btn-danger" \ No newline at end of file -- GitLab From c4e70b666f8084b49c089b7faad6670ad5ceed81 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Thu, 17 Sep 2020 10:21:23 -1000 Subject: [PATCH 045/283] changing remove cohort user confirmation to a modal. --- app/views/users/edit.html.haml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/app/views/users/edit.html.haml b/app/views/users/edit.html.haml index 3513485..a702522 100644 --- a/app/views/users/edit.html.haml +++ b/app/views/users/edit.html.haml @@ -16,5 +16,14 @@ = check_box_tag :instructor, "forge.instructor", @cohort_user.roles.include?("forge.instructor"), class: "form-check-input" = label :instructor, "Instructor" = f.submit "Update Cohort User", class: "btn btn-primary" - %br - = link_to "Remove User From Cohort", cohort_user_path(@cohort_user.cohort_id, @cohort_user.user_id), method: :delete, data: { confirm: "Are you sure you want to remove #{@cohort_user.user.full_name} from this cohort?" }, class: "btn btn-danger" \ No newline at end of file + = link_to "Remove User From Cohort", "#my-modal", class: "btn btn-danger", "data-toggle": "modal", style: "float:right;" + .modal{id: "my-modal"} + .modal-dialog.modal-dialog-centered + .modal-content + .modal-header + %h3 Remove Cohort User + .modal-body + = p "Are you sure you want to remove #{@cohort_user.user.full_name} from this cohort?" + .modal-footer + %button{"data-dismiss": "modal", class: "btn btn-secondary"} Close + = link_to "Remove", cohort_user_path(@cohort_user.cohort_id, @cohort_user.user_id), method: :delete, class: "btn btn-danger" -- GitLab From 8b99482db003ea0fe8792821cd72b2832126e4e7 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Mon, 21 Sep 2020 11:49:53 -1000 Subject: [PATCH 046/283] Testing changes, bug fix --- app.json | 2 +- app/services/course_validator.rb | 2 +- config/secrets.yml | 4 +- .../api/v1/cohorts/cohorts_controller_spec.rb | 2 +- spec/controllers/cohorts_controller_spec.rb | 90 ++++++++++- spec/controllers/sessions_controller_spec.rb | 151 ++++++++++++++++++ spec/controllers/users_controller_spec.rb | 26 +-- 7 files changed, 254 insertions(+), 23 deletions(-) create mode 100644 spec/controllers/sessions_controller_spec.rb diff --git a/app.json b/app.json index ac9eda1..8384ccf 100644 --- a/app.json +++ b/app.json @@ -136,7 +136,7 @@ "AWS_SQLSNIPPETS_HOST": { "required": true }, - "GITLAB_GALVANIZE_COM_TOKEN": { + "GITLAB_DSOP_IL2_TOKEN": { "required": true } }, diff --git a/app/services/course_validator.rb b/app/services/course_validator.rb index b64db7d..0be07f2 100644 --- a/app/services/course_validator.rb +++ b/app/services/course_validator.rb @@ -143,7 +143,7 @@ class CourseValidator def gitlab_api_request(git_url, token) id = gitlab_project_search_by_repo_name(git_url, token) - open("https://#{git_url.host}/api/v4/projects/#{id}/repository/files/#{URI.encode(git_url.path, /\./)}?ref=#{git_url.branch}", + open("https://#{git_url.host}/api/v4/projects/#{id}/repository/files/#{CGI.escape(git_url.path)}?ref=#{git_url.branch}", "PRIVATE-TOKEN" => token.to_s, "User-Agent" => "Galvanize Forge").read end diff --git a/config/secrets.yml b/config/secrets.yml index cdf2219..fd7c36f 100644 --- a/config/secrets.yml +++ b/config/secrets.yml @@ -39,9 +39,9 @@ shared: github_com: type: github token: <%= ENV['GITHUB_COM_TOKEN'] %> - gitlab_galvanize_com: + code_il2_dsop_io: type: gitlab - token: <%= ENV['GITLAB_GALVANIZE_COM_TOKEN'] %> + token: <%= ENV['GITLAB_DSOP_IL2_TOKEN'] %> gitlab_com: type: gitlab token: <%= ENV['GITLAB_COM_TOKEN'] %> diff --git a/spec/controllers/api/v1/cohorts/cohorts_controller_spec.rb b/spec/controllers/api/v1/cohorts/cohorts_controller_spec.rb index 8671ef4..fe60333 100644 --- a/spec/controllers/api/v1/cohorts/cohorts_controller_spec.rb +++ b/spec/controllers/api/v1/cohorts/cohorts_controller_spec.rb @@ -91,7 +91,7 @@ resource "Cohorts" do do_request # }.to have_enqueued_job(CreateApiInteractionJob) - puts "RESPONSE_JSON = " + response_json.to_s + # puts "RESPONSE_JSON = " + response_json.to_s expect(status).to eq 401 expect(response_json["errors"]["code"]).to eq("unauthorized") diff --git a/spec/controllers/cohorts_controller_spec.rb b/spec/controllers/cohorts_controller_spec.rb index c03a805..7572f53 100644 --- a/spec/controllers/cohorts_controller_spec.rb +++ b/spec/controllers/cohorts_controller_spec.rb @@ -14,6 +14,80 @@ describe CohortsController do sign_in(admin) end + describe "GET #new" do + it "cohort should be new" do + expect(Cohort).to receive(:new).and_return(Cohort.new) + get :new + end + end + + describe "POST #create" do + + it "creates cohort" do + cohort_params = attributes_for(:cohort, product_type: "test", name: "Ruby", starts_on: Time.zone.now) + # cohort_params = { product_type: "test", name: "Ruby", starts_on: Time.zone.now } + expect { post :create, params: { cohort: cohort_params } }.to change(Cohort, :count).by(1) + end + + it 'redirects to the setup path' do + post :create, params: { cohort: attributes_for(:cohort, product_type: "class", name: "Intro to CSS") } + + cohort = Cohort.last + expect(response).to redirect_to(setup_cohort_path(cohort)) + end + + end + + describe "GET #edit" do + let(:current_cohort) { create(:cohort) } + + it "cohort can be edited" do + # get :edit, params: { cohort: { id: current_cohort.id } } + # expect(response).to have_http_status(:success) # 200 + end + end + + describe "PATCH #update" do + let!(:current_cohort) { create(:cohort) } + + before do + allow(Cohort).to receive(:find).and_return(current_cohort) + allow(current_cohort).to receive(:update).and_return(true) + end + + it "updates the cohort" do + patch :update_cohort, params: { + id: current_cohort.id, + cohort: { name: "New Name" } + } + expect(current_cohort).to have_received(:update) + end + + context "when the update succeeds" do + it "redirects to the cohort page" do + patch :update_cohort, params: { + id: current_cohort.id, + cohort: { name: "New Name" } + } + expect(response).to redirect_to(setup_cohort_path(current_cohort)) + end + end + + context "when the update fails" do + before do + allow(current_cohort).to receive(:update).and_return(false) + end + + it "renders the edit page again" do + patch :update_cohort, params: { + id: current_cohort.id, + cohort: { name: "New Name" } + } + expect(response).to render_template(:edit) + end + end + end + describe "GET #index" do it "returns locals with a list of all cohorts" do allow(Rails.application.secrets).to receive(:auth_url).and_return("http://auth.galvanize.com") @@ -91,14 +165,14 @@ describe CohortsController do let!(:unassociated_release) { create(:release) } let!(:failed_job_result) { create(:resync_job_result, edges: { cohort_id: cohort.id }, status: 'failure' ) } let!(:success_job_result) { create(:resync_job_result, edges: { cohort_id: cohort.id }, created_at: 1.day.ago) } - + context "when in a sandbox" do let(:sandbox) { create(:cohort, sandbox: true) } let(:instructor) { create(:cohort_user, :instructor, cohort: sandbox).user } - + it "should redirect to the cohort#show page" do sign_in(instructor) - + expect( get :setup, params: { id: sandbox.id } ).to redirect_to(content_cohort_path(sandbox)) @@ -124,10 +198,10 @@ describe CohortsController do context "when in a sandbox" do let(:sandbox) { create(:cohort, sandbox: true) } let(:instructor) { create(:cohort_user, :instructor, cohort: sandbox).user } - + it "should redirect to the cohort#show page" do sign_in(instructor) - + expect( get :users, params: { id: sandbox.id } ).to redirect_to(content_cohort_path(sandbox)) @@ -139,10 +213,10 @@ describe CohortsController do context "when in a sandbox" do let(:sandbox) { create(:cohort, sandbox: true) } let(:instructor) { create(:cohort_user, :instructor, cohort: sandbox).user } - + it "should redirect to the cohort#show page" do sign_in(instructor) - + expect( get :partnerup, params: { id: sandbox.id } ).to redirect_to(content_cohort_path(sandbox)) @@ -158,7 +232,7 @@ describe CohortsController do end it "should redirect to the cohort#show page" do sign_in(instructor) - + expect( get :partnerup, params: { id: cohort.id } ).to redirect_to(content_cohort_path(cohort)) diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb new file mode 100644 index 0000000..c2391dc --- /dev/null +++ b/spec/controllers/sessions_controller_spec.rb @@ -0,0 +1,151 @@ +require "spec_helper" + +describe SessionsController do + describe "GET #new" do + context "when signing in as a user not authenticated" do + render_views + + it "redirects to KeyCloak" do + get :new + expect(response).to redirect_to '/auth/keycloakopenid' + end + + end + + context "when signing in as a user already authenticated" do + + before do + existing_user = create(:user) + sign_in(existing_user) + session[:user_uid] = existing_user.uid + end + + it "redirects to root" do + get :new + expect(response).to redirect_to '/' + end + + end + # # dbl = double(Keycloak::Internal) + # expect(Keycloak::Internal).to receive(:get_user_info).with( + # email, + # true, + # Rails.application.secrets.keycloak_client_id, + # Rails.application.secrets.keycloak_client_secret + # ).and_return(OpenStruct.new({ id: "4b58555dbbc93c9016f7325ead84667d", + # firstName: first_name, + # lastName: last_name, + # email: email + # })) + # expect { + # do_request + # }.to have_enqueued_job(CreateApiInteractionJob) + # + # new_user = User.find_by(email: email) + # expect(new_user.first_name).to eq(first_name) + # expect(new_user.last_name).to eq(last_name) + # expect(new_user.email).to eq(email) + # + # expect(status).to eq 200 + # + # expect(response_json["status"]).to eq("ok") + + + # context "when signed in as a user with access to a cohort" do + # let(:cohort_user) { create(:cohort_user, :student) } + # + # before do + # create(:cohort_user, :student, user: cohort_user.user) + # sign_in(cohort_user.user) + # end + # + # context "when signed in with a requested path" do + # it "redirects the user to the requested path" do + # get :index, session: { requested_path: submissions_dashboard_cohort_user_path(cohort_user.cohort, cohort_user.user) } + # + # expect(response).to redirect_to(submissions_dashboard_cohort_user_path(cohort_user.cohort, cohort_user.user)) + # expect(session[:requested_path]).to eq(nil) + # end + # end + # + # it "redirects to the last created cohort" do + # last_created_cohort = create(:cohort_user, :student, user: cohort_user.user).cohort + # get :index + # + # expect(response).to redirect_to(cohort_path(last_created_cohort)) + # end + # end + # + # context "when signed in as an admin without any cohort relationships" do + # let!(:user) { create(:user, :admin) } + # + # before { sign_in(user) } + # + # it "redirects to the cohorts list" do + # get :index + # + # expect(response).to redirect_to(cohorts_path) + # end + # end + # + # context "when the user has a last viewed cohort id" do + # let(:user) { create(:user) } + # let(:cohort) { create(:cohort) } + # + # before do + # user.update(last_viewed_cohort_id: cohort.id) + # sign_in(user) + # end + # + # context "when the user is a student for the given cohort" do + # before { create(:cohort_user, :student, user: user, cohort: cohort) } + # + # it "redirects to the last viewed cohort path" do + # get :index + # + # expect(response).to redirect_to(cohort_path(cohort)) + # end + # end + # + # context "when the user is an instructor for the given cohort" do + # before { create(:cohort_user, :instructor, user: user, cohort: cohort) } + # + # it "redirects to the last viewed cohort path" do + # get :index + # + # expect(response).to redirect_to(cohort_path(cohort)) + # end + # end + # + # context "when the user is an admin" do + # before { user.update(roles: [User::ROLES[:admin]]) } + # + # it "redirects to the last viewed cohort path" do + # get :index + # + # expect(response).to redirect_to(cohort_path(cohort)) + # end + # end + # + # context "when the user doesn't have access to the cohort" do + # context "but has access to a different cohort" do + # let(:other_cohort) { create(:cohort) } + # + # before { create(:cohort_user, :student, user: user, cohort: other_cohort) } + # + # it "redirects to the other cohort path" do + # get :index + # + # expect(response).to redirect_to(cohort_path(other_cohort)) + # end + # end + # + # context "and doesn't have access to any other cohort" do + # it "renders the no Cohorts page" do + # expect(get(:index)).to render_template(:index) + # end + # end + # end + # end + end +end diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index c7bf525..7c16a5c 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -1,18 +1,24 @@ -require "integration_helper" +require "spec_helper" describe UsersController do - let(:user) { create(:user, :admin, api_token: "token") } - let(:student_to_enroll) { create(:user) } - let!(:cohort) { create(:cohort) } - let!(:enrolled_student) { create(:user, first_name: "Eric", last_name: "Ericson", email: "eric@example.com") } - let!(:cohort_user) { create(:cohort_user, created_at: 3.days.ago, cohort: cohort, user: enrolled_student) } + # let(:user) { create(:user, :admin, api_token: "token") } + # let(:student_to_enroll) { create(:user) } + # let!(:cohort) { create(:cohort) } + # let!(:enrolled_student) { create(:user, first_name: "Eric", last_name: "Ericson", email: "eric@example.com") } + # let!(:cohort_user) { create(:cohort_user, created_at: 3.days.ago, cohort: cohort, user: enrolled_student) } describe "GET #new" do - context "create a new user" do - # get "/cohorts/:cohort_id/users/:id" do - # - # end + let!(:cohort) { create(:cohort) } + let(:cohort_id) { cohort.id } + + context "create a new user for a given cohort" do + + it "creates new users for a cohort from a list of users" do + get "/cohorts/:cohort_id/users/new" do + print "COHORT_ID = " + @cohort_id + end + end end end -- GitLab From 3eda8c7240ef9b64b95f8d08b42034158784bcc6 Mon Sep 17 00:00:00 2001 From: Benton Gallun Date: Tue, 22 Sep 2020 00:25:28 +0000 Subject: [PATCH 047/283] first time temp ci file for forge development --- .gitlab-ci.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..dcfae11 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,4 @@ +include: + - project: 'platform-one/devops/pipeline-products' + ref: 'learn-ci' + file: 'products/tron/galvanize/learn/forge-ci.yml' -- GitLab From 23cb2d8d4c794d0c29b1093d82a42ef6695e9cf8 Mon Sep 17 00:00:00 2001 From: Benton Gallun Date: Tue, 22 Sep 2020 01:02:15 +0000 Subject: [PATCH 048/283] change repo/docker image --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 194e722..3589313 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ -FROM docker2.k8s.revacomm.net:5000/galvanize/rails-2.6.0-node:latest - +#FROM docker2.k8s.revacomm.net:5000/galvanize/rails-2.6.0-node:latest +FROM registry.il2.dsop.io/tron/products/learn-lms/microservices/forge/cht-rails # Copy in all the application dependencies ADD . . ADD Gemfile /usr/src/app/Gemfile -- GitLab From 48dca02a8d14c4287131a31ad424c3de52d45f8e Mon Sep 17 00:00:00 2001 From: Benton Gallun Date: Tue, 22 Sep 2020 01:09:47 +0000 Subject: [PATCH 049/283] port contents from Dockerfile.base --- Dockerfile | 49 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3589313..cbbb371 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,49 @@ -#FROM docker2.k8s.revacomm.net:5000/galvanize/rails-2.6.0-node:latest -FROM registry.il2.dsop.io/tron/products/learn-lms/microservices/forge/cht-rails +FROM bitnami/ruby:2.6.0 + +ENV count 6 + +# Install what we can through OS package management +RUN apt-get -y update +RUN apt-get -y install --no-install-recommends \ + curl \ + software-properties-common \ + postgresql-client\ + libpq-dev \ + libxml2-dev \ + libxslt1-dev \ + qt5-default \ + libqt5webkit5-dev \ + xvfb + +# Install the right version of nodejs +RUN curl -sL https://deb.nodesource.com/setup_12.x | bash - +RUN apt-get -y install --no-install-recommends nodejs +RUN apt-get -q clean +RUN npm cache clean -f +RUN npm install -g n +RUN n stable +RUN update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10 + # Copy in all the application dependencies +ADD package.json /usr/src/app/package.json +RUN npm install + +# Set the user +RUN groupadd -r ruby +RUN useradd --no-log-init -r -g ruby ruby +# USER ruby +RUN whoami + +# Setup our environment +WORKDIR /usr/src/app +ENV RAILS_ENV production + +# Stuff that changes ADD . . ADD Gemfile /usr/src/app/Gemfile ADD Gemfile.lock /usr/src/app/Gemfile.lock -RUN gem install bundler --version 1.17.3 -RUN bundle -v +# RUN gem install bundler --version 1.17.3 +RUN gem install rake -v '12.3.1' --source 'https://rubygems.org/' RUN bundle install ENV PATH /usr/src/app/node_modules/.bin:$PATH -ADD package.json /usr/src/app/package.json -RUN npm install -ENV COUNT 1 CMD ["./entrypoint-server.sh"] -- GitLab From 6eb10bf7d7834bb070153eecf97ff4682d79bf4f Mon Sep 17 00:00:00 2001 From: Benton Gallun Date: Mon, 21 Sep 2020 18:31:25 -0700 Subject: [PATCH 050/283] delete bad block parser, replace with good --- gems/block-parser | 1 - gems/bp/Dockerfile | 12 + gems/bp/Gemfile | 6 + gems/bp/Gemfile.lock | 110 ++ gems/bp/README.md | 25 + gems/bp/Rakefile | 6 + gems/bp/bin/console | 14 + gems/bp/bin/parse_block | 21 + gems/bp/bin/setup | 8 + gems/bp/block_parser-0.1.0.gem | Bin 0 -> 5120 bytes gems/bp/block_parser.gemspec | 45 + gems/bp/build | 3 + gems/bp/lib/block_parser.rb | 26 + gems/bp/lib/block_parser/build_challenge.rb | 143 ++ gems/bp/lib/block_parser/build_html.rb | 85 + .../block_parser/build_html_from_md_json.rb | 158 ++ gems/bp/lib/block_parser/build_image_link.rb | 32 + gems/bp/lib/block_parser/build_link.rb | 76 + .../build_title_from_filename_and_html.rb | 28 + .../challenge_validators/challenge.rb | 148 ++ .../challenge_validator.rb | 41 + .../checkbox_challenge_validator.rb | 43 + .../code_snippet_challenge_validator.rb | 32 + .../custom_snippet_challenge_validator.rb | 34 + .../local_snippet_challenge_validator.rb | 16 + .../multiple_choice_challenge_validator.rb | 34 + .../number_challenge_validator.rb | 16 + .../paragraph_challenge_validator.rb | 6 + .../poll_challenge_validator.rb | 6 + .../project_challenge_validator.rb | 14 + .../short_answer_challenge_validator.rb | 14 + .../testable_project_challenge_validator.rb | 167 ++ .../bp/lib/block_parser/convert_md_to_json.rb | 361 ++++ gems/bp/lib/block_parser/parse_directory.rb | 182 ++ .../lib/block_parser/parse_markdown_file.rb | 40 + gems/bp/lib/block_parser/parse_standards.rb | 145 ++ gems/bp/lib/block_parser/version.rb | 3 + gems/bp/pkg/block_parser-0.1.0.gem | Bin 0 -> 5120 bytes gems/bp/spec/build_challenge_spec.rb | 1317 +++++++++++++ gems/bp/spec/build_html_from_md_json_spec.rb | 316 +++ gems/bp/spec/build_html_spec.rb | 196 ++ gems/bp/spec/build_image_link_spec.rb | 308 +++ gems/bp/spec/build_link_spec.rb | 173 ++ ...build_title_from_filename_and_html_spec.rb | 53 + .../challenge_validators/challenge_spec.rb | 288 +++ .../challenge_validator_spec.rb | 116 ++ .../checkbox_challenge_validator_spec.rb | 118 ++ .../code_snippet_challenge_validator_spec.rb | 131 ++ ...custom_snippet_challenge_validator_spec.rb | 69 + ...ultiple_choice_challenge_validator_spec.rb | 107 ++ .../number_challenge_validator_spec.rb | 72 + .../project_challenge_validator_spec.rb | 56 + .../short_answer_challenge_validator_spec.rb | 53 + ...stable_project_challenge_validator_spec.rb | 296 +++ gems/bp/spec/convert_md_to_json_spec.rb | 1702 +++++++++++++++++ .../bad-challenges.md | 128 ++ .../config.yaml | 14 + .../config.yaml | 14 + .../no-challenges.md | 1 + .../config.yaml | 3 + .../no-lessons-nor-checkpoints/config.yaml | 14 + .../no-lessons-nor-checkpoints/resources.md | 1 + .../config.yaml | 2 + gems/bp/spec/fixtures/sample-iframe.md | 5 + .../fixtures/test-block-repo-yml/config.yml | 13 + .../fixtures/test-block-repo-yml/dummy.pdf | Bin 0 -> 13264 bytes .../test-block-repo-yml/folder/sibling.md | 3 + .../test-block-repo-yml/folder/target.md | 3 + .../images/galvanize-logo.png | Bin 0 -> 4134 bytes .../images/register_klass.gif | Bin 0 -> 20804 bytes .../fixtures/test-block-repo-yml/lessoN.md | 1 + .../test-block-repo-yml/markdown-smoketest.md | 107 ++ .../fixtures/test-block-repo-yml/target.md | 1 + .../spec/fixtures/test-block-repo/README.md | 22 + .../spec/fixtures/test-block-repo/config.yaml | 18 + .../test-block-repo/folder/sibling.md | 3 + .../fixtures/test-block-repo/folder/target.md | 3 + .../test-block-repo/images/galvanize-logo.png | Bin 0 -> 4134 bytes .../test-block-repo/images/register_klass.gif | Bin 0 -> 20804 bytes .../fixtures/test-block-repo/ipynb-test.ipynb | 524 +++++ .../fixtures/test-block-repo/ipynb-test.md | 220 +++ .../spec/fixtures/test-block-repo/lessoN.md | 1 + .../test-block-repo/markdown-smoketest.md | 107 ++ .../spec/fixtures/test-block-repo/target.md | 1 + .../test-block-two-configs/config.yaml | 2 + .../test-block-two-configs/config.yml | 2 + .../Dockerfile | 0 .../test.sh | 0 .../config.yaml | 2 + gems/bp/spec/parse_directory_spec.rb | 320 ++++ gems/bp/spec/parse_markdown_file_spec.rb | 29 + gems/bp/spec/parse_standards_spec.rb | 368 ++++ gems/bp/spec/spec_helper.rb | 23 + gems/bp/spec/support/freeloader.rb | 8 + gems/bp/spec/support/mocktokit.rb | 31 + gems/bp/spec/tmp/.keep | 1 + gems/bp/validate-block | 11 + 97 files changed, 9477 insertions(+), 1 deletion(-) delete mode 160000 gems/block-parser create mode 100644 gems/bp/Dockerfile create mode 100644 gems/bp/Gemfile create mode 100644 gems/bp/Gemfile.lock create mode 100644 gems/bp/README.md create mode 100644 gems/bp/Rakefile create mode 100755 gems/bp/bin/console create mode 100755 gems/bp/bin/parse_block create mode 100755 gems/bp/bin/setup create mode 100644 gems/bp/block_parser-0.1.0.gem create mode 100644 gems/bp/block_parser.gemspec create mode 100755 gems/bp/build create mode 100644 gems/bp/lib/block_parser.rb create mode 100644 gems/bp/lib/block_parser/build_challenge.rb create mode 100644 gems/bp/lib/block_parser/build_html.rb create mode 100644 gems/bp/lib/block_parser/build_html_from_md_json.rb create mode 100644 gems/bp/lib/block_parser/build_image_link.rb create mode 100644 gems/bp/lib/block_parser/build_link.rb create mode 100644 gems/bp/lib/block_parser/build_title_from_filename_and_html.rb create mode 100644 gems/bp/lib/block_parser/challenge_validators/challenge.rb create mode 100644 gems/bp/lib/block_parser/challenge_validators/challenge_validator.rb create mode 100644 gems/bp/lib/block_parser/challenge_validators/checkbox_challenge_validator.rb create mode 100644 gems/bp/lib/block_parser/challenge_validators/code_snippet_challenge_validator.rb create mode 100644 gems/bp/lib/block_parser/challenge_validators/custom_snippet_challenge_validator.rb create mode 100644 gems/bp/lib/block_parser/challenge_validators/local_snippet_challenge_validator.rb create mode 100644 gems/bp/lib/block_parser/challenge_validators/multiple_choice_challenge_validator.rb create mode 100644 gems/bp/lib/block_parser/challenge_validators/number_challenge_validator.rb create mode 100644 gems/bp/lib/block_parser/challenge_validators/paragraph_challenge_validator.rb create mode 100644 gems/bp/lib/block_parser/challenge_validators/poll_challenge_validator.rb create mode 100644 gems/bp/lib/block_parser/challenge_validators/project_challenge_validator.rb create mode 100644 gems/bp/lib/block_parser/challenge_validators/short_answer_challenge_validator.rb create mode 100644 gems/bp/lib/block_parser/challenge_validators/testable_project_challenge_validator.rb create mode 100644 gems/bp/lib/block_parser/convert_md_to_json.rb create mode 100644 gems/bp/lib/block_parser/parse_directory.rb create mode 100644 gems/bp/lib/block_parser/parse_markdown_file.rb create mode 100644 gems/bp/lib/block_parser/parse_standards.rb create mode 100644 gems/bp/lib/block_parser/version.rb create mode 100644 gems/bp/pkg/block_parser-0.1.0.gem create mode 100644 gems/bp/spec/build_challenge_spec.rb create mode 100644 gems/bp/spec/build_html_from_md_json_spec.rb create mode 100644 gems/bp/spec/build_html_spec.rb create mode 100644 gems/bp/spec/build_image_link_spec.rb create mode 100644 gems/bp/spec/build_link_spec.rb create mode 100644 gems/bp/spec/build_title_from_filename_and_html_spec.rb create mode 100644 gems/bp/spec/challenge_validators/challenge_spec.rb create mode 100644 gems/bp/spec/challenge_validators/challenge_validator_spec.rb create mode 100644 gems/bp/spec/challenge_validators/checkbox_challenge_validator_spec.rb create mode 100644 gems/bp/spec/challenge_validators/code_snippet_challenge_validator_spec.rb create mode 100644 gems/bp/spec/challenge_validators/custom_snippet_challenge_validator_spec.rb create mode 100644 gems/bp/spec/challenge_validators/multiple_choice_challenge_validator_spec.rb create mode 100644 gems/bp/spec/challenge_validators/number_challenge_validator_spec.rb create mode 100644 gems/bp/spec/challenge_validators/project_challenge_validator_spec.rb create mode 100644 gems/bp/spec/challenge_validators/short_answer_challenge_validator_spec.rb create mode 100644 gems/bp/spec/challenge_validators/testable_project_challenge_validator_spec.rb create mode 100644 gems/bp/spec/convert_md_to_json_spec.rb create mode 100644 gems/bp/spec/fixtures/checkpoint-with-bad-challenge-tag/bad-challenges.md create mode 100644 gems/bp/spec/fixtures/checkpoint-with-bad-challenge-tag/config.yaml create mode 100644 gems/bp/spec/fixtures/checkpoint-without-challenges-block-repo/config.yaml create mode 100644 gems/bp/spec/fixtures/checkpoint-without-challenges-block-repo/no-challenges.md create mode 100644 gems/bp/spec/fixtures/invalid-config-test-block-repo/config.yaml create mode 100644 gems/bp/spec/fixtures/no-lessons-nor-checkpoints/config.yaml create mode 100644 gems/bp/spec/fixtures/no-lessons-nor-checkpoints/resources.md create mode 100644 gems/bp/spec/fixtures/no-standards-config-test-block-repo/config.yaml create mode 100644 gems/bp/spec/fixtures/sample-iframe.md create mode 100644 gems/bp/spec/fixtures/test-block-repo-yml/config.yml create mode 100644 gems/bp/spec/fixtures/test-block-repo-yml/dummy.pdf create mode 100644 gems/bp/spec/fixtures/test-block-repo-yml/folder/sibling.md create mode 100644 gems/bp/spec/fixtures/test-block-repo-yml/folder/target.md create mode 100644 gems/bp/spec/fixtures/test-block-repo-yml/images/galvanize-logo.png create mode 100644 gems/bp/spec/fixtures/test-block-repo-yml/images/register_klass.gif create mode 100644 gems/bp/spec/fixtures/test-block-repo-yml/lessoN.md create mode 100644 gems/bp/spec/fixtures/test-block-repo-yml/markdown-smoketest.md create mode 100644 gems/bp/spec/fixtures/test-block-repo-yml/target.md create mode 100644 gems/bp/spec/fixtures/test-block-repo/README.md create mode 100644 gems/bp/spec/fixtures/test-block-repo/config.yaml create mode 100644 gems/bp/spec/fixtures/test-block-repo/folder/sibling.md create mode 100644 gems/bp/spec/fixtures/test-block-repo/folder/target.md create mode 100644 gems/bp/spec/fixtures/test-block-repo/images/galvanize-logo.png create mode 100644 gems/bp/spec/fixtures/test-block-repo/images/register_klass.gif create mode 100644 gems/bp/spec/fixtures/test-block-repo/ipynb-test.ipynb create mode 100644 gems/bp/spec/fixtures/test-block-repo/ipynb-test.md create mode 100644 gems/bp/spec/fixtures/test-block-repo/lessoN.md create mode 100644 gems/bp/spec/fixtures/test-block-repo/markdown-smoketest.md create mode 100644 gems/bp/spec/fixtures/test-block-repo/target.md create mode 100644 gems/bp/spec/fixtures/test-block-two-configs/config.yaml create mode 100644 gems/bp/spec/fixtures/test-block-two-configs/config.yml create mode 100644 gems/bp/spec/fixtures/valid-custom-snippet-challenge-directory/Dockerfile create mode 100644 gems/bp/spec/fixtures/valid-custom-snippet-challenge-directory/test.sh create mode 100644 gems/bp/spec/fixtures/valid-yaml-array-test-block-repo/config.yaml create mode 100644 gems/bp/spec/parse_directory_spec.rb create mode 100644 gems/bp/spec/parse_markdown_file_spec.rb create mode 100644 gems/bp/spec/parse_standards_spec.rb create mode 100644 gems/bp/spec/spec_helper.rb create mode 100644 gems/bp/spec/support/freeloader.rb create mode 100644 gems/bp/spec/support/mocktokit.rb create mode 100644 gems/bp/spec/tmp/.keep create mode 100755 gems/bp/validate-block diff --git a/gems/block-parser b/gems/block-parser deleted file mode 160000 index bdf3acd..0000000 --- a/gems/block-parser +++ /dev/null @@ -1 +0,0 @@ -Subproject commit bdf3acdb4145805d306fc022f4abc2803a6bacb7 diff --git a/gems/bp/Dockerfile b/gems/bp/Dockerfile new file mode 100644 index 0000000..34a3ba8 --- /dev/null +++ b/gems/bp/Dockerfile @@ -0,0 +1,12 @@ +FROM ruby:latest +RUN mkdir /app +WORKDIR /app +ENV LANG=C.UTF-8 +ADD Gemfile . +ADD Gemfile.lock . +ADD block_parser.gemspec . +ADD lib/block_parser/version.rb lib/block_parser/version.rb +RUN gem install bundler +RUN bundle +ADD . . +ENTRYPOINT /app/bin/parse_block /block diff --git a/gems/bp/Gemfile b/gems/bp/Gemfile new file mode 100644 index 0000000..cc9928f --- /dev/null +++ b/gems/bp/Gemfile @@ -0,0 +1,6 @@ +source "https://rubygems.org" + +git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } + +# Specify your gem's dependencies in block_parser.gemspec +gemspec diff --git a/gems/bp/Gemfile.lock b/gems/bp/Gemfile.lock new file mode 100644 index 0000000..f077409 --- /dev/null +++ b/gems/bp/Gemfile.lock @@ -0,0 +1,110 @@ +PATH + remote: . + specs: + block_parser (0.1.0) + activemodel (> 4.2) + github-markdown (= 0.6.9) + github-markup (= 1.6.1) + github_url (= 0.2.1) + gitlab (= 4.14.1) + nokogiri (= 1.8.0) + octokit (= 4.3.0) + psych (= 2.2.4) + redcarpet (= 3.3.4) + rspec_junit_formatter (> 0.2.3) + +GEM + remote: https://rubygems.org/ + specs: + activemodel (6.0.3.1) + activesupport (= 6.0.3.1) + activesupport (6.0.3.1) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + zeitwerk (~> 2.2, >= 2.2.2) + addressable (2.4.0) + ast (2.4.0) + byebug (9.1.0) + concurrent-ruby (1.1.6) + diff-lcs (1.3) + faraday (0.9.2) + multipart-post (>= 1.2, < 3) + github-markdown (0.6.9) + github-markup (1.6.1) + github_url (0.2.1) + gitlab (4.14.1) + httparty (~> 0.14, >= 0.14.0) + terminal-table (~> 1.5, >= 1.5.1) + httparty (0.18.0) + mime-types (~> 3.0) + multi_xml (>= 0.5.2) + i18n (1.8.2) + concurrent-ruby (~> 1.0) + mime-types (3.3.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2020.0512) + mini_portile2 (2.2.0) + minitest (5.14.1) + multi_xml (0.6.0) + multipart-post (2.1.1) + nokogiri (1.8.0) + mini_portile2 (~> 2.2.0) + octokit (4.3.0) + sawyer (~> 0.7.0, >= 0.5.3) + parallel (1.19.1) + parser (2.7.1.2) + ast (~> 2.4.0) + psych (2.2.4) + rainbow (3.0.0) + rake (10.5.0) + redcarpet (3.3.4) + rexml (3.2.4) + rspec (3.9.0) + rspec-core (~> 3.9.0) + rspec-expectations (~> 3.9.0) + rspec-mocks (~> 3.9.0) + rspec-core (3.9.2) + rspec-support (~> 3.9.3) + rspec-expectations (3.9.2) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.9.0) + rspec-mocks (3.9.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.9.0) + rspec-support (3.9.3) + rspec_junit_formatter (0.4.1) + rspec-core (>= 2, < 4, != 2.12.0) + rubocop (0.83.0) + parallel (~> 1.10) + parser (>= 2.7.0.1) + rainbow (>= 2.2.2, < 4.0) + rexml + ruby-progressbar (~> 1.7) + unicode-display_width (>= 1.4.0, < 2.0) + ruby-progressbar (1.10.1) + sawyer (0.7.0) + addressable (>= 2.3.5, < 2.5) + faraday (~> 0.8, < 0.10) + terminal-table (1.8.0) + unicode-display_width (~> 1.1, >= 1.1.1) + thread_safe (0.3.6) + tzinfo (1.2.7) + thread_safe (~> 0.1) + unicode-display_width (1.7.0) + zeitwerk (2.3.0) + +PLATFORMS + ruby + +DEPENDENCIES + block_parser! + bundler (~> 1.15) + byebug (= 9.1.0) + rake (~> 10.0) + rspec (~> 3.0) + rubocop (> 0.72) + +BUNDLED WITH + 1.17.2 diff --git a/gems/bp/README.md b/gems/bp/README.md new file mode 100644 index 0000000..2646cc2 --- /dev/null +++ b/gems/bp/README.md @@ -0,0 +1,25 @@ +# block_parser + +`block_parser` contains shared curriculum repository processing logic used in our Learn and Forge applications. + +## Validating Local Blocks via Docker + +Ensure that you have docker installed and running. + +Then fork and clone this repository and run: + +``` +./build +``` + +You can validate the current directory by doing this: + +``` +/path/to/this/repo/validate-block . +``` + +You can validate the another directory by doing this: + +``` +/path/to/this/repo/validate-block ../some/other/dir +``` diff --git a/gems/bp/Rakefile b/gems/bp/Rakefile new file mode 100644 index 0000000..c92b11e --- /dev/null +++ b/gems/bp/Rakefile @@ -0,0 +1,6 @@ +require "bundler/gem_tasks" +require "rspec/core/rake_task" + +RSpec::Core::RakeTask.new(:spec) + +task default: :spec diff --git a/gems/bp/bin/console b/gems/bp/bin/console new file mode 100755 index 0000000..b6e7308 --- /dev/null +++ b/gems/bp/bin/console @@ -0,0 +1,14 @@ +#!/usr/bin/env ruby + +require "bundler/setup" +require "block_parser" + +# You can add fixtures and/or initialization code here to make experimenting +# with your gem easier. You can also use a different console, if you like. + +# (If you use this, don't forget to add pry to your Gemfile!) +# require "pry" +# Pry.start + +require "irb" +IRB.start(__FILE__) diff --git a/gems/bp/bin/parse_block b/gems/bp/bin/parse_block new file mode 100755 index 0000000..7704898 --- /dev/null +++ b/gems/bp/bin/parse_block @@ -0,0 +1,21 @@ +#!/usr/bin/env ruby + +require "bundler/setup" +require "block_parser" + +unless ARGV.length == 1 + puts "Please pass exactly one argument." + return +end + +result = BlockParser::ParseDirectory.new(path: ARGV[0], asset_uploader: nil).execute + +if result[:errors].any? + result[:errors].each do |error| + puts error + end + + exit(1) +else + puts "Directory is valid." +end diff --git a/gems/bp/bin/setup b/gems/bp/bin/setup new file mode 100755 index 0000000..dce67d8 --- /dev/null +++ b/gems/bp/bin/setup @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -euo pipefail +IFS=$'\n\t' +set -vx + +bundle install + +# Do any other automated setup that you need to do here diff --git a/gems/bp/block_parser-0.1.0.gem b/gems/bp/block_parser-0.1.0.gem new file mode 100644 index 0000000000000000000000000000000000000000..d98013fdc53ad0f531beb556989cfd115dc929d3 GIT binary patch literal 5120 zcmeH}dpHwpAIC?@DO5yl&eT&5Gi+p9Npegz6owZe6ml41P9=oNkhCl&goTlig+xP6 zlVeUx4mlr&P|P0B`~Fc^f4uK=UC-6^_D8>ee)swM-QWAZKljhw32pCakG2Op2LgVU zLADJFg#!Na+xDYZhN-FplvSbX$`CbW2owf@Y*)6OB;;oW^!>WNK4^RI?U4LkoSfXg z@A#qozxw~Pw{M&KVfwFHm5Aj69J)Ma&Ay}ifw502WKZP6*Zm|V0+yloFcOarY=kzT zAD$DKLm!apAs&#uxX*9sbSNf8pusQc?Xaw>(Cm)HOE1ad!fcx2@lznv`hn<}g|L^4 zz!*qncMa9V^V97_ooDRYz=;^LbSswQbdQ|^e?)u>vw!zq!-Y8Z&}mMci5A7=quQue zseCkEMNQTruyqNRG@{;aRf+~(Ap$S%3b|iv=dzC%&lL{5Eh~zRy-~jtzO@xD+mb<5 zcu8dwh>`2lEWnhw)zSnL z0+hfzJSRD0U%g9T%cLM-=_5U&Yb%v`ClSjGCkm#nAEjix5Db%&MOn6B|hnbLh?$edayr{mxUmWQs&VA|$tLT7Aeqf<@b$Ql-* zH*TcUK851kWh!(+OlVq{VUU~IF;)cJo;q=&)p@H@Vob?oaIePbx%`X^++&FF zRpG4`kkF*AmtMO`fteh3l36f1RHHV%-O$wU5zwPLa*!Tc*PjKVa$9)Z_VX3Fc`Le7 zZnm#1Y+Y)oTPV1Yhy7Jp%3W%J=@!WNMdGD#2npniR3-5ejH5Wrr}wsbOFku*fnk?B ziyCEP^o)=JBzUSSVLxxha(@~BU>Ty+_Bid#agF?(uZIug<+MtKT%FsdJXQMK)V3IM z-mj78K`#Ie`#xDvlg2Chwf0SQTtPljc#^O-{%QJfR{3zQY1c9;hpHCAE+gIAlsyrk zlNl_V=9tO{O>rkBP zLQHup9k{!v1C!s;1@~`X`vs1p`&3DOr{129R%MC4;wsS3#<@PfrHJaQTiT$bPq|qR z_ewqtB6ZZO!2%xISp<>Q*f9`EMa2tJQw?%u=S7FdhbCrhZ7y%bFhqXUNB>=1|7QO- z0so);SA)QQpkUjK?%^3SrSLKt3ZXD(y7685aVw=+mDQ!m&%E`kiJD$pjNw!t$5uR@pQTsl zvnj#f!MM-zk7S*aNAssu2YfEfxo|$ZIw}fx2;jTOPictJ$6oL;sXe4riMsjjjh!Z6 z!fF*b54B|Pdkdul03Q*ET2z3;JvK!}p|pve#Kp)vxn9LqKDOe}yC<{KS8s|Eoii>) z^7gZ#NLAwCVlMHd+w+m79|bsF3X11V<7c{)>etAfjj@Sfo@1_u&*_h1jvZ3;`Up0W2|A~1 zEfTRfI&9II?5RDm1?^+zFheVNV=X=IyE&}gBe%F(_I9niyJ5jQnxdbo=kzfTYIu=V1oHWwWHhwd; z7o`2f`|Wx1#^*ppb?AoSvyEx6%b{YDk;Jiwv*@~f*KzQc?({N zGYUm;Or4}%!IeF2w{GYuO|bNIjJuMiKMKIB5B}kzsn|X)76NfRhf};&DASLqqw@#v zYPX7t?Gh}a-76}*FE%%rp9XX 1.15" + spec.add_development_dependency "byebug", "9.1.0" + spec.add_development_dependency "rake", "~> 10.0" + spec.add_development_dependency "rspec", "~> 3.0" + spec.add_development_dependency "rubocop", "> 0.72" + + spec.add_dependency "activemodel", "> 4.2" + spec.add_dependency "github-markdown", "0.6.9" + spec.add_dependency "github-markup", "1.6.1" + spec.add_dependency "github_url", "0.2.1" + spec.add_dependency "gitlab", "4.14.1" + spec.add_dependency "nokogiri", "1.8.0" + spec.add_dependency "octokit", "4.3.0" + spec.add_dependency "psych", "2.2.4" + spec.add_dependency "redcarpet", "3.3.4" + spec.add_dependency "rspec_junit_formatter", "> 0.2.3" +end diff --git a/gems/bp/build b/gems/bp/build new file mode 100755 index 0000000..c1512e5 --- /dev/null +++ b/gems/bp/build @@ -0,0 +1,3 @@ +#!/bin/bash + +docker build -t block-parser . diff --git a/gems/bp/lib/block_parser.rb b/gems/bp/lib/block_parser.rb new file mode 100644 index 0000000..4888a71 --- /dev/null +++ b/gems/bp/lib/block_parser.rb @@ -0,0 +1,26 @@ +require "active_model" +require "block_parser/build_challenge" +require "block_parser/build_html_from_md_json" +require "block_parser/build_html" +require "block_parser/build_image_link" +require "block_parser/build_link" +require "block_parser/build_title_from_filename_and_html" +require "block_parser/convert_md_to_json" +require "block_parser/parse_directory" +require "block_parser/parse_markdown_file" +require "block_parser/parse_standards" +require "block_parser/version" + +require "block_parser/challenge_validators/challenge_validator" +require "block_parser/challenge_validators/challenge" +require "block_parser/challenge_validators/checkbox_challenge_validator" +require "block_parser/challenge_validators/code_snippet_challenge_validator" +require "block_parser/challenge_validators/custom_snippet_challenge_validator" +require "block_parser/challenge_validators/local_snippet_challenge_validator" +require "block_parser/challenge_validators/multiple_choice_challenge_validator" +require "block_parser/challenge_validators/number_challenge_validator" +require "block_parser/challenge_validators/paragraph_challenge_validator" +require "block_parser/challenge_validators/poll_challenge_validator" +require "block_parser/challenge_validators/project_challenge_validator" +require "block_parser/challenge_validators/short_answer_challenge_validator" +require "block_parser/challenge_validators/testable_project_challenge_validator" diff --git a/gems/bp/lib/block_parser/build_challenge.rb b/gems/bp/lib/block_parser/build_challenge.rb new file mode 100644 index 0000000..a81ef4e --- /dev/null +++ b/gems/bp/lib/block_parser/build_challenge.rb @@ -0,0 +1,143 @@ +module BlockParser + class BuildChallenge + class ChallengeDataInvalidError < StandardError + end + + def self.execute( + content_object:, + json_hash:, + position:, + asset_uploader:, + root_directory_path:, + current_content_file_path:, + content_file_paths:, + autoscore: false + ) + + challenge_hash = json_hash[:challenges][content_object[:id].to_sym] + challenge_validator = validator(challenge_hash, autoscore, root_directory_path) + errors = [] + warnings = [] + + unless challenge_validator.valid? + if challenge_hash[:type] == "custom-snippet" + warnings.concat(challenge_validator.errors.full_messages) + else + raise ChallengeDataInvalidError, challenge_validator.errors.full_messages.join(", ") + end + end + + html_explanation_text = + if challenge_hash[:explanation].present? + explanation = BuildHtmlFromMdJson.process_challenge_json( + json_hash: challenge_hash[:explanation], + asset_uploader: asset_uploader, + root_directory_path: root_directory_path, + current_content_file_path: current_content_file_path, + content_file_paths: content_file_paths + ) + + errors.concat(explanation[:errors]) + warnings.concat(explanation[:warnings]) + explanation[:html] + end + + html_hints = challenge_hash[:hints]&.map do |hint| + processed_md = BuildHtml.execute( + html: GitHub::Markup.render("file.markdown", hint), + current_content_file_path: current_content_file_path, + content_file_paths: content_file_paths, + asset_uploader: asset_uploader, + root_directory_path: root_directory_path + ) + + processed_md[:html] + end + + html_rubric_text = + if challenge_hash[:rubric].present? + rubric = BuildHtmlFromMdJson.process_challenge_json( + json_hash: challenge_hash[:rubric], + asset_uploader: asset_uploader, + root_directory_path: root_directory_path, + current_content_file_path: current_content_file_path, + content_file_paths: content_file_paths + ) + + errors.concat(rubric[:errors]) + warnings.concat(rubric[:warnings]) + rubric[:html] + end + + question_result = BuildHtmlFromMdJson.process_challenge_json( + json_hash: challenge_hash[:question], + asset_uploader: asset_uploader, + root_directory_path: root_directory_path, + current_content_file_path: current_content_file_path, + content_file_paths: content_file_paths + ) + + errors.concat(question_result[:errors]) + warnings.concat(question_result[:warnings]) + question = question_result[:html] + + { + attributes: { + uid: challenge_hash[:id], + challenge_type: challenge_hash[:type], + title: challenge_hash[:title], + hints: html_hints || [], + rubric: html_rubric_text, + explanation: html_explanation_text, + decimal: challenge_hash[:decimal], + answer: challenge_hash[:answer], + question: question, + position: position, + points: challenge_hash[:points] || 1, + partial_credit: challenge_hash[:partial_credit] || false, + language: challenge_hash[:language], + data_path: challenge_hash[:data_path], + upstream_repo_path: challenge_hash[:upstream_repo_path], + setup: challenge_hash[:setup] || "", + tests: challenge_hash[:tests], + topics: challenge_hash[:topics], + show_tests: challenge_hash[:show_tests] || false, + raw_json: challenge_hash, + validate_fork: challenge_hash[:validate_fork] || false, + docker_directory_path: challenge_hash[:docker_directory_path] || nil, + external_id: challenge_hash[:external_id] || nil, + external_source: challenge_hash[:external_source] || nil + }, + errors: errors, + warnings: warnings, + html: "
    " + } + rescue ChallengeDataInvalidError => e + { + errors: [e.message], + warnings: [] + } + end + + def self.validator(challenge_hash, autoscore, root_directory_path) + unless ChallengeValidators::Challenge::TYPES.values.include?(challenge_hash[:type]) + raise ChallengeDataInvalidError, "#{challenge_hash[:type]} is not a valid challenge type" + end + + if autoscore && ChallengeValidators::Challenge::MANUAL_SCORE_TYPES.values.include?(challenge_hash[:type]) + autoscore_error = "#{challenge_hash[:type]} is not an autoscoreable challenge type but was found in an autograde checkpoint." + raise ChallengeDataInvalidError, autoscore_error + end + + if challenge_hash[:type] == ChallengeValidators::Challenge::TYPES[:custom_snippet] + challenge_hash[:root_directory_path] = root_directory_path + end + + ( + "BlockParser::ChallengeValidators::" + + challenge_hash[:type].underscore.classify + + "ChallengeValidator" + ).constantize.new(challenge_hash) + end + end +end diff --git a/gems/bp/lib/block_parser/build_html.rb b/gems/bp/lib/block_parser/build_html.rb new file mode 100644 index 0000000..e67ce60 --- /dev/null +++ b/gems/bp/lib/block_parser/build_html.rb @@ -0,0 +1,85 @@ +module BlockParser + class BuildHtml + def self.execute(html:, asset_uploader:, root_directory_path:, current_content_file_path:, content_file_paths:, resource_paths: []) + doc = Nokogiri::HTML::DocumentFragment.parse(html) + doc.css("meta, script, style, link, title").each do |bad_element| + html = html.sub("#{bad_element.to_html}\n", "") + end + + warnings = [] + + if html.include?("[ ]") || + html.include?("[x]") || + html.include?("[X]") + + html = html.gsub("[ ]", ""). + gsub("[X]", ""). + gsub("[x]", "") + end + + headers = {} + doc.css("a, img, pre", "h1, h2, h3, h4, h5, h6").each do |element| + original_text = nil + new_text = nil + if element.name == "a" + begin + original_text, new_text = + BuildLink.execute( + link: element, + current_content_file_path: current_content_file_path, + content_file_paths: content_file_paths, + root_directory_path: root_directory_path, + resource_paths: resource_paths + ) + rescue BuildLink::BadInternalLink => e + warnings << "#{current_content_file_path.gsub(root_directory_path, '')}: #{e.message}" + end + elsif element.name == "img" + image_link = + BuildImageLink.execute( + asset_uploader: asset_uploader, + element: element, + current_content_file_path: current_content_file_path, + root_directory_path: root_directory_path + ) + + if image_link[:errors].any? + warnings.concat(image_link[:errors]) + else + original_text, new_text = image_link[:result] + end + elsif ["h1", "h2", "h3", "h4", "h5", "h6"].include? element.name + original_text, new_text, headers = process_header(element, headers) + end + + html = html.sub(original_text, new_text) if original_text + end + + { + html: html, + errors: [], + warnings: warnings + } + end + + def self.process_header(header, existing_headers) + punctuation_regexp = /[^\p{Word}\- ]/u + text = header.text + id = text.downcase + id.gsub!(punctuation_regexp, "") # remove punctuation + id.tr!(" ", "-") # replace spaces with dash + + if existing_headers[id.to_sym].present? + existing_headers[id.to_sym] = existing_headers[id.to_sym] + 1 + id = "#{id}-#{existing_headers[id.to_sym]}" + else + existing_headers[id.to_sym] = 1 + end + + new_header = header.clone + new_header.set_attribute("id", id) + + [header.to_html, new_header.to_html, existing_headers] + end + end +end diff --git a/gems/bp/lib/block_parser/build_html_from_md_json.rb b/gems/bp/lib/block_parser/build_html_from_md_json.rb new file mode 100644 index 0000000..7ff3277 --- /dev/null +++ b/gems/bp/lib/block_parser/build_html_from_md_json.rb @@ -0,0 +1,158 @@ +require "github/markup" + +module BlockParser + class BuildHtmlFromMdJson + class InvalidMdError < StandardError; end + + def self.process_json(json_hash:, asset_uploader:, root_directory_path:, current_content_file_path:, content_file_paths:, autoscore: false, resource_paths: []) + challenge_position = 0 + vimeo_position = -1 + challenges = [] + errors = [] + warnings = [] + + html = json_hash[:content].collect do |content_object| + if content_object[:type] == "markdown" + processed_md = process_md( + content_object_value: content_object[:value], + current_content_file_path: current_content_file_path, + content_file_paths: content_file_paths, + asset_uploader: asset_uploader, + root_directory_path: root_directory_path, + resource_paths: resource_paths + ) + + errors.concat(processed_md[:errors]) + warnings.concat(processed_md[:warnings]) + + processed_md[:html] + elsif content_object[:type] == "callout" + processed_md = process_md( + content_object_value: content_object[:value], + current_content_file_path: current_content_file_path, + content_file_paths: content_file_paths, + asset_uploader: asset_uploader, + root_directory_path: root_directory_path, + resource_paths: resource_paths + ) + + errors.concat(processed_md[:errors]) + warnings.concat(processed_md[:warnings]) + + processed_md[:html] = "
    #{callout_html(processed_md, content_object[:class])}
    " + elsif content_object[:type] == "vimeo" + vimeo_position += 1 + process_vimeo_json(content_object, vimeo_position) + elsif content_object[:type] == "challenge" + challenge_position += 1 + + processed_challenge = BuildChallenge.execute( + content_object: content_object, + json_hash: json_hash, + position: challenge_position, + asset_uploader: asset_uploader, + root_directory_path: root_directory_path, + current_content_file_path: current_content_file_path, + content_file_paths: content_file_paths, + autoscore: autoscore + ) + + challenges << processed_challenge[:attributes] if processed_challenge[:errors].empty? + errors.concat(processed_challenge[:errors].map { |error| "Challenge ##{challenge_position}: #{content_object[:id]} #{error}" }) + warnings.concat(processed_challenge[:warnings].map { |warning| "Challenge ##{challenge_position}: #{content_object[:id]} #{warning}" }) + + processed_challenge[:html] + end + end.join + + errors << "content cannot be blank" if html.blank? + + html.gsub!("#{content_object_class.gsub('callout-', '').capitalize}" + + icon = if ["callout", "callout-info", "callout-warning", "callout-secondary", "callout-attention", "callout-note", "callout-tip", "callout-hint", "callout-primary", "callout-caution", "callout-light", "callout-dark", "callout-admonition"].include?(content_object_class) + "" + elsif ["callout-danger", "callout-error"].include?(content_object_class) + "" + elsif ["callout-success", "callout-important"].include?(content_object_class) + "" + else + "" + end + + if starts_with_header + icon + processed_md[:html] + else + icon + heading + processed_md[:html] + end + end + + def self.process_vimeo_json(content_object, vimeo_position) + player_id = "vpt_learn#{vimeo_position}" + out = "" + out << "" + + if content_object.key?(:transcript_project) + out << "" + end + + out + end + + def self.process_challenge_json(json_hash:, asset_uploader:, root_directory_path:, current_content_file_path:, content_file_paths:) + errors = [] + warnings = [] + + html = json_hash[:content].collect do |content_object| + next unless content_object[:type] == "markdown" + + processed_md = process_md( + content_object_value: content_object[:value], + asset_uploader: asset_uploader, + root_directory_path: root_directory_path, + current_content_file_path: current_content_file_path, + content_file_paths: content_file_paths + ) + + warnings.concat(processed_md[:warnings]) + if processed_md[:errors].any? + errors.concat(processed_md[:errors]) + else + processed_md[:html] + end + end.join + html.gsub(" _e + { errors: ["Bad image link #{element['src']}"] } + end + end + + private_class_method def self.empty_result + { errors: [], result: [] } + end + end +end diff --git a/gems/bp/lib/block_parser/build_link.rb b/gems/bp/lib/block_parser/build_link.rb new file mode 100644 index 0000000..6a678b5 --- /dev/null +++ b/gems/bp/lib/block_parser/build_link.rb @@ -0,0 +1,76 @@ +require "nokogiri" + +module BlockParser + class BuildLink + class BadInternalLink < StandardError + end + + def self.execute(link:, current_content_file_path:, content_file_paths:, root_directory_path:, resource_paths: []) + href_link = link["href"] + + return [] if ignored_link?(href_link) + + if href_link.start_with?("www", "http", "https") + if link_is_content_link?(href_link) + return transform_to_content_link(href_link, href_link) + else + return transform_to_external_link(href_link, href_link) + end + end + + external_link = true if resource_paths.map { |path| path.include?(href_link) }.include?(true) + + if href_link[0] == "/" + target_file_path = File.join(root_directory_path, href_link) + + raise BadInternalLink, "Bad internal link #{href_link}" unless content_file_paths.include?(link_without_anchor(target_file_path)) + + slashes_count = current_content_file_path.gsub(root_directory_path, "").count("/") + new_link = "" + slashes_count.times { new_link += "../" } + new_link += href_link[1..-1] + + return transform_to_external_link(href_link, new_link) if external_link + + ["href=\"#{href_link}\"", "href=\"#{new_link}\""] + else + target_file_path = Pathname.new(File.dirname(current_content_file_path)).join(CGI.unescape(href_link)).to_s + content_file_path = content_file_paths.find { |path| path.eql?(link_without_anchor(target_file_path)) } + + raise BadInternalLink, "Bad internal link #{href_link}" if content_file_path.blank? + + if external_link && link_is_content_link?(href_link) + transform_to_content_link(href_link, href_link) + elsif external_link + return transform_to_external_link(href_link, href_link) + end + + [] + end + end + + def self.link_is_content_link?(link) + link.include?("content_link/gSchool") + end + + def self.transform_to_external_link(link1, link2) + ["href=\"#{link1}\"", "href=\"#{link2}\" class=\"external-link\" target=\"_blank\""] + end + + def self.transform_to_content_link(link1, link2) + ["href=\"#{link1}\"", "href=\"#{link2}\""] + end + + def self.link_without_anchor(link) + link.include?("#") ? link.split("#").first : link + end + + def self.ignored_link?(href_link) + href_link.nil? || + href_link.strip.empty? || + href_link.start_with?("#") || + href_link.include?("?raw") || + href_link.start_with?("mailto:") + end + end +end diff --git a/gems/bp/lib/block_parser/build_title_from_filename_and_html.rb b/gems/bp/lib/block_parser/build_title_from_filename_and_html.rb new file mode 100644 index 0000000..0812752 --- /dev/null +++ b/gems/bp/lib/block_parser/build_title_from_filename_and_html.rb @@ -0,0 +1,28 @@ +class BuildTitleFromFilenameAndHtml + def self.execute(filename:, html:) + first_h1(html) || humanize_filename(filename) + end + + private_class_method def self.humanize_filename(filename) + title = if CGI.unescape(filename.downcase).start_with?("checkpoint", "instructor", "resource", "hidden") + filename.downcase + else + filename.downcase.gsub(/(\.instructor)/, ""). + gsub(/(\.checkpoint)/, ""). + gsub(/(\.hidden)/, ""). + gsub(/(\.resource)/, "") + end + CGI.unescape(title). + gsub(/\A\d+\s*-\s*/, ""). + gsub(/[-_]/, " "). + gsub(/(\.md)\z/, ""). + gsub(/(md)\z/, ""). + titleize + end + + private_class_method def self.first_h1(html) + return unless html.split("\n").first&.match(/\A

    ]*>(.*)<\/h1>/)[1]) + end +end diff --git a/gems/bp/lib/block_parser/challenge_validators/challenge.rb b/gems/bp/lib/block_parser/challenge_validators/challenge.rb new file mode 100644 index 0000000..cddb2ec --- /dev/null +++ b/gems/bp/lib/block_parser/challenge_validators/challenge.rb @@ -0,0 +1,148 @@ +module BlockParser + module ChallengeValidators + class Challenge + attr_accessor :id, :type, :title, :placeholder, :question, :explanation, :decimal, :answer, :options, :language, + :tests, :standard_uuids, :upstream_repo_path, :hints, :setup, :validate_fork, :docker_directory_path, + :show_tests, :data_path, :rubric, :points, :topics, :partial_credit, :external_source, :external_id + + AUTOSCORE_TYPES = { + checkbox: "checkbox", + code_snippet: "code-snippet", + local_snippet: "local-snippet", + custom_snippet: "custom-snippet", + multiple_choice: "multiple-choice", + number: "number", + poll: "poll", + short_answer: "short-answer", + testable_project: "testable-project" + }.freeze + + MANUAL_SCORE_TYPES = { + paragraph: "paragraph", + project: "project" + }.freeze + + TYPES = AUTOSCORE_TYPES.merge(MANUAL_SCORE_TYPES).freeze + + def initialize(challenge_types) + @hints = [] + @challenge_types = challenge_types + end + + def to_hash + attributes_hash = { + id: id, + type: type, + title: title, + placeholder: nil, + hints: hints + } + + if question.present? + attributes_hash[:question] = { + content: [ + { + type: "markdown", + value: question + } + ] + } + end + + if explanation.present? + attributes_hash[:explanation] = { + content: [ + { + type: "markdown", + value: explanation + } + ] + } + end + + if rubric.present? + attributes_hash[:rubric] = { + content: [ + { + type: "markdown", + value: rubric + } + ] + } + end + + attributes_hash[:decimal] = decimal if type == @challenge_types[:number] + + if type == @challenge_types[:code_snippet] || type == @challenge_types[:local_snippet] + attributes_hash[:show_tests] = convert_bool_string(show_tests) + end + + attributes_hash[:language] = language if type == @challenge_types[:code_snippet] || type == @challenge_types[:custom_snippet] + + attributes_hash[:placeholder] = placeholder unless placeholder.nil? + + attributes_hash[:options] = build_array_from_bullets(options) unless options.nil? + + attributes_hash[:data_path] = data_path unless data_path.nil? + + attributes_hash[:setup] = setup + + attributes_hash[:tests] = tests unless tests.nil? + + attributes_hash[:topics] = topics unless topics.nil? + + attributes_hash[:external_id] = external_id unless external_id.nil? + + attributes_hash[:external_source] = external_source unless external_source.nil? + + if locally_gradeable? || type == @challenge_types[:checkbox] + attributes_hash[:answer] = if locally_gradeable? && type == @challenge_types[:checkbox] + build_array_from_bullets(answer) + elsif locally_gradeable? + answer&.start_with?("* ") ? answer.gsub("* ", "") : answer + end + end + + attributes_hash[:upstream_repo_path] = upstream_repo_path if type == @challenge_types[:testable_project] + + attributes_hash[:standard_uuids] = standard_uuids unless standard_uuids.nil? + + attributes_hash[:points] = points unless points.nil? + + attributes_hash[:partial_credit] = partial_credit.nil? ? false : partial_credit + + attributes_hash[:validate_fork] = convert_bool_string(validate_fork) unless validate_fork.nil? + + attributes_hash[:docker_directory_path] = docker_directory_path if type == @challenge_types[:custom_snippet] + + attributes_hash + end + + private + + def convert_bool_string(bool_string) + bool_string == "true" + end + + def build_array_from_bullets(content) + content.split(/\n\s*[*-]+/).reject(&:empty?).map { |option| unindent(option).gsub(/^[*-]\s/, "") }.map(&:strip) + end + + def unindent(str) + return str unless str.include?("\n") + + lines = str.split("\n") + + minimum_indent = lines.map { |line| !line.empty? ? line[/\A */].size : nil }.compact.min + lines.map { |line| line.gsub(/^ {#{minimum_indent}}/, "") }.join("\n") + end + + def locally_gradeable? + type == @challenge_types[:number] || + type == @challenge_types[:short_answer] || + type == @challenge_types[:multiple_choice] || + type == @challenge_types[:checkbox] + end + end + end +end diff --git a/gems/bp/lib/block_parser/challenge_validators/challenge_validator.rb b/gems/bp/lib/block_parser/challenge_validators/challenge_validator.rb new file mode 100644 index 0000000..72604d4 --- /dev/null +++ b/gems/bp/lib/block_parser/challenge_validators/challenge_validator.rb @@ -0,0 +1,41 @@ +module BlockParser + module ChallengeValidators + class ChallengeValidator + include ::ActiveModel::Validations + + attr_reader :id, :type, :title + + validates :id, presence: true + validates :type, presence: true + validates :title, presence: true + validate :validate_question + validate :validate_points + validate :validate_topics + + def initialize(attributes) + @id = attributes[:id] + @type = attributes[:type] + @title = attributes[:title] + @question = attributes[:question] + @points = attributes[:points] + @topics = attributes[:topics] + end + + private + + def validate_question + return unless @question.nil? || @question[:content].all? { |content| content[:value].blank? } + + errors.add(:question, "can't be blank") + end + + def validate_points + errors.add(:points, "can't be worth more than 10") if !@points.nil? && @points > 10 + end + + def validate_topics + errors.add(:topics, "can't have a length of more than 20 characters") if @topics&.any? { |t| t.length > 20 } + end + end + end +end diff --git a/gems/bp/lib/block_parser/challenge_validators/checkbox_challenge_validator.rb b/gems/bp/lib/block_parser/challenge_validators/checkbox_challenge_validator.rb new file mode 100644 index 0000000..0b0e25a --- /dev/null +++ b/gems/bp/lib/block_parser/challenge_validators/checkbox_challenge_validator.rb @@ -0,0 +1,43 @@ +module BlockParser + module ChallengeValidators + class CheckboxChallengeValidator < ChallengeValidator + attr_reader :options, :answer + + validates :answer, presence: true + validates :options, presence: true + validate :options_has_at_least_two_choices + validate :answer_has_at_least_one_choice + validate :answers_exist_in_options + + def initialize(attributes) + @options = attributes[:options] + @answer = attributes[:answer] + super(attributes) + end + + private + + def options_has_at_least_two_choices + return unless options.present? && options.length < 2 + + errors.add(:options, "must have at least two choices") + end + + def answer_has_at_least_one_choice + return if answer.present? && !answer.empty? + + errors.add(:answer, "must have at least one choice") + end + + def answers_exist_in_options + o = (options || []).map { |opt| opt.delete("\r") } + a = (answer || []).map { |ans| ans.delete("\r") } + return if (o & a).length == a.length + # This is a allow "any" answer hack + return if a.length == 1 && a.first == "*" + + errors.add(:answer, "set must exist in the options") + end + end + end +end diff --git a/gems/bp/lib/block_parser/challenge_validators/code_snippet_challenge_validator.rb b/gems/bp/lib/block_parser/challenge_validators/code_snippet_challenge_validator.rb new file mode 100644 index 0000000..28ed635 --- /dev/null +++ b/gems/bp/lib/block_parser/challenge_validators/code_snippet_challenge_validator.rb @@ -0,0 +1,32 @@ +module BlockParser + module ChallengeValidators + class CodeSnippetChallengeValidator < ChallengeValidator + attr_reader :language, :tests + + validates( + :language, + presence: true, + inclusion: { + in: ["java", "javascript", "python2.7", "python3.6", "sql"], + message: "language must be java, javascript, python2.7, or python3.6, or sql" + } + ) + validates :tests, presence: true + + validate :validate_data_path + + def initialize(attributes) + @language = attributes[:language] + @tests = attributes[:tests] + @data_path = attributes[:data_path] + super(attributes) + end + + def validate_data_path + return true unless @language == "sql" + + errors.add(:data_path, "can't be blank") if @data_path.blank? + end + end + end +end diff --git a/gems/bp/lib/block_parser/challenge_validators/custom_snippet_challenge_validator.rb b/gems/bp/lib/block_parser/challenge_validators/custom_snippet_challenge_validator.rb new file mode 100644 index 0000000..86a4e22 --- /dev/null +++ b/gems/bp/lib/block_parser/challenge_validators/custom_snippet_challenge_validator.rb @@ -0,0 +1,34 @@ +module BlockParser + module ChallengeValidators + class CustomSnippetChallengeValidator < ChallengeValidator + attr_reader :docker_directory_path, :language + + validates( + :docker_directory_path, + :language, + presence: true + ) + + validate :valid_docker_directory, if: :docker_directory_path + + def initialize(attributes) + return unless attributes[:root_directory_path] && attributes[:docker_directory_path] + + @docker_directory_path = File.join(attributes[:root_directory_path], attributes[:docker_directory_path]) + @language = attributes[:language] + super(attributes) + end + + private + + def valid_docker_directory + return errors.add(:docker_directory_path, "points to a directory that doesn't exist") unless File.directory?(@docker_directory_path) + + file_entries = Dir.entries(@docker_directory_path) + ["Dockerfile", "test.sh"].each do |filename| + errors.add(:docker_directory_path, "is missing required file '#{filename}'") unless file_entries.include?(filename) + end + end + end + end +end diff --git a/gems/bp/lib/block_parser/challenge_validators/local_snippet_challenge_validator.rb b/gems/bp/lib/block_parser/challenge_validators/local_snippet_challenge_validator.rb new file mode 100644 index 0000000..bdfcbdb --- /dev/null +++ b/gems/bp/lib/block_parser/challenge_validators/local_snippet_challenge_validator.rb @@ -0,0 +1,16 @@ +module BlockParser + module ChallengeValidators + class LocalSnippetChallengeValidator < ChallengeValidator + attr_reader :placeholder, :tests + + validates :placeholder, presence: true + validates :tests, presence: true + + def initialize(attributes) + @tests = attributes[:tests] + @placeholder = attributes[:placeholder] + super(attributes) + end + end + end +end diff --git a/gems/bp/lib/block_parser/challenge_validators/multiple_choice_challenge_validator.rb b/gems/bp/lib/block_parser/challenge_validators/multiple_choice_challenge_validator.rb new file mode 100644 index 0000000..bc0aa8c --- /dev/null +++ b/gems/bp/lib/block_parser/challenge_validators/multiple_choice_challenge_validator.rb @@ -0,0 +1,34 @@ +module BlockParser + module ChallengeValidators + class MultipleChoiceChallengeValidator < ChallengeValidator + attr_reader :options, :answer + + validates :answer, presence: true + validates :options, presence: true + validate :options_has_at_least_two_choices + validate :answer_exists_in_options + + def initialize(attributes) + @options = attributes[:options] + @answer = attributes[:answer] + super(attributes) + end + + private + + def options_has_at_least_two_choices + return unless options.present? && options.length < 2 + + errors.add(:options, "must have at least two choices") + end + + def answer_exists_in_options + return if options.present? && options.map { |option| option.delete("\r") }.include?(answer) + # This is a allow "any" answer hack + return if answer == "*" + + errors.add(:answer, "must exist in the options") + end + end + end +end diff --git a/gems/bp/lib/block_parser/challenge_validators/number_challenge_validator.rb b/gems/bp/lib/block_parser/challenge_validators/number_challenge_validator.rb new file mode 100644 index 0000000..76a0db0 --- /dev/null +++ b/gems/bp/lib/block_parser/challenge_validators/number_challenge_validator.rb @@ -0,0 +1,16 @@ +module BlockParser + module ChallengeValidators + class NumberChallengeValidator < ChallengeValidator + attr_reader :answer, :decimal + + validates :answer, presence: true + validates :decimal, numericality: { only_integer: true, allow_blank: true, allow_nil: true } + + def initialize(attributes) + super(attributes) + @answer = attributes[:answer] + @decimal = attributes[:decimal] + end + end + end +end diff --git a/gems/bp/lib/block_parser/challenge_validators/paragraph_challenge_validator.rb b/gems/bp/lib/block_parser/challenge_validators/paragraph_challenge_validator.rb new file mode 100644 index 0000000..7c04eac --- /dev/null +++ b/gems/bp/lib/block_parser/challenge_validators/paragraph_challenge_validator.rb @@ -0,0 +1,6 @@ +module BlockParser + module ChallengeValidators + class ParagraphChallengeValidator < ChallengeValidator + end + end +end diff --git a/gems/bp/lib/block_parser/challenge_validators/poll_challenge_validator.rb b/gems/bp/lib/block_parser/challenge_validators/poll_challenge_validator.rb new file mode 100644 index 0000000..b17d911 --- /dev/null +++ b/gems/bp/lib/block_parser/challenge_validators/poll_challenge_validator.rb @@ -0,0 +1,6 @@ +module BlockParser + module ChallengeValidators + class PollChallengeValidator < ChallengeValidator + end + end +end diff --git a/gems/bp/lib/block_parser/challenge_validators/project_challenge_validator.rb b/gems/bp/lib/block_parser/challenge_validators/project_challenge_validator.rb new file mode 100644 index 0000000..d3fcf41 --- /dev/null +++ b/gems/bp/lib/block_parser/challenge_validators/project_challenge_validator.rb @@ -0,0 +1,14 @@ +module BlockParser + module ChallengeValidators + class ProjectChallengeValidator < ChallengeValidator + attr_reader :upstream_repo_path + + validates :upstream_repo_path, absence: true + + def initialize(attributes) + super(attributes) + @upstream_repo_path = attributes[:upstream_repo_path] + end + end + end +end diff --git a/gems/bp/lib/block_parser/challenge_validators/short_answer_challenge_validator.rb b/gems/bp/lib/block_parser/challenge_validators/short_answer_challenge_validator.rb new file mode 100644 index 0000000..5e2357e --- /dev/null +++ b/gems/bp/lib/block_parser/challenge_validators/short_answer_challenge_validator.rb @@ -0,0 +1,14 @@ +module BlockParser + module ChallengeValidators + class ShortAnswerChallengeValidator < ChallengeValidator + attr_reader :answer + + validates :answer, presence: true + + def initialize(attributes) + super(attributes) + @answer = attributes[:answer] + end + end + end +end diff --git a/gems/bp/lib/block_parser/challenge_validators/testable_project_challenge_validator.rb b/gems/bp/lib/block_parser/challenge_validators/testable_project_challenge_validator.rb new file mode 100644 index 0000000..1288003 --- /dev/null +++ b/gems/bp/lib/block_parser/challenge_validators/testable_project_challenge_validator.rb @@ -0,0 +1,167 @@ +require "github_url" +require "octokit" +require "gitlab" + +module BlockParser + module ChallengeValidators + class TestableProjectChallengeValidator < ChallengeValidator + attr_reader :upstream_repo_path + + validates :upstream_repo_path, presence: true + validate :valid_upstream_test_repo + + class InvalidGithubUrlError < StandardError + end + + def initialize(attributes) + super(attributes) + @upstream_repo_path = attributes[:upstream_repo_path] + set_remote_token + @required_files = ["Dockerfile", "test.sh"] + end + + private + + def set_remote_token + return nil if @upstream_repo_path.blank? + + prevent_whitespace_input + if @upstream_repo_path.include?("github") + return if ENV["GITHUB_TOKEN"].nil? + + @remote = "github" + @token = ENV["GITHUB_TOKEN"] + + elsif @upstream_repo_path.include?("gitlab.galvanize") + return if ENV["GITLAB_GALVANIZE_TOKEN"].nil? + + @remote = "gitlab.galvanize" + @token = ENV["GITLAB_GALVANIZE_TOKEN"] + + elsif @upstream_repo_path.include?("gitlab") + return if ENV["GITLAB_TOKEN"].nil? + + @remote = "gitlab" + @token = ENV["GITLAB_TOKEN"] + end + end + + def client + return @client if @client + + if @remote == "github" + @client ||= Octokit::Client.new(api_endpoint: "https://api.github.com", access_token: @token) + elsif @remote == "gitlab.galvanize" + @client ||= Gitlab.client( + endpoint: "https://gitlab.galvanize.com/api/v4", + private_token: @token + ) + elsif @remote == "gitlab" + @client ||= Gitlab.client( + endpoint: "https://gitlab.com/api/v4", + private_token: @token + ) + end + end + + def valid_upstream_test_repo + if @remote == "github" && @token + valid_github + elsif @remote == "gitlab.galvanize" && @token + valid_gitlab + elsif @remote == "gitlab" && @token + valid_gitlab + else + errors.add(:upstream_repo_path, "must be from Github.com or Gitlab.com") + end + end + + def valid_gitlab + files = client.tree(gitlab_repo_props[:repo], ref: gitlab_repo_props[:branch], path: gitlab_repo_props[:path_to_folder]).map(&:name) + if (files & @required_files).length != @required_files.length + (@required_files - (files & @required_files)).each do |file| + errors.add(:upstream_repo_path, ": upstream test repo is missing required file - '#{file}'") + end + end + + return false if errors.any? + rescue Gitlab::Error::NotFound + errors.add(:upstream_repo_path, ": upstream test repo couldn't be found. Verify the repo/branch exists.") + false + end + + def valid_github + unless repo_exists?(client) + errors.add(:upstream_repo_path, ": upstream test repo couldn't be found. Verify the repo/branch exists.") + return false + end + + if repo_props[:path_to_folder] + begin + !!client.contents(repo_props[:repo], path: repo_props[:path_to_folder], ref: repo_props[:branch]) + rescue Octokit::NotFound + errors.add(:upstream_repo_path, ": upstream test repo is missing subfolder(s) '#{repo_props[:path_to_folder]}'") + return false + end + @required_files.map! { |file| file.prepend("#{repo_props[:path_to_folder]}/") } + end + + @required_files.each do |file| + !!client.contents(repo_props[:repo], path: file, ref: repo_props[:branch]) + rescue Octokit::NotFound + errors.add(:upstream_repo_path, ": upstream test repo is missing required file - '#{file}'") + end + + return false if errors.any? + rescue GithubUrl::Invalid => e + errors.add(:upstream_repo_path, e.message) + false + end + + def repo_props + @repo_props ||= parse_repo_url + end + + def gitlab_repo_props + @gitlab_repo_props ||= parse_gitlab_repo_url + end + + def parse_repo_url + github_url = GithubUrl.new(url: upstream_repo_path) + path = github_url.path != "" ? github_url.path : nil + + { repo: github_url.organization + "/" + github_url.repository, branch: github_url.branch, path_to_folder: path } + end + + def parse_gitlab_repo_url + gitlab_url = @upstream_repo_path.split(".com/").last + + @upstream_repo_path.gsub!("/-", "") if gitlab_url.include?("/-/tree/") + + git_url = if gitlab_url.include?("galvanize") + GithubUrl.new(url: @upstream_repo_path, host: "gitlab.galvanize.com") + else + GithubUrl.new(url: @upstream_repo_path, host: "gitlab.com") + end + path = git_url.path != "" ? git_url.path : nil + + { repo: git_url.organization + "/" + git_url.repository, branch: git_url.branch, path_to_folder: path } + end + + def prevent_whitespace_input + upstream_repo_path.gsub!(/\s+/, "") + end + + def repo_exists?(client) + if repo_props[:branch] == "master" + client.repository?(repo_props[:repo]) + else + !!client.branch(repo_props[:repo], repo_props[:branch]) + end + rescue Octokit::NotFound + errors.add(:upstream_repo_path, ": the provided branch of the upstream repo was not found.") + false + end + end + end +end diff --git a/gems/bp/lib/block_parser/convert_md_to_json.rb b/gems/bp/lib/block_parser/convert_md_to_json.rb new file mode 100644 index 0000000..550a70f --- /dev/null +++ b/gems/bp/lib/block_parser/convert_md_to_json.rb @@ -0,0 +1,361 @@ +require "json" + +module BlockParser + class ConvertMdToJson + class MdParseError < StandardError; end + + META_DATA_KEY_REGEX = /\A\s*\*\s+\S+:\s+/ + TYPE_REGEX = /\A\s*\*\s+type:\s+/ + ID_REGEX = /\A\s*\*\s+id:\s+/ + TITLE_REGEX = /\A\s*\*\s+title:\s+/ + STANDARD_UUIDS_REGEX = /\A\s*\*\s+standard_uuids:\s+/ + DECIMAL_REGEX = /\A\s*\*\s+decimal:\s+/ + LANGUAGE_REGEX = /\A\s*\*\s+language:\s+/ + DATAPATH_REGEX = /\A\s*\*\s+data_path:\s+/ + UPSTREAM_REPO_REGEX = /\A\s*\*\s+upstream:\s+/ + VALIDATE_FORK_REGEX = /\A\s*\*\s+validate_fork:\s+/ + DOCKER_DIRECTORY_PATH_REGEX = /\A\s*\*\s+docker_directory_path:\s+/ + SHOW_TESTS_REGEX = /\A\s*\*\s+show_tests:\s+/ + POINTS_REGEX = /\A\s*\*\s+points:\s+/ + PARTIAL_CREDIT_REGEX = /\A\s*\*\s+partial_credit:\s+/ + TOPICS_REGEX = /\A\s*\*\s+topics:\s+/ + EXTERNAL_ID_REGEX = /\A\s*\*\s+external_id:\s+/ + EXTERNAL_SOURCE_REGEX = /\A\s*\*\s+external_source:\s+/ + + TRANSCRIPT_PROJECT_REGEX = /\A\s*\*\s+transcript_project:\s+/ + TRANSCRIPT_FILE_REGEX = /\A\s*\*\s+transcript_file:\s+/ + TRANSCRIPT_PLUGIN_REGEX = /\A\s*\*\s+transcript_plugin:\s+/ + TRANSCRIPT_TAGS = %i[transcript_project transcript_file transcript_plugin] + + TAG_REGEX = /\A\s*\#{1,5}\s+\!.*\z/ + TAG_THAT_IS_NOT_START_CHALLENGE_CHILD_TAG_REGEX = + /\A\s*\#{1,5}\s+\!(?!(question|placeholder|explanation|options|given-code|rubric|callout)\s*\z)/ + + def self.convert(md_plain_text) + content_array = [] + challenges_hash = {} + + md_lines = [] + challenge_lines = [] + vimeo_lines = [] + callout_lines = [] + + parsing_challenge = false + parsing_instructor_notes = false + parsing_vimeo = false + parsing_callout = false + callout_type = nil + + vimeo_videos_count = 0 + + begin + lines = md_plain_text.split("\n") + rescue ArgumentError + raise MdParseError, "file does not appear to be a valid markdown file" + end + + lines.each do |line| + if parsing_challenge + if end_tag?("challenge", line) + parsing_challenge = false + + if challenge_lines.present? + challenge = build_challenge_object(challenge_lines) + + return raise MdParseError, "Found !challenge without an id." if challenge.id.nil? + return raise MdParseError, "Found duplicate challenge id: #{challenge.id}." if challenges_hash[challenge.id.to_sym].present? + + content_array << { + "type": "challenge", + "id": challenge.id + } + challenges_hash[challenge.id.to_sym] = challenge.to_hash + + challenge_lines = [] + end + elsif start_tag?("challenge", line) + raise MdParseError, "Found second !challenge tag before finding !end-challenge." + else + challenge_lines << line + end + elsif parsing_instructor_notes + parsing_instructor_notes = false if end_tag?("instructor", line) + elsif parsing_vimeo + if end_tag?("vimeo", line) + parsing_vimeo = false + + if vimeo_lines.any? + content_array << build_vimeo_object(vimeo_lines) + + vimeo_videos_count += 1 + vimeo_lines = [] + end + else + vimeo_lines << line + end + elsif parsing_callout + if end_tag?("callout", line) + parsing_callout = false + if callout_lines.any? + content_array << { + "type": "callout", + "class": callout_type, + "value": callout_lines.map(&:strip).join("\n") + } + callout_lines = [] + callout_type = nil + end + else + callout_lines << line + end + elsif start_tag?("challenge", line) + parsing_challenge = true + + if md_lines.present? + md_value = md_lines.join("\n") + if md_value.strip.present? + content_array << { + "type": "markdown", + "value": md_value + } + end + md_lines = [] + end + elsif start_tag?("instructor", line) + parsing_instructor_notes = true + elsif start_callout_tag?("callout", line) + parsing_callout = true + callout_type = line.split("!").last + if md_lines.present? + md_value = md_lines.join("\n") + if md_value.strip.present? + content_array << { + "type": "markdown", + "value": md_value + } + end + md_lines = [] + end + elsif start_tag?("vimeo", line) + parsing_vimeo = true + + if md_lines.present? + md_value = md_lines.join("\n") + if md_value.strip.present? + content_array << { + "type": "markdown", + "value": md_value + } + end + md_lines = [] + end + elsif end_tag?("instructor", line) + raise MdParseError, "Found invalid tag 'end-instructor' without a starting !instructor tag." + elsif end_tag?("challenge", line) + raise MdParseError, "Found invalid tag 'end-challenge' without a starting !challenge tag." + elsif end_tag?("vimeo", line) + raise MdParseError, "Found invalid tag 'end-vimeo' without a starting !vimeo tag." + elsif line.match(TAG_REGEX) + raise MdParseError, "Found invalid tag '#{line.strip}' outside of a !challenge tag." + else + md_lines << line + end + end + + raise MdParseError, "Didn't find !end-challenge tag." if parsing_challenge + raise MdParseError, "Didn't find !end-vimeo tag." if parsing_vimeo + raise MdParseError, "Missing !end-instructor tag for existing !instructor tag" if parsing_instructor_notes + raise MdParseError, "There can only be up to 10 vimeo videos in single page" if vimeo_videos_count > 10 + + if md_lines.present? + md_value = md_lines.join("\n") + if md_value.strip.present? + content_array << { + "type": "markdown", + "value": md_value + } + end + md_lines = [] + end + + result = { + "content": content_array + } + + result[:challenges] = challenges_hash if challenges_hash.present? + + result + end + + def self.build_vimeo_object(vimeo_lines) + line_index = 0 + + vimeo_object = { + type: "vimeo" + } + + while line_index < vimeo_lines.length + if vimeo_lines[line_index].downcase.match(ID_REGEX) + vimeo_object[:id] = vimeo_lines[line_index].gsub(ID_REGEX, "").strip + elsif vimeo_lines[line_index].downcase.match(TRANSCRIPT_PROJECT_REGEX) + vimeo_object[:transcript_project] = vimeo_lines[line_index].gsub(TRANSCRIPT_PROJECT_REGEX, "").strip + elsif vimeo_lines[line_index].downcase.match(TRANSCRIPT_FILE_REGEX) + vimeo_object[:transcript_file] = vimeo_lines[line_index].gsub(TRANSCRIPT_FILE_REGEX, "").strip + elsif vimeo_lines[line_index].downcase.match(TRANSCRIPT_PLUGIN_REGEX) + vimeo_object[:transcript_plugin] = vimeo_lines[line_index].gsub(TRANSCRIPT_PLUGIN_REGEX, "").strip + end + + line_index += 1 + end + + raise(MdParseError, "Vimeo tag missing ID") unless vimeo_object.key?(:id) + + # If transcript tags are present, but not all are provided + if !(TRANSCRIPT_TAGS & vimeo_object.keys).empty? && (TRANSCRIPT_TAGS & vimeo_object.keys).length != TRANSCRIPT_TAGS.length + raise(MdParseError, "Vimeo tags with transcripts must include the project, file, and plugin") + end + + vimeo_object + end + + def self.build_challenge_object(challenge_lines) + challenge = ChallengeValidators::Challenge.new(ChallengeValidators::Challenge::TYPES) + + line_index = 0 + + parsing_meta_information = true + has_setup = false + + while line_index < challenge_lines.length + parsing_meta_information = false if parsing_meta_information && challenge_lines[line_index].match(/\A\s*\#{1,5}\s+\!/) + + if parsing_meta_information + if challenge_lines[line_index].downcase.match(TYPE_REGEX) + challenge.type = challenge_lines[line_index].gsub(TYPE_REGEX, "").strip + elsif challenge_lines[line_index].downcase.match(ID_REGEX) + challenge.id = challenge_lines[line_index].gsub(ID_REGEX, "").strip + elsif challenge_lines[line_index].downcase.match(TITLE_REGEX) + challenge.title = challenge_lines[line_index].gsub(TITLE_REGEX, "").strip + elsif challenge_lines[line_index].downcase.match(STANDARD_UUIDS_REGEX) + if challenge.standard_uuids.present? + raise( + MdParseError, + "Found multiple standard assignments on '#{challenge_lines[line_index].strip}' within a !challenge tag." + ) + end + challenge.standard_uuids = challenge_lines[line_index].gsub(STANDARD_UUIDS_REGEX, "").split(",").map(&:strip) + elsif challenge_lines[line_index].downcase.match(DECIMAL_REGEX) + challenge.decimal = challenge_lines[line_index].gsub(DECIMAL_REGEX, "").strip + elsif challenge_lines[line_index].downcase.match(LANGUAGE_REGEX) + challenge.language = challenge_lines[line_index].gsub(LANGUAGE_REGEX, "").strip + elsif challenge_lines[line_index].downcase.match(DATAPATH_REGEX) + challenge.data_path = challenge_lines[line_index].gsub(DATAPATH_REGEX, "").strip + elsif challenge_lines[line_index].downcase.match(UPSTREAM_REPO_REGEX) + challenge.upstream_repo_path = challenge_lines[line_index].gsub(UPSTREAM_REPO_REGEX, "").strip + elsif challenge_lines[line_index].downcase.match(VALIDATE_FORK_REGEX) + challenge.validate_fork = challenge_lines[line_index].gsub(VALIDATE_FORK_REGEX, "").strip + elsif challenge_lines[line_index].downcase.match(DOCKER_DIRECTORY_PATH_REGEX) + challenge.docker_directory_path = challenge_lines[line_index].gsub(DOCKER_DIRECTORY_PATH_REGEX, "").strip + elsif challenge_lines[line_index].downcase.match(SHOW_TESTS_REGEX) + challenge.show_tests = challenge_lines[line_index].gsub(SHOW_TESTS_REGEX, "").strip.downcase + elsif challenge_lines[line_index].downcase.match(POINTS_REGEX) + challenge.points = challenge_lines[line_index].gsub(POINTS_REGEX, "").strip.downcase.to_i + elsif challenge_lines[line_index].downcase.match(PARTIAL_CREDIT_REGEX) + challenge.partial_credit = challenge_lines[line_index].gsub(PARTIAL_CREDIT_REGEX, "").strip + elsif challenge_lines[line_index].downcase.match(TOPICS_REGEX) + challenge.topics = challenge_lines[line_index].gsub(TOPICS_REGEX, "").gsub(/\[|\]/, "").split(",").map do |topic| + topic.delete('"').delete("'").strip.downcase + end.uniq + elsif challenge_lines[line_index].downcase.match(EXTERNAL_ID_REGEX) + challenge.external_id = challenge_lines[line_index].gsub(EXTERNAL_ID_REGEX, "").strip + elsif challenge_lines[line_index].downcase.match(EXTERNAL_SOURCE_REGEX) + challenge.external_source = challenge_lines[line_index].gsub(EXTERNAL_SOURCE_REGEX, "").strip + elsif challenge_lines[line_index].downcase.match(META_DATA_KEY_REGEX) + raise MdParseError, "Found invalid meta data key '#{challenge_lines[line_index].strip}' within a !challenge tag." + end + elsif start_tag?("placeholder", challenge_lines[line_index]) + line_index, placeholder_text = parse_challenge_child_tag(challenge_lines, line_index, "placeholder") + challenge.placeholder = placeholder_text.sub(/\A\s*```.*\s*/, "").sub(/```\s*\z/, "").strip + elsif start_tag?("question", challenge_lines[line_index]) + line_index, question_text = parse_challenge_child_tag(challenge_lines, line_index, "question") + challenge.question = question_text + elsif start_tag?("explanation", challenge_lines[line_index]) + line_index, explanation_text = parse_challenge_child_tag(challenge_lines, line_index, "explanation") + challenge.explanation = explanation_text + elsif start_tag?("rubric", challenge_lines[line_index]) + line_index, rubric_text = parse_challenge_child_tag(challenge_lines, line_index, "rubric") + challenge.rubric = rubric_text + elsif start_tag?("hint", challenge_lines[line_index]) + line_index, hint_text = parse_challenge_child_tag(challenge_lines, line_index, "hint") + if hint_text.include?("```") + lang = hint_text.match(/```(js|java|python|json)/m) + lang = lang[1] unless lang.nil? + plain_text = hint_text.sub(/\A\s*```.*\s*/, "").sub(/```\s*\z/, "") + proccessed = "
    #{plain_text.tr('"', "'")}
    " + challenge.hints << proccessed + elsif hint_text.include?("`") # TODO: if ambitious, these could be made into markdown content types... + backticks = hint_text.scan(/`.*?`/) + backticks.each { |backtick| hint_text.gsub!(backtick, "#{backtick[1..backtick.length - 2]}") } + challenge.hints << hint_text.strip + else + challenge.hints << hint_text.strip + end + elsif start_tag?("answer", challenge_lines[line_index]) + line_index, answer_text = parse_challenge_child_tag(challenge_lines, line_index, "answer") + challenge.answer = answer_text.strip + elsif start_tag?("options", challenge_lines[line_index]) + line_index, options_text = parse_challenge_child_tag(challenge_lines, line_index, "options") + challenge.options = options_text + elsif start_tag?("setup", challenge_lines[line_index]) + line_with_error = line_index + 2 + raise MdParseError, "Duplicate !setup tag detected on line #{line_with_error}" if has_setup + + line_index, setup_text = parse_challenge_child_tag(challenge_lines, line_index, "setup") + challenge.setup = setup_text.sub(/\A\s*```.*\s*/, "").sub(/```\s*\z/, "") + has_setup = true + elsif start_tag?("tests", challenge_lines[line_index]) + line_index, tests_text = parse_challenge_child_tag(challenge_lines, line_index, "tests") + challenge.tests = tests_text.sub(/\A\s*```.*\s*/, "").sub(/```\s*\z/, "") + elsif challenge_lines[line_index].downcase.match(TAG_THAT_IS_NOT_START_CHALLENGE_CHILD_TAG_REGEX) + raise MdParseError, "Found invalid tag '#{challenge_lines[line_index]}' within a !challenge tag." + end + line_index += 1 + end + challenge + end + + def self.parse_challenge_child_tag(challenge_lines, line_index, tag_name) + line_index += 1 + child_tag_lines = [] + while challenge_lines.length > line_index && !end_tag?(tag_name, challenge_lines[line_index]) + if challenge_lines[line_index].match(TAG_REGEX) + raise MdParseError, "Found invalid tag '#{challenge_lines[line_index].strip}' within a !#{tag_name} tag." + end + + child_tag_lines << challenge_lines[line_index] + line_index += 1 + end + + raise MdParseError, "Didn't find !end-#{tag_name} tag." if challenge_lines[line_index].nil? + + [line_index, child_tag_lines.join("\n")] + end + + def self.end_tag?(type, line) + end_tag_regex = /\A\s*\#{1,5}\s+\!end-#{type}\s*\z/ + line.downcase.match(end_tag_regex) + end + + def self.start_tag?(type, line) + end_tag_regex = /\A\s*\#{1,5}\s+\!#{type}\s*\z/ + line.downcase.match(end_tag_regex) + end + + def self.start_callout_tag?(_type, line) + end_tag_regex = /\A\s*\#{1,5}\s+\!callout.*\z/ + line.downcase.match(end_tag_regex) + end + + private_class_method :build_challenge_object, :build_vimeo_object, :parse_challenge_child_tag, :end_tag?, :start_tag? + end +end diff --git a/gems/bp/lib/block_parser/parse_directory.rb b/gems/bp/lib/block_parser/parse_directory.rb new file mode 100644 index 0000000..b5fc270 --- /dev/null +++ b/gems/bp/lib/block_parser/parse_directory.rb @@ -0,0 +1,182 @@ +require "psych" +require "yaml" + +module BlockParser + class ParseDirectory + README_CAPS = "README.md" + README_LOWER = "readme.md" + CONFIG_FILENAME_YAML = "config.yaml" + CONFIG_FILENAME_YML = "config.yml" + AUTO_CONFIG_FILENAME_YAML = "autoconfig.yaml" + class InvalidConfigError < StandardError + end + + def initialize(path:, asset_uploader:) + @block_hash = {} + @errors = [] + @warnings = [] + @content_file_attribute_hashes = [] + @path = path + @asset_uploader = asset_uploader + end + + def execute + raise InvalidConfigError, "Directory does not exist" unless File.directory?(@path) + + if Dir.entries(@path).include?(CONFIG_FILENAME_YAML) && Dir.entries(@path).include?(CONFIG_FILENAME_YML) + raise(InvalidConfigError, "Found both a config.yaml and a config.yml. only one config file is allowed.") + end + + unless Dir.entries(@path).include?(CONFIG_FILENAME_YAML) || + Dir.entries(@path).include?(CONFIG_FILENAME_YML) || + Dir.entries(@path).include?(AUTO_CONFIG_FILENAME_YAML) + raise(InvalidConfigError, "Root directory does not contain a #{CONFIG_FILENAME_YAML} or #{CONFIG_FILENAME_YML} file") + end + + config_path = if Dir.entries(@path).include?(CONFIG_FILENAME_YAML) + File.join(@path, CONFIG_FILENAME_YAML) + elsif Dir.entries(@path).include?(CONFIG_FILENAME_YML) + File.join(@path, CONFIG_FILENAME_YML) + elsif Dir.entries(@path).include?(AUTO_CONFIG_FILENAME_YAML) + File.join(@path, AUTO_CONFIG_FILENAME_YAML) + end + + readme_path = if Dir.entries(@path).include?(README_CAPS) + File.join(@path, README_CAPS) + elsif Dir.entries(@path).include?(README_LOWER) + File.join(@path, README_LOWER) + end + + @readme_text = unless readme_path.blank? + text = File.read(readme_path).split("\n").reject(&:empty?) + text[0..2].join("\n") + end + + begin + config = YAML.load_file(config_path) + rescue Psych::SyntaxError => e + raise InvalidConfigError, "Could not parse config.yaml: #{e.message.gsub("(#{config_path}): ", '')}" + end + + raise InvalidConfigError, "config.yaml must be a hash" unless config.is_a?(Hash) + raise InvalidConfigError, "config.yaml must have a key of 'Standards'" unless config.key?("Standards") + + parsed_standards = ParseStandards.new(config["Standards"], @path).execute + if parsed_standards[:errors].any? + @errors.concat(parsed_standards[:errors]) + else + content_file_local_paths = + Dir[File.join(@path, "**/*")]. + reject { |fn| File.directory?(fn) }. + select { |file_path| file_path[-3..-1] == ".md" || file_path[-6..-1] == ".ipynb" || file_path[-4..-1] == ".pdf" } + + resource_paths = [] + parsed_standards[:standards_attributes].each do |standard| + standard[:content_files_attributes].each do |cfa| + resource_paths << cfa[:path] if cfa[:content_file_type] == BlockParser::ParseStandards::CONTENT_FILE_TYPES[:resource] + end + end + + @block_hash = parsed_standards[:standards_attributes].map do |standard| + content_file_attribute_hashes = standard[:content_files_attributes].map do |cfa| + content_file_search_path = [@path.gsub(/\/$/, ""), cfa[:path].gsub(/^\//, "")].join("/") + content_file_local_path = content_file_local_paths.find { |path| path == content_file_search_path } + + raise InvalidConfigError, "content file in config.yaml must exist" if content_file_local_path.nil? + + parsed_file = parse_file( + content_file_local_path: content_file_local_path, + content_file_local_paths: content_file_local_paths, + resource_paths: resource_paths, + cfa: cfa + ) + @warnings.concat(parsed_file[:warnings]) + + path = content_file_local_path.gsub(@path.to_s, "") + + parsed_errors = parsed_file[:errors] + + if cfa[:content_file_type] == BlockParser::ParseStandards::CONTENT_FILE_TYPES[:checkpoint] && + (parsed_file[:challenges].nil? || parsed_file[:challenges].empty?) + + parsed_errors << "checkpoint must have at least one challenge and all challenges must be valid" + end + + @errors.concat(parsed_errors.map { |error| "#{path}: #{error}" }) + + { + title: parsed_file[:title], + html: parsed_file[:html], + challenges: parsed_file[:challenges], + path: content_file_local_path[-4..-1] == ".pdf" ? path.gsub(".pdf", "_pdf") : path, + content_file_type: cfa[:content_file_type], + uid: cfa[:uid], + autoscore: cfa[:autoscore], + default_visibility: cfa[:default_visibility], + max_checkpoint_submissions: cfa[:max_checkpoint_submissions], + time_limit: cfa[:time_limit], + warnings: parsed_file[:warnings] + } + end + + { standard: standard, content_file_attribute_hashes: content_file_attribute_hashes } + end + end + + results + rescue InvalidConfigError => e + @errors << e.message + results + end + + private + + def parse_file(content_file_local_path:, content_file_local_paths:, resource_paths:, cfa:) + if content_file_local_path[-3..-1] == ".md" + BlockParser::ParseMarkdownFile.execute( + file_body: File.read(content_file_local_path), + asset_uploader: @asset_uploader, + root_directory_path: @path, + current_content_file_path: content_file_local_path, + content_file_paths: content_file_local_paths, + autoscore: cfa[:autoscore], + resource_paths: resource_paths + ) + elsif content_file_local_path[-6..-1] == ".ipynb" + _out, failure, status = Open3.capture3("jupyter nbconvert --to markdown #{content_file_local_path}") + + if status.success? + BlockParser::ParseMarkdownFile.execute( + file_body: File.read(content_file_local_path.gsub(".ipynb", ".md")), + asset_uploader: @asset_uploader, + root_directory_path: @path, + current_content_file_path: content_file_local_path, + content_file_paths: content_file_local_paths, + autoscore: cfa[:autoscore], + resource_paths: resource_paths + ) + else + { title: "", html: "", challenges: [], errors: [failure], warnings: [] } + end + elsif content_file_local_path[-4..-1] == ".pdf" + content_url = @asset_uploader.find_or_create_content(full_path: content_file_local_path) + { + title: cfa[:path].split("/").last.titleize, + html: content_url, + errors: [], + warnings: [], + challenges: [] + } + end + end + + def results + { + readme_text: @readme_text, + errors: @errors, + warnings: @warnings, + block_hash: @block_hash + } + end + end +end diff --git a/gems/bp/lib/block_parser/parse_markdown_file.rb b/gems/bp/lib/block_parser/parse_markdown_file.rb new file mode 100644 index 0000000..34b55f3 --- /dev/null +++ b/gems/bp/lib/block_parser/parse_markdown_file.rb @@ -0,0 +1,40 @@ +module BlockParser + class ParseMarkdownFile + def self.execute(file_body:, asset_uploader:, root_directory_path:, + current_content_file_path:, content_file_paths:, autoscore: false, resource_paths: []) + errors = [] + warnings = [] + html = "" + + json_hash = ConvertMdToJson.convert(file_body) + processed_md_results = BuildHtmlFromMdJson.process_json( + json_hash: json_hash, + asset_uploader: asset_uploader, + root_directory_path: root_directory_path, + current_content_file_path: current_content_file_path, + content_file_paths: content_file_paths, + autoscore: autoscore, + resource_paths: resource_paths + ) + + html = processed_md_results[:html] + title = BuildTitleFromFilenameAndHtml.execute( + filename: File.basename(current_content_file_path), + html: processed_md_results[:html] + ) + challenges = processed_md_results[:challenges] + errors.concat(processed_md_results[:errors]) + warnings.concat(processed_md_results[:warnings]) + + results(html, title, challenges, errors, warnings) + rescue ConvertMdToJson::MdParseError => e + errors << "Could not parse markdown: #{e}" + + results(html, title, challenges, errors, warnings) + end + + def self.results(html, title, challenges, errors, warnings) + { challenges: challenges, errors: errors, html: html, title: title, warnings: warnings } + end + end +end diff --git a/gems/bp/lib/block_parser/parse_standards.rb b/gems/bp/lib/block_parser/parse_standards.rb new file mode 100644 index 0000000..83f842b --- /dev/null +++ b/gems/bp/lib/block_parser/parse_standards.rb @@ -0,0 +1,145 @@ +module BlockParser + class ParseStandards + CONTENT_FILE_TYPES = { + checkpoint: "checkpoint", + lesson: "lesson", + resource: "resource", + instructor: "instructor" + }.freeze + + def initialize(standards, absolute_directory_path) + @absolute_directory_path = absolute_directory_path + @standards = standards + @standards_attributes = [] + @errors = [] + end + + def execute + unless @standards&.any? + @errors << "Configuration must have at least one standard" + return results + end + + all_content_file_uids = {} # use this hash to ensure unique content file uids + @standards.each_with_index do |standard, index| + unless standard.is_a?(Hash) + @errors << "Standard ##{index + 1} must be a hash" + next + end + + standard_errors = [] + + standard_errors << "Standard ##{index + 1} must have Title" if standard["Title"].blank? + standard_errors << "Standard ##{index + 1} must have UID" if standard["UID"].blank? + standard_errors << "Standard ##{index + 1} must have Description" if standard["Description"].blank? + + unless standard.key?("SuccessCriteria") && standard["SuccessCriteria"].is_a?(Array) && standard["SuccessCriteria"].any? + standard_errors << "Standard ##{index + 1} must have at least one SuccessCriteria" + end + + content_files_attributes = [] + + if standard.key?("ContentFiles") && standard["ContentFiles"].is_a?(Array) && standard["ContentFiles"].any? + + checkpoint_count = standard["ContentFiles"].count { |content_file| content_file["Type"] == "Checkpoint" } + standard_errors << "Standard ##{index + 1} may not have more than one Checkpoint." unless checkpoint_count <= 1 + + standard["ContentFiles"].each_with_index do |content_file, content_file_index| + if content_file["Path"].present? && content_file["Path"].start_with?("/") + file_ext = content_file["Path"].split(".").last + if ["md", "ipynb", "pdf"].include?(file_ext) + if File.exist?(File.join(@absolute_directory_path, content_file["Path"])) + visibility = content_file["DefaultVisibility"].present? ? content_file["DefaultVisibility"] : "visible" + content_file_attributes = { + content_file_type: content_file["Type"].downcase, + path: content_file["Path"], + autoscore: false, + uid: content_file["UID"], + default_visibility: visibility.downcase + } + if content_file["UID"].blank? + standard_errors << "Standard ##{index + 1}: Content File referenced at #{content_file['Path']} does not have a UID" + elsif all_content_file_uids[content_file["UID"]] + standard_errors << "Duplicate Content File UID: #{content_file['UID']}" + end + all_content_file_uids[content_file["UID"]] = true + if content_file["Type"].casecmp(CONTENT_FILE_TYPES[:checkpoint]).zero? + content_file_attributes[:autoscore] = content_file["Autoscore"] == true + end + if content_file["Type"].casecmp(CONTENT_FILE_TYPES[:checkpoint]).zero? && + content_file["MaxCheckpointSubmissions"] && + content_file["MaxCheckpointSubmissions"].to_i != 0 + content_file_attributes[:max_checkpoint_submissions] = content_file["MaxCheckpointSubmissions"].to_i + end + if content_file["Type"].casecmp(CONTENT_FILE_TYPES[:checkpoint]).zero? && + content_file["TimeLimit"] && + content_file["TimeLimit"].to_i != 0 + if content_file["TimeLimit"].class == Integer + content_file_attributes[:time_limit] = content_file["TimeLimit"] + else + standard_errors << "Checkpoint #{content_file['UID']} TimeLimit must be a number only (number specifies minutes)" + end + end + content_files_attributes << content_file_attributes + else + standard_errors << "Standard ##{index + 1}: Content File referenced at #{content_file['Path']} does not exist" + end + else + valid_ext = ".md, .ipynb, or .pdf" + standard_errors << "Standard ##{index + 1}: Content File referenced at #{content_file['Path']} must be a #{valid_ext} file" + end + else + standard_errors << + "Standard ##{index + 1}: ContentFile ##{content_file_index + 1} must have a path starting with /" + end + end + + if content_files_attributes.none? { |cfa| %w[lesson checkpoint].include?(cfa[:content_file_type]) } + standard_errors << "Standard ##{index + 1}: Must have at least one lesson or checkpoint" + end + else + standard_errors << "Standard ##{index + 1} must have at least one ContentFile" + end + + @errors.concat(standard_errors) + + @standards_attributes << { + title: standard["Title"], + uid: standard["UID"], + description: standard["Description"], + success_criteria: standard["SuccessCriteria"], + content_files_attributes: content_files_attributes + } + end + + @standards_attributes.group_by { |attributes| attributes[:uid] }.values.select { |value| value.length > 1 }.each do |duplicate_set| + titles = duplicate_set.map { |standard| standard[:title] } + @errors << "Duplicate Standard UID used for standards with titles: #{titles.join(', ')}" + end + + content_file_paths = @standards_attributes.flat_map do |attrs| + attrs[:content_files_attributes].map { |content_file| content_file[:path] } + end + content_file_paths.select { |p1| content_file_paths.count { |p2| p2 == p1 } > 1 }.uniq.each do |duplicate_path| + @errors << "ContentFile #{duplicate_path} used more than once" + end + + checkpoint_content_file_uids = @standards_attributes.flat_map do |attrs| + attrs[:content_files_attributes].map do |content_file| + content_file[:uid] if content_file[:content_file_type] == CONTENT_FILE_TYPES[:checkpoint] + end + end.compact + checkpoint_content_file_uids.select { |p1| checkpoint_content_file_uids.count { |p2| p2 == p1 } > 1 }.uniq.each do |duplicate_uid| + @errors << "Checkpoint UID #{duplicate_uid} used more than once" + end + + results + end + + private + + def results + { errors: @errors, standards_attributes: @standards_attributes } + end + end +end diff --git a/gems/bp/lib/block_parser/version.rb b/gems/bp/lib/block_parser/version.rb new file mode 100644 index 0000000..121bc61 --- /dev/null +++ b/gems/bp/lib/block_parser/version.rb @@ -0,0 +1,3 @@ +module BlockParser + VERSION = "0.1.0" +end diff --git a/gems/bp/pkg/block_parser-0.1.0.gem b/gems/bp/pkg/block_parser-0.1.0.gem new file mode 100644 index 0000000000000000000000000000000000000000..0cee2b78d29536c4bedc1e70fc6639200e28076a GIT binary patch literal 5120 zcmeH}XH*l&7RMu~QKU#Of*?pU3Iqcf!37k7NLxTeK)?h-4Fm`^=1Gwb5{lGNLst+5 zMWkuyy@V2sG=UXGkt!f1S$ywjDj=D+^U{p*Cpd=?O}B z3nIc94_%H~NlTHae4LTwF^Qgq!YGM)#s{@eII=z7*&e54)ow2m^b1!*iU)Rd^Q{AG zHU#dUs~>vVZ0`0pI9{Wi36Yi*iRS2zK5(h>=4sYueAmthEBlp&=(ljLo(P##3y^X1 zVDE_%?+|%K31e(`$C-pFV4uZPZ)Lle_*0A%PH;I0ETk(~o#i42Ym0d8O$H%<+C}-d zeF!kVr@#=Bq2>7-p5T8@RdAKFUF}Ynn#Vr9rm*rdR-Ri|$4je{%p#)lpBNhjdg9M~ z*>UH)YtRKwTS%QkFRyrzA-EN3*Lim>+3<#U$bcQ!GDDMe63>8b|&5)ca)w7i!9Ji9)KYIp(+)mrX_+^%y9%3!mpj2uzA;EWp*py6_z;y?-GKlJZ(9$*NRX%n{Y_j^% zqj%RLVuy2*^BA0uvFDi;Isu;TtBDGax9l(BGj)I0#o@mbFF9vdD7|#+B7`v98Fl!5 zGD|B9$ko)~IrOUv(wCsILNw z;)Pl6R5V6+06ue|+7zSBww1M``g((8xTraogy(4a?#Sf>Wg%V;ThSLneI(RmAmPM- z)Eiqj`vd!$`>w~DW2NtHYxz1tW(w4#;zoTL6R(R*R%?PlgI04;s0GZrp=JLOObH+) z!2vjNQOaKA-2Qzb>D_H{Ym528Z0bEkajEAo)pb#Hl=4v)ob=cUF3knM6nB5hI?zE*z z0%oQ=b)1cc*P<+{@)tUW(Zho152WDgAWv2rZfAL3Ehm#R#lYYM65zGSx;Yyua`*Qm zMh#Ef>Zk$z!S>2*OB{TwupuLj2mEuQ1=B&xZcM$1krj!#cGwC|-yMTKlq6uf^>pzM z80W^nmY0r70kFrNkQ(Yd+4<-BCIwa|oB{x*lbX^AXhzLhO-G633HtX1Kj(=MEMK+o|6VniVHy_zJxqx?(N;TSdW?2}u>2i#A15ViQxu zOpRozpQ(^{s_=;6)_b*%-A=E$c&%U6Se9~l8>S?_UFyxTOzhC(ZQ%JNq0rIWo)id&W?ujN`@Dp)Kdg5X zkxpj>1S&000Qmk+R{p#(HV#M|XN;E%M#c~Bg8DJ9z}K(wfBFB*LBI;%@gJfHmfPe1 z&$tEO_>YWLc4d@fzOW0_>o8S> zqZ!e#{lS22CyzGg@^n$?v!=NIB;gR88?OQO3$U6!#CLN_T_clogSo=qTlNB|uY(i5 zKfI(7y6V=eQg0)Woao)duE|+}WQz6k`68prd$^=qt&w<8-IYT}pfgx#WOW%>T*8AQ V?)w>X@2# { + "id": content_file_identifier, + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:multiple_choice], + "title": "People Skills", + "answer": "Peter Grunde", + "topics": ["cool", "beans", "dude"], + "options": [ + "Peter Grunde", + "Dr. No", + "James Bond", + "La Chaiffre", + "Jaws" + ], + "question": { + content: [ + { + "type": "markdown", + "value": "\nWho is the coolest?\n" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\nBecause,duh.\n" + } + ] + }, + "rubric": { + "content": [ + { + "type": "markdown", + "value": "\nBecause,duh again.\n" + } + ] + } + } + } + } + end + + let(:checkbox_json) do + { + content: [ + { + type: "challenge", + id: content_file_identifier + } + ], + challenges: { + content_file_identifier.to_sym => { + "id": content_file_identifier, + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:checkbox], + "title": "Humans", + "answer": ["Peter Grunde", "Bradford Hamilton"], + "options": [ + "Peter Grunde", + "Dr. No", + "James Bond", + "La Chaiffre", + "Jaws", + "Bradford Hamilton" + ], + "question": { + content: [ + { + "type": "markdown", + "value": "\nWho is the coolest?\n" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\nThey are humans.\n" + } + ] + } + } + } + } + end + + let(:project_challenge_json) do + { + content: [ + { + type: "challenge", + id: content_file_identifier + } + ], + challenges: { + content_file_identifier.to_sym => { + "id": content_file_identifier, + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:project], + "title": "partial derivative", + "placeholder": "Enter the github URL to your work.", + "question": { + content: [ + { + "type": "markdown", + "value": "\nSubmit the link to your github repo. Make sure that the readme.md contains links to your Tracker backlog and hosted application.\n" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\nThanks for submitting! You will be able to download the [solutions](https://github.com/Galvanize-IT/lms-content-test/tree/master/dsi-example/estimation-sampling/solutions) once they are released.\n" + } + ] + } + } + } + } + end + + let(:short_answer_challenge_json) do + { + content: [ + { + type: "challenge", + id: content_file_identifier + } + ], + challenges: { + content_file_identifier.to_sym => { + "id": content_file_identifier, + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:short_answer], + "title": "add stuff", + "placeholder": "Write your answer here", + "question": { + content: [ + { + "type": "markdown", + "value": "\nWhat is 1 + 1?\n" + } + ] + }, + "answer": "2", + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\nIt is math\n" + } + ] + } + } + } + } + end + + let(:local_snippet_json) do + { + content: [ + { + type: "challenge", + id: content_file_identifier + } + ], + challenges: { + content_file_identifier.to_sym => { + "id": content_file_identifier, + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:local_snippet], + "title": "Random Code", + "question": { + content: [ + { + "type": "markdown", + "value": "\nFix the bug.\n" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\ngremlins\n" + } + ] + }, + placeholder: '\nfunction computeFactorialOfN(n) {\n // your code here\n}', + tests: 'describe("computeFactorialOfN", function() {\n it("should return a number", function() {\n expect(typeof computeFactorialOfN(7)).toBe("number");\n });\n it("should return the factorial of \'n\'", function() {\n expect(computeFactorialOfN(4)).toBe(24);\n });\n it("should return the factorial of 1", function() {\n expect(computeFactorialOfN(1)).toBe(1);\n });\n});\n', + show_tests: true + } + } + } + end + + context "short-answer type" do + it "returns the attributes for a short-answer record" do + result = described_class.execute( + content_object: short_answer_challenge_json[:content].first, + json_hash: short_answer_challenge_json, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [] + ) + + expect(result[:errors]).to eq([]) + + challenge = result[:attributes] + expect(challenge[:challenge_type]).to eq(BlockParser::ChallengeValidators::Challenge::TYPES[:short_answer]) + expect(challenge[:title]).to eq("add stuff") + expect(challenge[:explanation]).to eq("

    It is math

    \n") + expect(challenge[:answer]).to eq("2") + end + end + + context "multiple choice challenges" do + it "returns the attributes for a multiple-choice record" do + result = described_class.execute( + content_object: multiple_choice_json[:content].first, + json_hash: multiple_choice_json, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [] + ) + + expect(result[:errors]).to eq([]) + + challenge = result[:attributes] + expect(challenge[:challenge_type]).to eq(BlockParser::ChallengeValidators::Challenge::TYPES[:multiple_choice]) + expect(challenge[:title]).to eq("People Skills") + expect(challenge[:rubric]).to eq("

    Because,duh again.

    \n") + expect(challenge[:explanation]).to eq("

    Because,duh.

    \n") + expect(challenge[:topics]).to eq(["cool", "beans", "dude"]) + expect(challenge[:position]).to eq(1) + end + end + + context "checkbox challenges" do + it "returns the attributes for a checkbox record" do + result = described_class.execute( + content_object: checkbox_json[:content].first, + json_hash: checkbox_json, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [] + ) + + expect(result[:errors]).to eq([]) + + challenge = result[:attributes] + expect(challenge[:challenge_type]).to eq(BlockParser::ChallengeValidators::Challenge::TYPES[:checkbox]) + expect(challenge[:title]).to eq("Humans") + expect(challenge[:explanation]).to eq("

    They are humans.

    \n") + expect(challenge[:position]).to eq(1) + end + end + + context "local snippet challenges" do + it "returns the attributes for a multiple-choice record" do + result = described_class.execute( + content_object: local_snippet_json[:content].first, + json_hash: local_snippet_json, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [] + ) + + expect(result[:errors]).to eq([]) + + challenge = result[:attributes] + expect(challenge[:challenge_type]).to eq(BlockParser::ChallengeValidators::Challenge::TYPES[:local_snippet]) + expect(challenge[:title]).to eq("Random Code") + expect(challenge[:explanation]).to eq("

    gremlins

    \n") + expect(challenge[:position]).to eq(1) + expect(challenge[:show_tests]).to eq(true) + end + end + + context "project challenges" do + it "returns the attributes for a project challenge" do + json_hash = { + content: [ + { + type: "challenge", + id: content_file_identifier + } + ], + challenges: { + content_file_identifier.to_sym => { + "id": content_file_identifier, + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:project], + "title": "partial derivative", + "placeholder": "Enter the github URL to your work.", + "question": { + content: [ + { + "type": "markdown", + "value": "\nSubmit the link to your github repo. Make sure that the readme.md contains links to your Tracker backlog and hosted application.\n" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\nThanks for submitting! You will be able to download the [solutions](https://github.com/Galvanize-IT/lms-content-test/tree/master/dsi-example/estimation-sampling/solutions) once they are released.\n" + } + ] + } + } + } + } + + result = described_class.execute( + content_object: json_hash[:content].first, + json_hash: json_hash, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [] + ) + + expect(result[:errors]).to eq([]) + + challenge = result[:attributes] + expect(challenge[:challenge_type]).to eq(BlockParser::ChallengeValidators::Challenge::TYPES[:project]) + expect(challenge[:title]).to eq("partial derivative") + expect(challenge[:explanation]).to include('

    Thanks for submitting! You will be able to download the solutions once they are released.

    ') + expect(challenge[:position]).to eq(1) + expect(challenge[:validate_fork]).to eq(false) + end + + it "handles blank explanations" do + json_hash = { + content: [ + { + type: "challenge", + id: "asdf1234" + } + ], + challenges: { + "asdf1234": { + "id": "asdf1234", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:project], + "title": "new title", + "question": { + content: [ + { + "type": "markdown", + "value": "\nSubmit the link to your github repo. Make sure that the readme.md contains links to your Tracker backlog and hosted application.\n" + } + ] + } + } + } + } + + result = described_class.execute( + content_object: json_hash[:content].first, + json_hash: json_hash, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [] + ) + + expect(result[:errors]).to eq([]) + + expect(result[:attributes][:explanation]).to eq(nil) + end + + context "in an autograde checkpoint" do + it "raises an error" do + json_hash = { + content: [ + { + type: "challenge", + id: "asdf1234" + } + ], + challenges: { + "asdf1234": { + "id": "asdf1234", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:project], + "title": "error", + "question": { + content: [ + { + "type": "markdown", + "value": "\nnope\n" + } + ] + } + } + } + } + + result = described_class.execute( + content_object: json_hash[:content].first, + json_hash: json_hash, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [], + autoscore: true + ) + expect(result[:errors]).to eq(["project is not an autoscoreable challenge type but was found in an autograde checkpoint."]) + end + end + end + + context "custom snippet challenges" do + it "returns the attributes for a custom snippet challenge" do + json_hash = { + content: [ + { + type: "challenge", + id: content_file_identifier + } + ], + challenges: { + content_file_identifier.to_sym => { + "id": content_file_identifier, + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:custom_snippet], + "title": "some custom stuff", + "language": "java", + "placeholder": "Type some codes here", + "docker_directory_path": "/spec/fixtures/valid-custom-snippet-challenge-directory", + "question": { + content: [ + { + "type": "markdown", + "value": "\nHow's about you type some code in here.\n" + } + ] + } + } + } + } + + result = described_class.execute( + content_object: json_hash[:content].first, + json_hash: json_hash, + position: 1, + root_directory_path: File.dirname(__dir__), + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [] + ) + + expect(result[:errors]).to eq([]) + + challenge = result[:attributes] + expect(challenge[:challenge_type]).to eq(BlockParser::ChallengeValidators::Challenge::TYPES[:custom_snippet]) + expect(challenge[:title]).to eq("some custom stuff") + expect(challenge[:language]).to eq("java") + expect(challenge[:docker_directory_path]).to eq("/spec/fixtures/valid-custom-snippet-challenge-directory") + expect(challenge[:position]).to eq(1) + expect(challenge[:validate_fork]).to eq(false) + end + end + + context "testable project challenges" do + before { allow(ENV).to receive(:[]) { "foo" } } + it "returns the attributes for a project challenge" do + json_hash = { + content: [ + { + type: "challenge", + id: content_file_identifier + } + ], + challenges: { + content_file_identifier.to_sym => { + "id": content_file_identifier, + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:testable_project], + "title": "partial derivative", + "placeholder": "Enter the github URL to your work.", + "upstream_repo_path": "www.github.com/a/valid/repo/with/specs", + "question": { + content: [ + { + "type": "markdown", + "value": "\nSubmit the link to your github repo. Make sure that the readme.md contains links to your Tracker backlog and hosted application.\n" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\nThanks for submitting! You will be able to download the [solutions](https://github.com/Galvanize-IT/lms-content-test/tree/master/dsi-example/estimation-sampling/solutions) once they are released.\n" + } + ] + } + } + } + } + + result = described_class.execute( + content_object: json_hash[:content].first, + json_hash: json_hash, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [] + ) + + expect(result[:errors]).to eq([]) + + challenge = result[:attributes] + expect(challenge[:challenge_type]).to eq(BlockParser::ChallengeValidators::Challenge::TYPES[:testable_project]) + expect(challenge[:title]).to eq("partial derivative") + expect(challenge[:upstream_repo_path]).to eq("www.github.com/a/valid/repo/with/specs") + expect(challenge[:explanation]).to include('

    Thanks for submitting! You will be able to download the solutions once they are released.

    ') + expect(challenge[:position]).to eq(1) + expect(challenge[:validate_fork]).to eq(false) + end + + it "requires an upstream repo path" do + json_hash = { + content: [ + { + type: "challenge", + id: content_file_identifier + } + ], + challenges: { + content_file_identifier.to_sym => { + "id": content_file_identifier, + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:testable_project], + "title": "partial derivative", + "placeholder": "Enter the github URL to your work.", + "question": { + content: [ + { + "type": "markdown", + "value": "\nSubmit the link to your github repo. Make sure that the readme.md contains links to your Tracker backlog and hosted application.\n" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\nThanks for submitting! You will be able to download the [solutions](https://github.com/Galvanize-IT/lms-content-test/tree/master/dsi-example/estimation-sampling/solutions) once they are released.\n" + } + ] + } + } + } + } + + result = + described_class.execute( + content_object: json_hash[:content].first, + json_hash: json_hash, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [] + ) + + expect(result[:errors]).to eq(["Upstream repo path can't be blank, Upstream repo path must be from Github.com or Gitlab.com"]) + end + + it "handles blank explanations" do + json_hash = { + content: [ + { + type: "challenge", + id: "asdf1234" + } + ], + challenges: { + "asdf1234": { + "id": "asdf1234", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:project], + "title": "new title", + "question": { + content: [ + { + "type": "markdown", + "value": "\nSubmit the link to your github repo. Make sure that the readme.md contains links to your Tracker backlog and hosted application.\n" + } + ] + } + } + } + } + + result = described_class.execute( + content_object: json_hash[:content].first, + json_hash: json_hash, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [] + ) + expect(result[:attributes][:explanation]).to eq(nil) + end + + it "allows toggling of fork validation" do + json_hash = { + content: [ + { + type: "challenge", + id: "asdf1234" + } + ], + challenges: { + "asdf1234": { + "id": "asdf1234", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:project], + "title": "new title", + "question": { + content: [ + { + "type": "markdown", + "value": "\nSubmit the link to your github repo. Make sure that the readme.md contains links to your Tracker backlog and hosted application.\n" + } + ] + }, + "validate_fork": true + } + } + } + + result = described_class.execute( + content_object: json_hash[:content].first, + json_hash: json_hash, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [] + ) + + expect(result[:attributes][:validate_fork]).to eq(true) + end + end + + context "paragraph challenges" do + let(:json_hash) do + { + content: [ + { + type: "challenge", + id: content_file_identifier + } + ], + challenges: { + content_file_identifier.to_sym => { + "id": content_file_identifier, + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:paragraph], + "title": "partial derivative", + "placeholder": "Your answer here.", + "question": { + content: [ + { + "type": "markdown", + "value": "\nSomething something question about something?\n" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\nThanks for submitting!\n" + } + ] + } + } + } + } + end + + it "returns the attributes for a paragraph challenge record" do + challenge = described_class.execute( + content_object: json_hash[:content].first, + json_hash: json_hash, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [] + )[:attributes] + + expect(challenge[:challenge_type]).to eq(BlockParser::ChallengeValidators::Challenge::TYPES[:paragraph]) + expect(challenge[:title]).to eq("partial derivative") + expect(challenge[:explanation]).to eq("

    Thanks for submitting!

    \n") + end + + it "handles blank explanations" do + json_hash = { + content: [ + { + type: "challenge", + id: "asdf1234" + } + ], + challenges: { + "asdf1234": { + "id": "asdf1234", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:paragraph], + "title": "new title", + "question": { + content: [ + { + "type": "markdown", + "value": "\nSubmit your text.\n" + } + ] + } + } + } + } + + result = described_class.execute( + content_object: json_hash[:content].first, + json_hash: json_hash, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [] + ) + expect(result[:attributes][:explanation]).to eq(nil) + end + + context "in an autograde checkpoint" do + it "raises an error" do + json_hash = { + content: [ + { + type: "challenge", + id: "asdf1234" + } + ], + challenges: { + "asdf1234": { + "id": "asdf1234", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:paragraph], + "title": "error", + "question": { + content: [ + { + "type": "markdown", + "value": "\nnope\n" + } + ] + } + } + } + } + + result = described_class.execute( + content_object: json_hash[:content].first, + json_hash: json_hash, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [], + autoscore: true + ) + expect(result[:errors]).to eq(["paragraph is not an autoscoreable challenge type but was found in an autograde checkpoint."]) + end + end + end + + context "number challenges" do + let(:json_hash) do + { + content: [ + { + type: "challenge", + id: "1" + } + ], + challenges: { + "1": { + "id": "1", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:number], + "title": "sum", + "placeholder": "enter your answer here", + "decimal": "2", + "answer": "3", + "question": { + content: [ + { + "type": "markdown", + "value": "\n1+2=?\n" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\nGood job!\n" + } + ] + } + } + } + } + end + + it "returns the attributes for a number challenge" do + challenge = described_class.execute( + content_object: json_hash[:content].first, + json_hash: json_hash, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [] + )[:attributes] + + expect(challenge[:decimal]).to eq("2") + expect(challenge[:answer]).to eq("3") + end + + it "validates attributes on number challenges" do + json_hash[:challenges][:"1"].delete(:answer) + + result = + described_class.execute( + content_object: json_hash[:content].first, + json_hash: json_hash, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [] + ) + + expect(result[:errors]).to include("Answer can't be blank") + end + end + + context "code snippet challenges" do + let(:json_hash) do + { + content: [ + { + type: "challenge", + id: content_file_identifier + } + ], + challenges: { + content_file_identifier.to_sym => { + "id": content_file_identifier, + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:code_snippet], + "title": "repeats", + "placeholder": "// Write your function in Javascript below", + "hints": ["Eat more cake."], + "question": { + content: [ + { + "type": "markdown", + "value": "Write a function named repeats that returns true if the first half of the string equals the last half, and false if not." + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "You might have solved this with a while loop, but using recursion is another way to do this." + } + ] + }, + "show_tests": true, + "language": "javascript", + "setup": "(function () { + this.cStub = sinon.stub(console, 'log'); + })()", + "tests": %{describe('repeats', function() { + + it("returns true when given an empty string (which seems strange, but go with it :)", function() { + expect(repeats(""), "Default value is incorrect").to.deep.eq(true) + }) + + it("returns true when the second half of the string equals the first", function() { + expect(repeats("bahbah")).to.deep.eq(true) + expect(repeats("nananananananana")).to.deep.eq(true) + }) + + it("returns false when the second half of the string does not equal the first", function() { + expect(repeats("bahba")).to.deep.eq(false) + expect(repeats("nananananann")).to.deep.eq(false) + }) + + it("does not use .repeat", function() { + expect(repeats.toString()).to.not.match(/\.repeat/) + }) + + }) + } + } + } + } + end + + it "returns the attributes for a javascript code snippet challengeb" do + expected_tests = %{describe('repeats', function() { + + it("returns true when given an empty string (which seems strange, but go with it :)", function() { + expect(repeats(""), "Default value is incorrect").to.deep.eq(true) + }) + + it("returns true when the second half of the string equals the first", function() { + expect(repeats("bahbah")).to.deep.eq(true) + expect(repeats("nananananananana")).to.deep.eq(true) + }) + + it("returns false when the second half of the string does not equal the first", function() { + expect(repeats("bahba")).to.deep.eq(false) + expect(repeats("nananananann")).to.deep.eq(false) + }) + + it("does not use .repeat", function() { + expect(repeats.toString()).to.not.match(/\.repeat/) + }) + + }) + } + + challenge = described_class.execute( + content_object: json_hash[:content].first, + json_hash: json_hash, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [] + )[:attributes] + + expect(challenge[:language]).to eq("javascript") + expect(challenge[:tests]).to eq(expected_tests) + expect(challenge[:hints]).to match_array ["

    Eat more cake.

    \n"] + expect(challenge[:show_tests]).to eq true + end + + context "Python Challenges" do + it "returns the attributes for a python 2.7 code snippet challenge" do + json_hash = + { content: [{ type: "challenge", id: "python-challenge-01" }], + challenges: { "python-challenge-01": { id: "python-challenge-01", + type: BlockParser::ChallengeValidators::Challenge::TYPES[:code_snippet], + title: "filter by class", + placeholder: "def filter_by_class(X, y, label): + ''' + INPUT: 2 dimensional numpy array, numpy array, object + OUTPUT: 2 dimensional numpy array + + Return the rows from X whose corresponding label from y is the given label. + ''' + pass", + question: { content: [{ type: "markdown", + value: %{Implement the function `filter_by_class`: It takes a feature matrix, `X`, an array of classes, `y`, and a class label, `label`. It should return all of the rows from X whose label is the given label. + + >>> X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) + >>> y = np.array(["a", "c", "a", "b"]) + >>> filter_by_class(X, y, "a") + array([[1, 2, 3], + [7, 8, 9]]) + >>> filter_by_class(X, y, "b") + array([[10, 11, 12]]) + } }] }, + explanation: { content: [{ type: "markdown", + value: %{ + def filter_by_class(X, y, label): + return X[y == label] + } }] }, + language: "python2.7", + tests: %{ + def test_filter_by_class1(): + X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) + y = np.array(["a", "c", "a", "b"]) + result = p.filter_by_class(X, y, "a") + answer = np.array([[1, 2, 3], [7, 8, 9]]) + assert np.array_equal(result, answer) + + def test_filter_by_class2(): + X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) + y = np.array(["a", "c", "a", "b"]) + result = p.filter_by_class(X, y, "b") + answer = np.array([[10, 11, 12]]) + assert np.array_equal(result, answer) + } } } } + + expected_tests = %{ + def test_filter_by_class1(): + X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) + y = np.array(["a", "c", "a", "b"]) + result = p.filter_by_class(X, y, "a") + answer = np.array([[1, 2, 3], [7, 8, 9]]) + assert np.array_equal(result, answer) + + def test_filter_by_class2(): + X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) + y = np.array(["a", "c", "a", "b"]) + result = p.filter_by_class(X, y, "b") + answer = np.array([[10, 11, 12]]) + assert np.array_equal(result, answer) + } + + challenge = described_class.execute( + content_object: json_hash[:content].first, + json_hash: json_hash, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [] + )[:attributes] + + expect(challenge[:language]).to eq("python2.7") + expect(challenge[:tests]).to eq(expected_tests) + end + + it "returns the attributes for a python 3.6 code snippet challenge" do + json_hash = + { content: [{ type: "challenge", id: "python-challenge-01" }], + challenges: { "python-challenge-01": { id: "python-challenge-01", + type: BlockParser::ChallengeValidators::Challenge::TYPES[:code_snippet], + title: "filter by class", + placeholder: "def filter_by_class(X, y, label): + ''' + INPUT: 2 dimensional numpy array, numpy array, object + OUTPUT: 2 dimensional numpy array + + Return the rows from X whose corresponding label from y is the given label. + ''' + pass", + question: { content: [{ type: "markdown", + value: %{Implement the function `filter_by_class`: It takes a feature matrix, `X`, an array of classes, `y`, and a class label, `label`. It should return all of the rows from X whose label is the given label. + + >>> X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) + >>> y = np.array(["a", "c", "a", "b"]) + >>> filter_by_class(X, y, "a") + array([[1, 2, 3], + [7, 8, 9]]) + >>> filter_by_class(X, y, "b") + array([[10, 11, 12]]) + } }] }, + explanation: { content: [{ type: "markdown", + value: %{ + def filter_by_class(X, y, label): + return X[y == label] + } }] }, + language: "python3.6", + tests: %{ + def test_filter_by_class1(): + X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) + y = np.array(["a", "c", "a", "b"]) + result = p.filter_by_class(X, y, "a") + answer = np.array([[1, 2, 3], [7, 8, 9]]) + assert np.array_equal(result, answer) + + def test_filter_by_class2(): + X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) + y = np.array(["a", "c", "a", "b"]) + result = p.filter_by_class(X, y, "b") + answer = np.array([[10, 11, 12]]) + assert np.array_equal(result, answer) + } } } } + + expected_tests = %{ + def test_filter_by_class1(): + X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) + y = np.array(["a", "c", "a", "b"]) + result = p.filter_by_class(X, y, "a") + answer = np.array([[1, 2, 3], [7, 8, 9]]) + assert np.array_equal(result, answer) + + def test_filter_by_class2(): + X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) + y = np.array(["a", "c", "a", "b"]) + result = p.filter_by_class(X, y, "b") + answer = np.array([[10, 11, 12]]) + assert np.array_equal(result, answer) + } + + challenge = described_class.execute( + content_object: json_hash[:content].first, + json_hash: json_hash, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [] + )[:attributes] + + expect(challenge[:language]).to eq("python3.6") + expect(challenge[:tests]).to eq(expected_tests) + end + end + + context "java code snippet challenges" do + it "returns the attributes for a java code snippet challenge" do + expected_tests = %{@Test + public void passingTest(){ + assertThat(new Foo().bar(), equalTo("foo")); + } + + @Test + public void failingTest(){ + Assert.assertEquals("foo", "bar"); + } + + @Test + public void testJson() throws Exception { + ObjectMapper mapper = new ObjectMapper(); + System.out.println(mapper.writeValueAsString(new Date())); + } + } + + json_hash = + { content: [{ type: "challenge", id: "java-challenge-01" }], + challenges: { "java-challenge-01": { id: "java-challenge-01", + type: BlockParser::ChallengeValidators::Challenge::TYPES[:code_snippet], + title: "Java Challenge #1", + placeholder: "Input java code here", + question: { content: [{ + type: "markdown", + value: "Some java question" + }] }, + explanation: { content: [{ + type: "markdown", + value: "Cuz this is java" + }] }, + language: "java", + tests: expected_tests } } } + + challenge = described_class.execute( + content_object: json_hash[:content].first, + json_hash: json_hash, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [] + )[:attributes] + + expect(challenge[:language]).to eq("java") + expect(challenge[:tests]).to eq(expected_tests) + end + end + + it "returns expected html" do + expected_html = %(
    ) + result_html = described_class.execute( + content_object: json_hash[:content].first, + json_hash: json_hash, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [] + )[:html] + expect(result_html).to eq(expected_html) + end + end + + context "invalid challenge type" do + it "raises an exception with invalid challenge type message" do + json_hash = { + content: [ + { + type: "challenge", + id: content_file_identifier + } + ], + challenges: { + content_file_identifier.to_sym => { + "id": content_file_identifier, + "type": "type_of_q", + "title": "Some Challenge Title", + "placeholder": "Enter the github URL to your work.", + "question": { + content: [ + { + "type": "markdown", + "value": "\nSubmit the link to your github repo. Make sure that the readme.md contains links to your Tracker backlog and hosted application.\n" + } + ] + } + } + } + } + result = + described_class.execute( + content_object: json_hash[:content].first, + json_hash: json_hash, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [] + ) + expect(result[:errors]).to include("type_of_q is not a valid challenge type") + end + end + + context "data validations" do + it "raises an exception with the data validation error messages" do + json_hash = { + content: [ + { + type: "challenge", + id: content_file_identifier + } + ], + challenges: { + content_file_identifier.to_sym => { + "id": content_file_identifier, + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:short_answer], + "title": "", + "placeholder": "Enter the github URL to your work.", + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\nThanks for submitting! You will be able to download the [solutions](https://github.com/Galvanize-IT/lms-content-test/tree/master/dsi-example/estimation-sampling/solutions) once they are released.\n" + } + ] + } + } + } + } + + result = + described_class.execute( + content_object: json_hash[:content].first, + json_hash: json_hash, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [] + ) + + expect(result[:errors]).to include("Title can't be blank, Question can't be blank, Answer can't be blank") + end + end + + context "challenge is not gradeable" do + it "builds a project challenge in html" do + result = + described_class.execute( + content_object: project_challenge_json[:content].first, + json_hash: project_challenge_json, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [] + )[:html] + + expected_html = %(
    ) + + expect(result).to eq(expected_html) + end + end + + context "challenge is gradeable" do + it "builds a multiple choice (gradeable) challenge in html" do + result = + described_class.execute( + content_object: multiple_choice_json[:content].first, + json_hash: multiple_choice_json, + position: 1, + root_directory_path: "foo", + asset_uploader: Freeloader.new, + current_content_file_path: "", + content_file_paths: [] + )[:html] + + expected_html = %(
    ) + + expect(result).to eq(expected_html) + end + end + end +end diff --git a/gems/bp/spec/build_html_from_md_json_spec.rb b/gems/bp/spec/build_html_from_md_json_spec.rb new file mode 100644 index 0000000..3f4216c --- /dev/null +++ b/gems/bp/spec/build_html_from_md_json_spec.rb @@ -0,0 +1,316 @@ +require "spec_helper" + +describe BlockParser::BuildHtmlFromMdJson do + describe ".process_json" do + context "when a json_hash containing a vimeo embed without a transcript is passed" do + let(:json_hash) do + { + content: [ + { + type: "vimeo", + id: "123" + } + ] + } + end + + it "returns the vimeo embed tags" do + expected_html = "" + + expect(described_class.process_json( + json_hash: json_hash, + asset_uploader: Freeloader.new, + root_directory_path: "", + current_content_file_path: "", + content_file_paths: [] + )[:html]).to eq(expected_html) + end + end + + context "when a json_hash containing two vimeo embeds with transcripts is passed" do + let(:json_hash) do + { + content: [ + { + type: "vimeo", + id: "123", + transcript_project: "24099", + transcript_file: "1795859", + transcript_plugin: "11378" + }, + { + type: "vimeo", + id: "456", + transcript_project: "24099", + transcript_file: "1795859", + transcript_plugin: "11378" + } + ] + } + end + + it "returns the vimeo embed tags and the transcript tag" do + expected_html = + ""\ + ""\ + ""\ + ""\ + ""\ + "" + + expect(described_class.process_json( + json_hash: json_hash, + asset_uploader: Freeloader.new, + root_directory_path: "", + current_content_file_path: "", + content_file_paths: [] + )[:html]).to eq(expected_html) + end + end + + context "when a json_hash containing callout is passed" do + let(:json_hash) do + { + content: [ + { + type: "callout", + class: "callout-danger", + value: "#test\ntest" + } + ] + } + end + + it "returns the html wrapped in a callout container div" do + expected_html = "

    test

    \n\n

    test

    \n
    " + + expect(described_class.process_json( + json_hash: json_hash, + asset_uploader: Freeloader.new, + root_directory_path: "", + current_content_file_path: "", + content_file_paths: [] + )[:html]).to eq(expected_html) + end + end + + context "when a hash containing two challenges is passed" do + let(:two_challenge_hash) do + { + content: [ + { + type: "challenge", + id: "1" + }, + { + type: "challenge", + id: "abc" + } + ], + challenges: { + "1": { + "id": "1", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:project], + "title": "partial derivative", + "placeholder": "Enter the github URL to your work.", + "question": { + content: [ + { + "type": "markdown", + "value": "\nSubmit the link to your github repo. Make sure that the readme.md contains links to your Tracker backlog and hosted application.\n" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\nThanks for submitting! You will be able to download the [solutions](https://github.com/Galvanize-IT/lms-content-test/tree/master/dsi-example/estimation-sampling/solutions) once they are released.\n" + } + ] + } + }, + "abc": { + "id": "abc", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:paragraph], + "title": "Explain Yourself", + "placeholder": "Enter your work here.", + "question": { + content: [ + { + "type": "markdown", + "value": "\nExplain why you think you are right.\n" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\nThanks for submitting!\n" + } + ] + } + } + } + } + end + + it "converts markdown json to html" do + json_hash = { + content: [ + { + type: "markdown", + value: "## Header 1" + }, + { + type: "markdown", + value: "## Header 2" + } + ] + } + + expected_html = "

    Header 1

    \n

    Header 2

    \n" + + expect(described_class.process_json( + json_hash: json_hash, + asset_uploader: Freeloader.new, + root_directory_path: "", + current_content_file_path: "", + content_file_paths: [] + )[:html]).to eq(expected_html) + end + + it "adds additional classes to tables" do + json_hash = { + content: [ + { + type: "markdown", + value: "
    " + } + ] + } + + expected_html = "
    \n" + + expect(described_class.process_json( + json_hash: json_hash, + asset_uploader: Freeloader.new, + root_directory_path: "", + current_content_file_path: "", + content_file_paths: [] + )[:html]).to eq(expected_html) + end + + it "converts markdown challenges to html" do + json_hash = { + content: [ + { + type: "challenge", + id: "1" + } + ], + challenges: { + "1": { + "id": "1", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:project], + "title": "partial derivative", + "placeholder": "Enter the github URL to your work.", + "question": { + content: [ + { + "type": "markdown", + "value": "\nSubmit the link to your github repo. Make sure that the readme.md contains links to your Tracker backlog and hosted application.\n" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\nThanks for submitting! You will be able to download the [solutions](https://github.com/Galvanize-IT/lms-content-test/tree/master/dsi-example/estimation-sampling/solutions) once they are released.\n" + } + ] + } + } + } + } + + result = described_class.process_json( + json_hash: json_hash, + asset_uploader: Freeloader.new, + root_directory_path: "", + current_content_file_path: "", + content_file_paths: [] + ) + + expected_html = %(
    ) + + expect(result[:html]).to eq(expected_html) + end + + it "returns the position of the challenge" do + result = + described_class.process_json( + json_hash: two_challenge_hash, + asset_uploader: Freeloader.new, + root_directory_path: "", + current_content_file_path: "", + content_file_paths: [] + ) + + expect(result[:challenges].length).to eq(2) + expect(result[:challenges][0][:position]).to eq(1) + expect(result[:challenges][0][:challenge_type]).to eq(BlockParser::ChallengeValidators::Challenge::TYPES[:project]) + expect(result[:challenges][1][:position]).to eq(2) + expect(result[:challenges][1][:challenge_type]).to eq(BlockParser::ChallengeValidators::Challenge::TYPES[:paragraph]) + end + + it "ignores unknown content types" do + json_hash = { + content: [ + { + type: "markdown", + value: "## Header 1" + }, + { + type: "bad_type", + value: "## Header 2" + } + ] + } + + expected_html = "

    Header 1

    \n" + + expect( + described_class.process_json( + json_hash: json_hash, + asset_uploader: Freeloader.new, + root_directory_path: "", + current_content_file_path: "", + content_file_paths: [] + )[:html] + ).to eq(expected_html) + end + end + + context "when a hash containing challenges but with no content" do + it "returns an error for empty html parsing" do + json_hash = { + content: [], + challenges: {} + } + + result = described_class.process_json( + json_hash: json_hash, + asset_uploader: Freeloader.new, + root_directory_path: "", + current_content_file_path: "", + content_file_paths: [] + ) + + expect(result[:errors]).to include("content cannot be blank") + end + end + end +end diff --git a/gems/bp/spec/build_html_spec.rb b/gems/bp/spec/build_html_spec.rb new file mode 100644 index 0000000..e6301fa --- /dev/null +++ b/gems/bp/spec/build_html_spec.rb @@ -0,0 +1,196 @@ +require "spec_helper" + +describe BlockParser::BuildHtml do + describe ".execute" do + let(:test_client) { instance_double("Mocktokit::Client") } + + before { allow(ENV).to receive(:[]) { nil } } + before { allow(ENV).to receive(:[]).with("HOST").and_return("http://www.foo.com") } + + it "converts the markdown containing links into html that is ready to be rendered" do + content_file_paths = ["/foo/foo.md", "/foo/bar.md"] + + html = "foo" + expected_html = "foo" + + results = + described_class.execute( + html: html, + current_content_file_path: "/foo/bar.md", + content_file_paths: content_file_paths, + root_directory_path: "foo", + asset_uploader: Freeloader.new + ) + + expect(results[:html]).to eq(expected_html) + expect(results[:errors]).to eq([]) + expect(results[:warnings]).to eq([]) + end + + it "converts the markdown containing images into html that is ready to be rendered" do + expect_any_instance_of(Freeloader).to receive(:find_or_create_content) { "http://some-s3-url/" } + + html = '' + + expected_html = "" + + expect(described_class.execute( + html: html, + current_content_file_path: File.join(File.dirname(__FILE__), "fixtures", "test-block-repo", "bar.md"), + content_file_paths: [], + root_directory_path: File.join(File.dirname(__FILE__), "fixtures", "test-block-repo"), + asset_uploader: Freeloader.new + )[:html]).to eq(expected_html) + end + + it "converts the markdown containing headers to include ids for anchor tags" do + html = "

    Sum Title

    Sum Title

    " + + expected_html = "

    Sum Title

    Sum Title

    " + + expect(described_class.execute( + html: html, + current_content_file_path: "bar.md", + content_file_paths: [], + root_directory_path: File.join(File.dirname(__FILE__), "fixtures", "test-block-repo"), + asset_uploader: Freeloader.new + )[:html]).to eq(expected_html) + end + + it "still converts when there are no conversions to be made" do + html = "foo" + + expected_html = "foo" + + expect(described_class.execute( + html: html, + current_content_file_path: "bar.md", + content_file_paths: [], + root_directory_path: "baz", + asset_uploader: Freeloader.new + )[:html]).to eq(expected_html) + end + + it "converts lists of 'checkboxes' to inputs " do + html = "
      \n
    • [ ] Replace stringifyJSON with your own function in src/stringifyJSON.js, and make the specs pass.
    • \n
    • [ ] Implement getElementsByClassName with your own function in src/getElementsByClassName.js, and make the specs pass.\n\n
        \n
      • [ ] You should use document.body, element.childNodes, and element.classList\n
      • \n
      \n
    • \n
    " + + expected_html = "
      \n
    • Replace stringifyJSON with your own function in src/stringifyJSON.js, and make the specs pass.
    • \n
    • Implement getElementsByClassName with your own function in src/getElementsByClassName.js, and make the specs pass.\n\n
        \n
      • You should use document.body, element.childNodes, and element.classList\n
      • \n
      \n
    • \n
    " + + expect(described_class.execute( + html: html, + current_content_file_path: "bar.md", + content_file_paths: [], + root_directory_path: "baz", + asset_uploader: Freeloader.new + )[:html]).to eq(expected_html) + end + + it "removes meta, script, style, title, and link tags from html" do + html = %( + + +morning-slides slides + +

    Keep Me!

    +) + expected_html = "

    Keep Me!

    \n" + expect(described_class.execute( + html: html, + current_content_file_path: "bar.md", + content_file_paths: [], + root_directory_path: "baz", + asset_uploader: Freeloader.new + )[:html]).to eq(expected_html) + end + + context "when provided an iframe" do + let(:input_markdown) do + File.read(File.join(File.dirname(__FILE__), "fixtures", "sample-iframe.md")) + end + let(:processed_text) do + described_class.execute( + html: input_markdown, + current_content_file_path: "bar.md", + content_file_paths: [], + root_directory_path: File.join(File.dirname(__FILE__), "fixtures", "test-block-repo"), + asset_uploader: Freeloader.new + )[:html] + end + let(:expected_html) { input_markdown } + + it "should output the html exactly as provided" do + expect(processed_text).to eq(expected_html) + end + end + + context "when image tags fail" do + let(:text) { "" } + + it "continues to process the content file" do + result = described_class.execute( + html: text, + current_content_file_path: "bar.md", + content_file_paths: [], + root_directory_path: File.join(File.dirname(__FILE__), "fixtures", "test-block-repo"), + asset_uploader: Freeloader.new + ) + + expect(result[:html]).to eq(text) + expect(result[:warnings].first).to include("Bad image link /Curriculum/someFolder/bad_image_1.jpg") + expect(result[:errors]).to eq([]) + end + end + + context "when link tags fail" do + let(:text) { "" } + + it "continues to process the content file and adds warnings" do + result = described_class.execute( + html: text, + current_content_file_path: "bar.md", + content_file_paths: [], + root_directory_path: File.join(File.dirname(__FILE__), "fixtures", "test-block-repo"), + asset_uploader: Freeloader.new + ) + + expect(result[:html]).to eq(text) + expect(result[:errors]).to eq([]) + expect(result[:warnings]).to eq(["bar.md: Bad internal link ../bad_link_bears.md"]) + end + end + end + + describe ".process_header" do + it "adds an id for use as an anchor tag on all H tags" do + html = "

    Sum Header

    " + doc = Nokogiri::HTML::DocumentFragment.parse(html) + + expected_html = "

    Sum Header

    " + + results = described_class.process_header(doc.children.first, {}) + expect(results[0]).to eq(html) + expect(results[1]).to eq(expected_html) + expect(results[2]).to eq("sum-header": 1) + end + + it "appends a unique number if there are identical headers" do + html = "

    Header

    " + doc = Nokogiri::HTML::DocumentFragment.parse(html) + existing_headers = { 'header': 1 } + + expected_html = "

    Header

    " + + results = described_class.process_header(doc.children.first, existing_headers) + expect(results[0]).to eq(html) + expect(results[1]).to eq(expected_html) + expect(results[2]).to eq("header": 2) + end + end +end diff --git a/gems/bp/spec/build_image_link_spec.rb b/gems/bp/spec/build_image_link_spec.rb new file mode 100644 index 0000000..85b25e8 --- /dev/null +++ b/gems/bp/spec/build_image_link_spec.rb @@ -0,0 +1,308 @@ +require "spec_helper" + +describe BlockParser::BuildImageLink do + describe ".execute" do + let(:mock_uploader) { double("uploader") } + + context "when an update to the url is required" do + let(:image_text) { "image" } + + it "returns a tuple of strings to be gsub'ed for images with a relative src path to a different directory than the content file and uploads the file to s3" do + expect(File).to receive(:read) { image_text } + expect(mock_uploader).to receive(:find_or_create_content).with(full_path: "/images/test.jpg") { "http://some-s3-url/" } + + html = '' + doc = Nokogiri::HTML::DocumentFragment.parse(html) + + expect(described_class.execute( + element: doc.children.first, + current_content_file_path: "/stuff/foo.md", + asset_uploader: mock_uploader, + root_directory_path: File.join(File.dirname(__FILE__), "tmp", "block-repos", "sample-directory") + )[:result]).to eq(["src=\"../images\/test.jpg\"", "src=\"http://some-s3-url/\""]) + end + + it "returns a tuple of strings to be gsub'ed for images with an absolute src path from root of repo and uploads the file to s3" do + expect(File).to receive(:read) { image_text } + expect(mock_uploader).to receive(:find_or_create_content).with(any_args) { "http://some-s3-url/" } + + html = '' + doc = Nokogiri::HTML::DocumentFragment.parse(html) + + expect(described_class.execute( + element: doc.children.first, + current_content_file_path: "/stuff/foo.md", + asset_uploader: mock_uploader, + root_directory_path: File.join(File.dirname(__FILE__), "tmp", "block-repos", "sample-directory") + )[:result]).to eq(["src=\"/stuff\/images\/img.jpeg\"", "src=\"http://some-s3-url/\""]) + end + + it "returns a tuple of strings to be gsub'ed for images with an absolute src path from folder of repo and uploads the file to s3" do + expect(File).to receive(:read) { image_text } + expect(mock_uploader).to receive(:find_or_create_content).with(any_args) { "http://some-s3-url/" } + + html = '' + doc = Nokogiri::HTML::DocumentFragment.parse(html) + + expect(described_class.execute( + element: doc.children.first, + current_content_file_path: File.join(File.dirname(__FILE__), "fixtures", "test-block-repo", "folder", "target.md"), + asset_uploader: mock_uploader, + root_directory_path: File.join(File.dirname(__FILE__), "fixtures", "test-block-repo") + )[:result]).to eq(["src=\"\/images\/galvanize-logo.png\"", "src=\"http://some-s3-url/\""]) + end + + it "returns a tuple of strings to be gsub'ed for images with a relative src path within the content file folder and uploads the file to s3" do + expect(File).to receive(:read) { image_text } + expect(mock_uploader).to receive(:find_or_create_content).with(full_path: "/images/img.jpeg") { "http://some-s3-url/" } + + html = '' + doc = Nokogiri::HTML::DocumentFragment.parse(html) + + expect(described_class.execute( + element: doc.children.first, + current_content_file_path: "/foo.md", + asset_uploader: mock_uploader, + root_directory_path: File.join(File.dirname(__FILE__), "tmp", "block-repos", "sample-directory") + )[:result]).to eq(["src=\"images/img.jpeg\"", "src=\"http://some-s3-url/\""]) + end + + it "returns a tuple of strings to be gsub'ed for images with a relative src path within the content file (using dot slash) folder and uploads the file to s3" do + expect(File).to receive(:read) { image_text } + expect(mock_uploader).to receive(:find_or_create_content).with(full_path: "/images/img.jpeg") { "http://some-s3-url/" } + + html = '' + doc = Nokogiri::HTML::DocumentFragment.parse(html) + + expect(described_class.execute( + element: doc.children.first, + current_content_file_path: "/foo.md", + asset_uploader: mock_uploader, + root_directory_path: File.join(File.dirname(__FILE__), "tmp", "block-repos", "sample-directory") + )[:result]).to eq(["src=\"./images/img.jpeg\"", "src=\"http://some-s3-url/\""]) + end + end + + context "when an update to the url is NOT required" do + it "does not change image urls that start with www, http, or https" do + html = '' + doc = Nokogiri::HTML::DocumentFragment.parse(html) + + expect(described_class.execute( + element: doc.children.first, + current_content_file_path: "/foo.md", + asset_uploader: mock_uploader, + root_directory_path: File.join(File.dirname(__FILE__), "tmp", "block-repos", "sample-directory") + )[:result]).to eq([]) + end + + it "returns an empty array if there is no src for the image tag" do + html = '' + doc = Nokogiri::HTML::DocumentFragment.parse(html) + + expect(described_class.execute( + element: doc.children.first, + current_content_file_path: "/foo.md", + asset_uploader: mock_uploader, + root_directory_path: File.join(File.dirname(__FILE__), "tmp", "block-repos", "sample-directory") + )[:result]).to eq([]) + end + + it "raises a BadLink exception when unable to retrieve image" do + html = '' + doc = Nokogiri::HTML::DocumentFragment.parse(html) + + result = + described_class.execute( + element: doc.children.first, + current_content_file_path: "/foo.md", + asset_uploader: mock_uploader, + root_directory_path: File.join(File.dirname(__FILE__), "tmp", "block-repos", "sample-directory") + ) + expect(result[:errors].first).to include("Bad image link /images/img.jpeg") + end + + it "does not change base64 src images" do + html = %() + doc = Nokogiri::HTML::DocumentFragment.parse(html) + + expect(described_class.execute( + element: doc.children.first, + current_content_file_path: "/foo.md", + asset_uploader: mock_uploader, + root_directory_path: File.join(File.dirname(__FILE__), "tmp", "block-repos", "sample-directory") + )[:result]).to eq([]) + end + end + end +end diff --git a/gems/bp/spec/build_link_spec.rb b/gems/bp/spec/build_link_spec.rb new file mode 100644 index 0000000..8954b29 --- /dev/null +++ b/gems/bp/spec/build_link_spec.rb @@ -0,0 +1,173 @@ +require "spec_helper" + +describe BlockParser::BuildLink do + describe ".execute" do + before { allow(ENV).to receive(:[]) { nil } } + + it "returns an empty array if there is no href" do + html = "
    foo" + doc = Nokogiri::HTML::DocumentFragment.parse(html) + + expect( + described_class.execute(link: doc.children.first, current_content_file_path: "", content_file_paths: [], root_directory_path: "") + ).to eq([]) + end + + it "returns a content link if the link is an external http with content_link/gSchool" do + html = "foo" + doc = Nokogiri::HTML::DocumentFragment.parse(html) + + expect( + described_class.execute(link: doc.children.first, current_content_file_path: "", content_file_paths: [], root_directory_path: "") + ).to eq(["href=\"http://localhost:3003/content_link/gSchool/blocks-test/simple-challenge.md\"", "href=\"http://localhost:3003/content_link/gSchool/blocks-test/simple-challenge.md\""]) + end + + it "returns an external link if the link is an external http link" do + html = "foo" + doc = Nokogiri::HTML::DocumentFragment.parse(html) + + expect( + described_class.execute(link: doc.children.first, current_content_file_path: "", content_file_paths: [], root_directory_path: "") + ).to eq(["href=\"http://google.com\"", "href=\"http://google.com\" class=\"external-link\" target=\"_blank\""]) + end + + it "returns an external link if the link is an external https link" do + html = "foo" + doc = Nokogiri::HTML::DocumentFragment.parse(html) + + expect( + described_class.execute(link: doc.children.first, current_content_file_path: "", content_file_paths: [], root_directory_path: "") + ).to eq(["href=\"https://google.com\"", "href=\"https://google.com\" class=\"external-link\" target=\"_blank\""]) + end + + context "resource link" do + let(:current_content_file_path) { "/tmp/repo/foo/bar/baz/resource.md" } + let(:content_file_paths) { ["/tmp/repo/foo/bar/baz/resource.md", "/tmp/repo/bar.md"] } + + context "handles no leading slash" do + it "returns an external link if the link is a resource link" do + html = "foo" + doc = Nokogiri::HTML::DocumentFragment.parse(html) + expect( + described_class.execute(link: doc.children.first, current_content_file_path: current_content_file_path, content_file_paths: content_file_paths, root_directory_path: "", resource_paths: ["resource.md"]) + ).to eq(["href=\"resource.md\"", "href=\"resource.md\" class=\"external-link\" target=\"_blank\""]) + end + end + + context "handles a leading slash" do + it "returns an external link if the link is a resource link" do + html = "foo" + doc = Nokogiri::HTML::DocumentFragment.parse(html) + expect( + described_class.execute(link: doc.children.first, current_content_file_path: current_content_file_path, content_file_paths: content_file_paths, root_directory_path: "/tmp/repo/foo/bar/baz/", resource_paths: ["/resource.md"]) + ).to eq(["href=\"/resource.md\"", "href=\"resource.md\" class=\"external-link\" target=\"_blank\""]) + end + end + end + + it "returns an empty array if the link is to an email" do + html = "foo" + doc = Nokogiri::HTML::DocumentFragment.parse(html) + + expect( + described_class.execute(link: doc.children.first, current_content_file_path: "", content_file_paths: [], root_directory_path: "") + ).to eq([]) + end + + it "handles absolute links within a subdirectory" do + html = "foo" + doc = Nokogiri::HTML::DocumentFragment.parse(html) + current_content_file_path = "/tmp/repo/foo/bar/baz/foo.md" + content_file_paths = ["/tmp/repo/foo/bar/baz/foo.md", "/tmp/repo/bar.md"] + + expect( + described_class.execute( + link: doc.children.first, + current_content_file_path: current_content_file_path, + content_file_paths: content_file_paths, + root_directory_path: "/tmp/repo/" + ) + ).to eq(["href=\"/bar.md\"", "href=\"../../../bar.md\""]) + end + + it "handles invalid absolute links within a subdirectory" do + html = "foo" + doc = Nokogiri::HTML::DocumentFragment.parse(html) + current_content_file_path = "/tmp/repo/foo/bar/baz/foo.md" + content_file_paths = ["/tmp/repo/foo/bar/baz/foo.md", "/tmp/repo/bar.md"] + + expect do + described_class.execute( + link: doc.children.first, + current_content_file_path: current_content_file_path, + content_file_paths: content_file_paths, + root_directory_path: "/tmp/repo/" + ) + end.to raise_error(described_class::BadInternalLink) + end + + it "handles relative links within a subdirectory" do + html = "foo" + doc = Nokogiri::HTML::DocumentFragment.parse(html) + current_content_file_path = "/foo/bar.md" + content_file_paths = ["/foo/foo.md", "/foo/bar.md"] + + expect( + described_class.execute( + link: doc.children.first, + current_content_file_path: current_content_file_path, + content_file_paths: content_file_paths, + root_directory_path: "" + ) + ).to eq([]) + end + + it "handles relative link within a subdirectory with an anchor tag" do + html = "foo" + doc = Nokogiri::HTML::DocumentFragment.parse(html) + current_content_file_path = "/foo/bar.md" + content_file_paths = ["/foo/foo.md", "/foo/bar.md"] + + expect( + described_class.execute( + link: doc.children.first, + current_content_file_path: current_content_file_path, + content_file_paths: content_file_paths, + root_directory_path: "" + ) + ).to eq([]) + end + + it "raises an error when the linked file does not exist" do + html = "foo" + doc = Nokogiri::HTML::DocumentFragment.parse(html) + current_content_file_path = "/foo/bar.md" + content_file_paths = ["/foo/bar.md"] + + expect do + described_class.execute(link: doc.children.first, current_content_file_path: current_content_file_path, content_file_paths: content_file_paths, root_directory_path: "") + end.to raise_error(described_class::BadInternalLink) + end + + it "returns empty array if href is empty" do + html = "foo" + doc = Nokogiri::HTML::DocumentFragment.parse(html) + + expect(described_class.execute(link: doc.children.first, current_content_file_path: "", content_file_paths: [], root_directory_path: "")).to eq([]) + end + + it "returns empty array href starts with a #" do + html = "foo" + doc = Nokogiri::HTML::DocumentFragment.parse(html) + + expect(described_class.execute(link: doc.children.first, current_content_file_path: "", content_file_paths: [], root_directory_path: "")).to eq([]) + end + + it "returns empty array if href is a #" do + html = "foo" + doc = Nokogiri::HTML::DocumentFragment.parse(html) + + expect(described_class.execute(link: doc.children.first, current_content_file_path: "", content_file_paths: [], root_directory_path: "")).to eq([]) + end + end +end diff --git a/gems/bp/spec/build_title_from_filename_and_html_spec.rb b/gems/bp/spec/build_title_from_filename_and_html_spec.rb new file mode 100644 index 0000000..55030ad --- /dev/null +++ b/gems/bp/spec/build_title_from_filename_and_html_spec.rb @@ -0,0 +1,53 @@ +require "spec_helper" + +describe BuildTitleFromFilenameAndHtml do + context "when html does not start with an h1" do + it "removes the number and dash at the beginning of the filename" do + expect(described_class.execute(filename: "123 - Some Title.md", html: "")).to eq("Some Title") + end + + it "replaces dashes and underscores with spaces" do + expect(described_class.execute(filename: "Some_Title-Here.md", html: "")).to eq("Some Title Here") + end + + it "removes a trailing .md from the title" do + expect(described_class.execute(filename: "File.md", html: "")).to eq("File") + end + + it "titleizes the title" do + expect(described_class.execute(filename: "some title.md", html: "")).to eq("Some Title") + end + + it "url decodes the title" do + expect(described_class.execute(filename: "some%20title.md", html: "")).to eq("Some Title") + end + end + + context "when it includes a keyword (instructor, checkpoint, resource)" do + context "when its the first word" do + it "keeps the keyword in place" do + expect(described_class.execute(filename: "checkpoint.md", html: "")).to eq("Checkpoint") + expect(described_class.execute(filename: "instructor.md", html: "")).to eq("Instructor") + expect(described_class.execute(filename: "resource.md", html: "")).to eq("Resource") + expect(described_class.execute(filename: "hidden.md", html: "")).to eq("Hidden") + end + end + + context "when its not the first word" do + it "scrubs the keyword out of the title" do + expect(described_class.execute(filename: "some-checkpoint.md", html: "")).to eq("Some Checkpoint") + expect(described_class.execute(filename: "some-instructor.checkpoint.md", html: "")).to eq("Some Instructor") + expect(described_class.execute(filename: "some.instructor.checkpoint.md", html: "")).to eq("Some") + expect(described_class.execute(filename: "some.hidden.checkpoint.md", html: "")).to eq("Some") + expect(described_class.execute(filename: "node-checkpoint.md", html: "")).to eq("Node Checkpoint") + expect(described_class.execute(filename: "node-checkpoint.instructor.md", html: "")).to eq("Node Checkpoint") + end + end + end + + context "when the first line of the rendered text contains an h1 tag" do + it "returns the unescaped version of the h1 on the first line" do + expect(described_class.execute(filename: "some%20title.md", html: "

    "some text"

    ")).to eq('"some text"') + end + end +end diff --git a/gems/bp/spec/challenge_validators/challenge_spec.rb b/gems/bp/spec/challenge_validators/challenge_spec.rb new file mode 100644 index 0000000..7bcf0df --- /dev/null +++ b/gems/bp/spec/challenge_validators/challenge_spec.rb @@ -0,0 +1,288 @@ +require "spec_helper" + +describe BlockParser::ChallengeValidators::Challenge do + describe "#to_hash" do + it "returns a hash representing the attributes of the challenge" do + challenge = described_class.new(BlockParser::ChallengeValidators::Challenge::TYPES) + challenge.id = "123" + challenge.type = BlockParser::ChallengeValidators::Challenge::TYPES[:testable_project] + challenge.title = "exercise1" + challenge.placeholder = "Enter GH Url" + challenge.answer = "www.github.com/some/url" + challenge.question = "this is the question?" + challenge.explanation = "this is the solution" + challenge.standard_uuids = ["foo123", "bar123"] + challenge.rubric = "this is the rubric" + challenge.upstream_repo_path = "www.github.com/some/url" + challenge.hints = ["I am a hint1", "I am a hint2"] + challenge.setup = "I am the setup, most likely some stubs to run before tests" + challenge.validate_fork = "true" + challenge.topics = ["cool", "beans", "dude"] + + expect(challenge.to_hash).to eq( + id: "123", + type: BlockParser::ChallengeValidators::Challenge::TYPES[:testable_project], + title: "exercise1", + placeholder: "Enter GH Url", + standard_uuids: ["foo123", "bar123"], + hints: ["I am a hint1", "I am a hint2"], + setup: "I am the setup, most likely some stubs to run before tests", + topics: ["cool", "beans", "dude"], + partial_credit: false, + question: { + content: [ + { + type: "markdown", + value: "this is the question?" + } + ] + }, + upstream_repo_path: "www.github.com/some/url", + explanation: { + content: [ + { + type: "markdown", + value: "this is the solution" + } + ] + }, + rubric: { + content: [ + { + type: "markdown", + value: "this is the rubric" + } + ] + }, + validate_fork: true + ) + end + + it "returns a hash containing decimal and answer for number challenges" do + challenge = described_class.new(BlockParser::ChallengeValidators::Challenge::TYPES) + challenge.id = "123" + challenge.type = BlockParser::ChallengeValidators::Challenge::TYPES[:number] + challenge.title = "exercise1" + challenge.question = "this is the question?" + challenge.decimal = "2" + challenge.answer = "3" + + expect(challenge.to_hash).to eq( + id: "123", + type: BlockParser::ChallengeValidators::Challenge::TYPES[:number], + title: "exercise1", + placeholder: nil, + answer: "3", + decimal: "2", + setup: nil, + partial_credit: false, + hints: [], + question: { + content: [ + { + type: "markdown", + value: "this is the question?" + } + ] + } + ) + end + + it "returns a hash containing decimal and answer for number challenges" do + challenge = described_class.new(BlockParser::ChallengeValidators::Challenge::TYPES) + challenge.id = "123" + challenge.type = BlockParser::ChallengeValidators::Challenge::TYPES[:short_answer] + challenge.title = "Logan, so amaze!" + challenge.question = "this is the question?" + challenge.answer = "3" + + expect(challenge.to_hash).to eq( + id: "123", + type: BlockParser::ChallengeValidators::Challenge::TYPES[:short_answer], + title: "Logan, so amaze!", + hints: [], + placeholder: nil, + partial_credit: false, + answer: "3", + setup: nil, + question: { + content: [ + { + type: "markdown", + value: "this is the question?" + } + ] + } + ) + end + + it "returns a hash containing docker file path for a custom snippet" do + challenge = described_class.new(BlockParser::ChallengeValidators::Challenge::TYPES) + challenge.id = "123" + challenge.type = BlockParser::ChallengeValidators::Challenge::TYPES[:custom_snippet] + challenge.title = "Logan, so amaze!" + challenge.question = "a custom snippet question" + challenge.docker_directory_path = "/root/some/path/" + challenge.language = "Java" + + expect(challenge.to_hash).to eq( + id: "123", + type: BlockParser::ChallengeValidators::Challenge::TYPES[:custom_snippet], + title: "Logan, so amaze!", + placeholder: nil, + hints: [], + setup: nil, + partial_credit: false, + language: "Java", + question: { + content: [ + { + type: "markdown", + value: "a custom snippet question" + } + ] + }, + docker_directory_path: "/root/some/path/" + ) + end + + it "does not set a question hash if question is nil" do + challenge = described_class.new(BlockParser::ChallengeValidators::Challenge::TYPES) + challenge.id = "123" + challenge.type = BlockParser::ChallengeValidators::Challenge::TYPES[:project] + challenge.title = "exercise1" + challenge.placeholder = "Enter GH Url" + challenge.question = nil + challenge.explanation = "this is the solution" + expect(challenge.to_hash).to eq( + id: "123", + type: BlockParser::ChallengeValidators::Challenge::TYPES[:project], + title: "exercise1", + placeholder: "Enter GH Url", + setup: nil, + partial_credit: false, + hints: [], + explanation: { + content: [ + { + type: "markdown", + value: "this is the solution" + } + ] + } + ) + end + + it "does not set an explanation hash if the explanation is nil" do + challenge = described_class.new(BlockParser::ChallengeValidators::Challenge::TYPES) + challenge.id = "123" + challenge.type = BlockParser::ChallengeValidators::Challenge::TYPES[:testable_project] + challenge.title = "exercise1" + challenge.placeholder = "Enter GH Url" + challenge.question = "this is the question?" + challenge.answer = "www.githerb.com/some/url" + challenge.explanation = nil + challenge.upstream_repo_path = "www.githerb.com/some/url" + + expect(challenge.to_hash).to eq( + id: "123", + type: BlockParser::ChallengeValidators::Challenge::TYPES[:testable_project], + title: "exercise1", + hints: [], + placeholder: "Enter GH Url", + setup: nil, + partial_credit: false, + question: { + content: [ + { + type: "markdown", + value: "this is the question?" + } + ] + }, + upstream_repo_path: "www.githerb.com/some/url" + ) + end + + it "does not set validate_fork if the validate_fork is nil" do + challenge = described_class.new(BlockParser::ChallengeValidators::Challenge::TYPES) + challenge.id = "123" + challenge.type = BlockParser::ChallengeValidators::Challenge::TYPES[:testable_project] + challenge.title = "exercise1" + challenge.placeholder = "Enter GH Url" + challenge.question = "this is the question?" + challenge.answer = "www.githerb.com/some/url" + challenge.explanation = nil + challenge.upstream_repo_path = "www.githerb.com/some/url" + challenge.validate_fork = nil + + expect(challenge.to_hash).to eq( + id: "123", + type: BlockParser::ChallengeValidators::Challenge::TYPES[:testable_project], + title: "exercise1", + hints: [], + placeholder: "Enter GH Url", + setup: nil, + partial_credit: false, + question: { + content: [ + { + type: "markdown", + value: "this is the question?" + } + ] + }, + upstream_repo_path: "www.githerb.com/some/url" + ) + end + + it "coverts options into an array of strings" do + challenge = described_class.new(BlockParser::ChallengeValidators::Challenge::TYPES) + challenge.options = "\n * option 1\n- option 2\n" + + expect(challenge.to_hash[:options]).to eq(["option 1", "option 2"]) + end + + it "coverts options without a beginning newline into an array of strings" do + challenge = described_class.new(BlockParser::ChallengeValidators::Challenge::TYPES) + challenge.options = "- Nothing - it would work perfectly 1\n- ``\n" + + expect(challenge.to_hash[:options]).to eq(["Nothing - it would work perfectly 1", "``"]) + end + + it "coverts multiline options correctly" do + challenge = described_class.new(BlockParser::ChallengeValidators::Challenge::TYPES) + challenge.options = "\n* La Chaiffre\n*\n a bunch of text\n\n split across\n\n multiple lines\n" + + expect(challenge.to_hash[:options]).to eq(["La Chaiffre", "a bunch of text\n\nsplit across\n\nmultiple lines"]) + end + + it "coverts multiline options with backticks correctly" do + challenge = described_class.new(BlockParser::ChallengeValidators::Challenge::TYPES) + challenge.options = "\n* La Chaiffre\n*\n ```\na bunch of text\n\n split across\n\n multiple lines\n ```\n" + + expect(challenge.to_hash[:options]).to eq(["La Chaiffre", "```\na bunch of text\n\n split across\n\n multiple lines\n ```"]) + end + + it "coverts multiline options with math symbols that could confuse our line detection correctly" do + challenge = described_class.new(BlockParser::ChallengeValidators::Challenge::TYPES) + challenge.options = "\n* La Chaiffre\n*\n ```\na bunch of * text\n\n split - across\n\n multiple lines\n ```\n" + + expect(challenge.to_hash[:options]).to eq(["La Chaiffre", "```\na bunch of * text\n\n split - across\n\n multiple lines\n ```"]) + end + + it "coverts multiline options with backticks and a language correctly" do + challenge = described_class.new(BlockParser::ChallengeValidators::Challenge::TYPES) + challenge.options = "\n* La Chaiffre\n*\n ```java\na bunch of text\n\n split across\n\n multiple lines\n ```\n" + + expect(challenge.to_hash[:options]).to eq(["La Chaiffre", "```java\na bunch of text\n\n split across\n\n multiple lines\n ```"]) + end + + it "removes excessive indentation from multiline options" do + challenge = described_class.new(BlockParser::ChallengeValidators::Challenge::TYPES) + challenge.options = "\n* La Chaiffre\n*\n ```java\n a bunch of text\n\n split across\n\n multiple lines\n ```\n" + + expect(challenge.to_hash[:options]).to eq(["La Chaiffre", "```java\na bunch of text\n\nsplit across\n\n multiple lines\n```"]) + end + end +end diff --git a/gems/bp/spec/challenge_validators/challenge_validator_spec.rb b/gems/bp/spec/challenge_validators/challenge_validator_spec.rb new file mode 100644 index 0000000..dd35420 --- /dev/null +++ b/gems/bp/spec/challenge_validators/challenge_validator_spec.rb @@ -0,0 +1,116 @@ +require "spec_helper" + +describe BlockParser::ChallengeValidators::ChallengeValidator do + describe "validations" do + let(:valid_attributes) do + { + "id": "1", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:paragraph], + "title": "partial derivative", + "placeholder": "Enter the github URL to your work.", + "topics": ["first", "second"], + "question": { + content: [ + { + "type": "markdown", + "value": "\nSubmit the link to your github repo. Make sure that the readme.md contains links to your Tracker backlog and hosted application.\n" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\nThanks for submitting! You will be able to download the [solutions](https://github.com/Galvanize-IT/lms-content-test/tree/master/dsi-example/estimation-sampling/solutions) once they are released.\n" + } + ] + }, + "rubric": { + "content": [ + { + "type": "markdown", + "value": "\nI AM RUBRIC MAN\n" + } + ] + } + } + end + + it "can be valid" do + challenge_validator = described_class.new(valid_attributes) + + expect(challenge_validator.valid?).to eq(true) + end + + it "requires an id" do + valid_attributes.delete(:id) + challenge_validator = described_class.new(valid_attributes) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:id]).to eq(["can't be blank"]) + end + + it "requires a type" do + valid_attributes.delete(:type) + challenge_validator = described_class.new(valid_attributes) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:type]).to eq(["can't be blank"]) + end + + it "requires a title" do + valid_attributes.delete(:title) + challenge_validator = described_class.new(valid_attributes) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:title]).to eq(["can't be blank"]) + end + + it "requires a question" do + valid_attributes.delete(:question) + challenge_validator = described_class.new(valid_attributes) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:question]).to eq(["can't be blank"]) + + valid_attributes[:question] = { + content: [ + { + "type": "markdown", + "value": " " + } + ] + } + challenge_validator = described_class.new(valid_attributes) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:question]).to eq(["can't be blank"]) + end + + it "does not allow points over 10" do + valid_attributes[:points] = 11 + challenge_validator = described_class.new(valid_attributes) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:points]).to eq(["can't be worth more than 10"]) + + valid_attributes[:points] = 10 + challenge_validator = described_class.new(valid_attributes) + + expect(challenge_validator.valid?).to eq(true) + end + + it "does not allow topics to be over 20 characters" do + valid_attributes[:topics] = ["fivefivefivefivefiveWHAT", "one"] + challenge_validator = described_class.new(valid_attributes) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:topics]).to eq(["can't have a length of more than 20 characters"]) + + valid_attributes[:topics] = ["fivefivefivefivefive", "one"] + challenge_validator = described_class.new(valid_attributes) + + expect(challenge_validator.valid?).to eq(true) + end + end +end diff --git a/gems/bp/spec/challenge_validators/checkbox_challenge_validator_spec.rb b/gems/bp/spec/challenge_validators/checkbox_challenge_validator_spec.rb new file mode 100644 index 0000000..2f40e86 --- /dev/null +++ b/gems/bp/spec/challenge_validators/checkbox_challenge_validator_spec.rb @@ -0,0 +1,118 @@ +require "spec_helper" + +describe BlockParser::ChallengeValidators::CheckboxChallengeValidator do + describe "validations" do + let(:checkbox_json) do + { + "id": "1", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:checkbox], + "title": "People Skills", + "answer": ["Peter Grunde", "Bradford Hamilton"], + "options": [ + "Peter Grunde", + "Bradford Hamilton", + "Dr. No", + "James Bond", + "La Chaiffre", + "Jaws" + ], + "question": { + content: [ + { + "type": "markdown", + "value": "\nWho is the coolest?\n" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\nBecause,duh.\n" + } + ] + }, + "rubric": { + "content": [ + { + "type": "markdown", + "value": "\nI AM RUBRIC MAN\n" + } + ] + } + } + end + + subject { described_class.new(checkbox_json) } + + it "can be valid" do + subject.valid? + expect(subject.valid?).to eq(true) + end + + it "requires an answer" do + checkbox_json.delete(:answer) + + expect(subject.valid?).to eq(false) + expect(subject.errors[:answer]).to eq(["can't be blank", "must have at least one choice"]) + end + + context "options" do + it "cannot be blank" do + checkbox_json.delete(:options) + + expect(subject.valid?).to eq(false) + expect(subject.errors[:options]).to eq(["can't be blank"]) + end + + it "must have at least 2 options" do + checkbox_json[:options] = ["Hello"] + + expect(subject.valid?).to eq(false) + expect(subject.errors[:options]).to eq(["must have at least two choices"]) + end + + it "must have all answers that are listed in the options array" do + checkbox_json[:answer] = ["Peter Grunde", "No such answer"] + + expect(subject.valid?).to eq(false) + expect(subject.errors[:answer]).to eq(["set must exist in the options"]) + end + + context "when there are '\\r' return chars in the options" do + it "should still pass validations" do + checkbox_json[:options].push("Kool Aid Man\r") + checkbox_json[:answer] = ["Kool Aid Man"] + + expect(subject.valid?).to eq(true) + end + end + + context "when there are '\\r' return chars in the answers" do + it "should still pass validations" do + checkbox_json[:options].push("Kool Aid Man") + checkbox_json[:answer] = ["Kool Aid Man\r"] + + expect(subject.valid?).to eq(true) + end + end + + context "when there is a multiline answer" do + it "should still pass validations" do + checkbox_json[:options].push("```java\na bunch of text\n\n split across\n\n multiple lines\n ```") + checkbox_json[:answer] = ["```java\na bunch of text\n\n split across\n\n multiple lines\n ```"] + + expect(subject.valid?).to eq(true) + end + end + + context "when the answer is an 'any' answer" do + it "should still pass validations" do + checkbox_json[:answer] = ["*"] + + expect(subject.valid?).to eq(true) + end + end + end + end +end diff --git a/gems/bp/spec/challenge_validators/code_snippet_challenge_validator_spec.rb b/gems/bp/spec/challenge_validators/code_snippet_challenge_validator_spec.rb new file mode 100644 index 0000000..15a5342 --- /dev/null +++ b/gems/bp/spec/challenge_validators/code_snippet_challenge_validator_spec.rb @@ -0,0 +1,131 @@ +require "spec_helper" + +describe BlockParser::ChallengeValidators::CodeSnippetChallengeValidator do + describe "validations" do + let(:code_snippet_json) do + { + "id": "123", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:code_snippet], + "title": "repeats", + "placeholder": "// Write your function in Javascript below", + "question": { + content: [ + { + "type": "markdown", + "value": "Write a function named repeats that returns true if the first half of the string equals the last half, and false if not." + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "You might have solved this with a while loop, but using recursion is another way to do this." + } + ] + }, + "rubric": { + "content": [ + { + "type": "markdown", + "value": "\nI AM RUBRIC MAN\n" + } + ] + }, + "language": "javascript", + "show_tests": true, + "tests": %{describe('repeats', function() { + it("returns true when given an empty string (which seems strange, but go with it :)", function() { + expect(repeats(""), "Default value is incorrect").to.deep.eq(true) + }) +}) +} + } + end + + it "can be valid" do + challenge_validator = described_class.new(code_snippet_json) + + expect(challenge_validator.valid?).to eq(true) + end + + it "requires that language is one of the approved types" do + code_snippet_json.delete(:language) + challenge_validator = described_class.new(code_snippet_json) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:language]).to eq(["can't be blank", "language must be java, javascript, python2.7, or python3.6, or sql"]) + + code_snippet_json[:language] = "Lua" + challenge_validator = described_class.new(code_snippet_json) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:language]).to eq(["language must be java, javascript, python2.7, or python3.6, or sql"]) + end + + it "requires tests" do + code_snippet_json.delete(:tests) + challenge_validator = described_class.new(code_snippet_json) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:tests]).to eq(["can't be blank"]) + end + + context "when the code snippet is of sql type" do + let(:sql_code_snippet_json) do + { + "id": "123", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:code_snippet], + "title": "repeats", + "placeholder": "// Write your function in Javascript below", + "question": { + content: [ + { + "type": "markdown", + "value": "Write a function named repeats that returns true if the first half of the string equals the last half, and false if not." + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "You might have solved this with a while loop, but using recursion is another way to do this." + } + ] + }, + "rubric": { + "content": [ + { + "type": "markdown", + "value": "\nI AM RUBRIC MAN\n" + } + ] + }, + "language": "sql", + "show_tests": true, + "tests": %{describe('repeats', function() { + it("returns true when given an empty string (which seems strange, but go with it :)", function() { + expect(repeats(""), "Default value is incorrect").to.deep.eq(true) + }) + }) + } + } + end + + it "should require the data path to be present" do + challenge_validator = described_class.new(sql_code_snippet_json) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:data_path]).to eq(["can't be blank"]) + end + + it "passes validation with data_path present" do + sql_code_snippet_json[:data_path] = "path" + challenge_validator = described_class.new(sql_code_snippet_json) + + expect(challenge_validator.valid?).to eq(true) + end + end + end +end diff --git a/gems/bp/spec/challenge_validators/custom_snippet_challenge_validator_spec.rb b/gems/bp/spec/challenge_validators/custom_snippet_challenge_validator_spec.rb new file mode 100644 index 0000000..93460f5 --- /dev/null +++ b/gems/bp/spec/challenge_validators/custom_snippet_challenge_validator_spec.rb @@ -0,0 +1,69 @@ +require "spec_helper" + +describe BlockParser::ChallengeValidators::CustomSnippetChallengeValidator do + describe "validations" do + let(:custom_snippet_json) do + { + "id": "123", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:custom_snippet], + "title": "derp", + "placeholder": "// Write your function in Java below", + "question": { + content: [ + { + "type": "markdown", + "value": "Write a function named repeats that returns true if the first half of the string equals the last half, and false if not." + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "You might have solved this with a while loop, but using recursion is another way to do this." + } + ] + }, + "rubric": { + "content": [ + { + "type": "markdown", + "value": "\nI AM RUBRIC MAN\n" + } + ] + }, + "language": "java", + "docker_directory_path": "/fixtures/valid-custom-snippet-challenge-directory" + } + end + subject { described_class.new(custom_snippet_json.merge(root_directory_path: File.dirname(__dir__))) } + + it "can be valid" do + expect(subject.valid?).to be true + end + + it "validates that language must be present" do + custom_snippet_json.delete(:language) + expect(subject.valid?).to be false + expect(subject.errors[:language]).to eq(["can't be blank"]) + end + + it "validates that docker_directory_path must be present" do + custom_snippet_json.delete(:docker_directory_path) + expect(subject.valid?).to be false + expect(subject.errors[:docker_directory_path]).to eq(["can't be blank"]) + end + + it "validates that docker_directory_path points to an existing directory" do + custom_snippet_json[:docker_directory_path] = "foo_directory" + expect(subject.valid?).to be false + expect(subject.errors[:docker_directory_path]).to eq(["points to a directory that doesn't exist"]) + end + + it "validates that docker_directory_path contains both a Dockerfile and a test.sh" do + custom_snippet_json[:docker_directory_path] = "/fixtures/no-standards-config-test-block-repo" + expect(subject.valid?).to be false + expect(subject.errors[:docker_directory_path]).to eq(["is missing required file 'Dockerfile'", "is missing required file 'test.sh'"]) + end + end +end diff --git a/gems/bp/spec/challenge_validators/multiple_choice_challenge_validator_spec.rb b/gems/bp/spec/challenge_validators/multiple_choice_challenge_validator_spec.rb new file mode 100644 index 0000000..df88362 --- /dev/null +++ b/gems/bp/spec/challenge_validators/multiple_choice_challenge_validator_spec.rb @@ -0,0 +1,107 @@ +require "spec_helper" + +describe BlockParser::ChallengeValidators::MultipleChoiceChallengeValidator do + describe "validations" do + let(:multiple_choice_json) do + { + "id": "1", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:multiple_choice], + "title": "People Skills", + "answer": "Peter Grunde", + "options": [ + "Peter Grunde", + "Dr. No", + "James Bond", + "La Chaiffre", + "Jaws" + ], + "question": { + content: [ + { + "type": "markdown", + "value": "\nWho is the coolest?\n" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\nBecause,duh.\n" + } + ] + }, + "rubric": { + "content": [ + { + "type": "markdown", + "value": "\nI AM RUBRIC MAN\n" + } + ] + } + } + end + + subject { described_class.new(multiple_choice_json) } + + it "can be valid" do + expect(subject.valid?).to eq(true) + end + + it "requires an answer" do + multiple_choice_json.delete(:answer) + + expect(subject.valid?).to eq(false) + expect(subject.errors[:answer]).to eq(["can't be blank", "must exist in the options"]) + end + + context "options" do + it "cannot be blank" do + multiple_choice_json.delete(:options) + + expect(subject.valid?).to eq(false) + expect(subject.errors[:options]).to eq(["can't be blank"]) + end + + it "must have at least 2 options" do + multiple_choice_json[:options] = ["Hello"] + + expect(subject.valid?).to eq(false) + expect(subject.errors[:options]).to eq(["must have at least two choices"]) + end + + it "must have an answer that is listed in the options array" do + multiple_choice_json[:answer] = "No such answer" + + expect(subject.valid?).to eq(false) + expect(subject.errors[:answer]).to eq(["must exist in the options"]) + end + + context "when there are '\\r' return chars in the options" do + it "should still pass validations" do + multiple_choice_json[:options].push("Kool Aid Man\r") + multiple_choice_json[:answer] = "Kool Aid Man" + + expect(subject.valid?).to eq(true) + end + end + + context "when there is a multiline answer" do + it "should still pass validations" do + multiple_choice_json[:options].push("```java\na bunch of text\n\n split across\n\n multiple lines\n ```") + multiple_choice_json[:answer] = "```java\na bunch of text\n\n split across\n\n multiple lines\n ```" + + expect(subject.valid?).to eq(true) + end + end + + context "when the answer is an 'any' answer" do + it "should still pass validations" do + multiple_choice_json[:answer] = "*" + + expect(subject.valid?).to eq(true) + end + end + end + end +end diff --git a/gems/bp/spec/challenge_validators/number_challenge_validator_spec.rb b/gems/bp/spec/challenge_validators/number_challenge_validator_spec.rb new file mode 100644 index 0000000..65a9f33 --- /dev/null +++ b/gems/bp/spec/challenge_validators/number_challenge_validator_spec.rb @@ -0,0 +1,72 @@ +require "spec_helper" + +describe BlockParser::ChallengeValidators::NumberChallengeValidator do + describe "validations" do + let(:valid_attributes) do + { + "id": "1", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:number], + "title": "sum", + "placeholder": "enter answer", + "answer": "3", + "decimal": "2", + "question": { + content: [ + { + "type": "markdown", + "value": "1+2" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "it's the sum" + } + ] + }, + "rubric": { + "content": [ + { + "type": "markdown", + "value": "\nI AM RUBRIC MAN\n" + } + ] + } + } + end + + it "can be valid" do + challenge_validator = described_class.new(valid_attributes) + + expect(challenge_validator.valid?).to eq(true) + end + + it "requires an answer" do + valid_attributes.delete(:answer) + challenge_validator = described_class.new(valid_attributes) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:answer]).to eq(["can't be blank"]) + end + + it "require decimal is a number if defined" do + valid_attributes.delete(:decimal) + + challenge_validator = described_class.new(valid_attributes) + expect(challenge_validator.valid?).to eq(true) + + valid_attributes[:decimal] = "" + + challenge_validator = described_class.new(valid_attributes) + expect(challenge_validator.valid?).to eq(true) + + valid_attributes[:decimal] = "asdf" + + challenge_validator = described_class.new(valid_attributes) + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:decimal]).to eq(["is not a number"]) + end + end +end diff --git a/gems/bp/spec/challenge_validators/project_challenge_validator_spec.rb b/gems/bp/spec/challenge_validators/project_challenge_validator_spec.rb new file mode 100644 index 0000000..52b65ff --- /dev/null +++ b/gems/bp/spec/challenge_validators/project_challenge_validator_spec.rb @@ -0,0 +1,56 @@ +require "spec_helper" + +describe BlockParser::ChallengeValidators::ProjectChallengeValidator do + describe "validations" do + let(:challenge_validator) { described_class.new(valid_attributes) } + let(:valid_attributes) do + { + "id": "1", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:testable_project], + "title": "js-native-array-methods", + "placeholder": "https://github.com/js-native-array-methods", + "question": { + content: [ + { + "type": "markdown", + "value": "This is a project challenge?" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "Wait for your project to be graded!" + } + ] + }, + "rubric": { + "content": [ + { + "type": "markdown", + "value": "\nI AM RUBRIC MAN\n" + } + ] + }, + "upstream_repo_path": upstream_repo_path + } + end + + context "when upstream_repo_path is present" do + let(:upstream_repo_path) { "https://github.com/gSchool/js-native-array-methods" } + + it "should not be valid" do + expect(challenge_validator.valid?).to eq(false) + end + end + + context "when upstream_repo_path is not present" do + let(:upstream_repo_path) { nil } + + it "should be valid" do + expect(challenge_validator.valid?).to eq(true) + end + end + end +end diff --git a/gems/bp/spec/challenge_validators/short_answer_challenge_validator_spec.rb b/gems/bp/spec/challenge_validators/short_answer_challenge_validator_spec.rb new file mode 100644 index 0000000..9363377 --- /dev/null +++ b/gems/bp/spec/challenge_validators/short_answer_challenge_validator_spec.rb @@ -0,0 +1,53 @@ +require "spec_helper" + +describe BlockParser::ChallengeValidators::ShortAnswerChallengeValidator do + describe "validations" do + let(:valid_attributes) do + { + "id": "1", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:short_answer], + "title": "sum", + "placeholder": "enter answer", + "answer": "much wood", + "question": { + content: [ + { + "type": "markdown", + "value": "how much wood would a woodchuck purchase?" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "Woody Harilyson" + } + ] + }, + "rubric": { + "content": [ + { + "type": "markdown", + "value": "\nI AM RUBRIC MAN\n" + } + ] + } + } + end + + it "can be valid" do + challenge_validator = described_class.new(valid_attributes) + + expect(challenge_validator.valid?).to eq(true) + end + + it "requires an answer" do + valid_attributes.delete(:answer) + challenge_validator = described_class.new(valid_attributes) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:answer]).to eq(["can't be blank"]) + end + end +end diff --git a/gems/bp/spec/challenge_validators/testable_project_challenge_validator_spec.rb b/gems/bp/spec/challenge_validators/testable_project_challenge_validator_spec.rb new file mode 100644 index 0000000..231b9fb --- /dev/null +++ b/gems/bp/spec/challenge_validators/testable_project_challenge_validator_spec.rb @@ -0,0 +1,296 @@ +require "spec_helper" + +describe BlockParser::ChallengeValidators::TestableProjectChallengeValidator do + before { allow(ENV).to receive(:[]) { "foo" } } + describe "validations" do + let(:challenge_validator) { described_class.new(valid_attributes) } + let(:valid_attributes) do + { + "id": "1", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:testable_project], + "title": "js-native-array-methods", + "placeholder": "https://github.com/js-native-array-methods", + "question": { + content: [ + { + "type": "markdown", + "value": "This is a project challenge?" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "Wait for your project to be graded!" + } + ] + }, + "rubric": { + "content": [ + { + "type": "markdown", + "value": "\nI AM RUBRIC MAN\n" + } + ] + }, + "upstream_repo_path": upstream_repo_path + } + end + let(:upstream_repo_path) { "https://github.com/gSchool/js-native-array-methods" } + let(:repo_name) { "gSchool/js-native-array-methods" } + + context "when upstream_repo_path is gitlab" do + let(:upstream_repo_path) { "https://gitlab.com/gSchool/js-native-array-methods" } + + it "yields no errors when it contains the required files" do + allow_any_instance_of(Gitlab::Client).to receive(:tree).and_return( + [OpenStruct.new(name: "Dockerfile"), OpenStruct.new(name: "test.sh")] + ) + expect(challenge_validator.valid?).to eq(true) + end + it "should fail validation when a file is not present" do + allow_any_instance_of(Gitlab::Client).to receive(:tree).and_return( + [OpenStruct.new(name: "test.sh")] + ) + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:upstream_repo_path]).to eq([": upstream test repo is missing required file - 'Dockerfile'"]) + end + end + + context "when upstream_repo_path is not present" do + let(:upstream_repo_path) { nil } + + it "should not be valid" do + expect(challenge_validator.valid?).to eq(false) + end + end + + context "when upstream_repo_path is not a github url or gitlab url" do + let!(:upstream_repo_path) { "http://www.google.com" } + + it "should be invalid" do + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:upstream_repo_path]).to eq(["must be from Github.com or Gitlab.com"]) + end + end + + context "when repo is on master" do + let(:branch) { "master" } + + context "and upstream repo exists on github" do + it "should be valid" do + allow_any_instance_of(Mocktokit::Client).to receive(:repository?).with(repo_name).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).and_return(true) + expect(challenge_validator.valid?).to eq(true) + end + end + + context "and repo is not found" do + it "should not be valid" do + allow_any_instance_of(Mocktokit::Client).to receive(:repository?).with(repo_name).and_return(false) + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:upstream_repo_path]).to eq([": upstream test repo couldn't be found. Verify the repo/branch exists."]) + end + end + + context "and upstream repo is missing Dockerfile" do + it "should not be valid" do + allow_any_instance_of(Mocktokit::Client).to receive(:repository?).with(repo_name).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: "Dockerfile", ref: branch).and_raise(Octokit::NotFound) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: "test.sh", ref: branch).and_return(true) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:upstream_repo_path]).to eq([": upstream test repo is missing required file - 'Dockerfile'"]) + end + end + + context "upstream repo is missing test.sh" do + it "should not be valid" do + allow_any_instance_of(Mocktokit::Client).to receive(:repository?).with(repo_name).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: "Dockerfile", ref: branch).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: "test.sh", ref: branch).and_raise(Octokit::NotFound) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:upstream_repo_path]).to eq([": upstream test repo is missing required file - 'test.sh'"]) + end + end + + context "upstream repo is missing both Dockerfile and test.sh" do + it "should not be valid and return both errors" do + allow_any_instance_of(Mocktokit::Client).to receive(:repository?).with(repo_name).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: "Dockerfile", ref: branch).and_raise(Octokit::NotFound) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: "test.sh", ref: branch).and_raise(Octokit::NotFound) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:upstream_repo_path]).to eq([ + ": upstream test repo is missing required file - 'Dockerfile'", + ": upstream test repo is missing required file - 'test.sh'" + ]) + end + end + + context "and pointing to a subfolder" do + let(:upstream_repo_path) { "https://github.com/gSchool/js-native-array-methods/tree/master/sub-folder" } + let(:path_to_folder) { "sub-folder" } + let(:branch) { "master" } + + context "upstream repo is valid" do + it "should be valid" do + allow_any_instance_of(Mocktokit::Client).to receive(:repository?).with(repo_name).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: path_to_folder, ref: branch).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: "#{path_to_folder}/Dockerfile", ref: branch).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: "#{path_to_folder}/test.sh", ref: branch).and_return(true) + + expect(challenge_validator.valid?).to eq(true) + end + end + + context "repo is not found" do + it "should not be valid" do + allow_any_instance_of(Mocktokit::Client).to receive(:repository?).with(repo_name).and_return(false) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:upstream_repo_path]).to eq([": upstream test repo couldn't be found. Verify the repo/branch exists."]) + end + end + + context "sub folder is not found" do + it "should not be valid" do + allow_any_instance_of(Mocktokit::Client).to receive(:repository?).with(repo_name).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: path_to_folder, ref: branch).and_raise(Octokit::NotFound) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:upstream_repo_path]).to eq([": upstream test repo is missing subfolder(s) '#{path_to_folder}'"]) + end + end + + context "upstream repo is missing Dockerfile" do + it "should not be valid" do + allow_any_instance_of(Mocktokit::Client).to receive(:repository?).with(repo_name).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: path_to_folder, ref: branch).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: "#{path_to_folder}/Dockerfile", ref: branch).and_raise(Octokit::NotFound) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: "#{path_to_folder}/test.sh", ref: branch).and_return(true) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:upstream_repo_path]).to eq([": upstream test repo is missing required file - '#{path_to_folder}/Dockerfile'"]) + end + end + + context "upstream repo is missing test.sh" do + it "should not be valid" do + allow_any_instance_of(Mocktokit::Client).to receive(:repository?).with(repo_name).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: path_to_folder, ref: branch).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: "#{path_to_folder}/Dockerfile", ref: branch).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: "#{path_to_folder}/test.sh", ref: branch).and_raise(Octokit::NotFound) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:upstream_repo_path]).to eq([": upstream test repo is missing required file - '#{path_to_folder}/test.sh'"]) + end + end + end + end + + context "repo is on a branch" do + let(:upstream_repo_path) { "https://github.com/gSchool/js-native-array-methods/tree/sub-branch" } + let(:branch) { "sub-branch" } + + context "upstream repo exists on github" do + it "should be valid" do + allow_any_instance_of(Mocktokit::Client).to receive(:branch).with(repo_name, branch).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).and_return(true) + expect(challenge_validator.valid?).to eq(true) + end + end + + context "repo is not found" do + it "should not be valid" do + allow_any_instance_of(Mocktokit::Client).to receive(:branch).with(repo_name, branch).and_raise(Octokit::NotFound) + expect(challenge_validator.valid?).to eq(false) + end + end + + context "upstream repo is missing Dockerfile" do + it "should not be valid" do + allow_any_instance_of(Mocktokit::Client).to receive(:branch).with(repo_name, branch).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: "Dockerfile", ref: branch).and_raise(Octokit::NotFound) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: "test.sh", ref: branch).and_return(true) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:upstream_repo_path]).to eq([": upstream test repo is missing required file - 'Dockerfile'"]) + end + end + + context "upstream repo is missing test.sh" do + it "should not be valid" do + allow_any_instance_of(Mocktokit::Client).to receive(:branch).with(repo_name, branch).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: "Dockerfile", ref: branch).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: "test.sh", ref: branch).and_raise(Octokit::NotFound) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:upstream_repo_path]).to eq([": upstream test repo is missing required file - 'test.sh'"]) + end + end + + context "and pointing to a subfolder" do + let(:upstream_repo_path) { "https://github.com/gSchool/js-native-array-methods/tree/sub-branch/sub-folder" } + let(:path_to_folder) { "sub-folder" } + let(:branch) { "sub-branch" } + + context "upstream repo is valid" do + it "should be valid" do + allow_any_instance_of(Mocktokit::Client).to receive(:branch).with(repo_name, branch).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: path_to_folder, ref: branch).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: "#{path_to_folder}/Dockerfile", ref: branch).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: "#{path_to_folder}/test.sh", ref: branch).and_return(true) + + expect(challenge_validator.valid?).to eq(true) + end + end + + context "repo is not found" do + it "should not be valid" do + allow_any_instance_of(Mocktokit::Client).to receive(:branch).with(repo_name, branch).and_return(false) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:upstream_repo_path]).to eq([": upstream test repo couldn't be found. Verify the repo/branch exists."]) + end + end + + context "sub folder is not found" do + it "should not be valid" do + allow_any_instance_of(Mocktokit::Client).to receive(:branch).with(repo_name, branch).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: path_to_folder, ref: branch).and_raise(Octokit::NotFound) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:upstream_repo_path]).to eq([": upstream test repo is missing subfolder(s) '#{path_to_folder}'"]) + end + end + + context "upstream repo is missing Dockerfile" do + it "should not be valid" do + allow_any_instance_of(Mocktokit::Client).to receive(:branch).with(repo_name, branch).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: path_to_folder, ref: branch).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: "#{path_to_folder}/Dockerfile", ref: branch).and_raise(Octokit::NotFound) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: "#{path_to_folder}/test.sh", ref: branch).and_return(true) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:upstream_repo_path]).to eq([": upstream test repo is missing required file - '#{path_to_folder}/Dockerfile'"]) + end + end + + context "upstream repo is missing test.sh" do + it "should not be valid" do + allow_any_instance_of(Mocktokit::Client).to receive(:branch).with(repo_name, branch).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: path_to_folder, ref: branch).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: "#{path_to_folder}/Dockerfile", ref: branch).and_return(true) + allow_any_instance_of(Mocktokit::Client).to receive(:contents).with(repo_name, path: "#{path_to_folder}/test.sh", ref: branch).and_raise(Octokit::NotFound) + + expect(challenge_validator.valid?).to eq(false) + expect(challenge_validator.errors[:upstream_repo_path]).to eq([": upstream test repo is missing required file - '#{path_to_folder}/test.sh'"]) + end + end + end + end + end +end diff --git a/gems/bp/spec/convert_md_to_json_spec.rb b/gems/bp/spec/convert_md_to_json_spec.rb new file mode 100644 index 0000000..c799953 --- /dev/null +++ b/gems/bp/spec/convert_md_to_json_spec.rb @@ -0,0 +1,1702 @@ +require "spec_helper" + +describe BlockParser::ConvertMdToJson do + describe ".convert" do + it "converts plain md to a json representation" do + md_input = "## Hello\nhi" + + expected_output = { + "content": [ + { + "type": "markdown", + "value": "## Hello\nhi" + } + ] + } + + expect(described_class.convert(md_input)).to eq(expected_output) + end + + it "converts custom snippet challenge markdown into json" do + md_input = %(## A Challenge + +### !cHaLlEnGe + + * type: custom-snippet +* id: 101 +* standard_uuids: foo123 +* title: some custom snippet +* language: java +* points: 55 +* docker_directory_path: /some/docker/path +* external_id: 2 +* external_source: 1 + +#### !question + +What is the code that will answer this question? + +#### !end-question + +#### !rubric + +What a neat rubric this is. + +#### !end-rubric + +#### !placeholder + +Write your code here + +#### !end-placeholder + +#### !explanation + +Thanks for submitting! Your tests are evaluating. + +#### !end-explanation + +### !eNd-ChAlLeNgE +) + + expected_output = { + "content": [ + { + "type": "markdown", + "value": "## A Challenge\n" + }, + { + "type": "challenge", + "id": "101" + } + ], + "challenges": { + "101": { + "id": "101", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:custom_snippet], + "title": "some custom snippet", + "points": 55, + "placeholder": "Write your code here", + "standard_uuids": ["foo123"], + "language": "java", + "partial_credit": false, + "hints": [], + "question": { + content: [ + { + "type": "markdown", + "value": "\nWhat is the code that will answer this question?\n" + } + ] + }, + "docker_directory_path": "/some/docker/path", + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\nThanks for submitting! Your tests are evaluating.\n" + } + ] + }, + "rubric": { + "content": [ + { + "type": "markdown", + "value": "\nWhat a neat rubric this is.\n" + } + ] + }, + "setup": nil, + "external_id": "2", + "external_source": "1" + } + } + } + + expect(described_class.convert(md_input)).to eq(expected_output) + end + + it "converts project challenge markdown into json" do + md_input = %{## A Challenge + +### !cHaLlEnGe + + * type: testable-project +* id: 121 +* standard_uuids: foo123, bar456, baz789 +* title: partial derivative +* upstream: www.github.com/hello/world +* validate_fork: true + +#### !question + +Submit the link to your github repo. Make sure that the readme.md contains links to your Tracker backlog and hosted application. + +#### !end-question + +#### !placeholder + +Enter the github URL to your work. + +#### !end-placeholder + +#### !explanation + +Thanks for submitting! You will be able to download the [solutions](https://github.com/Galvanize-IT/lms-content-test/tree/master/dsi-example/estimation-sampling/solutions) once they are released. + +#### !end-explanation + +### !eNd-ChAlLeNgE +} + + expected_output = { + "content": [ + { + "type": "markdown", + "value": "## A Challenge\n" + }, + { + "type": "challenge", + "id": "121" + } + ], + "challenges": { + "121": { + "id": "121", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:testable_project], + "title": "partial derivative", + "placeholder": "Enter the github URL to your work.", + "standard_uuids": ["foo123", "bar456", "baz789"], + "hints": [], + "partial_credit": false, + "question": { + content: [ + { + "type": "markdown", + "value": "\nSubmit the link to your github repo. Make sure that the readme.md contains links to your Tracker backlog and hosted application.\n" + } + ] + }, + "upstream_repo_path": "www.github.com/hello/world", + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\nThanks for submitting! You will be able to download the [solutions](https://github.com/Galvanize-IT/lms-content-test/tree/master/dsi-example/estimation-sampling/solutions) once they are released.\n" + } + ] + }, + "setup": nil, + "validate_fork": true + } + } + } + + expect(described_class.convert(md_input)).to eq(expected_output) + end + + it "raises an error when multiple stand_uuid lines are present" do + md_input = %{## A Challenge + +### !cHaLlEnGe + + * type: project +* id: 121 +* standard_uuids: foo123, bar456, baz789 +* standard_uuids: foo123, bar456, baz789 +* title: partial derivative + +#### !question + +Submit the link to your github repo. Make sure that the readme.md contains links to your Tracker backlog and hosted application. + +#### !end-question + +#### !placeholder + +Enter the github URL to your work. + +#### !end-placeholder + +#### !explanation + +Thanks for submitting! You will be able to download the [solutions](https://github.com/Galvanize-IT/lms-content-test/tree/master/dsi-example/estimation-sampling/solutions) once they are released. + +#### !end-explanation + +### !eNd-ChAlLeNgE +} + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError) + end + + it "converts number challenge markdown into json" do + md_input = %(### !cHaLlEnGe + +* type: number +* id: 321 +* title: sum numbers +* decimal: 2 + +#### !question + +What is 1 + 2? + +#### !end-question + +#### !placeholder + +Enter your answer here + +#### !end-placeholder + +#### !answer + +3 + +#### !end-answer + +#### !explanation + +Good job at adding numbers! + +#### !end-explanation + +#### !hint + +You `suk` + +#### !end-hint + +### !eNd-ChAlLeNgE +) + + expected_output = { + "content": [ + { + "type": "challenge", + "id": "321" + } + ], + "challenges": { + "321": { + "id": "321", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:number], + "title": "sum numbers", + "decimal": "2", + "placeholder": "Enter your answer here", + "answer": "3", + "partial_credit": false, + "hints": ["You suk"], + "question": { + content: [ + { + "type": "markdown", + "value": "\nWhat is 1 + 2?\n" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\nGood job at adding numbers!\n" + } + ] + }, + "setup": nil + } + } + } + + expect(described_class.convert(md_input)).to eq(expected_output) + end + + it "converts short-answer challenge markdown into json" do + md_input = %(### !challenge +* type: short-answer +* id: 1 +* title: array CFU +* topics: ["\" Cool\"", " 'Beans'", " DUDE ", " dude"] + +##### !question + +What will the following code produce? + +##### !end-question + +##### !placeholder + +Enter your answer here + +##### !end-placeholder + +##### !answer + +Logan is cool + +##### !end-answer + +##### !explanation + +Logan is the coolest! + +##### !end-explanation + +### !end-challenge + +) + + expected_output = { + "content": [ + { + "type": "challenge", + "id": "1" + } + ], + "challenges": { + "1": { + "id": "1", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:short_answer], + "title": "array CFU", + "placeholder": "Enter your answer here", + "answer": "Logan is cool", + "hints": [], + partial_credit: false, + "topics": ["cool", "beans", "dude"], + "question": { + content: [ + { + "type": "markdown", + "value": "\nWhat will the following code produce?\n" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\nLogan is the coolest!\n" + } + ] + }, + "setup": nil + } + } + } + + expect(described_class.convert(md_input)).to eq(expected_output) + end + + it "converts local-snippet challenge markdown into json" do + md_input = %(### !challenge +* type: local-snippet +* id: 1 +* title: Grass-fed Snippet + +##### !question + +Fix the bug in the following code. + +##### !end-question + +##### !placeholder + +function returnTrue () { + return false +} + +##### !end-placeholder + +##### !tests + +describe("returnTrue", function() { + it("should return true", function() { + expect(returnTrue()).toEqual(true); + }); +}); + +##### !end-tests + +##### !explanation + +Hard to say. What is true, really? + +##### !end-explanation + +### !end-challenge + +) + + expected_output = { + "content": [ + { + "type": "challenge", + "id": "1" + } + ], + "challenges": { + "1": { + "id": "1", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:local_snippet], + "title": "Grass-fed Snippet", + partial_credit: false, + "question": { + content: [ + { + "type": "markdown", + "value": "\nFix the bug in the following code.\n" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\nHard to say. What is true, really?\n" + } + ] + }, + "placeholder": "function returnTrue () {\n return false\n}", + "show_tests": false, + "tests": %[\ndescribe("returnTrue", function() {\n it("should return true", function() {\n expect(returnTrue()).toEqual(true);\n });\n});\n], + "setup": nil, + "hints": [] + } + } + } + + # Iterate for easier to read test failures + result = described_class.convert(md_input) + expected_output[:challenges][:"1"].each do |k, v| + expect(v).to eq(result[:challenges][:"1"][k]) + end + + expect(described_class.convert(md_input)).to eq(expected_output) + end + + it "converts sql code snippet challenge markdown into json" do + md_input = %(# !challenge + +* type: code-snippet +* language: sql +* id: 123 +* title: Absence of a join with Left Outer Join +* data_path: ./sql/food_trucks.sql + +##### !question + +Given a `users` table with a primary key of `id` and a `trucks` table with a foreign key that references the `users.id` column, select all user information from users who do not own trucks, ordered by their last name, `users.last`. + +##### !end-question + +##### !placeholder + +```sql +-- Write your query +``` + +##### !end-placeholder + +##### !tests + +SELECT users.* FROM users LEFT OUTER JOIN trucks ON trucks.owner_id = users.id WHERE owner_id IS NULL ORDER BY users.last; + +##### !end-tests + +#### !explanation + +`LEFT OUTER JOIN` can connect table A to table B, and if a record in table A does not have a matching record in table B, it will still yield a record for it, _however all table B data will contain null values_. A `WHERE` clause that specifies a column can be used with `IS NULL` to only select those columns when they are null. + +#### !end-explanation + +# !end-challenge) + + expected_output = { + content: [ + { + type: "challenge", + id: "123" + } + ], + challenges: { + "123": { + "id": "123", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:code_snippet], + "title": "Absence of a join with Left Outer Join", + "data_path": "./sql/food_trucks.sql", + "placeholder": "-- Write your query", + "hints": [], + partial_credit: false, + "question": { + "content": [ + { + "type": "markdown", + "value": "\nGiven a `users` table with a primary key of `id` and a `trucks` table with a foreign key that references the `users.id` column, select all user information from users who do not own trucks, ordered by their last name, `users.last`.\n" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\n`LEFT OUTER JOIN` can connect table A to table B, and if a record in table A does not have a matching record in table B, it will still yield a record for it, _however all table B data will contain null values_. A `WHERE` clause that specifies a column can be used with `IS NULL` to only select those columns when they are null.\n" + } + ] + }, + "language": "sql", + "setup": nil, + "show_tests": false, + "tests": %(\nSELECT users.* FROM users LEFT OUTER JOIN trucks ON trucks.owner_id = users.id WHERE owner_id IS NULL ORDER BY users.last;\n) + } + } + } + + expect(described_class.convert(md_input)).to eq(expected_output) + end + + it "converts multiple choice challenge markdown into json" do + md_input = %(### !challenge + +* type: multiple-choice +* id: 1 +* title: People Skills + +##### !question + +### People Skills + +Who is the coolest? + +##### !end-question + +##### !options + +* Peter Grunde +* Dr. No +* James Bond +* La Chaiffre +* Jaws + +##### !end-options + +##### !answer + +Peter Grunde + +##### !end-answer + +##### !explanation + +Because, duh. + +##### !end-explanation + +### !end-challenge + +) + + expected_output = { + content: [ + { + type: "challenge", + id: "1" + } + ], + challenges: { + "1": { + "id": "1", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:multiple_choice], + "title": "People Skills", + "placeholder": nil, + "hints": [], + partial_credit: false, + "question": { + content: [ + { + "type": "markdown", + "value": "\n### People Skills\n\nWho is the coolest?\n" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\nBecause, duh.\n" + } + ] + }, + "setup": nil, + "options": [ + "Peter Grunde", + "Dr. No", + "James Bond", + "La Chaiffre", + "Jaws" + ], + "answer": "Peter Grunde" + } + } + } + + expect(described_class.convert(md_input)).to eq(expected_output) + end + + context "when !setup tag is present" do + let(:md_input) do + %{### !challenge +* type: code-snippet +* language: javascript +* id: 123 +* title: repeats + +### !question +Write a function named repeats that returns true if the first half of the string equals the last half, and false if not. +### !end-question + +### !placeholder +```js +function repeats(input) { +// Write your function in Javascript below +} +``` +### !end-placeholder + +### !setup +```js +(function () { +this.cStub = sinon.stub(console, "log"); +})() +``` +### !end-setup + +### !tests +```js +describe('repeats', function() { + + it("returns true when given an empty string (which seems strange, but go with it :)", function() { + expect(repeats(""), "Default value is incorrect").to.deep.eq(true) + }) + + it("returns true when the second half of the string equals the first", function() { + expect(repeats("bahbah")).to.deep.eq(true) + expect(repeats("nananananananana")).to.deep.eq(true) + }) + + it("returns false when the second half of the string does not equal the first", function() { + expect(repeats("bahba")).to.deep.eq(false) + expect(repeats("nananananann")).to.deep.eq(false) + }) + + it("does not use .repeat", function() { + expect(repeats.toString()).to.not.match(/\.repeat/) + }) + +}) +``` +### !end-tests + +### !explanation +You might have solved this with a while loop, but using recursion is another way to do this. +### !end-explanation + +### !end-challenge +} + end + it "converts javascript code snippet challenges markdown into json" do + expected_output = { + content: [ + { + type: "challenge", + id: "123" + } + ], + challenges: { + "123": { + "id": "123", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:code_snippet], + "title": "repeats", + "placeholder": "function repeats(input) {\n// Write your function in Javascript below\n}", + "hints": [], + partial_credit: false, + "question": { + content: [ + { + "type": "markdown", + "value": "Write a function named repeats that returns true if the first half of the string equals the last half, and false if not." + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "You might have solved this with a while loop, but using recursion is another way to do this." + } + ] + }, + "language": "javascript", + "setup": "(function () {\nthis.cStub = sinon.stub(console, \"log\");\n})()\n", + "show_tests": false, + "tests": %{describe('repeats', function() { + + it("returns true when given an empty string (which seems strange, but go with it :)", function() { + expect(repeats(""), "Default value is incorrect").to.deep.eq(true) + }) + + it("returns true when the second half of the string equals the first", function() { + expect(repeats("bahbah")).to.deep.eq(true) + expect(repeats("nananananananana")).to.deep.eq(true) + }) + + it("returns false when the second half of the string does not equal the first", function() { + expect(repeats("bahba")).to.deep.eq(false) + expect(repeats("nananananann")).to.deep.eq(false) + }) + + it("does not use .repeat", function() { + expect(repeats.toString()).to.not.match(/\.repeat/) + }) + +}) +} + } + } + } + + expect(described_class.convert(md_input)).to eq(expected_output) + end + + it "prevents two setup tags within a single challenge markdown block" do + md_input.gsub!("### !end-challenge\n", "### !setup\n ### !end-challenge\n") + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError) + end + end + + it "converts python code snippet challenges markdown into json" do + md_input = %{### !challenge +* type: code-snippet +* language: python2.7 +* id: 123 +* title: repeats + +### !question +Write a function named repeats that returns true if the first half of the string equals the last half, and false if not. +### !end-question + +### !placeholder +```python +def filter_by_class(X, y, label): + ''' + INPUT: 2 dimensional numpy array, numpy array, object + OUTPUT: 2 dimensional numpy array + + Return the rows from X whose corresponding label from y is the given label. + ''' + pass +``` +### !end-placeholder + +### !tests +```python +def test_filter_by_class1(): + X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) + y = np.array(["a", "c", "a", "b"]) + result = p.filter_by_class(X, y, "a") + answer = np.array([[1, 2, 3], [7, 8, 9]]) + assert np.array_equal(result, answer) + +def test_filter_by_class2(): + X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) + y = np.array(["a", "c", "a", "b"]) + result = p.filter_by_class(X, y, "b") + answer = np.array([[10, 11, 12]]) + assert np.array_equal(result, answer) +``` +### !end-tests + +### !explanation +You might have solved this with a while loop, but using recursion is another way to do this. +### !end-explanation + +### !end-challenge +} + + expected_output = { + content: [ + { + type: "challenge", + id: "123" + } + ], + challenges: { + "123": { + "id": "123", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:code_snippet], + "title": "repeats", + partial_credit: false, + "placeholder": "def filter_by_class(X, y, label): + ''' + INPUT: 2 dimensional numpy array, numpy array, object + OUTPUT: 2 dimensional numpy array + + Return the rows from X whose corresponding label from y is the given label. + ''' + pass", + "hints": [], + "question": { + content: [ + { + "type": "markdown", + "value": "Write a function named repeats that returns true if the first half of the string equals the last half, and false if not." + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "You might have solved this with a while loop, but using recursion is another way to do this." + } + ] + }, + "language": "python2.7", + "setup": nil, + "show_tests": false, + "tests": %{def test_filter_by_class1(): + X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) + y = np.array(["a", "c", "a", "b"]) + result = p.filter_by_class(X, y, "a") + answer = np.array([[1, 2, 3], [7, 8, 9]]) + assert np.array_equal(result, answer) + +def test_filter_by_class2(): + X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) + y = np.array(["a", "c", "a", "b"]) + result = p.filter_by_class(X, y, "b") + answer = np.array([[10, 11, 12]]) + assert np.array_equal(result, answer) +} + } + } + } + + expect(described_class.convert(md_input)).to eq(expected_output) + end + + context "when md file includes valid callout blocks" do + let(:md_input) do + %(### !callout-danger + # test + test + ### !end-callout + ) + end + + it "returns a callout content object" do + expected_output = { + "content": [ + { + "type": "callout", + "class": "callout-danger", + "value": "# test\ntest" + } + ] + } + + expect(described_class.convert(md_input)).to eq(expected_output) + end + end + + context "when a vimeo tag includes valid transcript information" do + let(:md_input) do + %(### !vimeo + * id: 214062173 + * transcript_project: 24099 + * transcript_file: 1795859 + * transcript_plugin: 11378 + ### !end-vimeo + ) + end + + it "returns a vimeo content object with transcript information" do + expected_output = { + "content": [ + { + "type": "vimeo", + "id": "214062173", + "transcript_project": "24099", + "transcript_file": "1795859", + "transcript_plugin": "11378" + } + ] + } + + expect(described_class.convert(md_input)).to eq(expected_output) + end + end + + context "when a vimeo includes transcript tags, but not a vimeo ID" do + let(:md_input) do + %(### !vimeo + * transcript_project: 24099 + * transcript_file: 1795859 + * transcript_plugin: 11378 + ### !end-vimeo + ) + end + + it "raises an error" do + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Vimeo tag missing ID") + end + end + + context "when a vimeo tag includes some, but not all of the required transcript tags" do + let(:md_input) do + %(### !vimeo + * id: 214062173 + * transcript_project: 24099 + * transcript_file: 1795859 + ### !end-vimeo + ) + end + + it "raises an error" do + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Vimeo tags with transcripts must include the project, file, and plugin") + end + end + + context "when a vimeo tag does not include transcript information" do + let(:md_input) do + %( + ### !vimeo + * id: 214062173 + ### !end-vimeo + ) + end + + it "returns a vimeo content object without transcript information" do + expected_output = { + "content": [ + { + "type": "vimeo", + "id": "214062173" + } + ] + } + + expect(described_class.convert(md_input)).to eq(expected_output) + end + end + + context "when a there are more than 10 vimeo videos" do + let(:md_input) do + %( + ### !vimeo + * id: 214062173 + ### !end-vimeo + ### !vimeo + * id: 214062173 + ### !end-vimeo + ### !vimeo + * id: 214062173 + ### !end-vimeo + ### !vimeo + * id: 214062173 + ### !end-vimeo + ### !vimeo + * id: 214062173 + ### !end-vimeo + ### !vimeo + * id: 214062173 + ### !end-vimeo + ### !vimeo + * id: 214062173 + ### !end-vimeo + ### !vimeo + * id: 214062173 + ### !end-vimeo + ### !vimeo + * id: 214062173 + ### !end-vimeo + ### !vimeo + * id: 214062173 + ### !end-vimeo + ### !vimeo + * id: 214062173 + ### !end-vimeo + ) + end + + it "raises an error" do + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "There can only be up to 10 vimeo videos in single page") + end + end + + it "handles multiple challenges in the md" do + md_input = %(### !challenge +* type: project +* id: 1 +* title: partial derivative 1 +#### !question +This is question 1 +#### !end-question + +#### !explanation +This is explanation 1 +#### !end-explanation +### !end-challenge +### !challenge +* type: project +* id: 2 +* title: partial derivative 2 +#### !question +This is question 2 +#### !end-question + +#### !explanation +This is explanation 2 +#### !end-explanation +### !end-challenge +) + + expected_output = { + "content": [ + { + "type": "challenge", + "id": "1" + }, + { + "type": "challenge", + "id": "2" + } + ], + "challenges": { + "1": { + "id": "1", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:project], + "title": "partial derivative 1", + "placeholder": nil, + "hints": [], + partial_credit: false, + "question": { + content: [ + { + "type": "markdown", + "value": "This is question 1" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "This is explanation 1" + } + ] + }, + "setup": nil + }, + "2": { + "id": "2", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:project], + "title": "partial derivative 2", + "placeholder": nil, + "hints": [], + partial_credit: false, + "question": { + content: [ + { + "type": "markdown", + "value": "This is question 2" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "This is explanation 2" + } + ] + }, + "setup": nil + } + } + } + + expect(described_class.convert(md_input)).to eq(expected_output) + end + + it "ignores !instructor tags" do + md_input = %(### !instructor +some text +### !end-instructor +) + expect(described_class.convert(md_input)).to eq(content: []) + end + + it "parses hints correctly" do + md_input = %(### !cHaLlEnGe + +* type: number +* id: 321 +* title: sum numbers +* decimal: 2 + +#### !question + +What is 1 + 2? + +#### !end-question + +#### !placeholder + +Enter your answer here + +#### !end-placeholder + +#### !answer + +3 + +#### !end-answer + +#### !explanation + +Good job at adding numbers! + +#### !end-explanation + +#### !hint + +You suk + +#### !end-hint + +#### !hint + +Cant help you + +#### !end-hint + +#### !hint + +```js +function sukLess ()=> { return 'code more' } +``` + +#### !end-hint + +### !eNd-ChAlLeNgE +) + + expected_output = { + "content": [ + { + "type": "challenge", + "id": "321" + } + ], + "challenges": { + "321": { + "id": "321", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:number], + "title": "sum numbers", + "decimal": "2", + "placeholder": "Enter your answer here", + "answer": "3", + partial_credit: false, + "hints": ["You suk", "Cant help you", "
    function sukLess ()=> { return 'code more' }\n
    "], + "question": { + content: [ + { + "type": "markdown", + "value": "\nWhat is 1 + 2?\n" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\nGood job at adding numbers!\n" + } + ] + }, + "setup": nil + } + } + } + + expect(described_class.convert(md_input)).to eq(expected_output) + end + + it "parses hints correctly even when there is no lang provided" do + md_input = %(### !cHaLlEnGe + +* type: number +* id: 321 +* title: sum numbers +* decimal: 2 + +#### !question + +What is 1 + 2? + +#### !end-question + +#### !placeholder + +Enter your answer here + +#### !end-placeholder + +#### !answer + +3 + +#### !end-answer + +#### !explanation + +Good job at adding numbers! + +#### !end-explanation + +#### !hint + +You suk + +#### !end-hint + +#### !hint + +Cant help you + +#### !end-hint + +#### !hint + +``` +function sukLess ()=> { return 'code more' } +``` + +#### !end-hint + +### !eNd-ChAlLeNgE +) + + expected_output = { + "content": [ + { + "type": "challenge", + "id": "321" + } + ], + "challenges": { + "321": { + "id": "321", + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:number], + "title": "sum numbers", + "decimal": "2", + "placeholder": "Enter your answer here", + "answer": "3", + partial_credit: false, + "hints": ["You suk", "Cant help you", "
    function sukLess ()=> { return 'code more' }\n
    "], + "question": { + content: [ + { + "type": "markdown", + "value": "\nWhat is 1 + 2?\n" + } + ] + }, + "explanation": { + "content": [ + { + "type": "markdown", + "value": "\nGood job at adding numbers!\n" + } + ] + }, + "setup": nil + } + } + } + + expect(described_class.convert(md_input)).to eq(expected_output) + end + + context "parse errors" do + it "raises an MdParseError when the input cannot be split into lines" do + md_input = "some-invalid-string" + expect(md_input).to receive(:split).and_raise(ArgumentError) + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "file does not appear to be a valid markdown file") + end + + context "inside parsing of challenges" do + it "raises an exception if there is a missing end-challenge tag" do + md_input = "### !challenge\n" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Didn't find !end-challenge tag.") + end + + it "raises an exception if there is a missing end-challenge tag with multiple challenge delimiters" do + md_input = "### !challenge\n### !challenge\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found second !challenge tag before finding !end-challenge.") + end + + it "raises an exception if there is a !end-placeholder tag without a !placeholder tag" do + md_input = "### !challenge\n### !end-placeholder\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found invalid tag '### !end-placeholder' within a !challenge tag.") + end + + it "raises an exception if there is a !end-question tag without a !question tag" do + md_input = "### !challenge\n### !end-question\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found invalid tag '### !end-question' within a !challenge tag.") + end + + it "raises an exception if there is a !end-explanation tag without a !explanation tag" do + md_input = "### !challenge\n### !end-explanation\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found invalid tag '### !end-explanation' within a !challenge tag.") + end + + it "raises an exception if there is a !end-options tag without a !options tag" do + md_input = "### !challenge\n### !end-options\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found invalid tag '### !end-options' within a !challenge tag.") + end + + it "raises an exception if there is an !end-hint tag without a !hint tag" do + md_input = "### !challenge\n### !end-hint\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found invalid tag '### !end-hint' within a !challenge tag.") + end + + it "raises an exception if there is an unknown tag" do + md_input = "### !challenge\n### !bob\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found invalid tag '### !bob' within a !challenge tag.") + end + + context "while parsing meta data" do + it "raises an exception if there is an unknown meta data key" do + md_input = "### !challenge\n* foo: bar\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found invalid meta data key '* foo: bar' within a !challenge tag.") + end + end + + context "inside parsing question" do + it "raises an exception if there is no !end-question tag after the !question tag" do + md_input = "### !challenge\n### !question\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Didn't find !end-question tag.") + end + + it "raises an exception if any non !end-question tag is found" do + md_input = "### !challenge\n### !question\n### !placeholder\n### !end-question\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found invalid tag '### !placeholder' within a !question tag.") + end + end + + context "inside parsing options" do + it "raises an exception if there is no !end-options tag after the !options tag" do + md_input = "### !challenge\n### !options\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Didn't find !end-options tag.") + end + + it "raises an exception if any non !end-options tag is found" do + md_input = "### !challenge\n### !options\n### !placeholder\n### !end-options\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found invalid tag '### !placeholder' within a !options tag.") + end + end + + context "inside parsing placeholder" do + it "raises an exception if there is no !end-placeholder tag after the !placeholder tag" do + md_input = "### !challenge\n### !placeholder\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Didn't find !end-placeholder tag.") + end + + it "raises an exception if any non !end-placeholder tag is found" do + md_input = "### !challenge\n### !placeholder\n### !question\n### !end-placeholder\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found invalid tag '### !question' within a !placeholder tag.") + end + end + + context "inside parsing explanation" do + it "raises an exception if there is no !end-explanation tag after the !explanation tag" do + md_input = "### !challenge\n### !explanation\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Didn't find !end-explanation tag.") + end + + it "raises an exception if any non !end-explanation tag is found" do + md_input = "### !challenge\n### !explanation\n### !question\n### !end-explanation\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found invalid tag '### !question' within a !explanation tag.") + end + end + + context "inside parsing hint" do + it "raises an exception if there is no !end-hint tag after the !hint tag" do + md_input = "### !challenge\n### !hint\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Didn't find !end-hint tag.") + end + + it "raises an exception if any non !end-hint tag is found" do + md_input = "### !challenge\n### !hint\n### !question\n### !end-hint\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found invalid tag '### !question' within a !hint tag.") + end + end + end + + context "outside of challenge parsing" do + it "raises an exception if there is a lone end-challenge" do + md_input = "### !end-challenge\n" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found invalid tag 'end-challenge' without a starting !challenge tag.") + end + + it "raises an exception if there is a lone end-instructor tag" do + md_input = "### !end-instructor\n" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found invalid tag 'end-instructor' without a starting !instructor tag.") + end + + it "raises an exception if there is a lone end-vimeo tag" do + md_input = "### !end-vimeo\n" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found invalid tag 'end-vimeo' without a starting !vimeo tag.") + end + + it "raises an exception if there is a !question tag outside of a !challenge" do + md_input = "### !question\n### !challenge\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found invalid tag '### !question' outside of a !challenge tag.") + end + + it "raises an exception if there is a !end-question tag outside of a !challenge" do + md_input = "### !end-question\n### !challenge\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found invalid tag '### !end-question' outside of a !challenge tag.") + end + + it "raises an exception if there is a !placeholder tag outside of a !challenge" do + md_input = "### !placeholder\n### !challenge\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found invalid tag '### !placeholder' outside of a !challenge tag.") + end + + it "raises an exception if there is a !end-placeholder tag outside of a !challenge" do + md_input = "### !end-placeholder\n### !challenge\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found invalid tag '### !end-placeholder' outside of a !challenge tag.") + end + + it "raises an exception if there is a !explanation tag outside of a !challenge" do + md_input = "### !explanation\n### !challenge\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found invalid tag '### !explanation' outside of a !challenge tag.") + end + + it "raises an exception if there is a !end-explanation tag outside of a !challenge" do + md_input = "### !end-explanation\n### !challenge\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found invalid tag '### !end-explanation' outside of a !challenge tag.") + end + + it "raises an exception if there is a unknown tag outside of a !challenge" do + md_input = "### !bob\n### !challenge\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found invalid tag '### !bob' outside of a !challenge tag.") + end + + it "raises an exception if there is a challenge without an id" do + md_input = "### !challenge\n* title: foo\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found !challenge without an id.") + end + + it "raises an exception if there is a duplicate challenge id found" do + md_input = "### !challenge\n* id: 1\n### !end-challenge\n### !challenge\n* id: 1\n### !end-challenge" + + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Found duplicate challenge id: 1.") + end + end + + it "raises an exception if there is a missing end-instructor tag" do + md_input = %(### !instructor +) + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Missing !end-instructor tag for existing !instructor tag") + end + + it "raises an exception if there is a missing end-vimeo tag" do + md_input = %(### !vimeo +) + expect do + described_class.convert(md_input) + end.to raise_error(described_class::MdParseError, "Didn't find !end-vimeo tag.") + end + end + end + + describe "show_tests" do + let(:id) { "444" } + let(:md_input) do + %( +### !cHaLlEnGe + +* type: code-snippet +* id: #{id} +* title: Shown Tests +* language: javascript +* show_tests: true + +#### !question + +Return true + +#### !end-question + +#### !placeholder +```js +function f () {} +``` +#### !end-placeholder + +### !tests +```js +describe('hmm', function() {}) +``` +### !end-tests + +### !eNd-ChAlLeNgE) + end + + it "accepts the show_tests option" do + expected_output = { + "content": [ + { + "type": "challenge", + "id": id + } + ], + challenges: { + id.to_sym => { + "id": id, + "type": BlockParser::ChallengeValidators::Challenge::TYPES[:code_snippet], + "title": "Shown Tests", + "placeholder": "function f () {}", + "hints": [], + partial_credit: false, + "question": { + content: [ + { + "type": "markdown", + "value": "\nReturn true\n" + } + ] + }, + "show_tests": true, + "language": "javascript", + "setup": nil, + "tests": "describe('hmm', function() {})\n" + } + } + } + + expect(described_class.convert(md_input)).to eq(expected_output) + end + end +end diff --git a/gems/bp/spec/fixtures/checkpoint-with-bad-challenge-tag/bad-challenges.md b/gems/bp/spec/fixtures/checkpoint-with-bad-challenge-tag/bad-challenges.md new file mode 100644 index 0000000..af9b3f7 --- /dev/null +++ b/gems/bp/spec/fixtures/checkpoint-with-bad-challenge-tag/bad-challenges.md @@ -0,0 +1,128 @@ +### !challenge + +* type: paragraph +* id: twenty-mc-double-billions +* title: Submit your project + +##### !question + +### Question + +How many words do you know now? + +##### !end-question + +##### !placeholder + +Write them all here + +##### !end-placeholder + +##### !explanation + +An instructor will review and grade this. Good Luck! + +##### !end-explanation + +##### !rubric + +Better do good + +##### !end-rubric + +### !end-challenge + +### !challenge + +# !challenge + +* type: code-snippet +* language: javascript +* id: 384ccd8d-0b4a-4586-b17e-048b99b0f333 +* title: repeats +* standard_uuids: W0018-V1 + +##### !question + +### JS Snippet + +Write a function named repeats that returns true if the first half of the string equals the last half, and false if not. + +##### !end-question + +##### !setup + +``` +var expect = require('chai').expect; + +function repeats(input) { +``` + +##### !end-setup + +##### !placeholder + +``` + +//function repeats(input) { +// return true if the first half of the string equals the last half, false if not + + if (input.length % 2 !== 0) { + return false; + } + var firstHalf = input.substr(0, input.length/2); + var secondHalf = input.substr(input.length/2); + return firstHalf == secondHalf; +} +``` + +##### !end-placeholder + +##### !tests + +``` +describe('repeats', function() { + + it("returns true when given an empty string (which seems strange, but go with it :) )", function() { + expect(repeats(""), "Default value is incorrect").to.deep.eq(true) + }) + + it("returns true when the second half of the string equals the first", function() { + expect(repeats("bahbah")).to.deep.eq(true) + expect(repeats("nananananananana")).to.deep.eq(true) + }) + + it("returns false when the second half of the string does not equal the first", function() { + expect(repeats("bahba")).to.deep.eq(false) + expect(repeats("nananananann")).to.deep.eq(false) + }) + + it("does not use .repeat", function() { + expect(repeats.toString()).to.not.match(/\.repeat/) + }) + +}) +``` + +##### !end-tests + +##### !explanation + +Be sure that you code checked for input of an string of odd-length. + +Here is one possible solution: + +``` +function repeats(myString) { + if (myString.length % 2 !== 0) { + return false; + } + var firstHalf = myString.substr(0, myString.length/2); + var secondHalf = myString.substr(myString.length/2); + return firstHalf == secondHalf; +} +``` + +##### !end-explanation + +# !end-challenge \ No newline at end of file diff --git a/gems/bp/spec/fixtures/checkpoint-with-bad-challenge-tag/config.yaml b/gems/bp/spec/fixtures/checkpoint-with-bad-challenge-tag/config.yaml new file mode 100644 index 0000000..8ce6623 --- /dev/null +++ b/gems/bp/spec/fixtures/checkpoint-with-bad-challenge-tag/config.yaml @@ -0,0 +1,14 @@ +--- +Standards: + - + Title: bar + UID: abc123 + Description: foobar + SuccessCriteria: + - Foo + - Bar + ContentFiles: + - + UID: none + Type: Checkpoint + Path: /bad-challenges.md diff --git a/gems/bp/spec/fixtures/checkpoint-without-challenges-block-repo/config.yaml b/gems/bp/spec/fixtures/checkpoint-without-challenges-block-repo/config.yaml new file mode 100644 index 0000000..2a83ef5 --- /dev/null +++ b/gems/bp/spec/fixtures/checkpoint-without-challenges-block-repo/config.yaml @@ -0,0 +1,14 @@ +--- +Standards: + - + Title: bar + UID: abc123 + Description: foobar + SuccessCriteria: + - Foo + - Bar + ContentFiles: + - + UID: none + Type: Checkpoint + Path: /no-challenges.md diff --git a/gems/bp/spec/fixtures/checkpoint-without-challenges-block-repo/no-challenges.md b/gems/bp/spec/fixtures/checkpoint-without-challenges-block-repo/no-challenges.md new file mode 100644 index 0000000..15319ba --- /dev/null +++ b/gems/bp/spec/fixtures/checkpoint-without-challenges-block-repo/no-challenges.md @@ -0,0 +1 @@ +# I ain't got no challenges! diff --git a/gems/bp/spec/fixtures/invalid-config-test-block-repo/config.yaml b/gems/bp/spec/fixtures/invalid-config-test-block-repo/config.yaml new file mode 100644 index 0000000..4726ad3 --- /dev/null +++ b/gems/bp/spec/fixtures/invalid-config-test-block-repo/config.yaml @@ -0,0 +1,3 @@ +--- +- Title: CNE Intro +BARF \ No newline at end of file diff --git a/gems/bp/spec/fixtures/no-lessons-nor-checkpoints/config.yaml b/gems/bp/spec/fixtures/no-lessons-nor-checkpoints/config.yaml new file mode 100644 index 0000000..afb4da2 --- /dev/null +++ b/gems/bp/spec/fixtures/no-lessons-nor-checkpoints/config.yaml @@ -0,0 +1,14 @@ +--- +Title: Block Name +Standards: + - + Title: No Lessons Nor Checkpoints + UID: xe81925b-4ef0-4ded-ae20-8fb01ce3b3f2 + Description: Do the first thing V10 + SuccessCriteria: + - TEST + ContentFiles: + - + Type: Resource + UID: 11e55988-5990-4a15-bf68-f8d729bedf41 + Path: /resources.md diff --git a/gems/bp/spec/fixtures/no-lessons-nor-checkpoints/resources.md b/gems/bp/spec/fixtures/no-lessons-nor-checkpoints/resources.md new file mode 100644 index 0000000..2ddd5bd --- /dev/null +++ b/gems/bp/spec/fixtures/no-lessons-nor-checkpoints/resources.md @@ -0,0 +1 @@ +Intentionally left blank. diff --git a/gems/bp/spec/fixtures/no-standards-config-test-block-repo/config.yaml b/gems/bp/spec/fixtures/no-standards-config-test-block-repo/config.yaml new file mode 100644 index 0000000..315d6e9 --- /dev/null +++ b/gems/bp/spec/fixtures/no-standards-config-test-block-repo/config.yaml @@ -0,0 +1,2 @@ +--- +Title: CNE Intro diff --git a/gems/bp/spec/fixtures/sample-iframe.md b/gems/bp/spec/fixtures/sample-iframe.md new file mode 100644 index 0000000..76755c4 --- /dev/null +++ b/gems/bp/spec/fixtures/sample-iframe.md @@ -0,0 +1,5 @@ + diff --git a/gems/bp/spec/fixtures/test-block-repo-yml/config.yml b/gems/bp/spec/fixtures/test-block-repo-yml/config.yml new file mode 100644 index 0000000..0e833fc --- /dev/null +++ b/gems/bp/spec/fixtures/test-block-repo-yml/config.yml @@ -0,0 +1,13 @@ +--- +Standards: + - + Title: bar + UID: abc123 + Description: foobar + SuccessCriteria: + - Foo + - Bar + ContentFiles: + - + Type: Lesson + Path: /markdown-smoketest.md diff --git a/gems/bp/spec/fixtures/test-block-repo-yml/dummy.pdf b/gems/bp/spec/fixtures/test-block-repo-yml/dummy.pdf new file mode 100644 index 0000000000000000000000000000000000000000..774c2ea70c55104973794121eae56bcad918da97 GIT binary patch literal 13264 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 literal 0 HcmV?d00001 diff --git a/gems/bp/spec/fixtures/test-block-repo-yml/folder/sibling.md b/gems/bp/spec/fixtures/test-block-repo-yml/folder/sibling.md new file mode 100644 index 0000000..0600109 --- /dev/null +++ b/gems/bp/spec/fixtures/test-block-repo-yml/folder/sibling.md @@ -0,0 +1,3 @@ +I am the sibling + +* [parent link](../markdown-smoketest.md) diff --git a/gems/bp/spec/fixtures/test-block-repo-yml/folder/target.md b/gems/bp/spec/fixtures/test-block-repo-yml/folder/target.md new file mode 100644 index 0000000..083c50b --- /dev/null +++ b/gems/bp/spec/fixtures/test-block-repo-yml/folder/target.md @@ -0,0 +1,3 @@ +nested target + +* [sibling](sibling.md) diff --git a/gems/bp/spec/fixtures/test-block-repo-yml/images/galvanize-logo.png b/gems/bp/spec/fixtures/test-block-repo-yml/images/galvanize-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..64319ca905483ea07335fb5f229576fec27d7036 GIT binary patch literal 4134 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 + +### Syntax Highlighting +Inline `code` has `back-ticks around` it. + +```javascript +var s = "JavaScript syntax highlighting"; +alert(s); +``` + +```python +s = "Python syntax highlighting" +print s +``` + +``` +For data point in training set: + calculate distance from data point to new_value +Order distances in increasing order and take the first k +Make the prediction + +No language indicated, so no syntax highlighting. +But let's throw in a tag. +``` + +### Maths +$$x = {-b \pm \sqrt{b^2-4ac} \over 2a}.$$ + +### Blockquotes + +> Blockquotes are very handy in email to emulate reply text. +> This line is part of the same quote. + +Quote break. + +> This is a very long line that will still be quoted properly when it wraps. + + + +### Tables + +| Tables | Are | Cool | +| ------------- |---------------| ------| +| enterprise | dsi | wdi | + +### Instructor tags (nothing should show up after this line) + +### !instructor + +# H1 + +Text + +![image](images/galvanize-logo.png) + +[relative link](target.md) + +Inline `code` has `back-ticks around` it. + +$$x = {-b \pm \sqrt{b^2-4ac} \over 2a}.$$ + +> Blockquotes are very handy in email to emulate reply text. +> This line is part of the same quote. + +### !end-instructor diff --git a/gems/bp/spec/fixtures/test-block-repo-yml/target.md b/gems/bp/spec/fixtures/test-block-repo-yml/target.md new file mode 100644 index 0000000..2901278 --- /dev/null +++ b/gems/bp/spec/fixtures/test-block-repo-yml/target.md @@ -0,0 +1 @@ +Top level target diff --git a/gems/bp/spec/fixtures/test-block-repo/README.md b/gems/bp/spec/fixtures/test-block-repo/README.md new file mode 100644 index 0000000..49b8920 --- /dev/null +++ b/gems/bp/spec/fixtures/test-block-repo/README.md @@ -0,0 +1,22 @@ +This is the first line + + + + + +Also second line + + + + + + +But also 3 lines + + + + + + + +Should not make the cut \ No newline at end of file diff --git a/gems/bp/spec/fixtures/test-block-repo/config.yaml b/gems/bp/spec/fixtures/test-block-repo/config.yaml new file mode 100644 index 0000000..03af23e --- /dev/null +++ b/gems/bp/spec/fixtures/test-block-repo/config.yaml @@ -0,0 +1,18 @@ +--- +Standards: + - + Title: bar + UID: abc123 + Description: foobar + SuccessCriteria: + - Foo + - Bar + ContentFiles: + - + Type: Lesson + UID: xyz456 + Path: /markdown-smoketest.md + - + Type: Lesson + UID: xyz456 + Path: /ipynb-test.ipynb diff --git a/gems/bp/spec/fixtures/test-block-repo/folder/sibling.md b/gems/bp/spec/fixtures/test-block-repo/folder/sibling.md new file mode 100644 index 0000000..0600109 --- /dev/null +++ b/gems/bp/spec/fixtures/test-block-repo/folder/sibling.md @@ -0,0 +1,3 @@ +I am the sibling + +* [parent link](../markdown-smoketest.md) diff --git a/gems/bp/spec/fixtures/test-block-repo/folder/target.md b/gems/bp/spec/fixtures/test-block-repo/folder/target.md new file mode 100644 index 0000000..083c50b --- /dev/null +++ b/gems/bp/spec/fixtures/test-block-repo/folder/target.md @@ -0,0 +1,3 @@ +nested target + +* [sibling](sibling.md) diff --git a/gems/bp/spec/fixtures/test-block-repo/images/galvanize-logo.png b/gems/bp/spec/fixtures/test-block-repo/images/galvanize-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..64319ca905483ea07335fb5f229576fec27d7036 GIT binary patch literal 4134 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 + +### Syntax Highlighting +Inline `code` has `back-ticks around` it. + +```javascript +var s = "JavaScript syntax highlighting"; +alert(s); +``` + +```python +s = "Python syntax highlighting" +print s +``` + +``` +For data point in training set: + calculate distance from data point to new_value +Order distances in increasing order and take the first k +Make the prediction + +No language indicated, so no syntax highlighting. +But let's throw in a tag. +``` + +### Maths +$$x = {-b \pm \sqrt{b^2-4ac} \over 2a}.$$ + +### Blockquotes + +> Blockquotes are very handy in email to emulate reply text. +> This line is part of the same quote. + +Quote break. + +> This is a very long line that will still be quoted properly when it wraps. + + + +### Tables + +| Tables | Are | Cool | +| ------------- |---------------| ------| +| enterprise | dsi | wdi | + +### Instructor tags (nothing should show up after this line) + +### !instructor + +# H1 + +Text + +![image](images/galvanize-logo.png) + +[relative link](target.md) + +Inline `code` has `back-ticks around` it. + +$$x = {-b \pm \sqrt{b^2-4ac} \over 2a}.$$ + +> Blockquotes are very handy in email to emulate reply text. +> This line is part of the same quote. + +### !end-instructor diff --git a/gems/bp/spec/fixtures/test-block-repo/target.md b/gems/bp/spec/fixtures/test-block-repo/target.md new file mode 100644 index 0000000..2901278 --- /dev/null +++ b/gems/bp/spec/fixtures/test-block-repo/target.md @@ -0,0 +1 @@ +Top level target diff --git a/gems/bp/spec/fixtures/test-block-two-configs/config.yaml b/gems/bp/spec/fixtures/test-block-two-configs/config.yaml new file mode 100644 index 0000000..3f6ef9d --- /dev/null +++ b/gems/bp/spec/fixtures/test-block-two-configs/config.yaml @@ -0,0 +1,2 @@ +--- +- Title: CNE Intro \ No newline at end of file diff --git a/gems/bp/spec/fixtures/test-block-two-configs/config.yml b/gems/bp/spec/fixtures/test-block-two-configs/config.yml new file mode 100644 index 0000000..3f6ef9d --- /dev/null +++ b/gems/bp/spec/fixtures/test-block-two-configs/config.yml @@ -0,0 +1,2 @@ +--- +- Title: CNE Intro \ No newline at end of file diff --git a/gems/bp/spec/fixtures/valid-custom-snippet-challenge-directory/Dockerfile b/gems/bp/spec/fixtures/valid-custom-snippet-challenge-directory/Dockerfile new file mode 100644 index 0000000..e69de29 diff --git a/gems/bp/spec/fixtures/valid-custom-snippet-challenge-directory/test.sh b/gems/bp/spec/fixtures/valid-custom-snippet-challenge-directory/test.sh new file mode 100644 index 0000000..e69de29 diff --git a/gems/bp/spec/fixtures/valid-yaml-array-test-block-repo/config.yaml b/gems/bp/spec/fixtures/valid-yaml-array-test-block-repo/config.yaml new file mode 100644 index 0000000..3f6ef9d --- /dev/null +++ b/gems/bp/spec/fixtures/valid-yaml-array-test-block-repo/config.yaml @@ -0,0 +1,2 @@ +--- +- Title: CNE Intro \ No newline at end of file diff --git a/gems/bp/spec/parse_directory_spec.rb b/gems/bp/spec/parse_directory_spec.rb new file mode 100644 index 0000000..9a32ded --- /dev/null +++ b/gems/bp/spec/parse_directory_spec.rb @@ -0,0 +1,320 @@ +require "spec_helper" + +describe BlockParser::ParseDirectory do + describe ".execute" do + describe "errors" do + subject { described_class.new(path: path, asset_uploader: Freeloader.new).execute } + + context "when the path does not exist" do + let(:path) { File.join(File.dirname(__FILE__), "tmp", SecureRandom.hex) } + + it "returns errors" do + expect(subject[:errors]).to include("Directory does not exist") + end + end + + context "when the path exists, but does not contain a config.yaml file" do + let(:path) { File.join(File.dirname(__FILE__), "tmp") } + + it "returns errors" do + expect(subject[:errors]).to include("Root directory does not contain a config.yaml or config.yml file") + end + end + + context "when the path exists and includes a config.yaml file" do + context "in valid format" do + let(:path) { File.join(File.dirname(__FILE__), "fixtures", "test-block-repo") } + before { allow_any_instance_of(BlockParser::ParseStandards).to receive(:execute).and_return(errors: [], standards_attributes: []) } + + it "returns no errors" do + expect(subject[:errors]).to eq([]) + end + end + + context "the yaml is valid, but does not return a hash" do + let(:path) { File.join(File.dirname(__FILE__), "fixtures", "valid-yaml-array-test-block-repo") } + before { allow_any_instance_of(BlockParser::ParseStandards).to receive(:execute).and_return(errors: [], standards_attributes: []) } + + it "returns errors" do + expect(subject[:errors]).to include("config.yaml must be a hash") + end + end + + context "the Standard references a content files" do + let(:path) { File.join(File.dirname(__FILE__), "fixtures", "test-block-repo") } + + context "when content file does not exist" do + before { allow_any_instance_of(BlockParser::ParseStandards).to receive(:execute).and_return(errors: [], standards_attributes: [{ content_files_attributes: [{ path: "/non-existing.md" }] }]) } + + it "returns errors" do + expect(subject[:errors]).to eq(["content file in config.yaml must exist"]) + end + end + + context "when content file does exist" do + before { allow_any_instance_of(BlockParser::ParseStandards).to receive(:execute).and_return(errors: [], standards_attributes: [{ content_files_attributes: [{ path: "markdown-smoketest.md" }] }]) } + + it "returns no errors" do + expect(subject[:errors]).to eq([]) + end + end + end + + context "when the standards cannot be parsed" do + let(:path) { File.join(File.dirname(__FILE__), "fixtures", "test-block-repo") } + before do + allow_any_instance_of(BlockParser::ParseStandards).to receive(:execute).and_return( + errors: ["parse standards error"], standards_attributes: [] + ) + end + + it "returns errors" do + expect(subject[:errors]).to include("parse standards error") + end + end + + context "when a checkpoint does not have any challenges" do + let(:path) { File.join(File.dirname(__FILE__), "fixtures", "checkpoint-without-challenges-block-repo") } + + it "returns errors" do + expect(subject[:errors]).to include("/no-challenges.md: checkpoint must have at least one challenge and all challenges must be valid") + end + end + + context "when there are no lessons nor checkpoints" do + let(:path) { File.join(File.dirname(__FILE__), "fixtures", "no-lessons-nor-checkpoints") } + + it "returns errors" do + expect(subject[:errors]).to include("Standard #1: Must have at least one lesson or checkpoint") + end + end + + context "when a markdown file contains invalid challenges" do + let(:path) { File.join(File.dirname(__FILE__), "fixtures", "checkpoint-with-bad-challenge-tag") } + + it "returns errors" do + expect(subject[:errors]).to include("/bad-challenges.md: Could not parse markdown: Found second !challenge tag before finding !end-challenge.") + expect(subject[:errors]).to include("/bad-challenges.md: checkpoint must have at least one challenge and all challenges must be valid") + end + end + + context "when no standards key is present" do + let(:path) { File.join(File.dirname(__FILE__), "fixtures", "no-standards-config-test-block-repo") } + + it "returns errors" do + expect(subject[:errors]).to include("config.yaml must have a key of 'Standards'") + end + end + + context "invalid syntax" do + let(:path) { File.join(File.dirname(__FILE__), "fixtures", "invalid-config-test-block-repo") } + + it "returns errors" do + expect(subject[:errors]).to include( + "Could not parse config.yaml: could not find expected ':' while scanning a simple key at line 3 column 1" + ) + end + end + end + + context "when the path given has both config.yaml and config.yml" do + let(:path) { File.join(File.dirname(__FILE__), "fixtures", "test-block-two-configs") } + + it "returns errors" do + expect(subject[:errors]).to include("Found both a config.yaml and a config.yml. only one config file is allowed.") + end + end + end + + describe "block_hash" do + it "returns the block_hash" do + allow(Open3).to receive(:capture3).and_return(["", "", OpenStruct.new(success?: true)]) + allow_any_instance_of(BlockParser::ParseStandards).to receive(:execute).and_return( + errors: [], + warnings: [], + standards_attributes: [ + { + content_files_attributes: [ + { path: "/ipynb-test.ipynb", content_file_type: BlockParser::ParseStandards::CONTENT_FILE_TYPES[:lesson], uid: "abc123", default_visibility: "visible" }, + { path: "/target.md", content_file_type: BlockParser::ParseStandards::CONTENT_FILE_TYPES[:checkpoint], uid: "1234", autoscore: true, default_visibility: "visible" } + ] + } + ] + ) + + results = BlockParser::ParseDirectory.new( + path: File.join(File.dirname(__FILE__), "fixtures", "test-block-repo"), + asset_uploader: Freeloader.new + ).execute + + expect(results[:readme_text]).to eq("This is the first line\nAlso second line\nBut also 3 lines") + expect(results[:block_hash]).to eq( + [ + { + standard: { + content_files_attributes: [ + { + path: "/ipynb-test.ipynb", + content_file_type: BlockParser::ParseStandards::CONTENT_FILE_TYPES[:lesson], + uid: "abc123", + default_visibility: "visible" + }, + { + path: "/target.md", + content_file_type: BlockParser::ParseStandards::CONTENT_FILE_TYPES[:checkpoint], + uid: "1234", + autoscore: true, + default_visibility: "visible" + } + ] + }, + content_file_attribute_hashes: [ + { + title: "Ipynb Test.Ipynb", + html: "

    Introduction

    \n\n

    To open this notebook so you can run this code, navigate to this file's directory at the comandline and then type jupyter notebook

    \n\n

    This notebook here is meant to get you oriented with one of the tools that we will be using for our pre-class material. The notes and exercises will be built into IPython notebooks (like this one). Before coming to each class, you should work through the materials in the pre-class folder and play around/follow along with the code in those notebooks. You should run the code provided, and additionally modify it to learn what happens when you change certain/different pieces.

    \n\n

    Effectively learning to program means having your hands-on the keyboard often. It means playing with code, breaking code, reading errors, and reading google. It means banging your head against the keyboard, but getting to revel in that time spent banging your head when you're program finally works. To that end, this notebook here will hopefully give you a taste of that.

    \n\n

    You might not know exactly what all the lines of code in this notebook do. But, don't worry, because you will know all about these ideas in a week. For now, it's going to be good to get used to your environment and reading and writing some simple Python code. Besides, there's a good chance you'll know what's going on in most of these exercises.

    \n\n

    You'll start off by type some working code, and playing around with it. Then, we'll walk you through an example of working with some broken code (don't worry, it won't be too bad). Finally, you'll finish up by learning how to move the working code into a script, and you'll run you're very first Python program!

    \n\n

    For all of the exercises below, we've included the exact number of cells for you to complete the assignment in. However, if you want more to experiment with, at any time you can click the + button in the upper-left hand corner of the notebook, and a new cell will be created below the one that is currently selected. If you would like to delete a cell you've created for experimentation, simply select the cell and click the edit tab at the top of the notebook. Then, select "Delete Cells".

    \n\n

    Part 1 - Working with Working Code

    \n\n

    For the first part, type in the following code. Type it one line at a time into a cell, and then run that cell (click the button at the top to do this, or try Shift + Enter). Don't copy and paste it, but instead type it - fingers on the keyboard style. Building up your programming chops will come through muscle memory, and tonight will get you started with that. You will be writing your own programs soon enough!

    \n\n

    Type this code out and run it one line at at time:

    \n\n
    my_first_var = 'Wohoo!'\nprint(my_first_var)\n\nmy_second_var = "I'm typing code."\nprint(my_second_var)\n\nmy_third_var = "Even though this doesn't feel like code, I've been told it is code."\nprint(my_third_var) \n\nmy_combined_var = my_first_var + ' ' + my_second_var + ' ' + my_third_var \nprint(my_combined_var)\n
    \n\n

    We've included a cell below for each one of the lines above.

    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n

    Above, we just worked with text. Let's try working with some numbers now.

    \n\n

    Type this code out line by line:

    \n\n
    my_first_num = 3\nprint(my_first_num)\n\nmy_second_num = 13\nprint(my_second_num)\n\nquotient = my_second_num // my_first_num\nremainder = my_second_num % my_first_num\n\nprint(quotient, remainder)\n
    \n\n

    We've included a cell below for each one of the lines above.

    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n

    Part 2 - Working with Error Messages

    \n\n

    Now, let's work with some code that will break (sorry). This can and will happen all the time when writing code. Half the battle of being a good programmer is learning how to read through error messages and fix your code. Google will be your best friend through this. If you ask any software engineer or programmer you may know, she/he will be likely to tell you the same.

    \n\n

    Type out the code below, again line by line. When you encounter the error, we'll walk you through it.

    \n\n
    my_str_var = 'Hello. My favorite number is '\nprint(my_str_var)\n\nmy_fav_num = 3\nprint(my_fav_num)\n\nfull_str = my_str_var + my_fav_num \nprint(full_str)\n
    \n\n

    There is a cell below for each one of the lines above.

    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n

    By now, you'll have encountered the following error:

    \n\n
    TypeError: cannot concatenate 'str' and 'int' objects\n
    \n\n

    We've said Google will be your best friend. Let's put that to the test. Take that error (the entire thing) and paste it into Google. The first link should be this page, a stackoverflow post explaining what this error means and how to fix it. Reading through the first five posts there, we see that we can fix it if we simply throw a str around the variable my_fav_num above. This means the line

    \n\n

    full_str = my_str_var + my_fav_num

    \n\n

    will become:

    \n\n

    full_str = my_str_var + str(my_fav_num).

    \n\n

    Make this change above, and then re-run all your code.

    \n\n
    \n
    \n\n

    Notice, too, that you could put that line in the cell below and it would still work. This is because the notebook's state is the same no matter what cell you're in. This is true throughout the life of a notebook session. So you could actually insert a cell at the top of the notebook and run the same line! However, this is a very dangerous thing to do! If you inserted that line in a cell at the top of the notebook, and then came back to it later after it was shutdown, it would not run. This is because the variables my_str_var and my_fav_num wouldn't have been defined yet. You can try this if you want. Insert the that line at the top of the notebook, then click the Kernel tab at the top of the notebook and select "Restart". This put's the notebook in a state as though you just opened it. Try running that top line now. It won't work. But, if you run the cells that define my_str_var and my_fav_num it will!

    \n\n

    Part 3 - Moving to a Script

    \n\n

    Now that you have some functioning code here in a notebook, it's time for you to turn it into a Python script!

    \n\n

    Aside: Python is known as a scripting language, which means that you technically write scripts, not programs. This distinction is normally not important, and as a result you will frequently hear people say they wrote a Python program (and that's accepted language).

    \n\n

    Python scripts live in .py files. So, what you're going to need to do is re-write all of the code from the exercise above in a file. This will be done in your text editor (Atom if you followed the advice from the introduction).

    \n\n

    Start a new file and name it my_first_program.py. Inside of the file, re-type all of the lines of code from the working version of the example from above. Once you're done, save it in today's folder.

    \n\n

    Now you have a python script you can run! This can be done in one of two ways. The first is by navigating to the directory that contains my_first_program.py and then typing python my_first_program.py at the command line. You should see the statements that were printed above appear in the console.

    \n\n

    The other way to run a python script is from IPython. To do this from the directory that contains my_first_program.py, type ipython. This will start the IPython console, which allows you to interact with Python code in much the same way as we have done in this notebook. Now, to run your script. Simply type run my_first_program.py into IPython and watch the same output appear on the screen!

    \n\n
    \n
    \n", + challenges: [], + path: "/ipynb-test.ipynb", + content_file_type: BlockParser::ParseStandards::CONTENT_FILE_TYPES[:lesson], + uid: "abc123", + default_visibility: "visible", + autoscore: nil, + max_checkpoint_submissions: nil, + time_limit: nil, + warnings: [] + }, + { + title: "Target", + html: "

    Top level target

    \n", + challenges: [], + path: "/target.md", + content_file_type: BlockParser::ParseStandards::CONTENT_FILE_TYPES[:checkpoint], + uid: "1234", + autoscore: true, + default_visibility: "visible", + max_checkpoint_submissions: nil, + time_limit: nil, + warnings: [] + } + ] + } + ] + ) + end + + it "returns the block_hash when repo has config.yml file" do + allow_any_instance_of(BlockParser::ParseStandards).to receive(:execute).and_return( + errors: [], + warnings: [], + standards_attributes: [{ content_files_attributes: [ + { + path: "/target.md", + content_file_type: BlockParser::ParseStandards::CONTENT_FILE_TYPES[:checkpoint], + uid: "1234", + autoscore: true, + default_visibility: "hidden", + max_checkpoint_submissions: 3, + time_limit: 30 + } + ] }] + ) + + results = BlockParser::ParseDirectory.new( + path: File.join(File.dirname(__FILE__), "fixtures", "test-block-repo-yml"), + asset_uploader: Freeloader.new + ).execute + + expect(results[:block_hash]).to eq( + [ + { + standard: { + content_files_attributes: [ + { + path: "/target.md", + content_file_type: BlockParser::ParseStandards::CONTENT_FILE_TYPES[:checkpoint], + uid: "1234", + autoscore: true, + default_visibility: "hidden", + max_checkpoint_submissions: 3, + time_limit: 30 + } + ] + }, + content_file_attribute_hashes: [ + { + title: "Target", + html: "

    Top level target

    \n", + challenges: [], + path: "/target.md", + content_file_type: BlockParser::ParseStandards::CONTENT_FILE_TYPES[:checkpoint], + uid: "1234", + autoscore: true, + default_visibility: "hidden", + max_checkpoint_submissions: 3, + time_limit: 30, + warnings: [] + } + ] + } + ] + ) + end + + it "it calls out to the asset uploader when the directory contains a pdf" do + allow_any_instance_of(BlockParser::ParseStandards).to receive(:execute).and_return( + errors: [], + warnings: [], + standards_attributes: [{ content_files_attributes: [ + { + path: "/dummy.pdf", + content_file_type: BlockParser::ParseStandards::CONTENT_FILE_TYPES[:lesson], + uid: "1234", + autoscore: false, + default_visibility: "hidden", + max_checkpoint_submissions: nil + } + ] }] + ) + allow_any_instance_of(Freeloader).to receive(:find_or_create_content).and_return("url_save") + + results = BlockParser::ParseDirectory.new( + path: File.join(File.dirname(__FILE__), "fixtures", "test-block-repo-yml"), + asset_uploader: Freeloader.new + ).execute + + expect(results[:block_hash]).to eq( + [ + { + standard: { + content_files_attributes: [ + { + path: "/dummy.pdf", + content_file_type: BlockParser::ParseStandards::CONTENT_FILE_TYPES[:lesson], + uid: "1234", + autoscore: false, + default_visibility: "hidden", + max_checkpoint_submissions: nil + } + ] + }, + content_file_attribute_hashes: [ + { + title: "Dummy.Pdf", + html: "url_save", + challenges: [], + path: "/dummy_pdf", + content_file_type: BlockParser::ParseStandards::CONTENT_FILE_TYPES[:lesson], + uid: "1234", + autoscore: false, + default_visibility: "hidden", + max_checkpoint_submissions: nil, + time_limit: nil, + warnings: [] + } + ] + } + ] + ) + end + end + end +end diff --git a/gems/bp/spec/parse_markdown_file_spec.rb b/gems/bp/spec/parse_markdown_file_spec.rb new file mode 100644 index 0000000..7e50b14 --- /dev/null +++ b/gems/bp/spec/parse_markdown_file_spec.rb @@ -0,0 +1,29 @@ +require "spec_helper" + +describe BlockParser::ParseMarkdownFile do + let(:asset_uploader) { Freeloader.new } + let(:root_directory_path) { File.join(File.dirname(__FILE__), "fixtures", "test-block-repo") } + subject do + described_class.execute( + file_body: file_body, + asset_uploader: asset_uploader, + root_directory_path: root_directory_path, + current_content_file_path: File.join(root_directory_path, "markdown-smoketest.md"), + content_file_paths: + Dir[File.join(File.join(File.dirname(__FILE__), "fixtures", "test-block-repo"), "**/*")]. + reject { |fn| File.directory?(fn) }. + select { |file_path| file_path[-3..-1] == ".md" } + ) + end + + context "when passed the markdown smoketest" do + let(:file_body) { File.read(File.join(File.dirname(__FILE__), "fixtures", "test-block-repo", "markdown-smoketest.md")) } + + it "parses the markdown smoketest without errors" do + expect(subject[:errors]).to eq([]) + expect(subject[:html]).to include("

    Markdown Smoketest

    ") + expect(subject[:html]).to include("") + expect(subject[:title]).to include("Markdown Smoketest") + end + end +end diff --git a/gems/bp/spec/parse_standards_spec.rb b/gems/bp/spec/parse_standards_spec.rb new file mode 100644 index 0000000..5f0e834 --- /dev/null +++ b/gems/bp/spec/parse_standards_spec.rb @@ -0,0 +1,368 @@ +require "spec_helper" + +describe BlockParser::ParseStandards do + describe "#execute" do + subject { described_class.new(standards, File.join(File.dirname(__FILE__), "fixtures", "test-block-repo")).execute } + + context "when standards is nil" do + let(:standards) { nil } + + it "returns an error" do + expect(subject[:errors]).to include("Configuration must have at least one standard") + end + end + + context "when there are no standards" do + let(:standards) { [] } + + it "returns an error" do + expect(subject[:errors]).to include("Configuration must have at least one standard") + end + end + + context "when the standard is not a hash" do + let(:standards) { ["foo"] } + + it "returns an error" do + expect(subject[:errors]).to include("Standard #1 must be a hash") + end + end + + context "when the standard does not contain a title" do + let(:standards) { [{ "foo" => "bar" }] } + + it "returns an error" do + expect(subject[:errors]).to include("Standard #1 must have Title") + end + end + + context "when the standard does not contain a uid" do + let(:standards) { [{ "foo" => "bar" }] } + + it "returns an error" do + expect(subject[:errors]).to include("Standard #1 must have UID") + end + end + + context "when the standard does not contain a description" do + let(:standards) { [{ "foo" => "bar" }] } + + it "returns an error" do + expect(subject[:errors]).to include("Standard #1 must have Description") + end + end + + context "when the standard does not contain success criteria" do + let(:standards) { [{ "foo" => "bar" }] } + + it "returns an error" do + expect(subject[:errors]).to include("Standard #1 must have at least one SuccessCriteria") + end + end + + context "when the standard does not contain content files" do + let(:standards) { [{ "foo" => "bar" }] } + + it "returns an error" do + expect(subject[:errors]).to include("Standard #1 must have at least one ContentFile") + end + end + + describe "ContentFile Validation" do + context "when the ContentFile does not have a path" do + let(:standards) { [{ "foo" => "bar", "ContentFiles" => [{ "Type" => "foo" }] }] } + + it "returns an error" do + expect(subject[:errors]).to include("Standard #1: ContentFile #1 must have a path starting with /") + end + end + + context "when the ContentFile does not have a path starting with /" do + let(:standards) { [{ "foo" => "bar", "ContentFiles" => [{ "Type" => "foo", "Path" => "foo.md" }] }] } + + it "returns an error" do + expect(subject[:errors]).to include("Standard #1: ContentFile #1 must have a path starting with /") + end + end + + context "when the ContentFile is not a markdown or ipynb file" do + let(:standards) { [{ "foo" => "bar", "ContentFiles" => [{ "Type" => "foo", "Path" => "/foo.js" }] }] } + + it "returns an error" do + expect(subject[:errors]).to include("Standard #1: Content File referenced at /foo.js must be a .md, .ipynb, or .pdf file") + end + end + + context "when the ContentFile does not exist at the given path" do + let(:standards) { [{ "foo" => "bar", "ContentFiles" => [{ "Type" => "foo", "Path" => "/food.md" }] }] } + + it "returns an error" do + expect(subject[:errors]).to include("Standard #1: Content File referenced at /food.md does not exist") + end + end + + context "when ContentFile is a checkpoint and does not have a UID" do + let(:standards) { [{ "foo" => "bar", "ContentFiles" => [{ "Type" => "Checkpoint", "Path" => "/markdown-smoketest.md" }] }] } + + it "returns an error" do + expect(subject[:errors]).to include("Standard #1: Content File referenced at /markdown-smoketest.md does not have a UID") + end + end + end + + context "when the standard does not contain a checkpoint" do + let(:standards) do + [ + { + "Title" => "foo", "UID" => "abc123", + "Description" => "A short description.", + "SuccessCriteria" => ["Foo"], + "ContentFiles" => [ + { "Type" => "Lesson", "UID" => "a", "Path" => "/lessoN.md" } + ] + } + ] + end + + it "does not return errors" do + expect(subject[:errors]).to eq([]) + end + end + + context "when the standard contains two checkpoints" do + let(:standards) { [{ "foo" => "bar", "ContentFiles" => [{ "Type" => "Checkpoint" }, { "Type" => "Checkpoint" }] }] } + + it "returns an error" do + expect(subject[:errors]).to include("Standard #1 may not have more than one Checkpoint.") + end + end + + context "when the standard contains a TimeLimit checkpoint with non-numbers" do + let(:standards) { [{ "foo" => "bar", "ContentFiles" => [{ "Path" => "/target.md", "UID" => "abc12", "Type" => "Checkpoint", "TimeLimit" => "1 day" }] }] } + + it "returns an error" do + expect(subject[:errors]).to include("Checkpoint abc12 TimeLimit must be a number only (number specifies minutes)") + end + end + + context "when there are more than two checkpoints with the same UID" do + let(:standards) do + [ + { + "Title" => "foo", + "UID" => "abczxc", + "Description" => "A short description.", + "SuccessCriteria" => ["Foo"], "ContentFiles" => [{ "Type" => "Checkpoint", "Path" => "/markdown-smoketest.md", "UID" => "1234" }] + }, + { + "Title" => "bar", + "UID" => "abc123", + "Description" => "A short description.", + "SuccessCriteria" => ["Foo"], "ContentFiles" => [{ "Type" => "Checkpoint", "Path" => "/target.md", "UID" => "1234" }] + } + ] + end + + it "returns an error" do + expect(subject[:errors]).to include("Checkpoint UID 1234 used more than once") + end + end + + context "when there are two standards with the same UID" do + let(:standards) do + [ + { + "Title" => "foo", + "UID" => "abc123", + "Description" => "A short description.", + "SuccessCriteria" => ["Foo"], "ContentFiles" => [{ "Type" => "Checkpoint", "Path" => "/foo1.md" }] + }, + { + "Title" => "bar", + "UID" => "abc123", + "Description" => "A short description.", + "SuccessCriteria" => ["Foo"], "ContentFiles" => [{ "Type" => "Checkpoint", "Path" => "/foo2.md" }] + }, + { + "Title" => "baz", + "UID" => "abc125", + "Description" => "A short description.", + "SuccessCriteria" => ["Foo"], "ContentFiles" => [{ "Type" => "Checkpoint", "Path" => "/foo3.md" }] + }, + { + "Title" => "fizz", + "UID" => "abc125", + "Description" => "A short description.", + "SuccessCriteria" => ["Foo"], "ContentFiles" => [{ "Type" => "Checkpoint", "Path" => "/foo4.md" }] + }, + { + "Title" => "buzz", + "UID" => "abc127", + "Description" => "A short description.", + "SuccessCriteria" => ["Foo"], "ContentFiles" => [{ "Type" => "Checkpoint", "Path" => "/foo5.md" }] + } + ] + end + + it "returns an error" do + expect(subject[:errors]).to include("Duplicate Standard UID used for standards with titles: foo, bar") + expect(subject[:errors]).to include("Duplicate Standard UID used for standards with titles: baz, fizz") + end + end + + context "when there are two content files with the same UID" do + let(:standards) do + [ + { + "Title" => "foo", "UID" => "abc123", + "Description" => "A short description.", + "SuccessCriteria" => ["Foo"], + "ContentFiles" => [ + { "Type" => "Lesson", "UID" => "a", "Path" => "/lessoN.md" }, + { "Type" => "Checkpoint", "UID" => "b", "Path" => "/markdown-smoketest.md" } + ] + }, + { + "Title" => "bar", + "UID" => "abc124", + "Description" => "A short description.", + "SuccessCriteria" => ["Foo"], + "ContentFiles" => [ + { "Type" => "Lesson", "UID" => "a", "Path" => "/target.md" }, + { "Type" => "Checkpoint", "UID" => "c", "Path" => "/folder/target.md" } + ] + } + ] + end + + it "returns an error" do + expect(subject[:errors]).to include("Duplicate Content File UID: a") + end + end + + context "when there are Lessons without a UID" do + let(:standards) do + [ + { + "Title" => "bar", + "UID" => "abc124", + "Description" => "A short description.", + "SuccessCriteria" => ["Foo"], + "ContentFiles" => [ + { "Type" => "Lesson", "Path" => "/target.md" }, + { "Type" => "Checkpoint", "UID" => "c", "Path" => "/folder/target.md" } + ] + } + ] + end + + it "returns an error" do + expect(subject[:errors]).to include("Standard #1: Content File referenced at /target.md does not have a UID") + end + end + + context "when a content file is used more than once" do + let(:standards) do + [ + { + "Title" => "foo", + "UID" => "abc123", + "Description" => "A short description.", + "SuccessCriteria" => ["Foo"], + "ContentFiles" => [{ "Type" => "Checkpoint", "Path" => "/target.md" }] + }, + { + "Title" => "bar", + "UID" => "abc124", + "Description" => "A short description.", + "SuccessCriteria" => ["Foo"], + "ContentFiles" => [{ "Type" => "Checkpoint", "Path" => "/target.md" }] + }, + { + "Title" => "bar", + "UID" => "abc124", + "Description" => "A short description.", + "SuccessCriteria" => ["Foo"], + "ContentFiles" => [{ "Type" => "Checkpoint", "Path" => "/lessoN.md" }] + } + ] + end + + it "returns an error" do + expect(subject[:errors]).to include("ContentFile /target.md used more than once") + end + end + + context "when a content file is marked as autoscored" do + let(:standards) do + [ + { + "Title" => "bar", + "UID" => "abc123", + "Description" => "A short description.", + "SuccessCriteria" => ["Foo"], + "ContentFiles" => [{ "Type" => "Checkpoint", "Path" => "/target.md", "UID" => "1234", "Autoscore" => true }] + } + ] + end + + it "indicates the content file is autoscored" do + expect(subject[:standards_attributes][0][:content_files_attributes][0][:autoscore]).to eq(true) + end + end + + context "when a content file is marked with default_visibility 'hidden'" do + let(:standards) do + [ + { + "Title" => "bar", + "UID" => "abc123", + "Description" => "A short description.", + "SuccessCriteria" => ["Foo"], + "ContentFiles" => [{ "Type" => "Checkpoint", "Path" => "/target.md", "UID" => "1234", "Autoscore" => true, "DefaultVisibility" => "HiDDeN" }] + } + ] + end + + it "indicates the content file's default_visibility" do + expect(subject[:standards_attributes][0][:content_files_attributes][0][:default_visibility]).to eq("hidden") + end + end + + context "when a content file is does not provide DefaultVisibility attribute" do + let(:standards) do + [ + { + "Title" => "bar", + "UID" => "abc123", + "Description" => "A short description.", + "SuccessCriteria" => ["Foo"], + "ContentFiles" => [{ "Type" => "Checkpoint", "Path" => "/target.md", "UID" => "1234", "Autoscore" => true }] + } + ] + end + + it "indicates the content file's default_visibility" do + expect(subject[:standards_attributes][0][:content_files_attributes][0][:default_visibility]).to eq("visible") + end + end + + context "when the standard is valid" do + let(:standards) { [{ "Title" => "bar", "UID" => "abc123", "Description" => "A short description.", "SuccessCriteria" => ["Foo"], "ContentFiles" => [{ "Type" => "Lesson", "Path" => "/ipynb-test.ipynb", "UID" => "abc123" }, { "Type" => "Checkpoint", "Path" => "/target.md", "UID" => "1234" }] }] } + + it "returns standard attributes" do + expect(subject[:errors]).to eq([]) + expect(subject[:standards_attributes][0]).to eq( + title: "bar", + uid: "abc123", + description: "A short description.", + success_criteria: ["Foo"], + content_files_attributes: [ + { content_file_type: described_class::CONTENT_FILE_TYPES[:lesson], path: "/ipynb-test.ipynb", uid: "abc123", autoscore: false, default_visibility: "visible" }, + { content_file_type: described_class::CONTENT_FILE_TYPES[:checkpoint], path: "/target.md", uid: "1234", autoscore: false, default_visibility: "visible" } + ] + ) + end + end + end +end diff --git a/gems/bp/spec/spec_helper.rb b/gems/bp/spec/spec_helper.rb new file mode 100644 index 0000000..1d31ebc --- /dev/null +++ b/gems/bp/spec/spec_helper.rb @@ -0,0 +1,23 @@ +require "bundler/setup" +require "block_parser" +require "byebug" + +Dir[File.dirname(__FILE__) + "/support/**/*.rb"].sort.each { |file| require file } + +RSpec.configure do |config| + # Enable flags like --only-failures and --next-failure + config.example_status_persistence_file_path = ".rspec_status" + + # Disable RSpec exposing methods globally on `Module` and `main` + config.disable_monkey_patching! + + config.expose_dsl_globally = true + + config.expect_with :rspec do |c| + c.syntax = :expect + end + + config.before(:each) do + allow(Octokit::Client).to receive(:new).and_return(Mocktokit::Client.new) + end +end diff --git a/gems/bp/spec/support/freeloader.rb b/gems/bp/spec/support/freeloader.rb new file mode 100644 index 0000000..2cfee29 --- /dev/null +++ b/gems/bp/spec/support/freeloader.rb @@ -0,0 +1,8 @@ +class Freeloader + def initialize(*_args) + end + + def find_or_create_content(*_args) + "conent_url" + end +end diff --git a/gems/bp/spec/support/mocktokit.rb b/gems/bp/spec/support/mocktokit.rb new file mode 100644 index 0000000..06fbc64 --- /dev/null +++ b/gems/bp/spec/support/mocktokit.rb @@ -0,0 +1,31 @@ +module Mocktokit + class Client + def branch(*_args) + nil + end + + def repository(org_name) + org = org_name.split("/")[0] + name = org_name.split("/")[1] + + { + name: name, + organization: { + login: org + } + } + end + + def repository?(*_args) + true + end + + def content(*_args) + nil + end + + def contents(*_args) + nil + end + end +end diff --git a/gems/bp/spec/tmp/.keep b/gems/bp/spec/tmp/.keep new file mode 100644 index 0000000..58069b8 --- /dev/null +++ b/gems/bp/spec/tmp/.keep @@ -0,0 +1 @@ +keep me \ No newline at end of file diff --git a/gems/bp/validate-block b/gems/bp/validate-block new file mode 100755 index 0000000..25eac24 --- /dev/null +++ b/gems/bp/validate-block @@ -0,0 +1,11 @@ +#!/bin/bash + +dir_resolve() { + local dir=`dirname "$1"` + local file=`basename "$1"` + pushd "$dir" &>/dev/null || return $? # On error, return error code + echo "`pwd -P`/$file" # output full, link-resolved path with filename + popd &> /dev/null +} + +docker run --rm -v $(dir_resolve $1):/block -it block-parser -- GitLab From 1f822c5849199e7504e9bde89f3e947f6e6d83af Mon Sep 17 00:00:00 2001 From: Benton Gallun Date: Mon, 21 Sep 2020 18:35:23 -0700 Subject: [PATCH 051/283] change file name --- gems/{bp => block-parser}/Dockerfile | 0 gems/{bp => block-parser}/Gemfile | 0 gems/{bp => block-parser}/Gemfile.lock | 0 gems/{bp => block-parser}/README.md | 0 gems/{bp => block-parser}/Rakefile | 0 gems/{bp => block-parser}/bin/console | 0 gems/{bp => block-parser}/bin/parse_block | 0 gems/{bp => block-parser}/bin/setup | 0 gems/{bp => block-parser}/block_parser-0.1.0.gem | Bin gems/{bp => block-parser}/block_parser.gemspec | 0 gems/{bp => block-parser}/build | 0 gems/{bp => block-parser}/lib/block_parser.rb | 0 .../lib/block_parser/build_challenge.rb | 0 .../lib/block_parser/build_html.rb | 0 .../lib/block_parser/build_html_from_md_json.rb | 0 .../lib/block_parser/build_image_link.rb | 0 .../lib/block_parser/build_link.rb | 0 .../build_title_from_filename_and_html.rb | 0 .../block_parser/challenge_validators/challenge.rb | 0 .../challenge_validators/challenge_validator.rb | 0 .../checkbox_challenge_validator.rb | 0 .../code_snippet_challenge_validator.rb | 0 .../custom_snippet_challenge_validator.rb | 0 .../local_snippet_challenge_validator.rb | 0 .../multiple_choice_challenge_validator.rb | 0 .../number_challenge_validator.rb | 0 .../paragraph_challenge_validator.rb | 0 .../poll_challenge_validator.rb | 0 .../project_challenge_validator.rb | 0 .../short_answer_challenge_validator.rb | 0 .../testable_project_challenge_validator.rb | 0 .../lib/block_parser/convert_md_to_json.rb | 0 .../lib/block_parser/parse_directory.rb | 0 .../lib/block_parser/parse_markdown_file.rb | 0 .../lib/block_parser/parse_standards.rb | 0 .../lib/block_parser/version.rb | 0 .../{bp => block-parser}/pkg/block_parser-0.1.0.gem | Bin .../spec/build_challenge_spec.rb | 0 .../spec/build_html_from_md_json_spec.rb | 0 gems/{bp => block-parser}/spec/build_html_spec.rb | 0 .../spec/build_image_link_spec.rb | 0 gems/{bp => block-parser}/spec/build_link_spec.rb | 0 .../spec/build_title_from_filename_and_html_spec.rb | 0 .../spec/challenge_validators/challenge_spec.rb | 0 .../challenge_validator_spec.rb | 0 .../checkbox_challenge_validator_spec.rb | 0 .../code_snippet_challenge_validator_spec.rb | 0 .../custom_snippet_challenge_validator_spec.rb | 0 .../multiple_choice_challenge_validator_spec.rb | 0 .../number_challenge_validator_spec.rb | 0 .../project_challenge_validator_spec.rb | 0 .../short_answer_challenge_validator_spec.rb | 0 .../testable_project_challenge_validator_spec.rb | 0 .../spec/convert_md_to_json_spec.rb | 0 .../bad-challenges.md | 0 .../checkpoint-with-bad-challenge-tag/config.yaml | 0 .../config.yaml | 0 .../no-challenges.md | 0 .../invalid-config-test-block-repo/config.yaml | 0 .../fixtures/no-lessons-nor-checkpoints/config.yaml | 0 .../no-lessons-nor-checkpoints/resources.md | 0 .../no-standards-config-test-block-repo/config.yaml | 0 .../spec/fixtures/sample-iframe.md | 0 .../spec/fixtures/test-block-repo-yml/config.yml | 0 .../spec/fixtures/test-block-repo-yml/dummy.pdf | Bin .../fixtures/test-block-repo-yml/folder/sibling.md | 0 .../fixtures/test-block-repo-yml/folder/target.md | 0 .../test-block-repo-yml/images/galvanize-logo.png | Bin .../test-block-repo-yml/images/register_klass.gif | Bin .../spec/fixtures/test-block-repo-yml/lessoN.md | 0 .../test-block-repo-yml/markdown-smoketest.md | 0 .../spec/fixtures/test-block-repo-yml/target.md | 0 .../spec/fixtures/test-block-repo/README.md | 0 .../spec/fixtures/test-block-repo/config.yaml | 0 .../spec/fixtures/test-block-repo/folder/sibling.md | 0 .../spec/fixtures/test-block-repo/folder/target.md | 0 .../test-block-repo/images/galvanize-logo.png | Bin .../test-block-repo/images/register_klass.gif | Bin .../spec/fixtures/test-block-repo/ipynb-test.ipynb | 0 .../spec/fixtures/test-block-repo/ipynb-test.md | 0 .../spec/fixtures/test-block-repo/lessoN.md | 0 .../fixtures/test-block-repo/markdown-smoketest.md | 0 .../spec/fixtures/test-block-repo/target.md | 0 .../fixtures/test-block-two-configs/config.yaml | 0 .../spec/fixtures/test-block-two-configs/config.yml | 0 .../Dockerfile | 0 .../test.sh | 0 .../valid-yaml-array-test-block-repo/config.yaml | 0 .../spec/parse_directory_spec.rb | 0 .../spec/parse_markdown_file_spec.rb | 0 .../spec/parse_standards_spec.rb | 0 gems/{bp => block-parser}/spec/spec_helper.rb | 0 .../{bp => block-parser}/spec/support/freeloader.rb | 0 gems/{bp => block-parser}/spec/support/mocktokit.rb | 0 gems/{bp => block-parser}/spec/tmp/.keep | 0 gems/{bp => block-parser}/validate-block | 0 96 files changed, 0 insertions(+), 0 deletions(-) rename gems/{bp => block-parser}/Dockerfile (100%) rename gems/{bp => block-parser}/Gemfile (100%) rename gems/{bp => block-parser}/Gemfile.lock (100%) rename gems/{bp => block-parser}/README.md (100%) rename gems/{bp => block-parser}/Rakefile (100%) rename gems/{bp => block-parser}/bin/console (100%) rename gems/{bp => block-parser}/bin/parse_block (100%) rename gems/{bp => block-parser}/bin/setup (100%) rename gems/{bp => block-parser}/block_parser-0.1.0.gem (100%) rename gems/{bp => block-parser}/block_parser.gemspec (100%) rename gems/{bp => block-parser}/build (100%) rename gems/{bp => block-parser}/lib/block_parser.rb (100%) rename gems/{bp => block-parser}/lib/block_parser/build_challenge.rb (100%) rename gems/{bp => block-parser}/lib/block_parser/build_html.rb (100%) rename gems/{bp => block-parser}/lib/block_parser/build_html_from_md_json.rb (100%) rename gems/{bp => block-parser}/lib/block_parser/build_image_link.rb (100%) rename gems/{bp => block-parser}/lib/block_parser/build_link.rb (100%) rename gems/{bp => block-parser}/lib/block_parser/build_title_from_filename_and_html.rb (100%) rename gems/{bp => block-parser}/lib/block_parser/challenge_validators/challenge.rb (100%) rename gems/{bp => block-parser}/lib/block_parser/challenge_validators/challenge_validator.rb (100%) rename gems/{bp => block-parser}/lib/block_parser/challenge_validators/checkbox_challenge_validator.rb (100%) rename gems/{bp => block-parser}/lib/block_parser/challenge_validators/code_snippet_challenge_validator.rb (100%) rename gems/{bp => block-parser}/lib/block_parser/challenge_validators/custom_snippet_challenge_validator.rb (100%) rename gems/{bp => block-parser}/lib/block_parser/challenge_validators/local_snippet_challenge_validator.rb (100%) rename gems/{bp => block-parser}/lib/block_parser/challenge_validators/multiple_choice_challenge_validator.rb (100%) rename gems/{bp => block-parser}/lib/block_parser/challenge_validators/number_challenge_validator.rb (100%) rename gems/{bp => block-parser}/lib/block_parser/challenge_validators/paragraph_challenge_validator.rb (100%) rename gems/{bp => block-parser}/lib/block_parser/challenge_validators/poll_challenge_validator.rb (100%) rename gems/{bp => block-parser}/lib/block_parser/challenge_validators/project_challenge_validator.rb (100%) rename gems/{bp => block-parser}/lib/block_parser/challenge_validators/short_answer_challenge_validator.rb (100%) rename gems/{bp => block-parser}/lib/block_parser/challenge_validators/testable_project_challenge_validator.rb (100%) rename gems/{bp => block-parser}/lib/block_parser/convert_md_to_json.rb (100%) rename gems/{bp => block-parser}/lib/block_parser/parse_directory.rb (100%) rename gems/{bp => block-parser}/lib/block_parser/parse_markdown_file.rb (100%) rename gems/{bp => block-parser}/lib/block_parser/parse_standards.rb (100%) rename gems/{bp => block-parser}/lib/block_parser/version.rb (100%) rename gems/{bp => block-parser}/pkg/block_parser-0.1.0.gem (100%) rename gems/{bp => block-parser}/spec/build_challenge_spec.rb (100%) rename gems/{bp => block-parser}/spec/build_html_from_md_json_spec.rb (100%) rename gems/{bp => block-parser}/spec/build_html_spec.rb (100%) rename gems/{bp => block-parser}/spec/build_image_link_spec.rb (100%) rename gems/{bp => block-parser}/spec/build_link_spec.rb (100%) rename gems/{bp => block-parser}/spec/build_title_from_filename_and_html_spec.rb (100%) rename gems/{bp => block-parser}/spec/challenge_validators/challenge_spec.rb (100%) rename gems/{bp => block-parser}/spec/challenge_validators/challenge_validator_spec.rb (100%) rename gems/{bp => block-parser}/spec/challenge_validators/checkbox_challenge_validator_spec.rb (100%) rename gems/{bp => block-parser}/spec/challenge_validators/code_snippet_challenge_validator_spec.rb (100%) rename gems/{bp => block-parser}/spec/challenge_validators/custom_snippet_challenge_validator_spec.rb (100%) rename gems/{bp => block-parser}/spec/challenge_validators/multiple_choice_challenge_validator_spec.rb (100%) rename gems/{bp => block-parser}/spec/challenge_validators/number_challenge_validator_spec.rb (100%) rename gems/{bp => block-parser}/spec/challenge_validators/project_challenge_validator_spec.rb (100%) rename gems/{bp => block-parser}/spec/challenge_validators/short_answer_challenge_validator_spec.rb (100%) rename gems/{bp => block-parser}/spec/challenge_validators/testable_project_challenge_validator_spec.rb (100%) rename gems/{bp => block-parser}/spec/convert_md_to_json_spec.rb (100%) rename gems/{bp => block-parser}/spec/fixtures/checkpoint-with-bad-challenge-tag/bad-challenges.md (100%) rename gems/{bp => block-parser}/spec/fixtures/checkpoint-with-bad-challenge-tag/config.yaml (100%) rename gems/{bp => block-parser}/spec/fixtures/checkpoint-without-challenges-block-repo/config.yaml (100%) rename gems/{bp => block-parser}/spec/fixtures/checkpoint-without-challenges-block-repo/no-challenges.md (100%) rename gems/{bp => block-parser}/spec/fixtures/invalid-config-test-block-repo/config.yaml (100%) rename gems/{bp => block-parser}/spec/fixtures/no-lessons-nor-checkpoints/config.yaml (100%) rename gems/{bp => block-parser}/spec/fixtures/no-lessons-nor-checkpoints/resources.md (100%) rename gems/{bp => block-parser}/spec/fixtures/no-standards-config-test-block-repo/config.yaml (100%) rename gems/{bp => block-parser}/spec/fixtures/sample-iframe.md (100%) rename gems/{bp => block-parser}/spec/fixtures/test-block-repo-yml/config.yml (100%) rename gems/{bp => block-parser}/spec/fixtures/test-block-repo-yml/dummy.pdf (100%) rename gems/{bp => block-parser}/spec/fixtures/test-block-repo-yml/folder/sibling.md (100%) rename gems/{bp => block-parser}/spec/fixtures/test-block-repo-yml/folder/target.md (100%) rename gems/{bp => block-parser}/spec/fixtures/test-block-repo-yml/images/galvanize-logo.png (100%) rename gems/{bp => block-parser}/spec/fixtures/test-block-repo-yml/images/register_klass.gif (100%) rename gems/{bp => block-parser}/spec/fixtures/test-block-repo-yml/lessoN.md (100%) rename gems/{bp => block-parser}/spec/fixtures/test-block-repo-yml/markdown-smoketest.md (100%) rename gems/{bp => block-parser}/spec/fixtures/test-block-repo-yml/target.md (100%) rename gems/{bp => block-parser}/spec/fixtures/test-block-repo/README.md (100%) rename gems/{bp => block-parser}/spec/fixtures/test-block-repo/config.yaml (100%) rename gems/{bp => block-parser}/spec/fixtures/test-block-repo/folder/sibling.md (100%) rename gems/{bp => block-parser}/spec/fixtures/test-block-repo/folder/target.md (100%) rename gems/{bp => block-parser}/spec/fixtures/test-block-repo/images/galvanize-logo.png (100%) rename gems/{bp => block-parser}/spec/fixtures/test-block-repo/images/register_klass.gif (100%) rename gems/{bp => block-parser}/spec/fixtures/test-block-repo/ipynb-test.ipynb (100%) rename gems/{bp => block-parser}/spec/fixtures/test-block-repo/ipynb-test.md (100%) rename gems/{bp => block-parser}/spec/fixtures/test-block-repo/lessoN.md (100%) rename gems/{bp => block-parser}/spec/fixtures/test-block-repo/markdown-smoketest.md (100%) rename gems/{bp => block-parser}/spec/fixtures/test-block-repo/target.md (100%) rename gems/{bp => block-parser}/spec/fixtures/test-block-two-configs/config.yaml (100%) rename gems/{bp => block-parser}/spec/fixtures/test-block-two-configs/config.yml (100%) rename gems/{bp => block-parser}/spec/fixtures/valid-custom-snippet-challenge-directory/Dockerfile (100%) rename gems/{bp => block-parser}/spec/fixtures/valid-custom-snippet-challenge-directory/test.sh (100%) rename gems/{bp => block-parser}/spec/fixtures/valid-yaml-array-test-block-repo/config.yaml (100%) rename gems/{bp => block-parser}/spec/parse_directory_spec.rb (100%) rename gems/{bp => block-parser}/spec/parse_markdown_file_spec.rb (100%) rename gems/{bp => block-parser}/spec/parse_standards_spec.rb (100%) rename gems/{bp => block-parser}/spec/spec_helper.rb (100%) rename gems/{bp => block-parser}/spec/support/freeloader.rb (100%) rename gems/{bp => block-parser}/spec/support/mocktokit.rb (100%) rename gems/{bp => block-parser}/spec/tmp/.keep (100%) rename gems/{bp => block-parser}/validate-block (100%) diff --git a/gems/bp/Dockerfile b/gems/block-parser/Dockerfile similarity index 100% rename from gems/bp/Dockerfile rename to gems/block-parser/Dockerfile diff --git a/gems/bp/Gemfile b/gems/block-parser/Gemfile similarity index 100% rename from gems/bp/Gemfile rename to gems/block-parser/Gemfile diff --git a/gems/bp/Gemfile.lock b/gems/block-parser/Gemfile.lock similarity index 100% rename from gems/bp/Gemfile.lock rename to gems/block-parser/Gemfile.lock diff --git a/gems/bp/README.md b/gems/block-parser/README.md similarity index 100% rename from gems/bp/README.md rename to gems/block-parser/README.md diff --git a/gems/bp/Rakefile b/gems/block-parser/Rakefile similarity index 100% rename from gems/bp/Rakefile rename to gems/block-parser/Rakefile diff --git a/gems/bp/bin/console b/gems/block-parser/bin/console similarity index 100% rename from gems/bp/bin/console rename to gems/block-parser/bin/console diff --git a/gems/bp/bin/parse_block b/gems/block-parser/bin/parse_block similarity index 100% rename from gems/bp/bin/parse_block rename to gems/block-parser/bin/parse_block diff --git a/gems/bp/bin/setup b/gems/block-parser/bin/setup similarity index 100% rename from gems/bp/bin/setup rename to gems/block-parser/bin/setup diff --git a/gems/bp/block_parser-0.1.0.gem b/gems/block-parser/block_parser-0.1.0.gem similarity index 100% rename from gems/bp/block_parser-0.1.0.gem rename to gems/block-parser/block_parser-0.1.0.gem diff --git a/gems/bp/block_parser.gemspec b/gems/block-parser/block_parser.gemspec similarity index 100% rename from gems/bp/block_parser.gemspec rename to gems/block-parser/block_parser.gemspec diff --git a/gems/bp/build b/gems/block-parser/build similarity index 100% rename from gems/bp/build rename to gems/block-parser/build diff --git a/gems/bp/lib/block_parser.rb b/gems/block-parser/lib/block_parser.rb similarity index 100% rename from gems/bp/lib/block_parser.rb rename to gems/block-parser/lib/block_parser.rb diff --git a/gems/bp/lib/block_parser/build_challenge.rb b/gems/block-parser/lib/block_parser/build_challenge.rb similarity index 100% rename from gems/bp/lib/block_parser/build_challenge.rb rename to gems/block-parser/lib/block_parser/build_challenge.rb diff --git a/gems/bp/lib/block_parser/build_html.rb b/gems/block-parser/lib/block_parser/build_html.rb similarity index 100% rename from gems/bp/lib/block_parser/build_html.rb rename to gems/block-parser/lib/block_parser/build_html.rb diff --git a/gems/bp/lib/block_parser/build_html_from_md_json.rb b/gems/block-parser/lib/block_parser/build_html_from_md_json.rb similarity index 100% rename from gems/bp/lib/block_parser/build_html_from_md_json.rb rename to gems/block-parser/lib/block_parser/build_html_from_md_json.rb diff --git a/gems/bp/lib/block_parser/build_image_link.rb b/gems/block-parser/lib/block_parser/build_image_link.rb similarity index 100% rename from gems/bp/lib/block_parser/build_image_link.rb rename to gems/block-parser/lib/block_parser/build_image_link.rb diff --git a/gems/bp/lib/block_parser/build_link.rb b/gems/block-parser/lib/block_parser/build_link.rb similarity index 100% rename from gems/bp/lib/block_parser/build_link.rb rename to gems/block-parser/lib/block_parser/build_link.rb diff --git a/gems/bp/lib/block_parser/build_title_from_filename_and_html.rb b/gems/block-parser/lib/block_parser/build_title_from_filename_and_html.rb similarity index 100% rename from gems/bp/lib/block_parser/build_title_from_filename_and_html.rb rename to gems/block-parser/lib/block_parser/build_title_from_filename_and_html.rb diff --git a/gems/bp/lib/block_parser/challenge_validators/challenge.rb b/gems/block-parser/lib/block_parser/challenge_validators/challenge.rb similarity index 100% rename from gems/bp/lib/block_parser/challenge_validators/challenge.rb rename to gems/block-parser/lib/block_parser/challenge_validators/challenge.rb diff --git a/gems/bp/lib/block_parser/challenge_validators/challenge_validator.rb b/gems/block-parser/lib/block_parser/challenge_validators/challenge_validator.rb similarity index 100% rename from gems/bp/lib/block_parser/challenge_validators/challenge_validator.rb rename to gems/block-parser/lib/block_parser/challenge_validators/challenge_validator.rb diff --git a/gems/bp/lib/block_parser/challenge_validators/checkbox_challenge_validator.rb b/gems/block-parser/lib/block_parser/challenge_validators/checkbox_challenge_validator.rb similarity index 100% rename from gems/bp/lib/block_parser/challenge_validators/checkbox_challenge_validator.rb rename to gems/block-parser/lib/block_parser/challenge_validators/checkbox_challenge_validator.rb diff --git a/gems/bp/lib/block_parser/challenge_validators/code_snippet_challenge_validator.rb b/gems/block-parser/lib/block_parser/challenge_validators/code_snippet_challenge_validator.rb similarity index 100% rename from gems/bp/lib/block_parser/challenge_validators/code_snippet_challenge_validator.rb rename to gems/block-parser/lib/block_parser/challenge_validators/code_snippet_challenge_validator.rb diff --git a/gems/bp/lib/block_parser/challenge_validators/custom_snippet_challenge_validator.rb b/gems/block-parser/lib/block_parser/challenge_validators/custom_snippet_challenge_validator.rb similarity index 100% rename from gems/bp/lib/block_parser/challenge_validators/custom_snippet_challenge_validator.rb rename to gems/block-parser/lib/block_parser/challenge_validators/custom_snippet_challenge_validator.rb diff --git a/gems/bp/lib/block_parser/challenge_validators/local_snippet_challenge_validator.rb b/gems/block-parser/lib/block_parser/challenge_validators/local_snippet_challenge_validator.rb similarity index 100% rename from gems/bp/lib/block_parser/challenge_validators/local_snippet_challenge_validator.rb rename to gems/block-parser/lib/block_parser/challenge_validators/local_snippet_challenge_validator.rb diff --git a/gems/bp/lib/block_parser/challenge_validators/multiple_choice_challenge_validator.rb b/gems/block-parser/lib/block_parser/challenge_validators/multiple_choice_challenge_validator.rb similarity index 100% rename from gems/bp/lib/block_parser/challenge_validators/multiple_choice_challenge_validator.rb rename to gems/block-parser/lib/block_parser/challenge_validators/multiple_choice_challenge_validator.rb diff --git a/gems/bp/lib/block_parser/challenge_validators/number_challenge_validator.rb b/gems/block-parser/lib/block_parser/challenge_validators/number_challenge_validator.rb similarity index 100% rename from gems/bp/lib/block_parser/challenge_validators/number_challenge_validator.rb rename to gems/block-parser/lib/block_parser/challenge_validators/number_challenge_validator.rb diff --git a/gems/bp/lib/block_parser/challenge_validators/paragraph_challenge_validator.rb b/gems/block-parser/lib/block_parser/challenge_validators/paragraph_challenge_validator.rb similarity index 100% rename from gems/bp/lib/block_parser/challenge_validators/paragraph_challenge_validator.rb rename to gems/block-parser/lib/block_parser/challenge_validators/paragraph_challenge_validator.rb diff --git a/gems/bp/lib/block_parser/challenge_validators/poll_challenge_validator.rb b/gems/block-parser/lib/block_parser/challenge_validators/poll_challenge_validator.rb similarity index 100% rename from gems/bp/lib/block_parser/challenge_validators/poll_challenge_validator.rb rename to gems/block-parser/lib/block_parser/challenge_validators/poll_challenge_validator.rb diff --git a/gems/bp/lib/block_parser/challenge_validators/project_challenge_validator.rb b/gems/block-parser/lib/block_parser/challenge_validators/project_challenge_validator.rb similarity index 100% rename from gems/bp/lib/block_parser/challenge_validators/project_challenge_validator.rb rename to gems/block-parser/lib/block_parser/challenge_validators/project_challenge_validator.rb diff --git a/gems/bp/lib/block_parser/challenge_validators/short_answer_challenge_validator.rb b/gems/block-parser/lib/block_parser/challenge_validators/short_answer_challenge_validator.rb similarity index 100% rename from gems/bp/lib/block_parser/challenge_validators/short_answer_challenge_validator.rb rename to gems/block-parser/lib/block_parser/challenge_validators/short_answer_challenge_validator.rb diff --git a/gems/bp/lib/block_parser/challenge_validators/testable_project_challenge_validator.rb b/gems/block-parser/lib/block_parser/challenge_validators/testable_project_challenge_validator.rb similarity index 100% rename from gems/bp/lib/block_parser/challenge_validators/testable_project_challenge_validator.rb rename to gems/block-parser/lib/block_parser/challenge_validators/testable_project_challenge_validator.rb diff --git a/gems/bp/lib/block_parser/convert_md_to_json.rb b/gems/block-parser/lib/block_parser/convert_md_to_json.rb similarity index 100% rename from gems/bp/lib/block_parser/convert_md_to_json.rb rename to gems/block-parser/lib/block_parser/convert_md_to_json.rb diff --git a/gems/bp/lib/block_parser/parse_directory.rb b/gems/block-parser/lib/block_parser/parse_directory.rb similarity index 100% rename from gems/bp/lib/block_parser/parse_directory.rb rename to gems/block-parser/lib/block_parser/parse_directory.rb diff --git a/gems/bp/lib/block_parser/parse_markdown_file.rb b/gems/block-parser/lib/block_parser/parse_markdown_file.rb similarity index 100% rename from gems/bp/lib/block_parser/parse_markdown_file.rb rename to gems/block-parser/lib/block_parser/parse_markdown_file.rb diff --git a/gems/bp/lib/block_parser/parse_standards.rb b/gems/block-parser/lib/block_parser/parse_standards.rb similarity index 100% rename from gems/bp/lib/block_parser/parse_standards.rb rename to gems/block-parser/lib/block_parser/parse_standards.rb diff --git a/gems/bp/lib/block_parser/version.rb b/gems/block-parser/lib/block_parser/version.rb similarity index 100% rename from gems/bp/lib/block_parser/version.rb rename to gems/block-parser/lib/block_parser/version.rb diff --git a/gems/bp/pkg/block_parser-0.1.0.gem b/gems/block-parser/pkg/block_parser-0.1.0.gem similarity index 100% rename from gems/bp/pkg/block_parser-0.1.0.gem rename to gems/block-parser/pkg/block_parser-0.1.0.gem diff --git a/gems/bp/spec/build_challenge_spec.rb b/gems/block-parser/spec/build_challenge_spec.rb similarity index 100% rename from gems/bp/spec/build_challenge_spec.rb rename to gems/block-parser/spec/build_challenge_spec.rb diff --git a/gems/bp/spec/build_html_from_md_json_spec.rb b/gems/block-parser/spec/build_html_from_md_json_spec.rb similarity index 100% rename from gems/bp/spec/build_html_from_md_json_spec.rb rename to gems/block-parser/spec/build_html_from_md_json_spec.rb diff --git a/gems/bp/spec/build_html_spec.rb b/gems/block-parser/spec/build_html_spec.rb similarity index 100% rename from gems/bp/spec/build_html_spec.rb rename to gems/block-parser/spec/build_html_spec.rb diff --git a/gems/bp/spec/build_image_link_spec.rb b/gems/block-parser/spec/build_image_link_spec.rb similarity index 100% rename from gems/bp/spec/build_image_link_spec.rb rename to gems/block-parser/spec/build_image_link_spec.rb diff --git a/gems/bp/spec/build_link_spec.rb b/gems/block-parser/spec/build_link_spec.rb similarity index 100% rename from gems/bp/spec/build_link_spec.rb rename to gems/block-parser/spec/build_link_spec.rb diff --git a/gems/bp/spec/build_title_from_filename_and_html_spec.rb b/gems/block-parser/spec/build_title_from_filename_and_html_spec.rb similarity index 100% rename from gems/bp/spec/build_title_from_filename_and_html_spec.rb rename to gems/block-parser/spec/build_title_from_filename_and_html_spec.rb diff --git a/gems/bp/spec/challenge_validators/challenge_spec.rb b/gems/block-parser/spec/challenge_validators/challenge_spec.rb similarity index 100% rename from gems/bp/spec/challenge_validators/challenge_spec.rb rename to gems/block-parser/spec/challenge_validators/challenge_spec.rb diff --git a/gems/bp/spec/challenge_validators/challenge_validator_spec.rb b/gems/block-parser/spec/challenge_validators/challenge_validator_spec.rb similarity index 100% rename from gems/bp/spec/challenge_validators/challenge_validator_spec.rb rename to gems/block-parser/spec/challenge_validators/challenge_validator_spec.rb diff --git a/gems/bp/spec/challenge_validators/checkbox_challenge_validator_spec.rb b/gems/block-parser/spec/challenge_validators/checkbox_challenge_validator_spec.rb similarity index 100% rename from gems/bp/spec/challenge_validators/checkbox_challenge_validator_spec.rb rename to gems/block-parser/spec/challenge_validators/checkbox_challenge_validator_spec.rb diff --git a/gems/bp/spec/challenge_validators/code_snippet_challenge_validator_spec.rb b/gems/block-parser/spec/challenge_validators/code_snippet_challenge_validator_spec.rb similarity index 100% rename from gems/bp/spec/challenge_validators/code_snippet_challenge_validator_spec.rb rename to gems/block-parser/spec/challenge_validators/code_snippet_challenge_validator_spec.rb diff --git a/gems/bp/spec/challenge_validators/custom_snippet_challenge_validator_spec.rb b/gems/block-parser/spec/challenge_validators/custom_snippet_challenge_validator_spec.rb similarity index 100% rename from gems/bp/spec/challenge_validators/custom_snippet_challenge_validator_spec.rb rename to gems/block-parser/spec/challenge_validators/custom_snippet_challenge_validator_spec.rb diff --git a/gems/bp/spec/challenge_validators/multiple_choice_challenge_validator_spec.rb b/gems/block-parser/spec/challenge_validators/multiple_choice_challenge_validator_spec.rb similarity index 100% rename from gems/bp/spec/challenge_validators/multiple_choice_challenge_validator_spec.rb rename to gems/block-parser/spec/challenge_validators/multiple_choice_challenge_validator_spec.rb diff --git a/gems/bp/spec/challenge_validators/number_challenge_validator_spec.rb b/gems/block-parser/spec/challenge_validators/number_challenge_validator_spec.rb similarity index 100% rename from gems/bp/spec/challenge_validators/number_challenge_validator_spec.rb rename to gems/block-parser/spec/challenge_validators/number_challenge_validator_spec.rb diff --git a/gems/bp/spec/challenge_validators/project_challenge_validator_spec.rb b/gems/block-parser/spec/challenge_validators/project_challenge_validator_spec.rb similarity index 100% rename from gems/bp/spec/challenge_validators/project_challenge_validator_spec.rb rename to gems/block-parser/spec/challenge_validators/project_challenge_validator_spec.rb diff --git a/gems/bp/spec/challenge_validators/short_answer_challenge_validator_spec.rb b/gems/block-parser/spec/challenge_validators/short_answer_challenge_validator_spec.rb similarity index 100% rename from gems/bp/spec/challenge_validators/short_answer_challenge_validator_spec.rb rename to gems/block-parser/spec/challenge_validators/short_answer_challenge_validator_spec.rb diff --git a/gems/bp/spec/challenge_validators/testable_project_challenge_validator_spec.rb b/gems/block-parser/spec/challenge_validators/testable_project_challenge_validator_spec.rb similarity index 100% rename from gems/bp/spec/challenge_validators/testable_project_challenge_validator_spec.rb rename to gems/block-parser/spec/challenge_validators/testable_project_challenge_validator_spec.rb diff --git a/gems/bp/spec/convert_md_to_json_spec.rb b/gems/block-parser/spec/convert_md_to_json_spec.rb similarity index 100% rename from gems/bp/spec/convert_md_to_json_spec.rb rename to gems/block-parser/spec/convert_md_to_json_spec.rb diff --git a/gems/bp/spec/fixtures/checkpoint-with-bad-challenge-tag/bad-challenges.md b/gems/block-parser/spec/fixtures/checkpoint-with-bad-challenge-tag/bad-challenges.md similarity index 100% rename from gems/bp/spec/fixtures/checkpoint-with-bad-challenge-tag/bad-challenges.md rename to gems/block-parser/spec/fixtures/checkpoint-with-bad-challenge-tag/bad-challenges.md diff --git a/gems/bp/spec/fixtures/checkpoint-with-bad-challenge-tag/config.yaml b/gems/block-parser/spec/fixtures/checkpoint-with-bad-challenge-tag/config.yaml similarity index 100% rename from gems/bp/spec/fixtures/checkpoint-with-bad-challenge-tag/config.yaml rename to gems/block-parser/spec/fixtures/checkpoint-with-bad-challenge-tag/config.yaml diff --git a/gems/bp/spec/fixtures/checkpoint-without-challenges-block-repo/config.yaml b/gems/block-parser/spec/fixtures/checkpoint-without-challenges-block-repo/config.yaml similarity index 100% rename from gems/bp/spec/fixtures/checkpoint-without-challenges-block-repo/config.yaml rename to gems/block-parser/spec/fixtures/checkpoint-without-challenges-block-repo/config.yaml diff --git a/gems/bp/spec/fixtures/checkpoint-without-challenges-block-repo/no-challenges.md b/gems/block-parser/spec/fixtures/checkpoint-without-challenges-block-repo/no-challenges.md similarity index 100% rename from gems/bp/spec/fixtures/checkpoint-without-challenges-block-repo/no-challenges.md rename to gems/block-parser/spec/fixtures/checkpoint-without-challenges-block-repo/no-challenges.md diff --git a/gems/bp/spec/fixtures/invalid-config-test-block-repo/config.yaml b/gems/block-parser/spec/fixtures/invalid-config-test-block-repo/config.yaml similarity index 100% rename from gems/bp/spec/fixtures/invalid-config-test-block-repo/config.yaml rename to gems/block-parser/spec/fixtures/invalid-config-test-block-repo/config.yaml diff --git a/gems/bp/spec/fixtures/no-lessons-nor-checkpoints/config.yaml b/gems/block-parser/spec/fixtures/no-lessons-nor-checkpoints/config.yaml similarity index 100% rename from gems/bp/spec/fixtures/no-lessons-nor-checkpoints/config.yaml rename to gems/block-parser/spec/fixtures/no-lessons-nor-checkpoints/config.yaml diff --git a/gems/bp/spec/fixtures/no-lessons-nor-checkpoints/resources.md b/gems/block-parser/spec/fixtures/no-lessons-nor-checkpoints/resources.md similarity index 100% rename from gems/bp/spec/fixtures/no-lessons-nor-checkpoints/resources.md rename to gems/block-parser/spec/fixtures/no-lessons-nor-checkpoints/resources.md diff --git a/gems/bp/spec/fixtures/no-standards-config-test-block-repo/config.yaml b/gems/block-parser/spec/fixtures/no-standards-config-test-block-repo/config.yaml similarity index 100% rename from gems/bp/spec/fixtures/no-standards-config-test-block-repo/config.yaml rename to gems/block-parser/spec/fixtures/no-standards-config-test-block-repo/config.yaml diff --git a/gems/bp/spec/fixtures/sample-iframe.md b/gems/block-parser/spec/fixtures/sample-iframe.md similarity index 100% rename from gems/bp/spec/fixtures/sample-iframe.md rename to gems/block-parser/spec/fixtures/sample-iframe.md diff --git a/gems/bp/spec/fixtures/test-block-repo-yml/config.yml b/gems/block-parser/spec/fixtures/test-block-repo-yml/config.yml similarity index 100% rename from gems/bp/spec/fixtures/test-block-repo-yml/config.yml rename to gems/block-parser/spec/fixtures/test-block-repo-yml/config.yml diff --git a/gems/bp/spec/fixtures/test-block-repo-yml/dummy.pdf b/gems/block-parser/spec/fixtures/test-block-repo-yml/dummy.pdf similarity index 100% rename from gems/bp/spec/fixtures/test-block-repo-yml/dummy.pdf rename to gems/block-parser/spec/fixtures/test-block-repo-yml/dummy.pdf diff --git a/gems/bp/spec/fixtures/test-block-repo-yml/folder/sibling.md b/gems/block-parser/spec/fixtures/test-block-repo-yml/folder/sibling.md similarity index 100% rename from gems/bp/spec/fixtures/test-block-repo-yml/folder/sibling.md rename to gems/block-parser/spec/fixtures/test-block-repo-yml/folder/sibling.md diff --git a/gems/bp/spec/fixtures/test-block-repo-yml/folder/target.md b/gems/block-parser/spec/fixtures/test-block-repo-yml/folder/target.md similarity index 100% rename from gems/bp/spec/fixtures/test-block-repo-yml/folder/target.md rename to gems/block-parser/spec/fixtures/test-block-repo-yml/folder/target.md diff --git a/gems/bp/spec/fixtures/test-block-repo-yml/images/galvanize-logo.png b/gems/block-parser/spec/fixtures/test-block-repo-yml/images/galvanize-logo.png similarity index 100% rename from gems/bp/spec/fixtures/test-block-repo-yml/images/galvanize-logo.png rename to gems/block-parser/spec/fixtures/test-block-repo-yml/images/galvanize-logo.png diff --git a/gems/bp/spec/fixtures/test-block-repo-yml/images/register_klass.gif b/gems/block-parser/spec/fixtures/test-block-repo-yml/images/register_klass.gif similarity index 100% rename from gems/bp/spec/fixtures/test-block-repo-yml/images/register_klass.gif rename to gems/block-parser/spec/fixtures/test-block-repo-yml/images/register_klass.gif diff --git a/gems/bp/spec/fixtures/test-block-repo-yml/lessoN.md b/gems/block-parser/spec/fixtures/test-block-repo-yml/lessoN.md similarity index 100% rename from gems/bp/spec/fixtures/test-block-repo-yml/lessoN.md rename to gems/block-parser/spec/fixtures/test-block-repo-yml/lessoN.md diff --git a/gems/bp/spec/fixtures/test-block-repo-yml/markdown-smoketest.md b/gems/block-parser/spec/fixtures/test-block-repo-yml/markdown-smoketest.md similarity index 100% rename from gems/bp/spec/fixtures/test-block-repo-yml/markdown-smoketest.md rename to gems/block-parser/spec/fixtures/test-block-repo-yml/markdown-smoketest.md diff --git a/gems/bp/spec/fixtures/test-block-repo-yml/target.md b/gems/block-parser/spec/fixtures/test-block-repo-yml/target.md similarity index 100% rename from gems/bp/spec/fixtures/test-block-repo-yml/target.md rename to gems/block-parser/spec/fixtures/test-block-repo-yml/target.md diff --git a/gems/bp/spec/fixtures/test-block-repo/README.md b/gems/block-parser/spec/fixtures/test-block-repo/README.md similarity index 100% rename from gems/bp/spec/fixtures/test-block-repo/README.md rename to gems/block-parser/spec/fixtures/test-block-repo/README.md diff --git a/gems/bp/spec/fixtures/test-block-repo/config.yaml b/gems/block-parser/spec/fixtures/test-block-repo/config.yaml similarity index 100% rename from gems/bp/spec/fixtures/test-block-repo/config.yaml rename to gems/block-parser/spec/fixtures/test-block-repo/config.yaml diff --git a/gems/bp/spec/fixtures/test-block-repo/folder/sibling.md b/gems/block-parser/spec/fixtures/test-block-repo/folder/sibling.md similarity index 100% rename from gems/bp/spec/fixtures/test-block-repo/folder/sibling.md rename to gems/block-parser/spec/fixtures/test-block-repo/folder/sibling.md diff --git a/gems/bp/spec/fixtures/test-block-repo/folder/target.md b/gems/block-parser/spec/fixtures/test-block-repo/folder/target.md similarity index 100% rename from gems/bp/spec/fixtures/test-block-repo/folder/target.md rename to gems/block-parser/spec/fixtures/test-block-repo/folder/target.md diff --git a/gems/bp/spec/fixtures/test-block-repo/images/galvanize-logo.png b/gems/block-parser/spec/fixtures/test-block-repo/images/galvanize-logo.png similarity index 100% rename from gems/bp/spec/fixtures/test-block-repo/images/galvanize-logo.png rename to gems/block-parser/spec/fixtures/test-block-repo/images/galvanize-logo.png diff --git a/gems/bp/spec/fixtures/test-block-repo/images/register_klass.gif b/gems/block-parser/spec/fixtures/test-block-repo/images/register_klass.gif similarity index 100% rename from gems/bp/spec/fixtures/test-block-repo/images/register_klass.gif rename to gems/block-parser/spec/fixtures/test-block-repo/images/register_klass.gif diff --git a/gems/bp/spec/fixtures/test-block-repo/ipynb-test.ipynb b/gems/block-parser/spec/fixtures/test-block-repo/ipynb-test.ipynb similarity index 100% rename from gems/bp/spec/fixtures/test-block-repo/ipynb-test.ipynb rename to gems/block-parser/spec/fixtures/test-block-repo/ipynb-test.ipynb diff --git a/gems/bp/spec/fixtures/test-block-repo/ipynb-test.md b/gems/block-parser/spec/fixtures/test-block-repo/ipynb-test.md similarity index 100% rename from gems/bp/spec/fixtures/test-block-repo/ipynb-test.md rename to gems/block-parser/spec/fixtures/test-block-repo/ipynb-test.md diff --git a/gems/bp/spec/fixtures/test-block-repo/lessoN.md b/gems/block-parser/spec/fixtures/test-block-repo/lessoN.md similarity index 100% rename from gems/bp/spec/fixtures/test-block-repo/lessoN.md rename to gems/block-parser/spec/fixtures/test-block-repo/lessoN.md diff --git a/gems/bp/spec/fixtures/test-block-repo/markdown-smoketest.md b/gems/block-parser/spec/fixtures/test-block-repo/markdown-smoketest.md similarity index 100% rename from gems/bp/spec/fixtures/test-block-repo/markdown-smoketest.md rename to gems/block-parser/spec/fixtures/test-block-repo/markdown-smoketest.md diff --git a/gems/bp/spec/fixtures/test-block-repo/target.md b/gems/block-parser/spec/fixtures/test-block-repo/target.md similarity index 100% rename from gems/bp/spec/fixtures/test-block-repo/target.md rename to gems/block-parser/spec/fixtures/test-block-repo/target.md diff --git a/gems/bp/spec/fixtures/test-block-two-configs/config.yaml b/gems/block-parser/spec/fixtures/test-block-two-configs/config.yaml similarity index 100% rename from gems/bp/spec/fixtures/test-block-two-configs/config.yaml rename to gems/block-parser/spec/fixtures/test-block-two-configs/config.yaml diff --git a/gems/bp/spec/fixtures/test-block-two-configs/config.yml b/gems/block-parser/spec/fixtures/test-block-two-configs/config.yml similarity index 100% rename from gems/bp/spec/fixtures/test-block-two-configs/config.yml rename to gems/block-parser/spec/fixtures/test-block-two-configs/config.yml diff --git a/gems/bp/spec/fixtures/valid-custom-snippet-challenge-directory/Dockerfile b/gems/block-parser/spec/fixtures/valid-custom-snippet-challenge-directory/Dockerfile similarity index 100% rename from gems/bp/spec/fixtures/valid-custom-snippet-challenge-directory/Dockerfile rename to gems/block-parser/spec/fixtures/valid-custom-snippet-challenge-directory/Dockerfile diff --git a/gems/bp/spec/fixtures/valid-custom-snippet-challenge-directory/test.sh b/gems/block-parser/spec/fixtures/valid-custom-snippet-challenge-directory/test.sh similarity index 100% rename from gems/bp/spec/fixtures/valid-custom-snippet-challenge-directory/test.sh rename to gems/block-parser/spec/fixtures/valid-custom-snippet-challenge-directory/test.sh diff --git a/gems/bp/spec/fixtures/valid-yaml-array-test-block-repo/config.yaml b/gems/block-parser/spec/fixtures/valid-yaml-array-test-block-repo/config.yaml similarity index 100% rename from gems/bp/spec/fixtures/valid-yaml-array-test-block-repo/config.yaml rename to gems/block-parser/spec/fixtures/valid-yaml-array-test-block-repo/config.yaml diff --git a/gems/bp/spec/parse_directory_spec.rb b/gems/block-parser/spec/parse_directory_spec.rb similarity index 100% rename from gems/bp/spec/parse_directory_spec.rb rename to gems/block-parser/spec/parse_directory_spec.rb diff --git a/gems/bp/spec/parse_markdown_file_spec.rb b/gems/block-parser/spec/parse_markdown_file_spec.rb similarity index 100% rename from gems/bp/spec/parse_markdown_file_spec.rb rename to gems/block-parser/spec/parse_markdown_file_spec.rb diff --git a/gems/bp/spec/parse_standards_spec.rb b/gems/block-parser/spec/parse_standards_spec.rb similarity index 100% rename from gems/bp/spec/parse_standards_spec.rb rename to gems/block-parser/spec/parse_standards_spec.rb diff --git a/gems/bp/spec/spec_helper.rb b/gems/block-parser/spec/spec_helper.rb similarity index 100% rename from gems/bp/spec/spec_helper.rb rename to gems/block-parser/spec/spec_helper.rb diff --git a/gems/bp/spec/support/freeloader.rb b/gems/block-parser/spec/support/freeloader.rb similarity index 100% rename from gems/bp/spec/support/freeloader.rb rename to gems/block-parser/spec/support/freeloader.rb diff --git a/gems/bp/spec/support/mocktokit.rb b/gems/block-parser/spec/support/mocktokit.rb similarity index 100% rename from gems/bp/spec/support/mocktokit.rb rename to gems/block-parser/spec/support/mocktokit.rb diff --git a/gems/bp/spec/tmp/.keep b/gems/block-parser/spec/tmp/.keep similarity index 100% rename from gems/bp/spec/tmp/.keep rename to gems/block-parser/spec/tmp/.keep diff --git a/gems/bp/validate-block b/gems/block-parser/validate-block similarity index 100% rename from gems/bp/validate-block rename to gems/block-parser/validate-block -- GitLab From 169aada78a4278b7bd423224f9bd09b0a6deda08 Mon Sep 17 00:00:00 2001 From: Benton Gallun Date: Tue, 22 Sep 2020 01:50:11 +0000 Subject: [PATCH 052/283] change image target to registry1.dsop.io/ironbank/opensource/ruby/ruby26:latest --- Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index cbbb371..6f5acc2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,4 @@ -FROM bitnami/ruby:2.6.0 - +FROM registry1.dsop.io/ironbank/opensource/ruby/ruby26:latest ENV count 6 # Install what we can through OS package management -- GitLab From 18140c4b07c06e7b8c3bdadf39bb739f36bed114 Mon Sep 17 00:00:00 2001 From: Derrin Chong Date: Tue, 22 Sep 2020 08:00:13 -1000 Subject: [PATCH 053/283] Use bitnami ruby image --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 6f5acc2..e78d68a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM registry1.dsop.io/ironbank/opensource/ruby/ruby26:latest +FROM bitnami/ruby:2.6.0 ENV count 6 # Install what we can through OS package management -- GitLab From 5fac7cd0e75a67338cada2143d5beeef283915db Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 22 Sep 2020 11:28:00 -1000 Subject: [PATCH 054/283] creating new job runners for code snippets. changing to queue jobs on specific queues per language. --- app/jobs/java_code_evaluation_job.rb | 7 +++ app/jobs/javascript_code_evaluation_job.rb | 7 +++ app/jobs/python_code_evaluation_job.rb | 7 +++ app/services/assessment_service.rb | 54 ++++++++++++++-------- 4 files changed, 57 insertions(+), 18 deletions(-) create mode 100644 app/jobs/java_code_evaluation_job.rb create mode 100644 app/jobs/javascript_code_evaluation_job.rb create mode 100644 app/jobs/python_code_evaluation_job.rb diff --git a/app/jobs/java_code_evaluation_job.rb b/app/jobs/java_code_evaluation_job.rb new file mode 100644 index 0000000..27be584 --- /dev/null +++ b/app/jobs/java_code_evaluation_job.rb @@ -0,0 +1,7 @@ +class JavaCodeEvaluationJob < ApplicationJob + queue_as :java_evaluation + + def perform(setup:, code_to_assess:, tests_to_assess_against:, callback_url:) + puts "it ran" + end +end diff --git a/app/jobs/javascript_code_evaluation_job.rb b/app/jobs/javascript_code_evaluation_job.rb new file mode 100644 index 0000000..2432051 --- /dev/null +++ b/app/jobs/javascript_code_evaluation_job.rb @@ -0,0 +1,7 @@ +class JavascriptCodeEvaluationJob < ApplicationJob + queue_as :javascript_evaluation + + def perform(setup:, code_to_assess:, tests_to_assess_against:, callback_url:) + puts "it ran" + end +end diff --git a/app/jobs/python_code_evaluation_job.rb b/app/jobs/python_code_evaluation_job.rb new file mode 100644 index 0000000..4248a73 --- /dev/null +++ b/app/jobs/python_code_evaluation_job.rb @@ -0,0 +1,7 @@ +class PythonCodeEvaluationJob < ApplicationJob + queue_as :python_evaluation + + def perform(setup:, code_to_assess:, tests_to_assess_against:, callback_url:) + puts "it ran" + end +end diff --git a/app/services/assessment_service.rb b/app/services/assessment_service.rb index 6f2b01c..49f228d 100644 --- a/app/services/assessment_service.rb +++ b/app/services/assessment_service.rb @@ -2,27 +2,45 @@ class AssessmentService GITHUB_HOST = "github.com".freeze def self.evaluate_code_snippet(challenge, submitted_challenge_answer, callback_url) - connection = Faraday.new(url: Rails.application.secrets.assessments_service_domain) - connection.authorization :Token, token: Rails.application.secrets.assessments_api_key + args = { + setup: challenge.setup, + code_to_assess: submitted_challenge_answer.answer, + tests_to_assess_against: challenge.tests, + callback_url: callback_url + } - begin - response = connection.post do |req| - req.url "/assessments" - req.headers["Content-Type"] = "application/json" - req.body = { "code_to_assess": submitted_challenge_answer.answer, - "setup_to_run_before_code": challenge.setup, - "db_checksum": challenge.data_path_checksum, - "tests_to_assess_against": challenge.tests, - "language": challenge.language, - "callback_url": callback_url }.to_json - end - rescue Faraday::ConnectionFailed => e - Honeybadger.notify(e) - submitted_challenge_answer.update_attributes(status: "failed", test_results: "Connection failed") and return + if challenge.language == "javascript" + JavascriptCodeEvaluationJob.perform_later(args) + elsif challenge.language == "java" + JavaCodeEvaluationJob.perform_later(args) + elsif challenge.language.include?("python") + PythonCodeEvaluationJob.perform_later(args) + else + puts "Unfamiliar language: #{challenge.language}" end - submitted_challenge_answer.update_attributes(status: "failed", test_results: "Connection failed") if response.status != 200 - response + + # connection = Faraday.new(url: Rails.application.secrets.assessments_service_domain) + # connection.authorization :Token, token: Rails.application.secrets.assessments_api_key + # + # begin + # response = connection.post do |req| + # req.url "/assessments" + # req.headers["Content-Type"] = "application/json" + # req.body = { "code_to_assess": submitted_challenge_answer.answer, + # "setup_to_run_before_code": challenge.setup, + # "db_checksum": challenge.data_path_checksum, + # "tests_to_assess_against": challenge.tests, + # "language": challenge.language, + # "callback_url": callback_url }.to_json + # end + # rescue Faraday::ConnectionFailed => e + # Honeybadger.notify(e) + # submitted_challenge_answer.update_attributes(status: "failed", test_results: "Connection failed") and return + # end + # submitted_challenge_answer.update_attributes(status: "failed", test_results: "Connection failed") if response.status != 200 + # + # response end def self.evaluate_project(submitted_challenge_answer, callback_url) -- GitLab From 8b559055b7e78c2d798577343b504da8f1a9a1ea Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Tue, 22 Sep 2020 12:38:39 -1000 Subject: [PATCH 055/283] Fix s3 endpoints --- app/services/download_s3_repository_service.rb | 2 +- config/initializers/aws.rb | 2 +- config/secrets.yml | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/services/download_s3_repository_service.rb b/app/services/download_s3_repository_service.rb index 5f26fe3..8f41e3c 100644 --- a/app/services/download_s3_repository_service.rb +++ b/app/services/download_s3_repository_service.rb @@ -9,7 +9,7 @@ class DownloadS3RepositoryService < DownloadRepositoryService tmp_zip_file = tmp_zip_path(@tmp_path) File.open(tmp_zip_file, "wb") do |f| - client.get_object(bucket: Rails.application.secrets.s3_bucket_name, + client.get_object(bucket: Rails.application.secrets.glearn_bucket_name, key: @s3_key) { |chunk| f.write(chunk) } end diff --git a/config/initializers/aws.rb b/config/initializers/aws.rb index 606c756..9bc4636 100644 --- a/config/initializers/aws.rb +++ b/config/initializers/aws.rb @@ -35,5 +35,5 @@ end Rails.application.config.aws = if Rails.env.test? AwsMock.new else - Aws::S3::Resource.new(region: "us-west-2").bucket(Rails.application.secrets.s3_bucket_name) + Aws::S3::Resource.new(region: "us-gov-west-1").bucket(Rails.application.secrets.glearn_bucket_name) end diff --git a/config/secrets.yml b/config/secrets.yml index fd7c36f..ec63e6f 100644 --- a/config/secrets.yml +++ b/config/secrets.yml @@ -56,7 +56,6 @@ development: auth_url: http://localhost:5000 auth_webhook_token: 5d3b97936810572da8568e2712ec4557ffeecf0a06f3c77fcee5b5846c3389dc protocol: http:// - s3_bucket_name: forge-development.galvanize.com secret_key_base: 6f494a506dc84ee2752abbe81ec8168d6ce27ae30d6e392ecd6411b8224399089821759983823d433afa7662dfde34b4c4af3c6e7a7343c3d2dc146255c15da4 dev_notify_slack_url: development -- GitLab From 3b2fbd4e200e69bfb79eb0337724d72bbc33c853 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 22 Sep 2020 14:10:29 -1000 Subject: [PATCH 056/283] changing s3 region to come from secrets.yml and env file --- .env.example | 3 ++- config/initializers/aws.rb | 2 +- config/secrets.yml | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index 100441f..b8be933 100644 --- a/.env.example +++ b/.env.example @@ -10,4 +10,5 @@ STANDARD_EVENT_UIDS="40f3bb48-1d23-4105-a22a-7f07b90bd1e6,cc22ef7e-d9c9-4e3d-ae9 KEYCLOAK_CLIENT_ID=forge KEYCLOAK_CLIENT_SECRET=487b8a4a-e437-4795-9e1e-b68a9c340afb KEYCLOAK_ENDPOINT=http://localhost:8080 -KEYCLOAK_REALM=learn \ No newline at end of file +KEYCLOAK_REALM=learn +S3_REGION=us-gov-west-1 \ No newline at end of file diff --git a/config/initializers/aws.rb b/config/initializers/aws.rb index 9bc4636..9694d1d 100644 --- a/config/initializers/aws.rb +++ b/config/initializers/aws.rb @@ -35,5 +35,5 @@ end Rails.application.config.aws = if Rails.env.test? AwsMock.new else - Aws::S3::Resource.new(region: "us-gov-west-1").bucket(Rails.application.secrets.glearn_bucket_name) + Aws::S3::Resource.new(region: Rails.application.secrets.s3_region).bucket(Rails.application.secrets.glearn_bucket_name) end diff --git a/config/secrets.yml b/config/secrets.yml index ec63e6f..b8dcb24 100644 --- a/config/secrets.yml +++ b/config/secrets.yml @@ -34,6 +34,7 @@ shared: glearn_secret_access_key: <%= ENV['GLEARN_SECRET_ACCESS_KEY'] %> glearn_key_prefix: <%= ENV['GLEARN_KEY_PREFIX'] %> glearn_bucket_name: <%= ENV['GLEARN_BUCKET_NAME'] %> + s3_region: <%= ENV['S3_REGION'] %> dev_notify_slack_url: <%= ENV['DEV_NOTIFY_SLACK_URL'] %> git_download_tokens: github_com: -- GitLab From 40f1988e0b2d5b8f8dc308357c60a8f0402d6ffe Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Wed, 23 Sep 2020 09:53:15 -1000 Subject: [PATCH 057/283] removing pulling roles from keycloak --- app/services/keycloak_resolver_service.rb | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/app/services/keycloak_resolver_service.rb b/app/services/keycloak_resolver_service.rb index 27f7fc3..9ccd1d9 100644 --- a/app/services/keycloak_resolver_service.rb +++ b/app/services/keycloak_resolver_service.rb @@ -5,21 +5,12 @@ class KeycloakResolverService end def find_or_create_user - # default roles to empty array - roles = [] - - # if there are roles in the access token. get the roles from the access token. - if @auth_hash&.extra&.raw_info&.realm_access&.roles - roles = @auth_hash.extra.raw_info.realm_access.roles.to_a - end - existing_user = User.find_by(uid: @auth_hash.uid) if existing_user existing_user.update(first_name: @auth_hash.info.first_name, last_name: @auth_hash.info.last_name, - email: @auth_hash.info.email, - roles: roles + email: @auth_hash.info.email ) existing_user @@ -28,7 +19,7 @@ class KeycloakResolverService first_name: @auth_hash.info.first_name, last_name: @auth_hash.info.last_name, email: @auth_hash.info.email, - roles: roles + roles: [] ) user -- GitLab From 73c965911a6beb293fac0b93a3e64c3179c00c36 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Wed, 23 Sep 2020 12:46:16 -1000 Subject: [PATCH 058/283] adding edit of global roles on the cohort user screens --- app/controllers/users_controller.rb | 10 ++++++++++ app/views/users/edit.html.haml | 12 ++++++++++++ 2 files changed, 22 insertions(+) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 53d6131..9339cb6 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -7,11 +7,17 @@ class UsersController < ApplicationController def edit authorize(current_cohort) current_cohort_user + user end def update authorize(current_cohort) current_cohort_user.update(roles: [params[:instructor]].compact) + + if (user.admin?) + user.update(roles:[params[:forge_admin], params[:forge_blocks_manager], params[:auth_product_admin]].compact) + end + redirect_to users_cohort_path(current_cohort) end @@ -30,4 +36,8 @@ class UsersController < ApplicationController def current_cohort_user @cohort_user ||= CohortUser.find_by(cohort_id: params[:cohort_id], user_id: params[:id]) end + + def user + @user ||= User.find_by(id: params[:id]) + end end diff --git a/app/views/users/edit.html.haml b/app/views/users/edit.html.haml index a702522..d917643 100644 --- a/app/views/users/edit.html.haml +++ b/app/views/users/edit.html.haml @@ -15,6 +15,18 @@ .form-check = check_box_tag :instructor, "forge.instructor", @cohort_user.roles.include?("forge.instructor"), class: "form-check-input" = label :instructor, "Instructor" + - if @user.admin? + %h5 Global Roles: + .form-group + .form-check + = check_box_tag :forge_admin, "forge.admin", @user.roles.include?("forge.admin"), class: "form-check-input" + = label :forge_admin, "Forge Admin" + .form-check + = check_box_tag :forge_blocks_manager, "forge.blocks_manager", @user.roles.include?("forge.blocks_manager"), class: "form-check-input" + = label :forge_blocks_manager, "Forge Blocks Manager" + .form-check + = check_box_tag :auth_product_admin, "auth.product_admin", @user.roles.include?("auth.product_admin"), class: "form-check-input" + = label :auth_product_admin, "Forge Product Admin" = f.submit "Update Cohort User", class: "btn btn-primary" = link_to "Remove User From Cohort", "#my-modal", class: "btn btn-danger", "data-toggle": "modal", style: "float:right;" .modal{id: "my-modal"} -- GitLab From e950252f830fb78fcf1d038e1fe5fb3dec8366e9 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Wed, 23 Sep 2020 17:36:14 -1000 Subject: [PATCH 059/283] fixing labels --- app/views/users/edit.html.haml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/users/edit.html.haml b/app/views/users/edit.html.haml index d917643..cdc6a68 100644 --- a/app/views/users/edit.html.haml +++ b/app/views/users/edit.html.haml @@ -14,19 +14,19 @@ .form-group .form-check = check_box_tag :instructor, "forge.instructor", @cohort_user.roles.include?("forge.instructor"), class: "form-check-input" - = label :instructor, "Instructor" + = label_tag :instructor, "Instructor" - if @user.admin? %h5 Global Roles: .form-group .form-check = check_box_tag :forge_admin, "forge.admin", @user.roles.include?("forge.admin"), class: "form-check-input" - = label :forge_admin, "Forge Admin" + = label_tag :forge_admin, "Forge Admin" .form-check = check_box_tag :forge_blocks_manager, "forge.blocks_manager", @user.roles.include?("forge.blocks_manager"), class: "form-check-input" - = label :forge_blocks_manager, "Forge Blocks Manager" + = label_tag :forge_blocks_manager, "Forge Blocks Manager" .form-check = check_box_tag :auth_product_admin, "auth.product_admin", @user.roles.include?("auth.product_admin"), class: "form-check-input" - = label :auth_product_admin, "Forge Product Admin" + = label_tag :auth_product_admin, "Forge Product Admin" = f.submit "Update Cohort User", class: "btn btn-primary" = link_to "Remove User From Cohort", "#my-modal", class: "btn btn-danger", "data-toggle": "modal", style: "float:right;" .modal{id: "my-modal"} -- GitLab From 8f0844bd268dfea8761b725898ab634c38c9c83a Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Thu, 24 Sep 2020 12:30:35 -1000 Subject: [PATCH 060/283] changing image uploader --- app/services/encoded_image_link_service.rb | 16 ++++++++++++++++ app/services/release_helper_service.rb | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 app/services/encoded_image_link_service.rb diff --git a/app/services/encoded_image_link_service.rb b/app/services/encoded_image_link_service.rb new file mode 100644 index 0000000..523d3af --- /dev/null +++ b/app/services/encoded_image_link_service.rb @@ -0,0 +1,16 @@ +class EncodedImageLinkService + class Error < StandardError; end + + def initialize + end + + def find_or_create_content(full_path:, directory: nil) + begin + encoded_string = Base64.encode64(File.open(full_path).read) + image_mime_type = MIME::Types.type_for(full_path).first.content_type + return "data:#{image_mime_type};base64, #{encoded_string}" + rescue StandardError => e + raise(Error, e) + end + end +end diff --git a/app/services/release_helper_service.rb b/app/services/release_helper_service.rb index bdcbee1..b719ae5 100644 --- a/app/services/release_helper_service.rb +++ b/app/services/release_helper_service.rb @@ -6,7 +6,7 @@ module ReleaseHelperService path_results = BlockParser::ParseDirectory.new( path: path, - asset_uploader: S3AssetUploaderService.new + asset_uploader: EncodedImageLinkService.new ).execute if path_results[:warnings].any? -- GitLab From 57551bcd4d032b214f47657ecc774d7cbf5bedfd Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Thu, 24 Sep 2020 12:34:49 -1000 Subject: [PATCH 061/283] Fixes for gitlab subprojects --- app/models/block.rb | 9 +++--- app/services/course_validator.rb | 2 +- .../download_gitlab_repository_service.rb | 3 +- app/services/git_url_service.rb | 23 ++++++++++--- spec/services/git_url_service_spec.rb | 32 ++++++++++++++++++- 5 files changed, 58 insertions(+), 11 deletions(-) diff --git a/app/models/block.rb b/app/models/block.rb index 655e017..778a93f 100644 --- a/app/models/block.rb +++ b/app/models/block.rb @@ -2,7 +2,7 @@ class Block < ApplicationRecord validates :title, :repo_name, presence: true validates :title, uniqueness: true validate :repo_is_unique, on: :create - validate :validate_github_org_and_branch + # validate :validate_github_org_and_branch has_many :releases @@ -45,6 +45,10 @@ class Block < ApplicationRecord errors.add(:repo, "URL cannot include a branch") unless repo_name_only? end + def repo_name_only? + repo_name =~ /^[\w.-]*$/ + end + private def repo_is_unique @@ -53,7 +57,4 @@ class Block < ApplicationRecord end end - def repo_name_only? - repo_name =~ /^[\w.-]*$/ - end end diff --git a/app/services/course_validator.rb b/app/services/course_validator.rb index 0be07f2..08a4d1a 100644 --- a/app/services/course_validator.rb +++ b/app/services/course_validator.rb @@ -133,7 +133,7 @@ class CourseValidator json = JSON.parse( open("https://#{git_url.host}/api/v4/projects?search=#{git_url.repository}", "Private-Token" => token).read - ).find {|project| project["path_with_namespace"] == "#{git_url.organization}/#{git_url.repository}"} + ).find {|project| project["path_with_namespace"] == git_url.full_path} raise OpenURI::HTTPError.new("404 Not Found", nil) if json.nil? and return diff --git a/app/services/download_gitlab_repository_service.rb b/app/services/download_gitlab_repository_service.rb index 02611d4..ec5da41 100644 --- a/app/services/download_gitlab_repository_service.rb +++ b/app/services/download_gitlab_repository_service.rb @@ -54,7 +54,8 @@ class DownloadGitlabRepositoryService < DownloadRepositoryService end def gitlab_project_search_by_repo_name - project_search_url = "https://#{@origin}/api/#{GITLAB_API_VERSION}/projects?search=#{@repo_name}&membership=true" + name = @block.repo_name_only? ? @repo_name : @repo_name.split('/').last + project_search_url = "https://#{@origin}/api/#{GITLAB_API_VERSION}/projects?search=#{name}&membership=true" json = read_endpoint_data(project_search_url, headers). find {|project| project["path_with_namespace"] == "#{@org}/#{@repo_name}"} diff --git a/app/services/git_url_service.rb b/app/services/git_url_service.rb index ea88eaa..65c4bc8 100644 --- a/app/services/git_url_service.rb +++ b/app/services/git_url_service.rb @@ -13,6 +13,15 @@ class GitUrlService @host = URI.parse(@url).host || host + if default_branch? + @repository = url_path[-1] + else + segment = (["blob", "tree", "raw"] & url_path).last + segindex = url_path.index(segment) + @repository = url_path[segindex - 1] + @branch = url_path[segindex + 1] + end + validate_url end @@ -21,15 +30,21 @@ class GitUrlService end def repository - url_path[1] + @repository end def branch - default_branch? ? @default_branch : url_path[3] + default_branch? ? @default_branch : @branch end def path - default_branch? ? File.join(url_path[2..-1]) : File.join(url_path[4..-1].to_a) + segment = default_branch? ? repository : branch + segindex = url_path.index(segment) + url_path[segindex + 1..-1].join('/') + end + + def full_path + url_path.join('/') end private @@ -41,7 +56,7 @@ class GitUrlService def validate_url raise(Invalid, "Url cannot be blank.") if url.strip.empty? raise(Invalid, "Missing organization") if organization.nil? - raise(Invalid, "Missing repository") if repository.nil? + raise(Invalid, "Missing repository") if repository.nil? || url_path.length <= 1 raise(Invalid, "Missing branch") if !default_branch? && url_path[3].nil? end diff --git a/spec/services/git_url_service_spec.rb b/spec/services/git_url_service_spec.rb index a2d9f4e..66e9c98 100644 --- a/spec/services/git_url_service_spec.rb +++ b/spec/services/git_url_service_spec.rb @@ -139,7 +139,7 @@ describe GitUrlService do describe "#path" do context "for a master branch" do - let(:url) { "http://www.github.com/gSchool/fs-curriculum/foo/bar.md" } + let(:url) { "http://www.github.com/gSchool/fs-curriculum/blob/master/foo/bar.md" } it "returns the path" do expect(subject.path).to eq("foo/bar.md") @@ -154,5 +154,35 @@ describe GitUrlService do end end end + + describe "subgroup gitlab url" do + context "for a project with a branch" do + let(:url) { "https://code.il2.dsop.io/tron/products/learn-lms/microservices/forge/-/tree/keycloak-auth" } + + it "gets the correct repo" do + expect(subject.repository).to eq("forge") + end + + it "gets the correct org" do + expect(subject.organization).to eq("tron") + end + + it "gets the correct branch" do + expect(subject.branch).to eq("keycloak-auth") + end + + it "gets an empty path" do + expect(subject.path).to eq("") + end + end + + context "for a project with a file specified" do + let(:url) { "https://code.il2.dsop.io/tron/products/learn-lms/microservices/forge/-/blob/master/config/environment.rb" } + + it "gets the correct path" do + expect(subject.path).to eq("config/environment.rb") + end + end + end end -- GitLab From d340da09a2c299b3729f59bfc302518e716a6503 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Thu, 24 Sep 2020 14:10:10 -1000 Subject: [PATCH 062/283] removing public read from s3 --- app/services/s3_asset_uploader_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/s3_asset_uploader_service.rb b/app/services/s3_asset_uploader_service.rb index 0cab0cf..d9a32f4 100644 --- a/app/services/s3_asset_uploader_service.rb +++ b/app/services/s3_asset_uploader_service.rb @@ -24,7 +24,7 @@ class S3AssetUploaderService def new_upload file_content = File.read(@full_path) aws_image_object = Rails.application.config.aws.object(content_key) - aws_image_object.put(body: file_content, acl: "public-read") + aws_image_object.put(body: file_content) aws_image_object.public_url rescue StandardError => e raise(Error, e) -- GitLab From dddef043087f43358e844cd35112859eca3996cd Mon Sep 17 00:00:00 2001 From: Derrin Chong Date: Thu, 24 Sep 2020 15:35:34 -1000 Subject: [PATCH 063/283] Set not version --- Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index e78d68a..0c5eb73 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,11 +20,12 @@ RUN apt-get -y install --no-install-recommends nodejs RUN apt-get -q clean RUN npm cache clean -f RUN npm install -g n -RUN n stable +RUN n 10.15.1 RUN update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10 # Copy in all the application dependencies ADD package.json /usr/src/app/package.json +RUN cd /usr/src/app RUN npm install # Set the user -- GitLab From 5e4bfce6d9a35df35318fc131f865abd436cb69a Mon Sep 17 00:00:00 2001 From: Derrin Chong Date: Thu, 24 Sep 2020 15:54:22 -1000 Subject: [PATCH 064/283] jumbled stuff around --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 0c5eb73..a809810 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,10 +18,10 @@ RUN apt-get -y install --no-install-recommends \ RUN curl -sL https://deb.nodesource.com/setup_12.x | bash - RUN apt-get -y install --no-install-recommends nodejs RUN apt-get -q clean +RUN update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10 RUN npm cache clean -f RUN npm install -g n RUN n 10.15.1 -RUN update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10 # Copy in all the application dependencies ADD package.json /usr/src/app/package.json -- GitLab From 83fbe6a3ed24b5f9cc345648428696115aa8d13f Mon Sep 17 00:00:00 2001 From: Derrin Chong Date: Thu, 24 Sep 2020 16:20:38 -1000 Subject: [PATCH 065/283] mike is a hacker --- .circleci/config.yml | 4 ++-- .overcommit.yml | 8 ++++---- Dockerfile | 2 +- package.json => package-hidden-from-robot.json | 0 4 files changed, 7 insertions(+), 7 deletions(-) rename package.json => package-hidden-from-robot.json (100%) diff --git a/.circleci/config.yml b/.circleci/config.yml index 837f2f3..83e82a7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -34,12 +34,12 @@ jobs: root: . paths: vendor/bundle - restore_cache: - key: v1-yarn-{{ checksum "package.json" }} + key: v1-yarn-{{ checksum "package-hidden-from-robot.json" }} - run: name: Yarn Install JS Dependencies command: yarn install - save_cache: - key: v1-yarn-{{ checksum "package.json" }} + key: v1-yarn-{{ checksum "package-hidden-from-robot.json" }} paths: - ~/forge/node_modules - persist_to_workspace: diff --git a/.overcommit.yml b/.overcommit.yml index 13aa9ce..43a08df 100644 --- a/.overcommit.yml +++ b/.overcommit.yml @@ -718,7 +718,7 @@ PostCheckout: required_executable: 'npm' flags: ['install'] include: - - 'package.json' + - 'package-hidden-from-robot.json' - 'npm-shrinkwrap.json' SubmoduleStatus: @@ -783,7 +783,7 @@ PostCommit: required_executable: 'npm' flags: ['install'] include: - - 'package.json' + - 'package-hidden-from-robot.json' - 'npm-shrinkwrap.json' SubmoduleStatus: @@ -832,7 +832,7 @@ PostMerge: required_executable: 'npm' flags: ['install'] include: - - 'package.json' + - 'package-hidden-from-robot.json' - 'npm-shrinkwrap.json' SubmoduleStatus: @@ -881,7 +881,7 @@ PostRewrite: required_executable: 'npm' flags: ['install'] include: - - 'package.json' + - 'package-hidden-from-robot.json' - 'npm-shrinkwrap.json' SubmoduleStatus: diff --git a/Dockerfile b/Dockerfile index a809810..2be0ef9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,7 +24,7 @@ RUN npm install -g n RUN n 10.15.1 # Copy in all the application dependencies -ADD package.json /usr/src/app/package.json +ADD package-hidden-from-robot.json /usr/src/app/package.json RUN cd /usr/src/app RUN npm install diff --git a/package.json b/package-hidden-from-robot.json similarity index 100% rename from package.json rename to package-hidden-from-robot.json -- GitLab From f20237cbad3b7a2c17c6d157b0373824b9b08b3f Mon Sep 17 00:00:00 2001 From: Derrin Chong Date: Thu, 24 Sep 2020 17:01:32 -1000 Subject: [PATCH 066/283] change back to package.json --- .circleci/config.yml | 4 ++-- .overcommit.yml | 8 ++++---- Dockerfile | 2 +- package-hidden-from-robot.json => package.json | 0 4 files changed, 7 insertions(+), 7 deletions(-) rename package-hidden-from-robot.json => package.json (100%) diff --git a/.circleci/config.yml b/.circleci/config.yml index 83e82a7..837f2f3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -34,12 +34,12 @@ jobs: root: . paths: vendor/bundle - restore_cache: - key: v1-yarn-{{ checksum "package-hidden-from-robot.json" }} + key: v1-yarn-{{ checksum "package.json" }} - run: name: Yarn Install JS Dependencies command: yarn install - save_cache: - key: v1-yarn-{{ checksum "package-hidden-from-robot.json" }} + key: v1-yarn-{{ checksum "package.json" }} paths: - ~/forge/node_modules - persist_to_workspace: diff --git a/.overcommit.yml b/.overcommit.yml index 43a08df..13aa9ce 100644 --- a/.overcommit.yml +++ b/.overcommit.yml @@ -718,7 +718,7 @@ PostCheckout: required_executable: 'npm' flags: ['install'] include: - - 'package-hidden-from-robot.json' + - 'package.json' - 'npm-shrinkwrap.json' SubmoduleStatus: @@ -783,7 +783,7 @@ PostCommit: required_executable: 'npm' flags: ['install'] include: - - 'package-hidden-from-robot.json' + - 'package.json' - 'npm-shrinkwrap.json' SubmoduleStatus: @@ -832,7 +832,7 @@ PostMerge: required_executable: 'npm' flags: ['install'] include: - - 'package-hidden-from-robot.json' + - 'package.json' - 'npm-shrinkwrap.json' SubmoduleStatus: @@ -881,7 +881,7 @@ PostRewrite: required_executable: 'npm' flags: ['install'] include: - - 'package-hidden-from-robot.json' + - 'package.json' - 'npm-shrinkwrap.json' SubmoduleStatus: diff --git a/Dockerfile b/Dockerfile index 2be0ef9..a809810 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,7 +24,7 @@ RUN npm install -g n RUN n 10.15.1 # Copy in all the application dependencies -ADD package-hidden-from-robot.json /usr/src/app/package.json +ADD package.json /usr/src/app/package.json RUN cd /usr/src/app RUN npm install diff --git a/package-hidden-from-robot.json b/package.json similarity index 100% rename from package-hidden-from-robot.json rename to package.json -- GitLab From 2d3dadc5acd24f8f33dbf927affddd413de99287 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Thu, 24 Sep 2020 18:17:17 -1000 Subject: [PATCH 067/283] chaning node install --- Dockerfile | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/Dockerfile b/Dockerfile index a809810..e2a6d8f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,18 +15,20 @@ RUN apt-get -y install --no-install-recommends \ xvfb # Install the right version of nodejs -RUN curl -sL https://deb.nodesource.com/setup_12.x | bash - -RUN apt-get -y install --no-install-recommends nodejs -RUN apt-get -q clean -RUN update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10 -RUN npm cache clean -f -RUN npm install -g n -RUN n 10.15.1 +#RUN curl -sL https://deb.nodesource.com/setup_12.x | bash - +#RUN apt-get -y install --no-install-recommends nodejs +#RUN apt-get -q clean +#RUN update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10 +#RUN npm cache clean -f +#RUN npm install -g n +#RUN n 10.15.1 +RUN curl -L https://raw.githubusercontent.com/tj/n/master/bin/n -o n +RUN bash n 10.15.1 # Copy in all the application dependencies -ADD package.json /usr/src/app/package.json -RUN cd /usr/src/app -RUN npm install +#ADD package.json /usr/src/app/package.json +#RUN cd /usr/src/app +#RUN npm install # Set the user RUN groupadd -r ruby @@ -42,6 +44,10 @@ ENV RAILS_ENV production ADD . . ADD Gemfile /usr/src/app/Gemfile ADD Gemfile.lock /usr/src/app/Gemfile.lock + +# Run NPM Install +RUN npm install + # RUN gem install bundler --version 1.17.3 RUN gem install rake -v '12.3.1' --source 'https://rubygems.org/' RUN bundle install -- GitLab From d912afa6a32570fe23c8cbe18fe034f5acb99e4f Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Thu, 24 Sep 2020 19:42:32 -1000 Subject: [PATCH 068/283] fixing all build errors on docker file --- Dockerfile | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/Dockerfile b/Dockerfile index e2a6d8f..5c1766b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,21 +14,13 @@ RUN apt-get -y install --no-install-recommends \ libqt5webkit5-dev \ xvfb -# Install the right version of nodejs -#RUN curl -sL https://deb.nodesource.com/setup_12.x | bash - -#RUN apt-get -y install --no-install-recommends nodejs -#RUN apt-get -q clean -#RUN update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10 -#RUN npm cache clean -f -#RUN npm install -g n -#RUN n 10.15.1 -RUN curl -L https://raw.githubusercontent.com/tj/n/master/bin/n -o n -RUN bash n 10.15.1 +# Clear off space. +RUN apt-get -q clean -# Copy in all the application dependencies -#ADD package.json /usr/src/app/package.json -#RUN cd /usr/src/app -#RUN npm install +# Install Node.js. +ADD .nvmrc . +RUN curl -L https://raw.githubusercontent.com/tj/n/master/bin/n -o n +RUN bash n auto # Set the user RUN groupadd -r ruby @@ -42,14 +34,19 @@ ENV RAILS_ENV production # Stuff that changes ADD . . -ADD Gemfile /usr/src/app/Gemfile -ADD Gemfile.lock /usr/src/app/Gemfile.lock # Run NPM Install RUN npm install -# RUN gem install bundler --version 1.17.3 +# Install Rails Dependecies. +RUN gem install bundler:1.17.3 RUN gem install rake -v '12.3.1' --source 'https://rubygems.org/' + +# Run the bundle install RUN bundle install + +# Add the node_modules to the path. ENV PATH /usr/src/app/node_modules/.bin:$PATH + +# Set the entry point. CMD ["./entrypoint-server.sh"] -- GitLab From 9363bbe2831dc81e66e6fc5ad690955cb61471ca Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Thu, 24 Sep 2020 20:07:16 -1000 Subject: [PATCH 069/283] changing to use yarn instead of npm install --- Dockerfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5c1766b..288b52b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,6 +21,7 @@ RUN apt-get -q clean ADD .nvmrc . RUN curl -L https://raw.githubusercontent.com/tj/n/master/bin/n -o n RUN bash n auto +RUN npm install -g yarn # Set the user RUN groupadd -r ruby @@ -35,8 +36,8 @@ ENV RAILS_ENV production # Stuff that changes ADD . . -# Run NPM Install -RUN npm install +# Run Yarn Install +RUN yarn install # Install Rails Dependecies. RUN gem install bundler:1.17.3 -- GitLab From 06a1cb9a9439526b83b13df56ff965e9771a9cdb Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 25 Sep 2020 09:08:49 -1000 Subject: [PATCH 070/283] changing gem file block parser to use relative path. Adding webpack build to docker file --- Dockerfile | 3 +++ Gemfile | 2 +- Gemfile.lock | 5 ++--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 288b52b..ac31eef 100644 --- a/Dockerfile +++ b/Dockerfile @@ -46,6 +46,9 @@ RUN gem install rake -v '12.3.1' --source 'https://rubygems.org/' # Run the bundle install RUN bundle install +# Run Webpack build. +RUN NODE_ENV=production bin/webpack + # Add the node_modules to the path. ENV PATH /usr/src/app/node_modules/.bin:$PATH diff --git a/Gemfile b/Gemfile index ce249cb..028c022 100644 --- a/Gemfile +++ b/Gemfile @@ -60,7 +60,7 @@ gem "dry-validation", "~> 0.12.2" # file processing ### We need to pass git credentials into the docker build command so we can clone the block-parser # gem "block_parser", :git => "https://code.il2.dsop.io/tron/products/learn-lms/ruby-gems/block-parser.git" -gem "block_parser", path: "/usr/src/app/gems/block-parser" +gem "block_parser", path: "./gems/block-parser" # Reduces boot times through caching; required in config/boot.rb gem "bootsnap", ">= 1.1.0" diff --git a/Gemfile.lock b/Gemfile.lock index f922ed5..61a9802 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,5 @@ -GIT - remote: https://code.il2.dsop.io/tron/products/learn-lms/ruby-gems/block-parser.git - revision: bdf3acdb4145805d306fc022f4abc2803a6bacb7 +PATH + remote: gems/block-parser specs: block_parser (0.1.0) activemodel (> 4.2) -- GitLab From 5339572e46283ae51b7f9e73770151037b539c5f Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 25 Sep 2020 10:08:48 -1000 Subject: [PATCH 071/283] changing port on entry point --- entrypoint-server.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/entrypoint-server.sh b/entrypoint-server.sh index 35df35e..6fa9cea 100755 --- a/entrypoint-server.sh +++ b/entrypoint-server.sh @@ -1,4 +1,4 @@ #!/bin/sh rm -f tmp/pids/server.pid -RAILS_ENV=production rails server -b 0.0.0.0 -p 3003 +RAILS_ENV=production rails server -b 0.0.0.0 -p 3000 -- GitLab From 2a3daaf0a3cc07113023000198f3bc68622161c7 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Fri, 25 Sep 2020 10:27:01 -1000 Subject: [PATCH 072/283] Fixed getting gitlab subprojects in course.yaml --- .../components/cohorts/settings/CohortSettingsResync.tsx | 6 +++--- app/services/resync_course_service.rb | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app/javascript/components/cohorts/settings/CohortSettingsResync.tsx b/app/javascript/components/cohorts/settings/CohortSettingsResync.tsx index 2744868..43ad062 100644 --- a/app/javascript/components/cohorts/settings/CohortSettingsResync.tsx +++ b/app/javascript/components/cohorts/settings/CohortSettingsResync.tsx @@ -71,10 +71,10 @@ export default class CohortSettingsResync extends React.Component { else if (job.status === 'pending') { return { state: 'pending', job: job } } - else if (job.status === 'canceled') { + else if (job.status === 'canceled') { return { state: 'canceled', job: job } } - else if (job.status === 'timeout') { + else if (job.status === 'timeout') { return { state: 'timeout', job: job } } else if (! job.archived) { @@ -218,7 +218,7 @@ export default class CohortSettingsResync extends React.Component { var {fileUrl, working, current, buttonText} = this.state var {githubIconPath} = this.props - var urlIsValid = fileUrl.match(new RegExp('^https://github.com\/')) + var urlIsValid = fileUrl.match(new RegExp('^https://')) var disable = !urlIsValid || working || current.state === 'pending' var jobStatusLabel = this.jobStatusLabel() diff --git a/app/services/resync_course_service.rb b/app/services/resync_course_service.rb index 1f41b14..5f0cbe0 100644 --- a/app/services/resync_course_service.rb +++ b/app/services/resync_course_service.rb @@ -16,6 +16,12 @@ class ResyncCourseService git_url.repository.downcase, git_url.host.downcase, git_url.organization.downcase).first + if block.nil? + block = Block.where("lower(repo_name) = ? AND lower(origin) = ? AND lower(org) = ?", + git_url.full_path.gsub(git_url.organization + '/', '').downcase, + git_url.host.downcase, + git_url.organization.downcase).first + end if block.nil? failed_blocks.push( -- GitLab From f1cc089c3d1fba31330de9f5444fb97da058dc15 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 25 Sep 2020 10:38:52 -1000 Subject: [PATCH 073/283] allowing forge admin to see add users button --- app/views/cohorts/users.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/cohorts/users.html.haml b/app/views/cohorts/users.html.haml index 9d63cf7..55e7d0e 100644 --- a/app/views/cohorts/users.html.haml +++ b/app/views/cohorts/users.html.haml @@ -25,7 +25,7 @@ importPath: import_users_work_cohort_path(cohort), importStatusPath: import_users_work_status_cohort_path(cohort) .managebutton - - if current_user.role?(User::ROLES[:product_admin]) || current_user.product_admin_of?(cohort.id) + - if current_user.role?(User::ROLES[:admin]) || current_user.role?(User::ROLES[:product_admin]) || current_user.product_admin_of?(cohort.id) = link_to new_cohort_user_path(cohort.id), class: "lp-style-button", target: "_blank" do Add Users = react_component "SvgRenderer", viewBox: "-8 -8 10 24", style: {fill: "white"}, url: path_to_image("svg/svg-sprite-action-symbol.svg#ic_launch_24px") -- GitLab From 97ec3ea5eac6bdea3c56be5e4ce4a01e355cfdd3 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Fri, 25 Sep 2020 11:28:23 -1000 Subject: [PATCH 074/283] Fixes for gitlab subprojects --- .../blocks/content_files_controller.rb | 2 +- app/services/git_url_service.rb | 8 +++++++- spec/services/git_url_service_spec.rb | 20 +++++++++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/app/controllers/cohorts/blocks/content_files_controller.rb b/app/controllers/cohorts/blocks/content_files_controller.rb index 98a6b2c..cc30315 100644 --- a/app/controllers/cohorts/blocks/content_files_controller.rb +++ b/app/controllers/cohorts/blocks/content_files_controller.rb @@ -104,7 +104,7 @@ module Cohorts is_resource: current_content_file.resource?, title: current_content_file.title, path: current_content_file.path, - permalink: permalink_url(current_block.repo_name, current_content_file.path), + permalink: permalink_url(CGI.escape(current_block.repo_name), current_content_file.path), type: current_content_file.content_file_type, students_in_cohort: current_cohort.students.map do |s| { id: s.id, full_name: s.full_name, initials: s.initials, profile_image: s.profile_image } diff --git a/app/services/git_url_service.rb b/app/services/git_url_service.rb index 65c4bc8..59f01e9 100644 --- a/app/services/git_url_service.rb +++ b/app/services/git_url_service.rb @@ -44,7 +44,13 @@ class GitUrlService end def full_path - url_path.join('/') + if default_branch? + url_path.join('/') + else + segment = (["blob", "tree", "raw"] & url_path).last + segindex = url_path.index(segment) + url_path[0...segindex].join('/') + end end private diff --git a/spec/services/git_url_service_spec.rb b/spec/services/git_url_service_spec.rb index 66e9c98..8ec13b3 100644 --- a/spec/services/git_url_service_spec.rb +++ b/spec/services/git_url_service_spec.rb @@ -174,15 +174,35 @@ describe GitUrlService do it "gets an empty path" do expect(subject.path).to eq("") end + + it "gets the correct full path" do + expect(subject.full_path).to eq("tron/products/learn-lms/microservices/forge") + end end context "for a project with a file specified" do let(:url) { "https://code.il2.dsop.io/tron/products/learn-lms/microservices/forge/-/blob/master/config/environment.rb" } + it "returns a full path without file information" do + expect(subject.full_path).to eq("tron/products/learn-lms/microservices/forge") + end + it "gets the correct path" do expect(subject.path).to eq("config/environment.rb") end end + + context "for a project with just a repository" do + let(:url) { "https://code.il2.dsop.io/tron/products/learn-lms/microservices/forge" } + + it "returns a full path without file information" do + expect(subject.full_path).to eq("tron/products/learn-lms/microservices/forge") + end + + it "gets the correct path" do + expect(subject.path).to eq("") + end + end end end -- GitLab From bb0c289d15fb7458d94e6b7c181d41f9378f8c65 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 25 Sep 2020 13:29:49 -1000 Subject: [PATCH 075/283] removing keycloak gem for API. adding db change to remove not nulls on user fields and added a constraint on email field for user. modified the bulk add to create empty users with cohort users that will get set after first login. removing some keycloak env fields. changing s3 fields. --- Gemfile | 1 - .../api/v1/cohorts/users_controller.rb | 49 +++++-------------- app/models/user.rb | 2 +- app/services/keycloak_resolver_service.rb | 8 +-- .../layouts/_primary_navigation.html.haml | 3 +- config/initializers/keycloak.rb | 11 ----- config/secrets.yml | 14 ++---- ...0149_remove_null_constraints_from_users.rb | 8 +++ db/schema.rb | 10 ++-- 9 files changed, 37 insertions(+), 69 deletions(-) delete mode 100644 config/initializers/keycloak.rb create mode 100644 db/migrate/20200925230149_remove_null_constraints_from_users.rb diff --git a/Gemfile b/Gemfile index fe3d036..f109552 100644 --- a/Gemfile +++ b/Gemfile @@ -43,7 +43,6 @@ gem "apitome" # services gem "omniauth" gem "omniauth-keycloak" -gem "keycloak" gem "honeybadger", "~> 3.1" gem "github_url", "0.2.1" gem "gitlab" diff --git a/app/controllers/api/v1/cohorts/users_controller.rb b/app/controllers/api/v1/cohorts/users_controller.rb index f6cdd88..7d86cb9 100644 --- a/app/controllers/api/v1/cohorts/users_controller.rb +++ b/app/controllers/api/v1/cohorts/users_controller.rb @@ -14,16 +14,16 @@ class Api::V1::Cohorts::UsersController < Api::ApplicationController json_response({ error: "Validation Error: #{param_errors.join(', ')}" }, 400) and return end - if keycloak_user_data - user = find_or_create_user(keycloak_user_data) - - if add_user_to_cohort(user, current_cohort) - json_response({ status: "ok" }, :ok) and return - else - json_response({ error: "User is already in the cohort." }, 400) and return - end + user = find_or_create_user(params[:email]) + + if user.errors.full_messages.any? + json_response({ error: "Validation Error: #{user.errors.full_messages.join(', ')}" }, 400) and return + end + + if add_user_to_cohort(user, current_cohort) + json_response({ status: "ok" }, :ok) and return else - json_response({ error: "User not found in KeyCloak." }, 400) and return + json_response({ error: "User is already in the cohort." }, 400) and return end rescue Keycloak::UserLoginNotFound => e @@ -176,38 +176,13 @@ class Api::V1::Cohorts::UsersController < Api::ApplicationController validation_response end - def keycloak_user_data - if @keycloak_user_data - return @keycloak_user_data - end - - data = Keycloak::Internal.get_user_info(params[:email], - true, - Rails.application.secrets.keycloak_client_id, - Rails.application.secrets.keycloak_client_secret) - - if data - @keycloak_user_data = { - id: data["id"], - first_name: data["firstName"], - last_name: data["lastName"], - email: data["email"] - } - - @keycloak_user_data - end - end - - def find_or_create_user(user_data) - user = User.find_by(uid: user_data[:id]) + def find_or_create_user(email) + user = User.find_by(email: email) if user user else - user = User.create(uid: user_data[:id], - first_name: user_data[:first_name], - last_name: user_data[:last_name], - email: user_data[:email], + user = User.create(email: email, roles: []) user diff --git a/app/models/user.rb b/app/models/user.rb index c5748c5..612af35 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -8,7 +8,7 @@ class User < ApplicationRecord blocks_manager: "forge.blocks_manager" }.freeze - validates(:first_name, :last_name, :uid, presence: true) + validates(:email, presence: true) validates(:uid, uniqueness: true) has_many :cohort_users diff --git a/app/services/keycloak_resolver_service.rb b/app/services/keycloak_resolver_service.rb index 9ccd1d9..a9aacb1 100644 --- a/app/services/keycloak_resolver_service.rb +++ b/app/services/keycloak_resolver_service.rb @@ -5,12 +5,12 @@ class KeycloakResolverService end def find_or_create_user - existing_user = User.find_by(uid: @auth_hash.uid) + existing_user = User.find_by(email: @auth_hash.info.email) if existing_user - existing_user.update(first_name: @auth_hash.info.first_name, - last_name: @auth_hash.info.last_name, - email: @auth_hash.info.email + existing_user.update(uid: @auth_hash.uid, + first_name: @auth_hash.info.first_name, + last_name: @auth_hash.info.last_name ) existing_user diff --git a/app/views/layouts/_primary_navigation.html.haml b/app/views/layouts/_primary_navigation.html.haml index 638a6dc..d76b7f0 100644 --- a/app/views/layouts/_primary_navigation.html.haml +++ b/app/views/layouts/_primary_navigation.html.haml @@ -47,7 +47,8 @@ = sprite_navigation('#ic_arrow_drop_down_24px') %ul.list %li.item - = link_to("My Account", Rails.application.secrets.keycloak_user_account_url, target: :_blank) + -# = link_to("My Account", "") + %br %span.account-email=current_user.email - if @authorized_api_access %li.item diff --git a/config/initializers/keycloak.rb b/config/initializers/keycloak.rb deleted file mode 100644 index 9347bbe..0000000 --- a/config/initializers/keycloak.rb +++ /dev/null @@ -1,11 +0,0 @@ -# If true, then all request exception will explode in application (this is the default value) -Keycloak.generate_request_exception = false - -# realm name (only if the installation file is not present) -Keycloak.realm = Rails.application.secrets.keycloak_realm - -# realm url (only if the installation file is not present) -Keycloak.auth_server_url = Rails.application.secrets.keycloak_auth_url - -# The introspect of the token will be executed every time the Keycloak::Client.has_role? method is invoked, if this setting is set to true. -Keycloak.validate_token_when_call_has_role = false diff --git a/config/secrets.yml b/config/secrets.yml index b8dcb24..130173d 100644 --- a/config/secrets.yml +++ b/config/secrets.yml @@ -10,17 +10,13 @@ shared: keycloak_client_id: <%= ENV["KEYCLOAK_CLIENT_ID"] %> keycloak_client_secret: <%= ENV["KEYCLOAK_CLIENT_SECRET"] %> keycloak_logout_url: <%= "#{ENV["KEYCLOAK_ENDPOINT"]}/auth/realms/#{ENV["KEYCLOAK_REALM"]}/protocol/openid-connect/logout?redirect_uri=" %> - keycloak_endpoint: <%= ENV["KEYCLOAK_ENDPOINT"] %> - keycloak_realm: <%= ENV["KEYCLOAK_REALM"] %> - keycloak_auth_url: <%= "#{ENV["KEYCLOAK_ENDPOINT"]}/auth" %> - keycloak_user_account_url: <%= "#{ENV["KEYCLOAK_ENDPOINT"]}/auth/realms/#{ENV["KEYCLOAK_REALM"]}/account/?referrer=#{ENV["KEYCLOAK_CLIENT_ID"]}" %> keycloak_client_options: site: <%= ENV["KEYCLOAK_ENDPOINT"] %> realm: <%= ENV["KEYCLOAK_REALM"] %> github_token: <%= ENV["GITHUB_COM_TOKEN"] %> mixpanel_project_token: <%= ENV["MIXPANEL_PROJECT_TOKEN"] %> protocol: <%= ENV['PROTOCOL'] || "http://" %> - s3_bucket_name: <%= ENV["S3_BUCKET_NAME"] %> + s3_bucket_name: <%= ENV["appS3BucketUUID"] %> secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> sendgrid_password: <%= ENV['SENDGRID_PASSWORD'] %> sendgrid_username: <%= ENV['SENDGRID_USERNAME'] %> @@ -30,11 +26,11 @@ shared: aws_sqlsnippets_password: <%= ENV["AWS_SQLSNIPPETS_PASSWORD"] %> aws_sqlsnippets_user: <%= ENV["AWS_SQLSNIPPETS_USER"] %> aws_sqlsnippets_host: <%= ENV["AWS_SQLSNIPPETS_HOST"] %> - glearn_access_key_id: <%= ENV['GLEARN_ACCESS_KEY_ID'] %> - glearn_secret_access_key: <%= ENV['GLEARN_SECRET_ACCESS_KEY'] %> + glearn_access_key_id: <%= ENV['accesskey'] %> + glearn_secret_access_key: <%= ENV['secretkey'] %> glearn_key_prefix: <%= ENV['GLEARN_KEY_PREFIX'] %> - glearn_bucket_name: <%= ENV['GLEARN_BUCKET_NAME'] %> - s3_region: <%= ENV['S3_REGION'] %> + glearn_bucket_name: <%= ENV["appS3BucketUUID"] %> + s3_region: <%= ENV["S3_REGION"] || "us-gov-west-1" %> dev_notify_slack_url: <%= ENV['DEV_NOTIFY_SLACK_URL'] %> git_download_tokens: github_com: diff --git a/db/migrate/20200925230149_remove_null_constraints_from_users.rb b/db/migrate/20200925230149_remove_null_constraints_from_users.rb new file mode 100644 index 0000000..e48424e --- /dev/null +++ b/db/migrate/20200925230149_remove_null_constraints_from_users.rb @@ -0,0 +1,8 @@ +class RemoveNullConstraintsFromUsers < ActiveRecord::Migration[5.2] + def change + change_column( :users, :uid, :string, :null => true) + change_column( :users, :first_name, :string, :null => true) + change_column( :users, :last_name, :string, :null => true) + change_column( :users, :email, :string, :null => false) + end +end diff --git a/db/schema.rb b/db/schema.rb index c8e582b..f5e6ecd 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2020_08_28_165130) do +ActiveRecord::Schema.define(version: 2020_09_25_230149) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -356,10 +356,10 @@ ActiveRecord::Schema.define(version: 2020_08_28_165130) do end create_table "users", force: :cascade do |t| - t.string "uid", null: false - t.string "first_name", null: false - t.string "last_name", null: false - t.string "email" + t.string "uid" + t.string "first_name" + t.string "last_name" + t.string "email", null: false t.string "timezone" t.string "profile_image" t.datetime "created_at", null: false -- GitLab From a3207b2fc264d00cea61fbfbdafdd8063df2ad57 Mon Sep 17 00:00:00 2001 From: Derrin Chong Date: Fri, 25 Sep 2020 13:58:12 -1000 Subject: [PATCH 076/283] Set permissions --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index ac31eef..610417a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -34,6 +34,7 @@ WORKDIR /usr/src/app ENV RAILS_ENV production # Stuff that changes +RUN chmod 755 /usr/src/app ADD . . # Run Yarn Install -- GitLab From 3785861bf3d362aadc53c07822bd30de86140cd9 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 25 Sep 2020 14:01:43 -1000 Subject: [PATCH 077/283] removing keycloak exception --- Gemfile.lock | 23 ------------------- .../api/v1/cohorts/users_controller.rb | 2 -- 2 files changed, 25 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index f922ed5..dd969a2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -118,8 +118,6 @@ GEM debug_inspector (0.0.3) deterministic (0.6.0) diff-lcs (1.3) - domain_name (0.5.20190701) - unf (>= 0.0.5, < 1.0.0) dotenv (2.5.0) dotenv-rails (2.5.0) dotenv (= 2.5.0) @@ -180,9 +178,6 @@ GEM hashdiff (0.4.0) hashie (4.1.0) honeybadger (3.2.0) - http-accept (1.7.0) - http-cookie (1.0.3) - domain_name (~> 0.5) httparty (0.15.6) multi_xml (>= 0.5.2) i18n (1.6.0) @@ -197,7 +192,6 @@ GEM js-routes (1.4.2) railties (>= 3.2) sprockets-rails - json (2.3.1) json-jwt (1.13.0) activesupport (>= 4.2) aes_key_wrap @@ -206,10 +200,6 @@ GEM multi_json (~> 1.0) rspec (>= 2.0, < 4.0) jwt (2.2.2) - keycloak (3.0.0) - json - jwt - rest-client kramdown (2.1.0) launchy (2.4.3) addressable (~> 2.3) @@ -226,9 +216,6 @@ GEM railties (>= 3.0) memory_profiler (0.9.12) method_source (0.9.0) - mime-types (3.3.1) - mime-types-data (~> 3.2015) - mime-types-data (3.2020.0512) mimemagic (0.3.2) mini_mime (1.0.0) mini_portile2 (2.2.0) @@ -238,7 +225,6 @@ GEM multi_xml (0.6.0) multipart-post (2.0.0) mustache (1.1.0) - netrc (0.11.0) nio4r (2.3.1) nokogiri (1.8.0) mini_portile2 (~> 2.2.0) @@ -325,11 +311,6 @@ GEM tilt redcarpet (3.3.4) redis (3.3.5) - rest-client (2.1.0) - http-accept (>= 1.7.0, < 2.0) - http-cookie (>= 1.0.2, < 2.0) - mime-types (>= 1.16, < 4.0) - netrc (~> 0.8) rspec (3.7.0) rspec-core (~> 3.7.0) rspec-expectations (~> 3.7.0) @@ -417,9 +398,6 @@ GEM uglifier (4.0.2) execjs (>= 0.3.0, < 3) underscore-rails (1.8.3) - unf (0.1.4) - unf_ext - unf_ext (0.0.7.7) unicode-display_width (1.6.0) vcr (4.0.0) webmock (3.6.0) @@ -469,7 +447,6 @@ DEPENDENCIES jquery-rails js-routes json_spec - keycloak letter_opener mathjax-rails memory_profiler diff --git a/app/controllers/api/v1/cohorts/users_controller.rb b/app/controllers/api/v1/cohorts/users_controller.rb index 7d86cb9..ad3efca 100644 --- a/app/controllers/api/v1/cohorts/users_controller.rb +++ b/app/controllers/api/v1/cohorts/users_controller.rb @@ -26,8 +26,6 @@ class Api::V1::Cohorts::UsersController < Api::ApplicationController json_response({ error: "User is already in the cohort." }, 400) and return end - rescue Keycloak::UserLoginNotFound => e - json_response({ error: "User does not exist in KeyCloak." }, 400) and return rescue StandardError => e json_response({ error: e.message }, 400) and return end -- GitLab From 0feb559884356725823fd99d3708aaa9b93e45c3 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 25 Sep 2020 15:03:59 -1000 Subject: [PATCH 078/283] fixing bug in image encoding --- app/services/encoded_image_link_service.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/services/encoded_image_link_service.rb b/app/services/encoded_image_link_service.rb index 523d3af..123d57e 100644 --- a/app/services/encoded_image_link_service.rb +++ b/app/services/encoded_image_link_service.rb @@ -7,8 +7,9 @@ class EncodedImageLinkService def find_or_create_content(full_path:, directory: nil) begin encoded_string = Base64.encode64(File.open(full_path).read) - image_mime_type = MIME::Types.type_for(full_path).first.content_type - return "data:#{image_mime_type};base64, #{encoded_string}" + image_mime_type = Rack::Mime.mime_type(File.extname(full_path)) + + "data:#{image_mime_type};base64, #{encoded_string}" rescue StandardError => e raise(Error, e) end -- GitLab From 8f7dcc31049810b5d1feee692693321d12ffb1a1 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Fri, 25 Sep 2020 15:24:40 -1000 Subject: [PATCH 079/283] Add default for GLEARN_PREFIX --- config/secrets.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/secrets.yml b/config/secrets.yml index 130173d..c07c473 100644 --- a/config/secrets.yml +++ b/config/secrets.yml @@ -28,7 +28,7 @@ shared: aws_sqlsnippets_host: <%= ENV["AWS_SQLSNIPPETS_HOST"] %> glearn_access_key_id: <%= ENV['accesskey'] %> glearn_secret_access_key: <%= ENV['secretkey'] %> - glearn_key_prefix: <%= ENV['GLEARN_KEY_PREFIX'] %> + glearn_key_prefix: <%= ENV['GLEARN_KEY_PREFIX'] || "forge" %> glearn_bucket_name: <%= ENV["appS3BucketUUID"] %> s3_region: <%= ENV["S3_REGION"] || "us-gov-west-1" %> dev_notify_slack_url: <%= ENV['DEV_NOTIFY_SLACK_URL'] %> -- GitLab From 0901f122066451dad2fe60de6cda01e7c418a300 Mon Sep 17 00:00:00 2001 From: Derrin Chong Date: Fri, 25 Sep 2020 15:51:09 -1000 Subject: [PATCH 080/283] Another try at fixing permissions --- Dockerfile | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index 610417a..33a9396 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,26 +24,31 @@ RUN bash n auto RUN npm install -g yarn # Set the user -RUN groupadd -r ruby -RUN useradd --no-log-init -r -g ruby ruby -# USER ruby -RUN whoami +RUN set -ex && \ + groupadd --gid 950 ruby && \ + useradd --uid 950 --gid ruby --shell /bin/bash --create-home ruby +RUN ls -l /home # Setup our environment WORKDIR /usr/src/app ENV RAILS_ENV production # Stuff that changes +RUN chown -R ruby:ruby /usr/src/app RUN chmod 755 /usr/src/app +RUN ls -ld /usr/src/app ADD . . -# Run Yarn Install -RUN yarn install +USER ruby +RUN whoami # Install Rails Dependecies. RUN gem install bundler:1.17.3 RUN gem install rake -v '12.3.1' --source 'https://rubygems.org/' +# Run Yarn Install +RUN yarn install + # Run the bundle install RUN bundle install @@ -54,4 +59,5 @@ RUN NODE_ENV=production bin/webpack ENV PATH /usr/src/app/node_modules/.bin:$PATH # Set the entry point. +#CMD ["tail", "-f", "/dev/null"] CMD ["./entrypoint-server.sh"] -- GitLab From 2e88ce19073f3156d5360245f0ea41e72b0d3f6c Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 25 Sep 2020 16:43:58 -1000 Subject: [PATCH 081/283] turning off ssl for production build. commenting out user setup on docker file. --- Dockerfile | 27 +++++++++++++++------------ config/environments/production.rb | 2 +- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/Dockerfile b/Dockerfile index 33a9396..4fa228d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,34 +24,37 @@ RUN bash n auto RUN npm install -g yarn # Set the user -RUN set -ex && \ - groupadd --gid 950 ruby && \ - useradd --uid 950 --gid ruby --shell /bin/bash --create-home ruby -RUN ls -l /home +#RUN set -ex && \ +# groupadd --gid 950 ruby && \ +# useradd --uid 950 --gid ruby --shell /bin/bash --create-home ruby +#RUN ls -l /home # Setup our environment WORKDIR /usr/src/app ENV RAILS_ENV production # Stuff that changes -RUN chown -R ruby:ruby /usr/src/app -RUN chmod 755 /usr/src/app -RUN ls -ld /usr/src/app +#RUN chown -R ruby:ruby /usr/src/app +#RUN chmod 755 /usr/src/app +#RUN chown -R ruby:ruby /opt/bitnami/ruby +#RUN chmod 755 /opt/bitnami/ruby + +# Copy the files. ADD . . -USER ruby -RUN whoami +# Switch to ruby. +#USER ruby # Install Rails Dependecies. RUN gem install bundler:1.17.3 RUN gem install rake -v '12.3.1' --source 'https://rubygems.org/' -# Run Yarn Install -RUN yarn install - # Run the bundle install RUN bundle install +# Run Yarn Install +RUN yarn install + # Run Webpack build. RUN NODE_ENV=production bin/webpack diff --git a/config/environments/production.rb b/config/environments/production.rb index a268b7b..41f4ff0 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -46,7 +46,7 @@ Rails.application.configure do # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. - config.force_ssl = true + config.force_ssl = false # Use the lowest log level to ensure availability of diagnostic information # when problems arise. -- GitLab From c413117a04393904278d106885705d7db3d97142 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 25 Sep 2020 18:16:20 -1000 Subject: [PATCH 082/283] adding jwt gem and new resolver service to part the jwt and create/update users --- Gemfile | 1 + Gemfile.lock | 1 + .../platform_one_auth_resolver_service.rb | 27 +++++++++++++++++++ 3 files changed, 29 insertions(+) create mode 100644 app/services/platform_one_auth_resolver_service.rb diff --git a/Gemfile b/Gemfile index f109552..88eca97 100644 --- a/Gemfile +++ b/Gemfile @@ -41,6 +41,7 @@ gem "browser" gem "apitome" # services +gem 'jwt' gem "omniauth" gem "omniauth-keycloak" gem "honeybadger", "~> 3.1" diff --git a/Gemfile.lock b/Gemfile.lock index dd969a2..36dfc5d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -447,6 +447,7 @@ DEPENDENCIES jquery-rails js-routes json_spec + jwt letter_opener mathjax-rails memory_profiler diff --git a/app/services/platform_one_auth_resolver_service.rb b/app/services/platform_one_auth_resolver_service.rb new file mode 100644 index 0000000..22d0f00 --- /dev/null +++ b/app/services/platform_one_auth_resolver_service.rb @@ -0,0 +1,27 @@ +class PlatformOneAuthResolverService + def initialize(jwt_token) + @payload = JWT.decode(jwt_token, nil, false)[0] + end + + def find_or_create_user + existing_user = User.find_by(email: @payload.email) + + if existing_user + existing_user.update(uid: @payload["sub"], + first_name: @payload["given_name"], + last_name: @payload["family_name"] + ) + + existing_user + else + user = User.create(uid: @payload["sub"], + first_name: @payload["given_name"], + last_name: @payload["family_name"], + email: @payload["email"], + roles: [] + ) + + user + end + end +end -- GitLab From 5fd1269e08f0cfc0fed80ae1de78628e298c5b3c Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 25 Sep 2020 18:17:00 -1000 Subject: [PATCH 083/283] fixing bug --- app/services/platform_one_auth_resolver_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/platform_one_auth_resolver_service.rb b/app/services/platform_one_auth_resolver_service.rb index 22d0f00..05f913e 100644 --- a/app/services/platform_one_auth_resolver_service.rb +++ b/app/services/platform_one_auth_resolver_service.rb @@ -4,7 +4,7 @@ class PlatformOneAuthResolverService end def find_or_create_user - existing_user = User.find_by(email: @payload.email) + existing_user = User.find_by(email: @payload["email"]) if existing_user existing_user.update(uid: @payload["sub"], -- GitLab From e903cb8b8b97bbd08a4910bef1d5bf161268019c Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 25 Sep 2020 18:56:36 -1000 Subject: [PATCH 084/283] attempt at removing keycloak code and replacing with P1 jwt auth --- Gemfile | 2 -- app/controllers/sessions_controller.rb | 26 ++++++++++++++------------ config/initializers/omniauth.rb | 6 ------ config/routes.rb | 1 - 4 files changed, 14 insertions(+), 21 deletions(-) delete mode 100644 config/initializers/omniauth.rb diff --git a/Gemfile b/Gemfile index 88eca97..7ad8728 100644 --- a/Gemfile +++ b/Gemfile @@ -42,8 +42,6 @@ gem "apitome" # services gem 'jwt' -gem "omniauth" -gem "omniauth-keycloak" gem "honeybadger", "~> 3.1" gem "github_url", "0.2.1" gem "gitlab" diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 3bd600b..852edbc 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -1,24 +1,20 @@ class SessionsController < ActionController::Base + def new + if !current_user + @user = PlatformOneAuthResolverService.new(token).find_or_create_user + session[:user_uid] = @user.uid + end - def create - @user = KeycloakResolverService.new(auth_hash).find_or_create_user - session[:user_uid] = @user.uid redirect_to '/' end - def new - # Redirect back to root if signed in, otherwise kick off the defined omniauth strategy. - session[:after_auth_params] = params - redirect_to current_user ? '/' : '/auth/keycloakopenid' - end - def failure? redirect_to '/' end def destroy session[:user_uid] = nil - redirect_to "#{Rails.application.secrets.keycloak_logout_url}#{root_url}" + redirect_to '/' end protected @@ -27,7 +23,13 @@ class SessionsController < ActionController::Base @current_user ||= User.find_by(uid: session[:user_uid]) unless session[:user_uid].nil? end - def auth_hash - request.env['omniauth.auth'] + def token + if !request.env["Authorization"].nil? + pattern = /^Bearer / + header = request.env["Authorization"] + header.gsub(pattern, '') if header&.match(pattern) + elsif !request.query_parameters["token"].nil? + request.query_parameters["token"] + end end end diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb deleted file mode 100644 index 7cb4457..0000000 --- a/config/initializers/omniauth.rb +++ /dev/null @@ -1,6 +0,0 @@ -OmniAuth.config.allowed_request_methods = [:post, :get] - -Rails.application.config.middleware.use OmniAuth::Builder do - provider :keycloak_openid, Rails.application.secrets.keycloak_client_id, Rails.application.secrets.keycloak_client_secret, - client_options: Rails.application.secrets.keycloak_client_options -end diff --git a/config/routes.rb b/config/routes.rb index 60296a1..bf3c21c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -9,7 +9,6 @@ Rails.application.routes.draw do get "api_token", to: "application#api_token", as: "api_token" get "api_interactions", to: "application#api_interactions", as: "api_interactions" - get '/auth/:provider/callback', to: 'sessions#create' get '/sign_in', to: 'sessions#new' get '/sign_out', to: 'sessions#destroy', as: "sign_out" -- GitLab From 0a3a748e8711d4d2ceb3d57d9fc5b6f19ec8b670 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 25 Sep 2020 23:33:42 -1000 Subject: [PATCH 085/283] commenting out seed data --- db/seeds.rb | 216 ++++++++++++++++++++++++++-------------------------- 1 file changed, 108 insertions(+), 108 deletions(-) diff --git a/db/seeds.rb b/db/seeds.rb index a2cf07d..ab31218 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -6,114 +6,114 @@ # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) # Character.create(name: 'Luke', movie: movies.first) # -["learn-example-block", "learn-test", "blocks-test", "blocks-test-copy"].each do |repo| - block = Block.find_or_create_by(title: repo, repo_name: repo) - release = Release.create(notes: "Block Used for Learn V2 testing", block_id: block.id, github_sha: "pending") - CreateReleaseJob.perform_now(pending_release_id: release.id) -end +# ["learn-example-block", "learn-test", "blocks-test", "blocks-test-copy"].each do |repo| +# block = Block.find_or_create_by(title: repo, repo_name: repo) +# release = Release.create(notes: "Block Used for Learn V2 testing", block_id: block.id, github_sha: "pending") +# CreateReleaseJob.perform_now(pending_release_id: release.id) +# end Block.find_or_create_by(title: "preview", repo_name: "preview") -# these values are specific to galvanize-auth-staging values -cohort = Cohort.create(uid: "9871fef341f9ef250b", - name: "Story Testing", - product_type: "Other", - starts_on: Time.new("2018-02-02").utc, - mode: "Percentage", - allow_paired_submissions: true -) - -instructor_user = User.create(uid: "003V000000bNlMaIAK", - first_name: "Erin", - last_name: "Hough", - email: "erin.hough@galvanize.com", - timezone: "America/Denver", - roles: "{auth.admin, - auth.product_admin, - forge.admin, - forge.blocks_manager}", - last_viewed_cohort_id: cohort.id) - -student_user = User.create(uid: "003n000000SnC61AAF", - first_name: "Chauncey", - last_name: "Huffelfeffer", - email: "dev+learnstudent@galvanize.com", - timezone: "America/Denver", - roles: "{}", - last_viewed_cohort_id: cohort.id) - -CohortUser.create(cohort: cohort, user: instructor_user, roles: "{forge.instructor}") -CohortUser.create(cohort: cohort, user: student_user, roles: "{}") - -erin_student_user = User.create(uid: "003V000000cVzsKIAS", - first_name: "Erin", - last_name: "student", - email: "erin.hough+student@galvanize.com", - timezone: "America/Denver", - roles: "{}", - last_viewed_cohort_id: cohort.id) - -CohortUser.create(cohort: cohort, user: erin_student_user, roles: "{}") - - steve_student_user = User.create(uid: "003V000000ZlEYdIAN", - first_name: "Steve", - last_name: "Student", - email: "steve.perella+student@galvanize.com", - timezone: "America/Denver", - roles: "{}", - last_viewed_cohort_id: cohort.id) - -CohortUser.create(cohort: cohort, user: steve_student_user, roles: "{}") - -dev_auth_user = User.create( - uid: "003V000000VLPZCIA5 ", - first_name: "Dev", - last_name: "Auth", - email: "dev+auth@galvanize.com", - timezone: "America/Denver", - roles: "{auth.app_admin,auth.admin,auth.product_admin,members.admin,talent.admin,forge.admin,forge.blocks_manager}", - last_viewed_cohort_id: cohort.id -) - -sebp = Cohort.create( - uid: "01t0a000004hRLqAAM", - name: "Software Engineering Basic Prep", - product_type: "WDI", - starts_on: Time.new("2018-02-02").utc, - mode: "Mastery" -) - -dsip = Cohort.create( - uid: "01tj0000003h8lMAAQ", - name: "Data Science Immersive Prep", - product_type: "DSI", - starts_on: Time.new("2018-02-02").utc, - mode: "Mastery" -) - -CohortUser.create(cohort: sebp, user: dev_auth_user) -CohortUser.create(cohort: dsip, user: dev_auth_user) -CohortUser.create(cohort: sebp, user: instructor_user) -CohortUser.create(cohort: dsip, user: instructor_user) - -# sync initial cohort curriculum -course_url = "https://github.com/gSchool/learn-course-files/blob/master/test/learn-test.yaml" -result = ResyncJobResult.start(cohort.id, course_url) -CourseValidator.run(url: course_url).and_then do |results| - ResyncCourseService.run(cohort_id: cohort.id, - course_url: course_url, - sections: results[:course][:sections], - default_unit_visibility: results[:course][:default_unit_visibility]) -end.match do - success do - result.update(status: "success") - end - - failure do |error| - result.update(status: "failure", data: { - error_type: error.type, - course_config_url: course_url, - error_data: error.as_json["table"].without("type") - }) - end -end +# # these values are specific to galvanize-auth-staging values +# cohort = Cohort.create(uid: "9871fef341f9ef250b", +# name: "Story Testing", +# product_type: "Other", +# starts_on: Time.new("2018-02-02").utc, +# mode: "Percentage", +# allow_paired_submissions: true +# ) +# +# instructor_user = User.create(uid: "003V000000bNlMaIAK", +# first_name: "Erin", +# last_name: "Hough", +# email: "erin.hough@galvanize.com", +# timezone: "America/Denver", +# roles: "{auth.admin, +# auth.product_admin, +# forge.admin, +# forge.blocks_manager}", +# last_viewed_cohort_id: cohort.id) +# +# student_user = User.create(uid: "003n000000SnC61AAF", +# first_name: "Chauncey", +# last_name: "Huffelfeffer", +# email: "dev+learnstudent@galvanize.com", +# timezone: "America/Denver", +# roles: "{}", +# last_viewed_cohort_id: cohort.id) +# +# CohortUser.create(cohort: cohort, user: instructor_user, roles: "{forge.instructor}") +# CohortUser.create(cohort: cohort, user: student_user, roles: "{}") +# +# erin_student_user = User.create(uid: "003V000000cVzsKIAS", +# first_name: "Erin", +# last_name: "student", +# email: "erin.hough+student@galvanize.com", +# timezone: "America/Denver", +# roles: "{}", +# last_viewed_cohort_id: cohort.id) +# +# CohortUser.create(cohort: cohort, user: erin_student_user, roles: "{}") +# +# steve_student_user = User.create(uid: "003V000000ZlEYdIAN", +# first_name: "Steve", +# last_name: "Student", +# email: "steve.perella+student@galvanize.com", +# timezone: "America/Denver", +# roles: "{}", +# last_viewed_cohort_id: cohort.id) +# +# CohortUser.create(cohort: cohort, user: steve_student_user, roles: "{}") +# +# dev_auth_user = User.create( +# uid: "003V000000VLPZCIA5 ", +# first_name: "Dev", +# last_name: "Auth", +# email: "dev+auth@galvanize.com", +# timezone: "America/Denver", +# roles: "{auth.app_admin,auth.admin,auth.product_admin,members.admin,talent.admin,forge.admin,forge.blocks_manager}", +# last_viewed_cohort_id: cohort.id +# ) +# +# sebp = Cohort.create( +# uid: "01t0a000004hRLqAAM", +# name: "Software Engineering Basic Prep", +# product_type: "WDI", +# starts_on: Time.new("2018-02-02").utc, +# mode: "Mastery" +# ) +# +# dsip = Cohort.create( +# uid: "01tj0000003h8lMAAQ", +# name: "Data Science Immersive Prep", +# product_type: "DSI", +# starts_on: Time.new("2018-02-02").utc, +# mode: "Mastery" +# ) +# +# CohortUser.create(cohort: sebp, user: dev_auth_user) +# CohortUser.create(cohort: dsip, user: dev_auth_user) +# CohortUser.create(cohort: sebp, user: instructor_user) +# CohortUser.create(cohort: dsip, user: instructor_user) +# +# # sync initial cohort curriculum +# course_url = "https://github.com/gSchool/learn-course-files/blob/master/test/learn-test.yaml" +# result = ResyncJobResult.start(cohort.id, course_url) +# CourseValidator.run(url: course_url).and_then do |results| +# ResyncCourseService.run(cohort_id: cohort.id, +# course_url: course_url, +# sections: results[:course][:sections], +# default_unit_visibility: results[:course][:default_unit_visibility]) +# end.match do +# success do +# result.update(status: "success") +# end +# +# failure do |error| +# result.update(status: "failure", data: { +# error_type: error.type, +# course_config_url: course_url, +# error_data: error.as_json["table"].without("type") +# }) +# end +# end -- GitLab From 4f8f3f23ca7391742881039e2d01c56b7a6b89e6 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Sat, 26 Sep 2020 17:32:27 -1000 Subject: [PATCH 086/283] Test changes --- .gitignore | 3 +- Gemfile | 4 +- Gemfile.lock | 516 ------------------ spec/models/user_spec.rb | 43 +- .../keycloak_resolver_service_spec.rb | 9 +- spec/spec_helper.rb | 3 + 6 files changed, 52 insertions(+), 526 deletions(-) delete mode 100644 Gemfile.lock diff --git a/.gitignore b/.gitignore index cbbbfd1..70a3437 100644 --- a/.gitignore +++ b/.gitignore @@ -32,4 +32,5 @@ tags .zshrc .solargraph.yml .generators -.rakeTasks \ No newline at end of file +.rakeTasks +/coverage diff --git a/Gemfile b/Gemfile index fe3d036..2a33252 100644 --- a/Gemfile +++ b/Gemfile @@ -55,7 +55,8 @@ gem "solid_use_case", "~> 2.2.0" gem "dry-validation", "~> 0.12.2" # file processing -gem "block_parser", :git => "https://code.il2.dsop.io/tron/products/learn-lms/ruby-gems/block-parser.git" +#gem "block_parser", :git => "https://code.il2.dsop.io/tron/products/learn-lms/ruby-gems/block-parser.git" +gem "block_parser", path: "/Users/csakamaki/Projects/LEARN/RubyGems/block-parser" # Reduces boot times through caching; required in config/boot.rb gem "bootsnap", ">= 1.1.0" @@ -93,4 +94,5 @@ group :test do gem "webmock" gem "rails-controller-testing" gem "rspec_api_documentation" + gem 'simplecov', require: false, group: :test end diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index f922ed5..0000000 --- a/Gemfile.lock +++ /dev/null @@ -1,516 +0,0 @@ -GIT - remote: https://code.il2.dsop.io/tron/products/learn-lms/ruby-gems/block-parser.git - revision: bdf3acdb4145805d306fc022f4abc2803a6bacb7 - specs: - block_parser (0.1.0) - activemodel (> 4.2) - github-markdown (= 0.6.9) - github-markup (= 1.6.1) - github_url (= 0.2.1) - gitlab (= 4.14.1) - nokogiri (= 1.8.0) - octokit (= 4.3.0) - psych (= 2.2.4) - redcarpet (= 3.3.4) - rspec_junit_formatter (> 0.2.3) - -GEM - remote: https://rubygems.org/ - specs: - actioncable (5.2.1) - actionpack (= 5.2.1) - nio4r (~> 2.0) - websocket-driver (>= 0.6.1) - actionmailer (5.2.1) - actionpack (= 5.2.1) - actionview (= 5.2.1) - activejob (= 5.2.1) - mail (~> 2.5, >= 2.5.4) - rails-dom-testing (~> 2.0) - actionpack (5.2.1) - actionview (= 5.2.1) - activesupport (= 5.2.1) - rack (~> 2.0) - rack-test (>= 0.6.3) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.2.1) - activesupport (= 5.2.1) - builder (~> 3.1) - erubi (~> 1.4) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (5.2.1) - activesupport (= 5.2.1) - globalid (>= 0.3.6) - activemodel (5.2.1) - activesupport (= 5.2.1) - activerecord (5.2.1) - activemodel (= 5.2.1) - activesupport (= 5.2.1) - arel (>= 9.0) - activestorage (5.2.1) - actionpack (= 5.2.1) - activerecord (= 5.2.1) - marcel (~> 0.3.1) - activesupport (5.2.1) - concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - addressable (2.4.0) - aes_key_wrap (1.1.0) - analytics-ruby (2.0.13) - apitome (0.3.0) - kramdown - railties - arel (9.0.0) - ast (2.4.0) - autoprefixer-rails (7.2.5) - execjs - aws-sdk (2.6.50) - aws-sdk-resources (= 2.6.50) - aws-sdk-core (2.6.50) - aws-sigv4 (~> 1.0) - jmespath (~> 1.0) - aws-sdk-resources (2.6.50) - aws-sdk-core (= 2.6.50) - aws-sigv4 (1.0.2) - babel-source (5.8.35) - babel-transpiler (0.7.0) - babel-source (>= 4.0, < 6) - execjs (~> 2.0) - barnes (0.0.7) - multi_json (~> 1) - statsd-ruby (~> 1.1) - better_errors (2.5.0) - coderay (>= 1.0.0) - erubi (>= 1.0.0) - rack (>= 0.9.0) - bindata (2.4.8) - binding_of_caller (0.8.0) - debug_inspector (>= 0.0.1) - bootsnap (1.3.1) - msgpack (~> 1.0) - bootstrap (4.0.0) - autoprefixer-rails (>= 6.0.3) - popper_js (>= 1.12.9, < 2) - sass (>= 3.5.2) - browser (2.5.2) - builder (3.2.3) - byebug (9.1.0) - capybara (2.16.1) - addressable - mini_mime (>= 0.1.3) - nokogiri (>= 1.3.3) - rack (>= 1.0.0) - rack-test (>= 0.5.4) - xpath (~> 2.0) - childprocess (0.8.0) - ffi (~> 1.0, >= 1.0.11) - coderay (1.1.2) - concurrent-ruby (1.1.5) - connection_pool (2.2.1) - crack (0.4.3) - safe_yaml (~> 1.0.0) - crass (1.0.4) - database_cleaner (1.6.2) - debug_inspector (0.0.3) - deterministic (0.6.0) - diff-lcs (1.3) - domain_name (0.5.20190701) - unf (>= 0.0.5, < 1.0.0) - dotenv (2.5.0) - dotenv-rails (2.5.0) - dotenv (= 2.5.0) - railties (>= 3.2, < 6.0) - dry-configurable (0.7.0) - concurrent-ruby (~> 1.0) - dry-container (0.6.0) - concurrent-ruby (~> 1.0) - dry-configurable (~> 0.1, >= 0.1.3) - dry-core (0.4.7) - concurrent-ruby (~> 1.0) - dry-equalizer (0.2.1) - dry-inflector (0.1.2) - dry-logic (0.4.2) - dry-container (~> 0.2, >= 0.2.6) - dry-core (~> 0.2) - dry-equalizer (~> 0.2) - dry-types (0.13.2) - concurrent-ruby (~> 1.0) - dry-container (~> 0.3) - dry-core (~> 0.4, >= 0.4.4) - dry-equalizer (~> 0.2) - dry-inflector (~> 0.1, >= 0.1.2) - dry-logic (~> 0.4, >= 0.4.2) - dry-validation (0.12.2) - concurrent-ruby (~> 1.0) - dry-configurable (~> 0.1, >= 0.1.3) - dry-core (~> 0.2, >= 0.2.1) - dry-equalizer (~> 0.2) - dry-logic (~> 0.4, >= 0.4.0) - dry-types (~> 0.13.1) - erubi (1.7.1) - execjs (2.7.0) - factory_bot (4.8.2) - activesupport (>= 3.0.0) - factory_bot_rails (4.8.2) - factory_bot (~> 4.8.2) - railties (>= 3.0.0) - faraday (0.9.2) - multipart-post (>= 1.2, < 3) - ffi (1.9.18) - flamegraph (0.9.5) - font-awesome-rails (4.7.0.4) - railties (>= 3.2, < 6.0) - foreman (0.84.0) - thor (~> 0.19.1) - github-markdown (0.6.9) - github-markup (1.6.1) - github_url (0.2.1) - gitlab (4.14.1) - httparty (~> 0.14, >= 0.14.0) - terminal-table (~> 1.5, >= 1.5.1) - globalid (0.4.1) - activesupport (>= 4.2.0) - haml (5.0.4) - temple (>= 0.8.0) - tilt - hashdiff (0.4.0) - hashie (4.1.0) - honeybadger (3.2.0) - http-accept (1.7.0) - http-cookie (1.0.3) - domain_name (~> 0.5) - httparty (0.15.6) - multi_xml (>= 0.5.2) - i18n (1.6.0) - concurrent-ruby (~> 1.0) - iniparse (1.4.4) - jaro_winkler (1.5.3) - jmespath (1.3.1) - jquery-rails (4.3.1) - rails-dom-testing (>= 1, < 3) - railties (>= 4.2.0) - thor (>= 0.14, < 2.0) - js-routes (1.4.2) - railties (>= 3.2) - sprockets-rails - json (2.3.1) - json-jwt (1.13.0) - activesupport (>= 4.2) - aes_key_wrap - bindata - json_spec (1.1.5) - multi_json (~> 1.0) - rspec (>= 2.0, < 4.0) - jwt (2.2.2) - keycloak (3.0.0) - json - jwt - rest-client - kramdown (2.1.0) - launchy (2.4.3) - addressable (~> 2.3) - letter_opener (1.7.0) - launchy (~> 2.2) - loofah (2.2.2) - crass (~> 1.0.2) - nokogiri (>= 1.5.9) - mail (2.7.0) - mini_mime (>= 0.1.1) - marcel (0.3.2) - mimemagic (~> 0.3.2) - mathjax-rails (2.6.1) - railties (>= 3.0) - memory_profiler (0.9.12) - method_source (0.9.0) - mime-types (3.3.1) - mime-types-data (~> 3.2015) - mime-types-data (3.2020.0512) - mimemagic (0.3.2) - mini_mime (1.0.0) - mini_portile2 (2.2.0) - minitest (5.11.3) - msgpack (1.2.4) - multi_json (1.13.1) - multi_xml (0.6.0) - multipart-post (2.0.0) - mustache (1.1.0) - netrc (0.11.0) - nio4r (2.3.1) - nokogiri (1.8.0) - mini_portile2 (~> 2.2.0) - oauth2 (1.4.4) - faraday (>= 0.8, < 2.0) - jwt (>= 1.0, < 3.0) - multi_json (~> 1.3) - multi_xml (~> 0.5) - rack (>= 1.2, < 3) - octokit (4.3.0) - sawyer (~> 0.7.0, >= 0.5.3) - omniauth (1.9.1) - hashie (>= 3.4.6) - rack (>= 1.6.2, < 3) - omniauth-keycloak (1.2.0) - json-jwt (~> 1.12) - omniauth (~> 1.9.0) - omniauth-oauth2 (~> 1.6.0) - omniauth-oauth2 (1.6.0) - oauth2 (~> 1.1) - omniauth (~> 1.9) - overcommit (0.41.0) - childprocess (~> 0.6, >= 0.6.3) - iniparse (~> 1.4) - pagy (3.7.1) - parallel (1.17.0) - parser (2.6.3.0) - ast (~> 2.4.0) - pg (0.21.0) - popper_js (1.12.9) - psych (2.2.4) - puma (3.12.1) - pundit (1.1.0) - activesupport (>= 3.0.0) - rack (2.0.3) - rack-attack (6.2.1) - rack (>= 1.0, < 3) - rack-mini-profiler (1.0.0) - rack (>= 1.2.0) - rack-protection (2.0.0) - rack - rack-proxy (0.6.4) - rack - rack-test (0.8.2) - rack (>= 1.0, < 3) - rails (5.2.1) - actioncable (= 5.2.1) - actionmailer (= 5.2.1) - actionpack (= 5.2.1) - actionview (= 5.2.1) - activejob (= 5.2.1) - activemodel (= 5.2.1) - activerecord (= 5.2.1) - activestorage (= 5.2.1) - activesupport (= 5.2.1) - bundler (>= 1.3.0) - railties (= 5.2.1) - sprockets-rails (>= 2.0.0) - rails-controller-testing (1.0.2) - actionpack (~> 5.x, >= 5.0.1) - actionview (~> 5.x, >= 5.0.1) - activesupport (~> 5.x) - rails-dom-testing (2.0.3) - activesupport (>= 4.2.0) - nokogiri (>= 1.6) - rails-html-sanitizer (1.0.4) - loofah (~> 2.2, >= 2.2.2) - railties (5.2.1) - actionpack (= 5.2.1) - activesupport (= 5.2.1) - method_source - rake (>= 0.8.7) - thor (>= 0.19.0, < 2.0) - rainbow (3.0.0) - rake (12.3.1) - rb-fsevent (0.10.2) - rb-inotify (0.9.10) - ffi (>= 0.5.0, < 2) - react-rails (2.4.5) - babel-transpiler (>= 0.7.0) - connection_pool - execjs - railties (>= 3.2) - tilt - redcarpet (3.3.4) - redis (3.3.5) - rest-client (2.1.0) - http-accept (>= 1.7.0, < 2.0) - http-cookie (>= 1.0.2, < 2.0) - mime-types (>= 1.16, < 4.0) - netrc (~> 0.8) - rspec (3.7.0) - rspec-core (~> 3.7.0) - rspec-expectations (~> 3.7.0) - rspec-mocks (~> 3.7.0) - rspec-core (3.7.0) - rspec-support (~> 3.7.0) - rspec-expectations (3.7.0) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.7.0) - rspec-mocks (3.7.0) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.7.0) - rspec-rails (3.7.2) - actionpack (>= 3.0) - activesupport (>= 3.0) - railties (>= 3.0) - rspec-core (~> 3.7.0) - rspec-expectations (~> 3.7.0) - rspec-mocks (~> 3.7.0) - rspec-support (~> 3.7.0) - rspec-support (3.7.0) - rspec_api_documentation (6.1.0) - activesupport (>= 3.0.0) - mustache (~> 1.0, >= 0.99.4) - rspec (~> 3.0) - rspec_junit_formatter (0.3.0) - rspec-core (>= 2, < 4, != 2.12.0) - rubocop (0.72.0) - jaro_winkler (~> 1.5.1) - parallel (~> 1.10) - parser (>= 2.6) - rainbow (>= 2.2.2, < 4.0) - ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 1.7) - ruby-progressbar (1.10.1) - rubyzip (1.2.1) - safe_yaml (1.0.5) - sass (3.5.3) - sass-listen (~> 4.0.0) - sass-listen (4.0.0) - rb-fsevent (~> 0.9, >= 0.9.4) - rb-inotify (~> 0.9, >= 0.9.7) - sass-rails (5.0.7) - railties (>= 4.0.0, < 6) - sass (~> 3.1) - sprockets (>= 2.8, < 4.0) - sprockets-rails (>= 2.0, < 4.0) - tilt (>= 1.1, < 3) - sawyer (0.7.0) - addressable (>= 2.3.5, < 2.5) - faraday (~> 0.8, < 0.10) - scout_apm (2.4.19) - selenium-webdriver (3.8.0) - childprocess (~> 0.5) - rubyzip (~> 1.0) - shoulda-matchers (3.1.2) - activesupport (>= 4.0.0) - sidekiq (5.0.5) - concurrent-ruby (~> 1.0) - connection_pool (~> 2.2, >= 2.2.0) - rack-protection (>= 1.5.0) - redis (>= 3.3.4, < 5) - solid_use_case (2.2.0) - deterministic (~> 0.6.0) - sprockets (3.7.1) - concurrent-ruby (~> 1.0) - rack (> 1, < 3) - sprockets-rails (3.2.1) - actionpack (>= 4.0) - activesupport (>= 4.0) - sprockets (>= 3.0.0) - stackprof (0.2.12) - statsd-ruby (1.4.0) - temple (0.8.0) - terminal-table (1.8.0) - unicode-display_width (~> 1.1, >= 1.1.1) - thor (0.19.4) - thread_safe (0.3.6) - tilt (2.0.8) - timecop (0.9.1) - ts_routes (1.0.1) - railties (>= 5.0) - tzinfo (1.2.5) - thread_safe (~> 0.1) - uglifier (4.0.2) - execjs (>= 0.3.0, < 3) - underscore-rails (1.8.3) - unf (0.1.4) - unf_ext - unf_ext (0.0.7.7) - unicode-display_width (1.6.0) - vcr (4.0.0) - webmock (3.6.0) - addressable (>= 2.3.6) - crack (>= 0.3.2) - hashdiff (>= 0.4.0, < 2.0.0) - webpacker (3.5.5) - activesupport (>= 4.2) - rack-proxy (>= 0.6.1) - railties (>= 4.2) - websocket-driver (0.7.0) - websocket-extensions (>= 0.1.0) - websocket-extensions (0.1.3) - xpath (2.1.0) - nokogiri (~> 1.3) - zip-zip (0.3) - rubyzip (>= 1.0.0) - -PLATFORMS - ruby - -DEPENDENCIES - analytics-ruby (~> 2.0.0) - apitome - aws-sdk (~> 2.6.5) - barnes - better_errors - binding_of_caller - block_parser! - bootsnap (>= 1.1.0) - bootstrap (= 4.0.0) - browser - byebug - capybara - database_cleaner - dotenv-rails - dry-validation (~> 0.12.2) - factory_bot_rails - flamegraph - font-awesome-rails - foreman - github_url (= 0.2.1) - gitlab - haml - honeybadger (~> 3.1) - httparty - jquery-rails - js-routes - json_spec - keycloak - letter_opener - mathjax-rails - memory_profiler - octokit - omniauth - omniauth-keycloak - overcommit - pagy - pg (~> 0.18) - puma (~> 3.12.0) - pundit - rack-attack - rack-mini-profiler - rails (~> 5.2.1) - rails-controller-testing - react-rails (= 2.4.5) - redis (~> 3.0) - rspec-rails - rspec_api_documentation - rspec_junit_formatter - rubocop - rubyzip (>= 1.0.0) - sass-rails (~> 5.0) - scout_apm - selenium-webdriver - shoulda-matchers - sidekiq - solid_use_case (~> 2.2.0) - stackprof - timecop - ts_routes - tzinfo-data - uglifier (>= 1.3.0) - underscore-rails (= 1.8.3) - vcr - webmock - webpacker (~> 3.5) - zip-zip - -RUBY VERSION - ruby 2.6.0p0 - -BUNDLED WITH - 1.17.3 diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 195a032..a10197d 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -3,9 +3,7 @@ require "spec_helper" describe User do subject { create(:user) } - it { is_expected.to validate_presence_of(:first_name) } - it { is_expected.to validate_presence_of(:last_name) } - it { is_expected.to validate_presence_of(:uid) } + it { is_expected.to validate_presence_of(:email) } it { is_expected.to validate_uniqueness_of(:uid) } describe "#sandbox" do @@ -36,6 +34,12 @@ describe User do end end + describe "#onboarder?" do + it "returns if a user is an onboarder" do + expect(create(:user, :product_admin).onboarder?).to eq true + end + end + describe "#blocks_manager?" do it "returns if a user is a forge blocks manager" do expect(create(:user, :blocks_manager).blocks_manager?).to eq true @@ -84,6 +88,31 @@ describe User do end end + describe "#onboarder_or_admin?" do + let(:cohort_1) { create(:cohort) } + let(:cohort_2) { create(:cohort) } + + it "returns true if a product admin belongs to the given cohort" do + expect(create(:user, :product_admin).onboarder_or_admin?(cohort_1.id)).to be true + end + + it "returns true if a admin" do + expect(create(:user, :admin).onboarder_or_admin?(cohort_1.id)).to be true + end + + it "returns true if an onboarder" do + expect(create(:user, :product_admin).onboarder_or_admin?(cohort_1.id)).to be true + end + + it "returns false if cohort is nil" do + expect(create(:user, :blocks_manager).onboarder_or_admin?(nil)).to be false + end + + it "returns false if a the user is nil" do + expect(described_class.new.onboarder_or_admin?(cohort_1)).to be false + end + end + describe "#instructor_of?" do let(:cohort_1) { create(:cohort) } let(:cohort_2) { create(:cohort) } @@ -146,7 +175,7 @@ describe User do it "returns true" do expect(subject.signed_in?).to be true end - end + end end describe "#student_or_instructor_of?" do @@ -297,4 +326,10 @@ describe User do expect(subject.checkpoint_submissions_count(cohort.id, block.id, 'abc123')).to eq(2) end end + + describe "#auth_edit_url" do + it "returns the correct url" do + expect(subject.auth_edit_url).to eq("#{Rails.application.secrets.auth_url}/admin/users/#{subject.uid}/edit") + end + end end diff --git a/spec/services/keycloak_resolver_service_spec.rb b/spec/services/keycloak_resolver_service_spec.rb index 9407824..0e7a5ea 100644 --- a/spec/services/keycloak_resolver_service_spec.rb +++ b/spec/services/keycloak_resolver_service_spec.rb @@ -91,21 +91,22 @@ describe KeycloakResolverService do auth_user.roles = [User::ROLES[:admin], "futzy.butzy"] user = nil + p auth_hash expect { user = subject.find_or_create_user }.to change { User.count }.by(1) - expect(user.admin?).to be true + expect(user.admin?).to be false expect(user.first_name).to eq "Inigo" expect(user.last_name).to eq "Montoya" - expect(user.roles).to eq([User::ROLES[:admin], "futzy.butzy"]) + expect(user.roles).to eq([]) # It doesn't add a new user if the user already exists new_user = nil user_count = User.count new_user = subject.find_or_create_user expect(User.count).to eq user_count - expect(new_user.admin?).to be true + expect(new_user.admin?).to be false expect(new_user.first_name).to eq "Inigo" expect(new_user.last_name).to eq "Montoya" - expect(new_user.roles).to eq([User::ROLES[:admin], "futzy.butzy"]) + expect(new_user.roles).to eq([]) end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b09336f..333bf7d 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,3 +1,6 @@ +require 'simplecov' +SimpleCov.start + ENV["RAILS_ENV"] ||= "test" require File.expand_path("../../config/environment", __FILE__) abort("The Rails environment is running in production mode!") if Rails.env.production? -- GitLab From 9867d12cd3d6182f75f60c11b989d30a31012b2b Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Sat, 26 Sep 2020 17:52:15 -1000 Subject: [PATCH 087/283] fix --- Gemfile.lock | 527 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 527 insertions(+) create mode 100644 Gemfile.lock diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..3971a89 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,527 @@ +PATH + remote: /Users/csakamaki/Projects/LEARN/RubyGems/block-parser + specs: + block_parser (0.1.0) + activemodel (> 4.2) + github-markdown (= 0.6.9) + github-markup (= 1.6.1) + github_url (= 0.2.1) + gitlab (= 4.14.1) + nokogiri (= 1.8.0) + octokit (= 4.3.0) + psych (= 2.2.4) + redcarpet (= 3.3.4) + rspec_junit_formatter (> 0.2.3) + +GEM + remote: https://rubygems.org/ + specs: + actioncable (5.2.4.3) + actionpack (= 5.2.4.3) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailer (5.2.4.3) + actionpack (= 5.2.4.3) + actionview (= 5.2.4.3) + activejob (= 5.2.4.3) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 2.0) + actionpack (5.2.4.3) + actionview (= 5.2.4.3) + activesupport (= 5.2.4.3) + rack (~> 2.0, >= 2.0.8) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (5.2.4.3) + activesupport (= 5.2.4.3) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + activejob (5.2.4.3) + activesupport (= 5.2.4.3) + globalid (>= 0.3.6) + activemodel (5.2.4.3) + activesupport (= 5.2.4.3) + activerecord (5.2.4.3) + activemodel (= 5.2.4.3) + activesupport (= 5.2.4.3) + arel (>= 9.0) + activestorage (5.2.4.3) + actionpack (= 5.2.4.3) + activerecord (= 5.2.4.3) + marcel (~> 0.3.1) + activesupport (5.2.4.3) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + addressable (2.4.0) + aes_key_wrap (1.1.0) + analytics-ruby (2.0.13) + apitome (0.3.0) + kramdown + railties + arel (9.0.0) + ast (2.4.0) + autoprefixer-rails (9.7.4) + execjs + aws-eventstream (1.1.0) + aws-sdk (2.6.50) + aws-sdk-resources (= 2.6.50) + aws-sdk-core (2.6.50) + aws-sigv4 (~> 1.0) + jmespath (~> 1.0) + aws-sdk-resources (2.6.50) + aws-sdk-core (= 2.6.50) + aws-sigv4 (1.2.2) + aws-eventstream (~> 1, >= 1.0.2) + babel-source (5.8.35) + babel-transpiler (0.7.0) + babel-source (>= 4.0, < 6) + execjs (~> 2.0) + barnes (0.0.7) + multi_json (~> 1) + statsd-ruby (~> 1.1) + better_errors (2.5.0) + coderay (>= 1.0.0) + erubi (>= 1.0.0) + rack (>= 0.9.0) + bindata (2.4.8) + binding_of_caller (0.8.0) + debug_inspector (>= 0.0.1) + bootsnap (1.4.5) + msgpack (~> 1.0) + bootstrap (4.0.0) + autoprefixer-rails (>= 6.0.3) + popper_js (>= 1.12.9, < 2) + sass (>= 3.5.2) + browser (2.5.2) + builder (3.2.4) + byebug (11.0.1) + capybara (3.33.0) + addressable + mini_mime (>= 0.1.3) + nokogiri (~> 1.8) + rack (>= 1.6.0) + rack-test (>= 0.6.3) + regexp_parser (~> 1.5) + xpath (~> 3.2) + childprocess (0.8.0) + ffi (~> 1.0, >= 1.0.11) + coderay (1.1.2) + concurrent-ruby (1.1.6) + connection_pool (2.2.2) + crack (0.4.3) + safe_yaml (~> 1.0.0) + crass (1.0.6) + database_cleaner (1.8.5) + debug_inspector (0.0.3) + deterministic (0.6.0) + diff-lcs (1.4.4) + docile (1.3.2) + domain_name (0.5.20190701) + unf (>= 0.0.5, < 1.0.0) + dotenv (2.5.0) + dotenv-rails (2.5.0) + dotenv (= 2.5.0) + railties (>= 3.2, < 6.0) + dry-configurable (0.7.0) + concurrent-ruby (~> 1.0) + dry-container (0.6.0) + concurrent-ruby (~> 1.0) + dry-configurable (~> 0.1, >= 0.1.3) + dry-core (0.4.7) + concurrent-ruby (~> 1.0) + dry-equalizer (0.2.1) + dry-inflector (0.1.2) + dry-logic (0.4.2) + dry-container (~> 0.2, >= 0.2.6) + dry-core (~> 0.2) + dry-equalizer (~> 0.2) + dry-types (0.13.2) + concurrent-ruby (~> 1.0) + dry-container (~> 0.3) + dry-core (~> 0.4, >= 0.4.4) + dry-equalizer (~> 0.2) + dry-inflector (~> 0.1, >= 0.1.2) + dry-logic (~> 0.4, >= 0.4.2) + dry-validation (0.12.2) + concurrent-ruby (~> 1.0) + dry-configurable (~> 0.1, >= 0.1.3) + dry-core (~> 0.2, >= 0.2.1) + dry-equalizer (~> 0.2) + dry-logic (~> 0.4, >= 0.4.0) + dry-types (~> 0.13.1) + erubi (1.9.0) + execjs (2.7.0) + factory_bot (6.1.0) + activesupport (>= 5.0.0) + factory_bot_rails (6.1.0) + factory_bot (~> 6.1.0) + railties (>= 5.0.0) + faraday (0.9.2) + multipart-post (>= 1.2, < 3) + ffi (1.12.2) + flamegraph (0.9.5) + font-awesome-rails (4.7.0.4) + railties (>= 3.2, < 6.0) + foreman (0.84.0) + thor (~> 0.19.1) + github-markdown (0.6.9) + github-markup (1.6.1) + github_url (0.2.1) + gitlab (4.14.1) + httparty (~> 0.14, >= 0.14.0) + terminal-table (~> 1.5, >= 1.5.1) + globalid (0.4.2) + activesupport (>= 4.2.0) + haml (5.0.4) + temple (>= 0.8.0) + tilt + hashdiff (1.0.1) + hashie (4.1.0) + honeybadger (3.2.0) + http-accept (1.7.0) + http-cookie (1.0.3) + domain_name (~> 0.5) + httparty (0.18.0) + mime-types (~> 3.0) + multi_xml (>= 0.5.2) + i18n (1.8.3) + concurrent-ruby (~> 1.0) + iniparse (1.4.4) + jmespath (1.4.0) + jquery-rails (4.3.1) + rails-dom-testing (>= 1, < 3) + railties (>= 4.2.0) + thor (>= 0.14, < 2.0) + js-routes (1.4.2) + railties (>= 3.2) + sprockets-rails + json (2.3.1) + json-jwt (1.13.0) + activesupport (>= 4.2) + aes_key_wrap + bindata + json_spec (1.1.5) + multi_json (~> 1.0) + rspec (>= 2.0, < 4.0) + jwt (2.2.2) + keycloak (3.0.0) + json + jwt + rest-client + kramdown (2.1.0) + launchy (2.4.3) + addressable (~> 2.3) + letter_opener (1.7.0) + launchy (~> 2.2) + loofah (2.4.0) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + mail (2.7.1) + mini_mime (>= 0.1.1) + marcel (0.3.3) + mimemagic (~> 0.3.2) + mathjax-rails (2.6.1) + railties (>= 3.0) + memory_profiler (0.9.12) + method_source (1.0.0) + mime-types (3.3.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2020.0512) + mimemagic (0.3.5) + mini_mime (1.0.2) + mini_portile2 (2.2.0) + minitest (5.14.1) + msgpack (1.3.3) + multi_json (1.15.0) + multi_xml (0.6.0) + multipart-post (2.1.1) + mustache (1.1.0) + netrc (0.11.0) + nio4r (2.5.2) + nokogiri (1.8.0) + mini_portile2 (~> 2.2.0) + oauth2 (1.4.4) + faraday (>= 0.8, < 2.0) + jwt (>= 1.0, < 3.0) + multi_json (~> 1.3) + multi_xml (~> 0.5) + rack (>= 1.2, < 3) + octokit (4.3.0) + sawyer (~> 0.7.0, >= 0.5.3) + omniauth (1.9.1) + hashie (>= 3.4.6) + rack (>= 1.6.2, < 3) + omniauth-keycloak (1.2.0) + json-jwt (~> 1.12) + omniauth (~> 1.9.0) + omniauth-oauth2 (~> 1.6.0) + omniauth-oauth2 (1.6.0) + oauth2 (~> 1.1) + omniauth (~> 1.9) + overcommit (0.41.0) + childprocess (~> 0.6, >= 0.6.3) + iniparse (~> 1.4) + pagy (3.7.1) + parallel (1.19.1) + parser (2.7.1.2) + ast (~> 2.4.0) + pg (0.21.0) + popper_js (1.12.9) + psych (2.2.4) + puma (3.12.6) + pundit (1.1.0) + activesupport (>= 3.0.0) + rack (2.2.3) + rack-attack (6.2.1) + rack (>= 1.0, < 3) + rack-mini-profiler (1.0.0) + rack (>= 1.2.0) + rack-protection (2.0.5) + rack + rack-proxy (0.6.5) + rack + rack-test (1.1.0) + rack (>= 1.0, < 3) + rails (5.2.4.3) + actioncable (= 5.2.4.3) + actionmailer (= 5.2.4.3) + actionpack (= 5.2.4.3) + actionview (= 5.2.4.3) + activejob (= 5.2.4.3) + activemodel (= 5.2.4.3) + activerecord (= 5.2.4.3) + activestorage (= 5.2.4.3) + activesupport (= 5.2.4.3) + bundler (>= 1.3.0) + railties (= 5.2.4.3) + sprockets-rails (>= 2.0.0) + rails-controller-testing (1.0.4) + actionpack (>= 5.0.1.x) + actionview (>= 5.0.1.x) + activesupport (>= 5.0.1.x) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-html-sanitizer (1.3.0) + loofah (~> 2.3) + railties (5.2.4.3) + actionpack (= 5.2.4.3) + activesupport (= 5.2.4.3) + method_source + rake (>= 0.8.7) + thor (>= 0.19.0, < 2.0) + rainbow (3.0.0) + rake (13.0.1) + rb-fsevent (0.10.3) + rb-inotify (0.10.1) + ffi (~> 1.0) + react-rails (2.4.5) + babel-transpiler (>= 0.7.0) + connection_pool + execjs + railties (>= 3.2) + tilt + redcarpet (3.3.4) + redis (3.3.5) + regexp_parser (1.7.1) + rest-client (2.1.0) + http-accept (>= 1.7.0, < 2.0) + http-cookie (>= 1.0.2, < 2.0) + mime-types (>= 1.16, < 4.0) + netrc (~> 0.8) + rexml (3.2.4) + rspec (3.9.0) + rspec-core (~> 3.9.0) + rspec-expectations (~> 3.9.0) + rspec-mocks (~> 3.9.0) + rspec-core (3.9.2) + rspec-support (~> 3.9.3) + rspec-expectations (3.9.2) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.9.0) + rspec-mocks (3.9.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.9.0) + rspec-rails (4.0.1) + actionpack (>= 4.2) + activesupport (>= 4.2) + railties (>= 4.2) + rspec-core (~> 3.9) + rspec-expectations (~> 3.9) + rspec-mocks (~> 3.9) + rspec-support (~> 3.9) + rspec-support (3.9.3) + rspec_api_documentation (6.1.0) + activesupport (>= 3.0.0) + mustache (~> 1.0, >= 0.99.4) + rspec (~> 3.0) + rspec_junit_formatter (0.4.1) + rspec-core (>= 2, < 4, != 2.12.0) + rubocop (0.83.0) + parallel (~> 1.10) + parser (>= 2.7.0.1) + rainbow (>= 2.2.2, < 4.0) + rexml + ruby-progressbar (~> 1.7) + unicode-display_width (>= 1.4.0, < 2.0) + ruby-progressbar (1.10.1) + rubyzip (2.3.0) + safe_yaml (1.0.5) + sass (3.7.4) + sass-listen (~> 4.0.0) + sass-listen (4.0.0) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + sass-rails (5.1.0) + railties (>= 5.2.0) + sass (~> 3.1) + sprockets (>= 2.8, < 4.0) + sprockets-rails (>= 2.0, < 4.0) + tilt (>= 1.1, < 3) + sawyer (0.7.0) + addressable (>= 2.3.5, < 2.5) + faraday (~> 0.8, < 0.10) + scout_apm (2.4.19) + selenium-webdriver (3.142.7) + childprocess (>= 0.5, < 4.0) + rubyzip (>= 1.2.2) + shoulda-matchers (3.1.2) + activesupport (>= 4.0.0) + sidekiq (5.2.7) + connection_pool (~> 2.2, >= 2.2.2) + rack (>= 1.5.0) + rack-protection (>= 1.5.0) + redis (>= 3.3.5, < 5) + simplecov (0.17.1) + docile (~> 1.1) + json (>= 1.8, < 3) + simplecov-html (~> 0.10.0) + simplecov-html (0.10.2) + solid_use_case (2.2.0) + deterministic (~> 0.6.0) + sprockets (3.7.2) + concurrent-ruby (~> 1.0) + rack (> 1, < 3) + sprockets-rails (3.2.1) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) + stackprof (0.2.12) + statsd-ruby (1.4.0) + temple (0.8.0) + terminal-table (1.8.0) + unicode-display_width (~> 1.1, >= 1.1.1) + thor (0.19.4) + thread_safe (0.3.6) + tilt (2.0.10) + timecop (0.9.1) + ts_routes (1.0.1) + railties (>= 5.0) + tzinfo (1.2.7) + thread_safe (~> 0.1) + uglifier (4.0.2) + execjs (>= 0.3.0, < 3) + underscore-rails (1.8.3) + unf (0.1.4) + unf_ext + unf_ext (0.0.7.7) + unicode-display_width (1.7.0) + vcr (6.0.0) + webmock (3.8.3) + addressable (>= 2.3.6) + crack (>= 0.3.2) + hashdiff (>= 0.4.0, < 2.0.0) + webpacker (3.5.5) + activesupport (>= 4.2) + rack-proxy (>= 0.6.1) + railties (>= 4.2) + websocket-driver (0.7.3) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.5) + xpath (3.2.0) + nokogiri (~> 1.8) + zip-zip (0.3) + rubyzip (>= 1.0.0) + +PLATFORMS + ruby + +DEPENDENCIES + analytics-ruby (~> 2.0.0) + apitome + aws-sdk (~> 2.6.5) + barnes + better_errors + binding_of_caller + block_parser! + bootsnap (>= 1.1.0) + bootstrap (= 4.0.0) + browser + byebug + capybara + database_cleaner + dotenv-rails + dry-validation (~> 0.12.2) + factory_bot_rails + flamegraph + font-awesome-rails + foreman + github_url (= 0.2.1) + gitlab + haml + honeybadger (~> 3.1) + httparty + jquery-rails + js-routes + json_spec + keycloak + letter_opener + mathjax-rails + memory_profiler + octokit + omniauth + omniauth-keycloak + overcommit + pagy + pg (~> 0.18) + puma (~> 3.12.0) + pundit + rack-attack + rack-mini-profiler + rails (~> 5.2.1) + rails-controller-testing + react-rails (= 2.4.5) + redis (~> 3.0) + rspec-rails + rspec_api_documentation + rspec_junit_formatter + rubocop + rubyzip (>= 1.0.0) + sass-rails (~> 5.0) + scout_apm + selenium-webdriver + shoulda-matchers + sidekiq + simplecov + solid_use_case (~> 2.2.0) + stackprof + timecop + ts_routes + tzinfo-data + uglifier (>= 1.3.0) + underscore-rails (= 1.8.3) + vcr + webmock + webpacker (~> 3.5) + zip-zip + +RUBY VERSION + ruby 2.6.0p0 + +BUNDLED WITH + 2.1.4 -- GitLab From 738898ac13396c9f274f937e219f736ae2406046 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Sat, 26 Sep 2020 18:19:59 -1000 Subject: [PATCH 088/283] fix Gemfile.lock --- Gemfile.lock | 290 +++++++++++++++++++++++++-------------------------- 1 file changed, 142 insertions(+), 148 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 3971a89..44fc3d8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -16,43 +16,43 @@ PATH GEM remote: https://rubygems.org/ specs: - actioncable (5.2.4.3) - actionpack (= 5.2.4.3) + actioncable (5.2.1) + actionpack (= 5.2.1) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailer (5.2.4.3) - actionpack (= 5.2.4.3) - actionview (= 5.2.4.3) - activejob (= 5.2.4.3) + actionmailer (5.2.1) + actionpack (= 5.2.1) + actionview (= 5.2.1) + activejob (= 5.2.1) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.2.4.3) - actionview (= 5.2.4.3) - activesupport (= 5.2.4.3) - rack (~> 2.0, >= 2.0.8) + actionpack (5.2.1) + actionview (= 5.2.1) + activesupport (= 5.2.1) + rack (~> 2.0) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.2.4.3) - activesupport (= 5.2.4.3) + actionview (5.2.1) + activesupport (= 5.2.1) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (5.2.4.3) - activesupport (= 5.2.4.3) + activejob (5.2.1) + activesupport (= 5.2.1) globalid (>= 0.3.6) - activemodel (5.2.4.3) - activesupport (= 5.2.4.3) - activerecord (5.2.4.3) - activemodel (= 5.2.4.3) - activesupport (= 5.2.4.3) + activemodel (5.2.1) + activesupport (= 5.2.1) + activerecord (5.2.1) + activemodel (= 5.2.1) + activesupport (= 5.2.1) arel (>= 9.0) - activestorage (5.2.4.3) - actionpack (= 5.2.4.3) - activerecord (= 5.2.4.3) + activestorage (5.2.1) + actionpack (= 5.2.1) + activerecord (= 5.2.1) marcel (~> 0.3.1) - activesupport (5.2.4.3) + activesupport (5.2.1) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) @@ -65,9 +65,8 @@ GEM railties arel (9.0.0) ast (2.4.0) - autoprefixer-rails (9.7.4) + autoprefixer-rails (7.2.5) execjs - aws-eventstream (1.1.0) aws-sdk (2.6.50) aws-sdk-resources (= 2.6.50) aws-sdk-core (2.6.50) @@ -75,8 +74,7 @@ GEM jmespath (~> 1.0) aws-sdk-resources (2.6.50) aws-sdk-core (= 2.6.50) - aws-sigv4 (1.2.2) - aws-eventstream (~> 1, >= 1.0.2) + aws-sigv4 (1.0.2) babel-source (5.8.35) babel-transpiler (0.7.0) babel-source (>= 4.0, < 6) @@ -91,35 +89,34 @@ GEM bindata (2.4.8) binding_of_caller (0.8.0) debug_inspector (>= 0.0.1) - bootsnap (1.4.5) + bootsnap (1.3.1) msgpack (~> 1.0) bootstrap (4.0.0) autoprefixer-rails (>= 6.0.3) popper_js (>= 1.12.9, < 2) sass (>= 3.5.2) browser (2.5.2) - builder (3.2.4) - byebug (11.0.1) - capybara (3.33.0) + builder (3.2.3) + byebug (9.1.0) + capybara (2.16.1) addressable mini_mime (>= 0.1.3) - nokogiri (~> 1.8) - rack (>= 1.6.0) - rack-test (>= 0.6.3) - regexp_parser (~> 1.5) - xpath (~> 3.2) + nokogiri (>= 1.3.3) + rack (>= 1.0.0) + rack-test (>= 0.5.4) + xpath (~> 2.0) childprocess (0.8.0) ffi (~> 1.0, >= 1.0.11) coderay (1.1.2) - concurrent-ruby (1.1.6) - connection_pool (2.2.2) + concurrent-ruby (1.1.5) + connection_pool (2.2.1) crack (0.4.3) safe_yaml (~> 1.0.0) - crass (1.0.6) - database_cleaner (1.8.5) + crass (1.0.4) + database_cleaner (1.6.2) debug_inspector (0.0.3) deterministic (0.6.0) - diff-lcs (1.4.4) + diff-lcs (1.3) docile (1.3.2) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) @@ -154,16 +151,16 @@ GEM dry-equalizer (~> 0.2) dry-logic (~> 0.4, >= 0.4.0) dry-types (~> 0.13.1) - erubi (1.9.0) + erubi (1.7.1) execjs (2.7.0) - factory_bot (6.1.0) - activesupport (>= 5.0.0) - factory_bot_rails (6.1.0) - factory_bot (~> 6.1.0) - railties (>= 5.0.0) + factory_bot (4.8.2) + activesupport (>= 3.0.0) + factory_bot_rails (4.8.2) + factory_bot (~> 4.8.2) + railties (>= 3.0.0) faraday (0.9.2) multipart-post (>= 1.2, < 3) - ffi (1.12.2) + ffi (1.9.18) flamegraph (0.9.5) font-awesome-rails (4.7.0.4) railties (>= 3.2, < 6.0) @@ -175,24 +172,24 @@ GEM gitlab (4.14.1) httparty (~> 0.14, >= 0.14.0) terminal-table (~> 1.5, >= 1.5.1) - globalid (0.4.2) + globalid (0.4.1) activesupport (>= 4.2.0) haml (5.0.4) temple (>= 0.8.0) tilt - hashdiff (1.0.1) + hashdiff (0.4.0) hashie (4.1.0) honeybadger (3.2.0) http-accept (1.7.0) http-cookie (1.0.3) domain_name (~> 0.5) - httparty (0.18.0) - mime-types (~> 3.0) + httparty (0.15.6) multi_xml (>= 0.5.2) - i18n (1.8.3) + i18n (1.6.0) concurrent-ruby (~> 1.0) iniparse (1.4.4) - jmespath (1.4.0) + jaro_winkler (1.5.3) + jmespath (1.3.1) jquery-rails (4.3.1) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) @@ -218,31 +215,31 @@ GEM addressable (~> 2.3) letter_opener (1.7.0) launchy (~> 2.2) - loofah (2.4.0) + loofah (2.2.2) crass (~> 1.0.2) nokogiri (>= 1.5.9) - mail (2.7.1) + mail (2.7.0) mini_mime (>= 0.1.1) - marcel (0.3.3) + marcel (0.3.2) mimemagic (~> 0.3.2) mathjax-rails (2.6.1) railties (>= 3.0) memory_profiler (0.9.12) - method_source (1.0.0) + method_source (0.9.0) mime-types (3.3.1) mime-types-data (~> 3.2015) mime-types-data (3.2020.0512) - mimemagic (0.3.5) - mini_mime (1.0.2) + mimemagic (0.3.2) + mini_mime (1.0.0) mini_portile2 (2.2.0) - minitest (5.14.1) - msgpack (1.3.3) - multi_json (1.15.0) + minitest (5.11.3) + msgpack (1.2.4) + multi_json (1.13.1) multi_xml (0.6.0) - multipart-post (2.1.1) + multipart-post (2.0.0) mustache (1.1.0) netrc (0.11.0) - nio4r (2.5.2) + nio4r (2.3.1) nokogiri (1.8.0) mini_portile2 (~> 2.2.0) oauth2 (1.4.4) @@ -267,59 +264,59 @@ GEM childprocess (~> 0.6, >= 0.6.3) iniparse (~> 1.4) pagy (3.7.1) - parallel (1.19.1) - parser (2.7.1.2) + parallel (1.17.0) + parser (2.6.3.0) ast (~> 2.4.0) pg (0.21.0) popper_js (1.12.9) psych (2.2.4) - puma (3.12.6) + puma (3.12.1) pundit (1.1.0) activesupport (>= 3.0.0) - rack (2.2.3) + rack (2.0.3) rack-attack (6.2.1) rack (>= 1.0, < 3) rack-mini-profiler (1.0.0) rack (>= 1.2.0) - rack-protection (2.0.5) + rack-protection (2.0.0) rack - rack-proxy (0.6.5) + rack-proxy (0.6.4) rack - rack-test (1.1.0) + rack-test (0.8.2) rack (>= 1.0, < 3) - rails (5.2.4.3) - actioncable (= 5.2.4.3) - actionmailer (= 5.2.4.3) - actionpack (= 5.2.4.3) - actionview (= 5.2.4.3) - activejob (= 5.2.4.3) - activemodel (= 5.2.4.3) - activerecord (= 5.2.4.3) - activestorage (= 5.2.4.3) - activesupport (= 5.2.4.3) + rails (5.2.1) + actioncable (= 5.2.1) + actionmailer (= 5.2.1) + actionpack (= 5.2.1) + actionview (= 5.2.1) + activejob (= 5.2.1) + activemodel (= 5.2.1) + activerecord (= 5.2.1) + activestorage (= 5.2.1) + activesupport (= 5.2.1) bundler (>= 1.3.0) - railties (= 5.2.4.3) + railties (= 5.2.1) sprockets-rails (>= 2.0.0) - rails-controller-testing (1.0.4) - actionpack (>= 5.0.1.x) - actionview (>= 5.0.1.x) - activesupport (>= 5.0.1.x) + rails-controller-testing (1.0.2) + actionpack (~> 5.x, >= 5.0.1) + actionview (~> 5.x, >= 5.0.1) + activesupport (~> 5.x) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) - rails-html-sanitizer (1.3.0) - loofah (~> 2.3) - railties (5.2.4.3) - actionpack (= 5.2.4.3) - activesupport (= 5.2.4.3) + rails-html-sanitizer (1.0.4) + loofah (~> 2.2, >= 2.2.2) + railties (5.2.1) + actionpack (= 5.2.1) + activesupport (= 5.2.1) method_source rake (>= 0.8.7) thor (>= 0.19.0, < 2.0) rainbow (3.0.0) - rake (13.0.1) - rb-fsevent (0.10.3) - rb-inotify (0.10.1) - ffi (~> 1.0) + rake (12.3.1) + rb-fsevent (0.10.2) + rb-inotify (0.9.10) + ffi (>= 0.5.0, < 2) react-rails (2.4.5) babel-transpiler (>= 0.7.0) connection_pool @@ -328,57 +325,55 @@ GEM tilt redcarpet (3.3.4) redis (3.3.5) - regexp_parser (1.7.1) rest-client (2.1.0) http-accept (>= 1.7.0, < 2.0) http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 4.0) netrc (~> 0.8) - rexml (3.2.4) - rspec (3.9.0) - rspec-core (~> 3.9.0) - rspec-expectations (~> 3.9.0) - rspec-mocks (~> 3.9.0) - rspec-core (3.9.2) - rspec-support (~> 3.9.3) - rspec-expectations (3.9.2) + rspec (3.7.0) + rspec-core (~> 3.7.0) + rspec-expectations (~> 3.7.0) + rspec-mocks (~> 3.7.0) + rspec-core (3.7.0) + rspec-support (~> 3.7.0) + rspec-expectations (3.7.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.9.0) - rspec-mocks (3.9.1) + rspec-support (~> 3.7.0) + rspec-mocks (3.7.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.9.0) - rspec-rails (4.0.1) - actionpack (>= 4.2) - activesupport (>= 4.2) - railties (>= 4.2) - rspec-core (~> 3.9) - rspec-expectations (~> 3.9) - rspec-mocks (~> 3.9) - rspec-support (~> 3.9) - rspec-support (3.9.3) + rspec-support (~> 3.7.0) + rspec-rails (3.7.2) + actionpack (>= 3.0) + activesupport (>= 3.0) + railties (>= 3.0) + rspec-core (~> 3.7.0) + rspec-expectations (~> 3.7.0) + rspec-mocks (~> 3.7.0) + rspec-support (~> 3.7.0) + rspec-support (3.7.0) rspec_api_documentation (6.1.0) activesupport (>= 3.0.0) mustache (~> 1.0, >= 0.99.4) rspec (~> 3.0) - rspec_junit_formatter (0.4.1) + rspec_junit_formatter (0.3.0) rspec-core (>= 2, < 4, != 2.12.0) - rubocop (0.83.0) + rubocop (0.72.0) + jaro_winkler (~> 1.5.1) parallel (~> 1.10) - parser (>= 2.7.0.1) + parser (>= 2.6) rainbow (>= 2.2.2, < 4.0) - rexml ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 2.0) + unicode-display_width (>= 1.4.0, < 1.7) ruby-progressbar (1.10.1) - rubyzip (2.3.0) + rubyzip (1.2.1) safe_yaml (1.0.5) - sass (3.7.4) + sass (3.5.3) sass-listen (~> 4.0.0) sass-listen (4.0.0) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) - sass-rails (5.1.0) - railties (>= 5.2.0) + sass-rails (5.0.7) + railties (>= 4.0.0, < 6) sass (~> 3.1) sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) @@ -387,24 +382,23 @@ GEM addressable (>= 2.3.5, < 2.5) faraday (~> 0.8, < 0.10) scout_apm (2.4.19) - selenium-webdriver (3.142.7) - childprocess (>= 0.5, < 4.0) - rubyzip (>= 1.2.2) + selenium-webdriver (3.8.0) + childprocess (~> 0.5) + rubyzip (~> 1.0) shoulda-matchers (3.1.2) activesupport (>= 4.0.0) - sidekiq (5.2.7) - connection_pool (~> 2.2, >= 2.2.2) - rack (>= 1.5.0) + sidekiq (5.0.5) + concurrent-ruby (~> 1.0) + connection_pool (~> 2.2, >= 2.2.0) rack-protection (>= 1.5.0) - redis (>= 3.3.5, < 5) - simplecov (0.17.1) + redis (>= 3.3.4, < 5) + simplecov (0.19.0) docile (~> 1.1) - json (>= 1.8, < 3) - simplecov-html (~> 0.10.0) - simplecov-html (0.10.2) + simplecov-html (~> 0.11) + simplecov-html (0.12.3) solid_use_case (2.2.0) deterministic (~> 0.6.0) - sprockets (3.7.2) + sprockets (3.7.1) concurrent-ruby (~> 1.0) rack (> 1, < 3) sprockets-rails (3.2.1) @@ -418,11 +412,11 @@ GEM unicode-display_width (~> 1.1, >= 1.1.1) thor (0.19.4) thread_safe (0.3.6) - tilt (2.0.10) + tilt (2.0.8) timecop (0.9.1) ts_routes (1.0.1) railties (>= 5.0) - tzinfo (1.2.7) + tzinfo (1.2.5) thread_safe (~> 0.1) uglifier (4.0.2) execjs (>= 0.3.0, < 3) @@ -430,9 +424,9 @@ GEM unf (0.1.4) unf_ext unf_ext (0.0.7.7) - unicode-display_width (1.7.0) - vcr (6.0.0) - webmock (3.8.3) + unicode-display_width (1.6.0) + vcr (4.0.0) + webmock (3.6.0) addressable (>= 2.3.6) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) @@ -440,11 +434,11 @@ GEM activesupport (>= 4.2) rack-proxy (>= 0.6.1) railties (>= 4.2) - websocket-driver (0.7.3) + websocket-driver (0.7.0) websocket-extensions (>= 0.1.0) - websocket-extensions (0.1.5) - xpath (3.2.0) - nokogiri (~> 1.8) + websocket-extensions (0.1.3) + xpath (2.1.0) + nokogiri (~> 1.3) zip-zip (0.3) rubyzip (>= 1.0.0) @@ -524,4 +518,4 @@ RUBY VERSION ruby 2.6.0p0 BUNDLED WITH - 2.1.4 + 1.17.3 -- GitLab From 185a7f3f62f20aaa845a1d558b12ae2b31bab335 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Sat, 26 Sep 2020 22:00:55 -1000 Subject: [PATCH 089/283] Tests for cohort_users --- app/controllers/users_controller.rb | 9 +- spec/controllers/users_controller_spec.rb | 216 ++++++++-------------- 2 files changed, 89 insertions(+), 136 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 53d6131..d053711 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,5 +1,6 @@ class UsersController < ApplicationController def new + byebug authorize(Cohort) @cohort_id = params[:cohort_id] end @@ -11,8 +12,12 @@ class UsersController < ApplicationController def update authorize(current_cohort) - current_cohort_user.update(roles: [params[:instructor]].compact) - redirect_to users_cohort_path(current_cohort) + if current_cohort_user.update(roles: [params[:instructor]].compact) + redirect_to users_cohort_path(current_cohort) + else + flash[:error] = current_cohort_user.errors.full_messages.join(", ") + render :edit + end end def destroy diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 7c16a5c..308833f 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -7,150 +7,98 @@ describe UsersController do # let!(:cohort) { create(:cohort) } # let!(:enrolled_student) { create(:user, first_name: "Eric", last_name: "Ericson", email: "eric@example.com") } # let!(:cohort_user) { create(:cohort_user, created_at: 3.days.ago, cohort: cohort, user: enrolled_student) } + let(:cohort) { create(:cohort) } + let(:user) { create(:user) } describe "GET #new" do - let!(:cohort) { create(:cohort) } - let(:cohort_id) { cohort.id } - - context "create a new user for a given cohort" do + context "creates a new users for a given cohort" do it "creates new users for a cohort from a list of users" do - get "/cohorts/:cohort_id/users/new" do - print "COHORT_ID = " + @cohort_id - end + allow(controller).to receive(:render) + + get :new, params: { cohort_id: cohort.id } end end end - describe "Updating an enrollment" do - - # parameter ":cohort_id", "[Path Parameter]\nThe ID of the cohort. Matches the ID from the URL when viewing any cohort in Learn", required: true, example: "1500" - # parameter ":id", "[Path Parameter]\nThe ID of the user.", required: true, example: "456" - # parameter :instructor, "[Body Parameter]\nThe boolean that sets the forge.instructor role for enrollment.", required: true, example: "true = has instructor role\nfalse = has student role" - # parameter :onboard, "[Body Parameter]\nThe boolean that sets the auth.product_admin role for enrollment.", required: true, example: "true = user can enroll others in the cohort\nfalse = no onboarding ability" - # - # let(:cohort_id) { cohort.id } - # let(:id) { enrolled_student.id } - # let(:instructor) { true } - # let(:onboard) { true } - # - # patch "/cohorts/:cohort_id/users/:id" do - # example "Updating a user's enrollment roles" do - # explanation <<-MARKDOWN.strip_heredoc - # Update the roles for the user enrolled in the specified cohort. Can modify the forge.instructor and auth.product_admin roles for that enrollment only. The user will have only the roles specified after the action is taken. - # MARKDOWN - # header "Authorization", "Bearer #{user.api_token}" - # - # expect(Keycloak::Internal).to receive(:get_user_info).with( - # email, - # true, - # Rails.application.secrets.keycloak_client_id, - # Rails.application.secrets.keycloak_client_secret - # ).and_return(OpenStruct.new({ id: "test", - # firstName: first_name, - # lastName: last_name, - # email: email, - # roles: [ - # "forge.instructor" - # ] - # })) - # - # # dbl = double(AuthApi::Client) - # # expect(dbl).to receive(:update_user).with( - # # { - # # id: enrolled_student.uid, - # # user: { - # # registrations: [{ - # # product_uid: cohort.uid, - # # }] - # # } - # # } - # # ) - # # allow(AuthApi::Client).to receive(:new).and_return(dbl) - # - # expect { - # do_request - # }.to have_enqueued_job(CreateApiInteractionJob) - # - # puts "RESPONSE_JSON = " + response_json.to_s - # expect(status).to eq 200 - # expect(response_json["status"]).to eq("ok") - # end - # - # it "returns 404 status if there is no enrollment for that cohort and user" do - # header "Authorization", "Bearer #{user.api_token}" - # dbl = double(AuthApi::Client) - # CohortUser.destroy_all - # expect(dbl).to_not receive(:update_user).with( - # { - # id: enrolled_student.uid, - # user: { - # registrations: [{ - # product_uid: cohort.uid, - # roles: [] - # }] - # } - # } - # ) - # allow(AuthApi::Client).to receive(:new).and_return(dbl) - # expect { - # do_request - # }.to have_enqueued_job(CreateApiInteractionJob) - # expect(status).to eq 404 - # expect(response_json["status"]).to eq("404") - # end - # - # it "responds with a 400 when the auth API request fails" do - # header "Authorization", "Bearer #{user.api_token}" - # dbl = double(AuthApi::Client) - # expect(dbl).to receive(:update_user).and_raise(AuthApi::RequestFailed) - # allow(AuthApi::Client).to receive(:new).and_return(dbl) - # expect { - # do_request - # }.to have_enqueued_job(CreateApiInteractionJob) - # - # expect(status).to eq 400 - # - # expect(response_json["error"]).to eq("AuthApi::RequestFailed") - # end - # end + describe "GET #edit" do + context "edits a user for a given cohort" do + + it "edits users for a cohort" do + allow(controller).to receive(:render) + + get :edit, params: { cohort_id: cohort.id, id: user.id } + end + end end - describe "Deleting an enrollment" do - - # parameter ":cohort_id", "[Path Parameter]\nThe ID of the cohort. Matches the ID from the URL when viewing any cohort in Learn", required: true, example: "1500" - # parameter ":id", "[Path Parameter]\nThe ID of the user.", required: true, example: "456" - # - # let(:cohort_id) { cohort.id } - # let(:id) { enrolled_student.uid } - # - # delete "/cohorts/:cohort_id/users/:id" do - # example "Unenrolling a user from a cohort" do - # explanation <<-MARKDOWN.strip_heredoc - # Delete the enrollment for a specified cohort and user. - # MARKDOWN - # header "Authorization", "Bearer #{user.api_token}" - # dbl = double(AuthApi::Client) - # expect(dbl).to receive(:update_user).with( - # { - # id: enrolled_student.uid, - # user: { - # registrations: [{ - # product_uid: cohort.uid, - # _destroy: true - # }] - # } - # } - # ) - # allow(AuthApi::Client).to receive(:new).and_return(dbl) - # expect { - # do_request - # }.to have_enqueued_job(CreateApiInteractionJob) - # - # expect(status).to eq 200 - # expect(response_json["status"]).to eq("ok") - # end - # end + describe "PATCH #update" do + let(:cohort_user) { create(:cohort_user, cohort: cohort, user: user) } + + before do + sign_in(create(:user, :admin, :product_admin)) + allow(CohortUser).to receive(:find_by).and_return(cohort_user) + allow(cohort_user).to receive(:update).and_return(true) + end + + it "updates the cohort user" do + patch :update, params: { + cohort_id: cohort.id, + id: user.id + } + expect(cohort_user).to have_received(:update) + end + + context "when the update succeeds" do + it "redirects to the user cohorts page" do + patch :update, params: { + cohort_id: cohort.id, + id: user.id + } + expect(response).to redirect_to(users_cohort_path(cohort)) + end + end + + context "when the update fails" do + before do + allow(cohort_user).to receive(:update).and_return(false) + end + + it "renders the edit page again" do + patch :update, params: { + cohort_id: cohort.id, + id: user.id + } + expect(response).to render_template(:edit) + end + end end + describe "DELETE #destroy" do + let(:cohort_user) { create(:cohort_user, cohort: cohort, user: user) } + + before do + sign_in(create(:user, :admin, :product_admin)) + allow(CohortUser).to receive(:find_by).and_return(cohort_user) + allow(cohort_user).to receive(:destroy).and_return(true) + end + + it "deletes the cohort user" do + delete :destroy, params: { + cohort_id: cohort.id, + id: user.id + } + expect(cohort_user).to have_received(:destroy) + end + + context "when the delete succeeds" do + it "redirects to the user cohorts page" do + delete :destroy, params: { + cohort_id: cohort.id, + id: user.id + } + expect(response).to redirect_to(users_cohort_path(cohort)) + end + end + end end -- GitLab From 8686770416cd57ca883c4eca77db12b364f8b55d Mon Sep 17 00:00:00 2001 From: Derrin Chong Date: Mon, 28 Sep 2020 08:38:43 -1000 Subject: [PATCH 090/283] Set envs --- config/database.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config/database.yml b/config/database.yml index 2068095..b1c7d3f 100644 --- a/config/database.yml +++ b/config/database.yml @@ -2,10 +2,10 @@ default: &default adapter: postgresql encoding: unicode pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> - host: <%= ENV["POSTGRES_HOST"] || "localhost" %> - username: <%= ENV["POSTGRES_USER"] || "auth_user" %> - password: <%= ENV["POSTGRES_PASSWORD"] || "postgres" %> - database: <%= ENV["POSTGRES_DB"] || "auth_db" %> + host: <%= ENV["PGHOST"] || "localhost" %> + username: <%= ENV["POSTGRES_USER"] || "learn_admin_user" %> + password: <%= ENV["APP_DB_ADMIN_PASSWORD"] || "postgres" %> + database: <%= ENV["POSTGRES_DB"] || "learn_db" %> min_messages: warning pool: 5 timeout: 5000 -- GitLab From 8ceaa584b4524b9ceb117c5f39c6ab671959dad4 Mon Sep 17 00:00:00 2001 From: Derrin Chong Date: Mon, 28 Sep 2020 09:02:04 -1000 Subject: [PATCH 091/283] added db:migrate --- entrypoint-server.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/entrypoint-server.sh b/entrypoint-server.sh index 6fa9cea..3df1bbc 100755 --- a/entrypoint-server.sh +++ b/entrypoint-server.sh @@ -1,4 +1,5 @@ #!/bin/sh rm -f tmp/pids/server.pid +bundle exec rails db:migrate RAILS_ENV=production rails server -b 0.0.0.0 -p 3000 -- GitLab From e958bae101089daf0528d3398aef68e4cfcc4def Mon Sep 17 00:00:00 2001 From: Derrin Chong Date: Mon, 28 Sep 2020 09:39:52 -1000 Subject: [PATCH 092/283] Write to stderr --- config/environments/production.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/config/environments/production.rb b/config/environments/production.rb index 41f4ff0..52b5b46 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -48,9 +48,15 @@ Rails.application.configure do # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. config.force_ssl = false + # Enable stdout logger + 
config.logger = Logger.new(STDOUT) + + 

# Set log level
 + config.log_level = :ERROR + # Use the lowest log level to ensure availability of diagnostic information # when problems arise. - config.log_level = :debug + # config.log_level = :debug # Prepend all log lines with the following tags. config.log_tags = [:request_id] -- GitLab From be11987566f33fb2af8284689291fc3091f18728 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 28 Sep 2020 10:02:47 -1000 Subject: [PATCH 093/283] adding check for production env to not allow token in query params --- app/controllers/sessions_controller.rb | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 852edbc..a837b85 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -24,12 +24,18 @@ class SessionsController < ActionController::Base end def token - if !request.env["Authorization"].nil? + if Rails.env == 'production' pattern = /^Bearer / header = request.env["Authorization"] header.gsub(pattern, '') if header&.match(pattern) - elsif !request.query_parameters["token"].nil? - request.query_parameters["token"] + else + if !request.env["Authorization"].nil? + pattern = /^Bearer / + header = request.env["Authorization"] + header.gsub(pattern, '') if header&.match(pattern) + elsif !request.query_parameters["token"].nil? + request.query_parameters["token"] + end end end end -- GitLab From f611df0cbe75ef818fa66e4b750ed9013d636e3f Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 28 Sep 2020 10:10:16 -1000 Subject: [PATCH 094/283] removing keycloak settings --- .env.example | 9 +- app/services/keycloak_resolver_service.rb | 29 --- config/secrets.yml | 6 - .../keycloak_resolver_service_spec.rb | 190 ------------------ 4 files changed, 4 insertions(+), 230 deletions(-) delete mode 100644 app/services/keycloak_resolver_service.rb delete mode 100644 spec/services/keycloak_resolver_service_spec.rb diff --git a/.env.example b/.env.example index b8be933..2ad408f 100644 --- a/.env.example +++ b/.env.example @@ -7,8 +7,7 @@ ASSESSMENTS_CALLBACK_TOKEN= LEARN_FIND_COHORT_URL="http://localhost:3002/cohorts/find" DS_PREP_UID="01t0a000005He03AAC" STANDARD_EVENT_UIDS="40f3bb48-1d23-4105-a22a-7f07b90bd1e6,cc22ef7e-d9c9-4e3d-ae9f-39f3477c5861" -KEYCLOAK_CLIENT_ID=forge -KEYCLOAK_CLIENT_SECRET=487b8a4a-e437-4795-9e1e-b68a9c340afb -KEYCLOAK_ENDPOINT=http://localhost:8080 -KEYCLOAK_REALM=learn -S3_REGION=us-gov-west-1 \ No newline at end of file +S3_REGION=us-gov-west-1 +accesskey= +secretkey= +appS3BucketUUID= \ No newline at end of file diff --git a/app/services/keycloak_resolver_service.rb b/app/services/keycloak_resolver_service.rb deleted file mode 100644 index a9aacb1..0000000 --- a/app/services/keycloak_resolver_service.rb +++ /dev/null @@ -1,29 +0,0 @@ -class KeycloakResolverService - - def initialize(auth_hash) - @auth_hash = auth_hash - end - - def find_or_create_user - existing_user = User.find_by(email: @auth_hash.info.email) - - if existing_user - existing_user.update(uid: @auth_hash.uid, - first_name: @auth_hash.info.first_name, - last_name: @auth_hash.info.last_name - ) - - existing_user - else - user = User.create(uid: @auth_hash.uid, - first_name: @auth_hash.info.first_name, - last_name: @auth_hash.info.last_name, - email: @auth_hash.info.email, - roles: [] - ) - - user - end - end - -end diff --git a/config/secrets.yml b/config/secrets.yml index c07c473..e0048ab 100644 --- a/config/secrets.yml +++ b/config/secrets.yml @@ -7,12 +7,6 @@ shared: auth_client_secret: <%= ENV["AUTH_CLIENT_SECRET"] %> auth_url: <%= ENV["AUTH_URL"] %> auth_webhook_token: <%= ENV["AUTH_WEBHOOK_TOKEN"] %> - keycloak_client_id: <%= ENV["KEYCLOAK_CLIENT_ID"] %> - keycloak_client_secret: <%= ENV["KEYCLOAK_CLIENT_SECRET"] %> - keycloak_logout_url: <%= "#{ENV["KEYCLOAK_ENDPOINT"]}/auth/realms/#{ENV["KEYCLOAK_REALM"]}/protocol/openid-connect/logout?redirect_uri=" %> - keycloak_client_options: - site: <%= ENV["KEYCLOAK_ENDPOINT"] %> - realm: <%= ENV["KEYCLOAK_REALM"] %> github_token: <%= ENV["GITHUB_COM_TOKEN"] %> mixpanel_project_token: <%= ENV["MIXPANEL_PROJECT_TOKEN"] %> protocol: <%= ENV['PROTOCOL'] || "http://" %> diff --git a/spec/services/keycloak_resolver_service_spec.rb b/spec/services/keycloak_resolver_service_spec.rb deleted file mode 100644 index 9407824..0000000 --- a/spec/services/keycloak_resolver_service_spec.rb +++ /dev/null @@ -1,190 +0,0 @@ -require "spec_helper" - -# extra=# aud="account" auth_time=1599795038 azp="forge" cohort_params=#]> email="johndoe@test.com" email_verified=true exp=1599795338 family_name="Doe" given_name="John" groups=# iat=1599795038 iss="http://localhost:8080/auth/realms/learn" jti="f9089c34-7a56-414f-9467-61afdb8f043b" name="John Doe" preferred_username="johndoe" realm_access=#> resource_access=#>> scope="profile email" session_state="ab796f96-c77d-4f68-879e-d942c418c5bc" sub="a05f3bf9-a87a-4532-8e03-f53b62b320df" typ="Bearer">> info=# provider="keycloakopenid" uid="a05f3bf9-a87a-4532-8e03-f53b62b320df"> - -describe KeycloakResolverService do - omniauth_hash = { - provider: "keycloak", - uid: "swordfighter", - info: { - first_name: "Inigo", - last_name: "Montoya", - email: "inigo_montoya@example.com", - }, - extra: { - raw_info: { - realm_access: { - roles: [User::ROLES[:admin], "futzy.butzy"] - } - } - } - } - auth_hash = OmniAuth::AuthHash.new(omniauth_hash) - - subject { KeycloakResolverService.new(auth_hash) } - - it "is instantiated by RSpec" do - expect(subject).to be_a(KeycloakResolverService) - end - - describe ".resolve_user" do - let(:auth_user) do - User.new( - uid: "gunslinger", - first_name: "Roland", - last_name: "Deschain", - email: "tower_hunter77@example.com", - preferred_campus: "Denver", - github_username: "foobur", - roles: [] - ) - end - - let(:products) do - [ - Cohort.new( - uid: "abc123", - product_type: "Course/Foo", - gcode: "g123", - name: "dafuq", - starts_on: Time.zone.now - ), - Cohort.new( - uid: "xyz123", - product_type: "Other", - name: "dafuq-2" - ) - ] - end - - let(:registrations) do - [ - CohortUser.new( - roles: [], - data: {}, - product: products.first - ) - ] - end - - describe "creating a new user" do - before do - # create(:cohort, uid: "abc123") - # auth_user.registrations = registrations - end - - it "initializes auth-hash" do - expect(subject.instance_variable_get(:@auth_hash)).to eq auth_hash - end - - it "initializes new user" do - expect(auth_user.uid).to eq "gunslinger" - expect(auth_user.first_name).to eq "Roland" - expect(auth_user.last_name).to eq "Deschain" - expect(auth_user.email).to eq "tower_hunter77@example.com" - expect(auth_user.preferred_campus).to eq "Denver" - expect(auth_user.github_username).to eq "foobur" - expect(auth_user.roles).to eq [] - end - - it "creates a unique user with the admin role, saving other roles" do - auth_user.roles = [User::ROLES[:admin], "futzy.butzy"] - - user = nil - expect { user = subject.find_or_create_user }.to change { User.count }.by(1) - expect(user.admin?).to be true - expect(user.first_name).to eq "Inigo" - expect(user.last_name).to eq "Montoya" - expect(user.roles).to eq([User::ROLES[:admin], "futzy.butzy"]) - - # It doesn't add a new user if the user already exists - new_user = nil - user_count = User.count - new_user = subject.find_or_create_user - expect(User.count).to eq user_count - expect(new_user.admin?).to be true - expect(new_user.first_name).to eq "Inigo" - expect(new_user.last_name).to eq "Montoya" - expect(new_user.roles).to eq([User::ROLES[:admin], "futzy.butzy"]) - end - end - - describe "updating existing users" do - let!(:user) do - create(:user, - uid: "gunslinger", - first_name: "changeme", - last_name: "changeme2", - email: "changeagain@example.com", - preferred_campus: "Austin", - roles: [User::ROLES[:admin]]) - end - - xit "changes the intersected attributes" do - auth_user.roles = [User::ROLES[:admin]] - - subject.resolve_user(auth_user) - expect(user.reload.first_name).to eq "Roland" - expect(user.last_name).to eq "Deschain" - expect(user.preferred_campus).to eq "Denver" - expect(user.email).to eq "tower_hunter77@example.com" - expect(user.github_username).to eq "foobur" - end - - xit "removes the admin role" do - create(:cohort, uid: "abc123") - - subject.resolve_user(auth_user) - expect(user.reload.admin?).to be false - end - - xit "adds new cohort_users" do - create(:cohort, uid: "abc123") - create(:cohort_user, :student, cohort: create(:cohort, uid: "xyz123"), user: user) - auth_user.registrations = registrations - - subject.resolve_user(auth_user) - expect(user.cohorts.length).to eq 1 - expect(user.cohorts.first.uid).to eq "abc123" - end - - xit "removes existing cohort_users that aren't active anymore" do - create(:cohort_user, :student, cohort: create(:cohort, uid: "xyz123"), user: user) - - expect { subject.resolve_user(auth_user) }.to change { user.reload.cohorts.length }.from(1).to(0) - end - - context "when the user's auth registration role has changed" do - before do - auth_user.registrations = registrations - auth_user.registrations.first.roles << CohortUser::ROLES[:instructor] - create(:cohort_user, :student, cohort: create(:cohort, uid: "abc123"), user: user) - end - - xit "updates the existing cohort_user" do - expect { subject.resolve_user(auth_user) }.to_not(change { User.count }) - expect(user.reload.cohorts.length).to eq 1 - expect(user.cohorts.first.uid).to eq "abc123" - expect(user.cohort_users.first.roles).to include(CohortUser::ROLES[:instructor]) - end - end - end - - describe "soft-deleting a user" do - let!(:user) do - create(:user, - uid: "gunslinger", - first_name: "changeme", - last_name: "changeme2", - email: "changeagain@example.com") - end - - xit "removes all cohort user records" do - auth_user.attributes[:is_deleted] = true - auth_user.registrations = registrations - create(:cohort_user, :student, cohort: create(:cohort, uid: "abc123"), user: user) - expect { subject.resolve_user(auth_user) }.to change { user.reload.cohorts.length }.from(1).to(0) - end - end - end -end -- GitLab From 3990d40fddb3dda10fd2800dcb596c243e2df7d0 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 28 Sep 2020 10:13:44 -1000 Subject: [PATCH 095/283] removing weird characters --- config/environments/production.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/environments/production.rb b/config/environments/production.rb index 52b5b46..028aac6 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -48,10 +48,10 @@ Rails.application.configure do # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. config.force_ssl = false - # Enable stdout logger - 
config.logger = Logger.new(STDOUT) + # Enable stdout logger. + config.logger = Logger.new(STDOUT) - 

# Set log level
 + # Set log level. config.log_level = :ERROR # Use the lowest log level to ensure availability of diagnostic information -- GitLab From 0a336dfcd5c700fb86a8ac0d4e3901606058d5aa Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 28 Sep 2020 11:28:51 -1000 Subject: [PATCH 096/283] changing auth header name --- app/controllers/sessions_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 852edbc..1ef778b 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -24,9 +24,9 @@ class SessionsController < ActionController::Base end def token - if !request.env["Authorization"].nil? + if !request.env["HTTP_AUTHORIZATION"].nil? pattern = /^Bearer / - header = request.env["Authorization"] + header = request.env["HTTP_AUTHORIZATION"] header.gsub(pattern, '') if header&.match(pattern) elsif !request.query_parameters["token"].nil? request.query_parameters["token"] -- GitLab From c8537da3778475528658099ed70c5c6728c2e914 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 28 Sep 2020 12:05:30 -1000 Subject: [PATCH 097/283] changing log level. adding logs --- app/services/platform_one_auth_resolver_service.rb | 5 +++++ config/environments/production.rb | 5 +---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/services/platform_one_auth_resolver_service.rb b/app/services/platform_one_auth_resolver_service.rb index 05f913e..1f5b8c9 100644 --- a/app/services/platform_one_auth_resolver_service.rb +++ b/app/services/platform_one_auth_resolver_service.rb @@ -1,6 +1,7 @@ class PlatformOneAuthResolverService def initialize(jwt_token) @payload = JWT.decode(jwt_token, nil, false)[0] + puts @payload end def find_or_create_user @@ -21,6 +22,10 @@ class PlatformOneAuthResolverService roles: [] ) + unless user.valid? + puts user.errors.full_messages + end + user end end diff --git a/config/environments/production.rb b/config/environments/production.rb index 028aac6..48c5407 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -51,12 +51,9 @@ Rails.application.configure do # Enable stdout logger. config.logger = Logger.new(STDOUT) - # Set log level. - config.log_level = :ERROR - # Use the lowest log level to ensure availability of diagnostic information # when problems arise. - # config.log_level = :debug + config.log_level = :debug # Prepend all log lines with the following tags. config.log_tags = [:request_id] -- GitLab From 23f08c6abe1efac2bebe703052066fd6a4e1825b Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 28 Sep 2020 12:38:08 -1000 Subject: [PATCH 098/283] user certificate parsing --- .../platform_one_auth_resolver_service.rb | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/app/services/platform_one_auth_resolver_service.rb b/app/services/platform_one_auth_resolver_service.rb index 1f5b8c9..b01078f 100644 --- a/app/services/platform_one_auth_resolver_service.rb +++ b/app/services/platform_one_auth_resolver_service.rb @@ -1,24 +1,37 @@ class PlatformOneAuthResolverService + class UserCertificateError < StandardError + end + def initialize(jwt_token) @payload = JWT.decode(jwt_token, nil, false)[0] - puts @payload + user_certificate = @payload["usercertificate"] + user_parts = user_certificate.split(".") + + if user_parts.nil? || user_parts.length < 3 + raise UserCertificateError + end + + @dod_id = user_parts.last + @last_name = user_parts[0] + @first_name = user_parts[1] + @email = @payload["email"] || "#{@first_name}.#{@last_name}@changeme.com" end def find_or_create_user - existing_user = User.find_by(email: @payload["email"]) + existing_user = User.find_by(email: @email) if existing_user - existing_user.update(uid: @payload["sub"], - first_name: @payload["given_name"], - last_name: @payload["family_name"] + existing_user.update(uid: @dod_id, + first_name: @first_name, + last_name: @last_name ) existing_user else - user = User.create(uid: @payload["sub"], - first_name: @payload["given_name"], - last_name: @payload["family_name"], - email: @payload["email"], + user = User.create(uid: @dod_id, + first_name: @first_name, + last_name: @last_name, + email: @email, roles: [] ) -- GitLab From 0b45da6619a2bf7b3e0928d3159ad80bdfb7084d Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 28 Sep 2020 13:53:04 -1000 Subject: [PATCH 099/283] change to titleize the names from the jwt token. change to set email to blank string instead of fake email --- app/services/platform_one_auth_resolver_service.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/services/platform_one_auth_resolver_service.rb b/app/services/platform_one_auth_resolver_service.rb index b01078f..b24dc26 100644 --- a/app/services/platform_one_auth_resolver_service.rb +++ b/app/services/platform_one_auth_resolver_service.rb @@ -2,6 +2,9 @@ class PlatformOneAuthResolverService class UserCertificateError < StandardError end + class CreateUserError < StandardError + end + def initialize(jwt_token) @payload = JWT.decode(jwt_token, nil, false)[0] user_certificate = @payload["usercertificate"] @@ -12,9 +15,9 @@ class PlatformOneAuthResolverService end @dod_id = user_parts.last - @last_name = user_parts[0] - @first_name = user_parts[1] - @email = @payload["email"] || "#{@first_name}.#{@last_name}@changeme.com" + @last_name = user_parts[0].titleize + @first_name = user_parts[1].titleize + @email = @payload["email"] || "" end def find_or_create_user @@ -37,6 +40,7 @@ class PlatformOneAuthResolverService unless user.valid? puts user.errors.full_messages + raise CreateUserError end user -- GitLab From 43e71492b7c6d9facddaa243a806efb7e1dbda4d Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 28 Sep 2020 13:57:29 -1000 Subject: [PATCH 100/283] updating bundle lock file --- Gemfile.lock | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 6360384..b82f726 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -58,7 +58,6 @@ GEM minitest (~> 5.1) tzinfo (~> 1.1) addressable (2.4.0) - aes_key_wrap (1.1.0) analytics-ruby (2.0.13) apitome (0.3.0) kramdown @@ -86,7 +85,6 @@ GEM coderay (>= 1.0.0) erubi (>= 1.0.0) rack (>= 0.9.0) - bindata (2.4.8) binding_of_caller (0.8.0) debug_inspector (>= 0.0.1) bootsnap (1.3.1) @@ -175,7 +173,6 @@ GEM temple (>= 0.8.0) tilt hashdiff (0.4.0) - hashie (4.1.0) honeybadger (3.2.0) httparty (0.15.6) multi_xml (>= 0.5.2) @@ -191,10 +188,6 @@ GEM js-routes (1.4.2) railties (>= 3.2) sprockets-rails - json-jwt (1.13.0) - activesupport (>= 4.2) - aes_key_wrap - bindata json_spec (1.1.5) multi_json (~> 1.0) rspec (>= 2.0, < 4.0) @@ -227,24 +220,8 @@ GEM nio4r (2.3.1) nokogiri (1.8.0) mini_portile2 (~> 2.2.0) - oauth2 (1.4.4) - faraday (>= 0.8, < 2.0) - jwt (>= 1.0, < 3.0) - multi_json (~> 1.3) - multi_xml (~> 0.5) - rack (>= 1.2, < 3) octokit (4.3.0) sawyer (~> 0.7.0, >= 0.5.3) - omniauth (1.9.1) - hashie (>= 3.4.6) - rack (>= 1.6.2, < 3) - omniauth-keycloak (1.2.0) - json-jwt (~> 1.12) - omniauth (~> 1.9.0) - omniauth-oauth2 (~> 1.6.0) - omniauth-oauth2 (1.6.0) - oauth2 (~> 1.1) - omniauth (~> 1.9) overcommit (0.41.0) childprocess (~> 0.6, >= 0.6.3) iniparse (~> 1.4) @@ -451,8 +428,6 @@ DEPENDENCIES mathjax-rails memory_profiler octokit - omniauth - omniauth-keycloak overcommit pagy pg (~> 0.18) -- GitLab From 632d3c98ddb0306c9b97f9c52c5204ea74499933 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 28 Sep 2020 14:18:39 -1000 Subject: [PATCH 101/283] adding log --- app/services/platform_one_auth_resolver_service.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/services/platform_one_auth_resolver_service.rb b/app/services/platform_one_auth_resolver_service.rb index b24dc26..7fe812e 100644 --- a/app/services/platform_one_auth_resolver_service.rb +++ b/app/services/platform_one_auth_resolver_service.rb @@ -7,6 +7,7 @@ class PlatformOneAuthResolverService def initialize(jwt_token) @payload = JWT.decode(jwt_token, nil, false)[0] + puts @payload user_certificate = @payload["usercertificate"] user_parts = user_certificate.split(".") -- GitLab From 8c40495a568473f168c71fb278afdc154e1d6431 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 28 Sep 2020 14:55:04 -1000 Subject: [PATCH 102/283] adding handling for non CAC users. change db to allow empty emails --- app/models/user.rb | 2 +- .../platform_one_auth_resolver_service.rb | 32 +++++++++++-------- ...0929004708_remove_null_email_from_users.rb | 5 +++ db/schema.rb | 4 +-- 4 files changed, 27 insertions(+), 16 deletions(-) create mode 100644 db/migrate/20200929004708_remove_null_email_from_users.rb diff --git a/app/models/user.rb b/app/models/user.rb index 612af35..38dde44 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -8,7 +8,7 @@ class User < ApplicationRecord blocks_manager: "forge.blocks_manager" }.freeze - validates(:email, presence: true) + # validates(:email, presence: true) validates(:uid, uniqueness: true) has_many :cohort_users diff --git a/app/services/platform_one_auth_resolver_service.rb b/app/services/platform_one_auth_resolver_service.rb index 7fe812e..2d74bae 100644 --- a/app/services/platform_one_auth_resolver_service.rb +++ b/app/services/platform_one_auth_resolver_service.rb @@ -8,31 +8,37 @@ class PlatformOneAuthResolverService def initialize(jwt_token) @payload = JWT.decode(jwt_token, nil, false)[0] puts @payload - user_certificate = @payload["usercertificate"] - user_parts = user_certificate.split(".") + @email = @payload["email"] || "" - if user_parts.nil? || user_parts.length < 3 - raise UserCertificateError - end + if @payload["usercertificate"].nil? || @payload["usercertificate"].empty? + @uid = @payload["sub"] + @first_name = "" + @last_name = "" + else + user_certificate = @payload["usercertificate"] + user_parts = user_certificate.split(".") - @dod_id = user_parts.last - @last_name = user_parts[0].titleize - @first_name = user_parts[1].titleize - @email = @payload["email"] || "" + if user_parts.nil? || user_parts.length < 3 + raise UserCertificateError + end + + @uid = user_parts.last + @last_name = user_parts[0].titleize + @first_name = user_parts[1].titleize + end end def find_or_create_user - existing_user = User.find_by(email: @email) + existing_user = User.find_by(uid: @uid) if existing_user - existing_user.update(uid: @dod_id, - first_name: @first_name, + existing_user.update(first_name: @first_name, last_name: @last_name ) existing_user else - user = User.create(uid: @dod_id, + user = User.create(uid: @uid, first_name: @first_name, last_name: @last_name, email: @email, diff --git a/db/migrate/20200929004708_remove_null_email_from_users.rb b/db/migrate/20200929004708_remove_null_email_from_users.rb new file mode 100644 index 0000000..1610586 --- /dev/null +++ b/db/migrate/20200929004708_remove_null_email_from_users.rb @@ -0,0 +1,5 @@ +class RemoveNullEmailFromUsers < ActiveRecord::Migration[5.2] + def change + change_column( :users, :email, :string, :null => true) + end +end diff --git a/db/schema.rb b/db/schema.rb index f5e6ecd..f205c10 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2020_09_25_230149) do +ActiveRecord::Schema.define(version: 2020_09_29_004708) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -359,7 +359,7 @@ ActiveRecord::Schema.define(version: 2020_09_25_230149) do t.string "uid" t.string "first_name" t.string "last_name" - t.string "email", null: false + t.string "email" t.string "timezone" t.string "profile_image" t.datetime "created_at", null: false -- GitLab From 8efdde79f5d1533277e1113c1d160092c1c7e749 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 28 Sep 2020 15:26:43 -1000 Subject: [PATCH 103/283] changing to use keycloak id for everyone --- app/services/platform_one_auth_resolver_service.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/services/platform_one_auth_resolver_service.rb b/app/services/platform_one_auth_resolver_service.rb index 2d74bae..a32d5d1 100644 --- a/app/services/platform_one_auth_resolver_service.rb +++ b/app/services/platform_one_auth_resolver_service.rb @@ -8,10 +8,10 @@ class PlatformOneAuthResolverService def initialize(jwt_token) @payload = JWT.decode(jwt_token, nil, false)[0] puts @payload + @uid = @payload["sub"] @email = @payload["email"] || "" if @payload["usercertificate"].nil? || @payload["usercertificate"].empty? - @uid = @payload["sub"] @first_name = "" @last_name = "" else @@ -22,7 +22,6 @@ class PlatformOneAuthResolverService raise UserCertificateError end - @uid = user_parts.last @last_name = user_parts[0].titleize @first_name = user_parts[1].titleize end -- GitLab From 3b88a09d3a8c2fbe4635d79c01bce1ff0192ef33 Mon Sep 17 00:00:00 2001 From: Derrin Chong Date: Mon, 28 Sep 2020 18:45:01 -1000 Subject: [PATCH 104/283] Run webpack --- entrypoint-server.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/entrypoint-server.sh b/entrypoint-server.sh index 3df1bbc..74d5445 100755 --- a/entrypoint-server.sh +++ b/entrypoint-server.sh @@ -1,5 +1,7 @@ #!/bin/sh +/usr/src/app/bin/webpack + rm -f tmp/pids/server.pid bundle exec rails db:migrate RAILS_ENV=production rails server -b 0.0.0.0 -p 3000 -- GitLab From 4079abd87a5f56c977e02dcbf0e62f735810d7d5 Mon Sep 17 00:00:00 2001 From: Derrin Chong Date: Tue, 29 Sep 2020 10:08:27 -1000 Subject: [PATCH 105/283] Debug mode, on --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 4fa228d..3abf0b0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -62,5 +62,5 @@ RUN NODE_ENV=production bin/webpack ENV PATH /usr/src/app/node_modules/.bin:$PATH # Set the entry point. -#CMD ["tail", "-f", "/dev/null"] -CMD ["./entrypoint-server.sh"] +CMD ["tail", "-f", "/dev/null"] +#CMD ["./entrypoint-server.sh"] -- GitLab From fffa6260c89bf9e98bbcdee5767b493a40870a58 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 29 Sep 2020 11:07:23 -1000 Subject: [PATCH 106/283] fixing build issues. adding build files to git ignore. --- .gitignore | 4 +++- Dockerfile | 7 +++++-- app/controllers/cohorts_controller.rb | 2 +- config/environments/production.rb | 5 ++--- entrypoint-server.sh | 2 -- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index cbbbfd1..7aadd35 100644 --- a/.gitignore +++ b/.gitignore @@ -32,4 +32,6 @@ tags .zshrc .solargraph.yml .generators -.rakeTasks \ No newline at end of file +.rakeTasks +/public/assets/ +!/public/assets/images diff --git a/Dockerfile b/Dockerfile index 4fa228d..1148353 100644 --- a/Dockerfile +++ b/Dockerfile @@ -52,11 +52,14 @@ RUN gem install rake -v '12.3.1' --source 'https://rubygems.org/' # Run the bundle install RUN bundle install +# Precompile assets +RUN bundle exec rake assets:precompile + # Run Yarn Install RUN yarn install -# Run Webpack build. -RUN NODE_ENV=production bin/webpack +# Asset Clean +RUN bundle exec rake assets:clean # Add the node_modules to the path. ENV PATH /usr/src/app/node_modules/.bin:$PATH diff --git a/app/controllers/cohorts_controller.rb b/app/controllers/cohorts_controller.rb index 159fdd6..a8a564a 100644 --- a/app/controllers/cohorts_controller.rb +++ b/app/controllers/cohorts_controller.rb @@ -64,7 +64,7 @@ class CohortsController < ApplicationController learn_base_url: ENV["LEARN_BASE_URL"], cohort_types: cohort_types, cohort_campuses: cohort_campuses, - new_auth_product_url: Rails.application.secrets.auth_url + "/admin/products/new" + new_auth_product_url: "" } ) end diff --git a/config/environments/production.rb b/config/environments/production.rb index 48c5407..9e68ea7 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -23,15 +23,14 @@ Rails.application.configure do # Disable serving static files from the `/public` folder by default since # Apache or NGINX already handles this. - config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present? + config.public_file_server.enabled = true # Compress JavaScripts and CSS. config.assets.js_compressor = :uglifier config.assets.css_compressor = :sass # Do not fallback to assets pipeline if a precompiled asset is missed. - # config.assets.compile = false - config.assets.compile = true + config.assets.compile = false # Generate digests for assets URLs. config.assets.digest = true diff --git a/entrypoint-server.sh b/entrypoint-server.sh index 74d5445..3df1bbc 100755 --- a/entrypoint-server.sh +++ b/entrypoint-server.sh @@ -1,7 +1,5 @@ #!/bin/sh -/usr/src/app/bin/webpack - rm -f tmp/pids/server.pid bundle exec rails db:migrate RAILS_ENV=production rails server -b 0.0.0.0 -p 3000 -- GitLab From d5236f1d770306f736631f07de097e91bd2c9fb6 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 29 Sep 2020 11:09:10 -1000 Subject: [PATCH 107/283] switching to startup the app. --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7de8b07..1148353 100644 --- a/Dockerfile +++ b/Dockerfile @@ -65,5 +65,5 @@ RUN bundle exec rake assets:clean ENV PATH /usr/src/app/node_modules/.bin:$PATH # Set the entry point. -CMD ["tail", "-f", "/dev/null"] -#CMD ["./entrypoint-server.sh"] +#CMD ["tail", "-f", "/dev/null"] +CMD ["./entrypoint-server.sh"] -- GitLab From 6bc2cf0282288d40f5756ffcfb1fe4008d1facfc Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 29 Sep 2020 11:34:43 -1000 Subject: [PATCH 108/283] fixing issue on other tabs loading --- app/controllers/cohorts_controller.rb | 8 ++++---- app/models/user.rb | 2 +- app/views/cohorts/users.html.haml | 4 ++-- spec/features/cohorts/management_feature_spec.rb | 2 +- spec/features/home/header_feature_spec.rb | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/controllers/cohorts_controller.rb b/app/controllers/cohorts_controller.rb index a8a564a..916e7db 100644 --- a/app/controllers/cohorts_controller.rb +++ b/app/controllers/cohorts_controller.rb @@ -102,7 +102,7 @@ class CohortsController < ApplicationController locals: { cohort: current_cohort, release_count: release_count, - auth_product_url: Rails.application.secrets.auth_url + "/admin/products/#{current_cohort.uid}" + auth_product_url: "" } ) end @@ -127,7 +127,7 @@ class CohortsController < ApplicationController visibilities: visibilities ) end, - auth_product_url: Rails.application.secrets.auth_url + "/admin/products/#{current_cohort.uid}" + auth_product_url: "" } ) end @@ -315,7 +315,7 @@ class CohortsController < ApplicationController end, unattached_block_release_options: ReleaseFinder.latest_for_all_blocks_not_attached_to_cohort(current_cohort.id), - auth_product_url: Rails.application.secrets.auth_url + "/admin/products/#{current_cohort.uid}" + auth_product_url: "" } ) end @@ -339,7 +339,7 @@ class CohortsController < ApplicationController students: current_cohort.cohort_users.student.map { |s| { uid: s.user.uid, name: s.user.full_name, profile_image: s.user.profile_image }}, release_count: release_count, pairings: Pairing.where(cohort_id: current_cohort.id).order(created_at: :desc), - auth_product_url: "#{Rails.application.secrets.auth_url}/admin/products/#{current_cohort.uid}" + auth_product_url: "" } ) end diff --git a/app/models/user.rb b/app/models/user.rb index 38dde44..c56665e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -120,6 +120,6 @@ class User < ApplicationRecord end def auth_edit_url - "#{Rails.application.secrets.auth_url}/admin/users/#{uid}/edit" + "" end end diff --git a/app/views/cohorts/users.html.haml b/app/views/cohorts/users.html.haml index 55e7d0e..aff6bbc 100644 --- a/app/views/cohorts/users.html.haml +++ b/app/views/cohorts/users.html.haml @@ -45,7 +45,7 @@ %td.action-cell yes %div.user-action - = react_component "cohorts/settings/UserCohortKebab", studentId: instructor.id, studentUid: instructor.uid, cohortId: cohort.id, authUrl: Rails.application.secrets.auth_url + = react_component "cohorts/settings/UserCohortKebab", studentId: instructor.id, studentUid: instructor.uid, cohortId: cohort.id, authUrl: "" - cohort.students.order(first_name: :asc).each do |student| %tr.cohortsetuprow %td.cohortusername= student.full_name @@ -54,4 +54,4 @@ %td.action-cell no %div.user-action - = react_component "cohorts/settings/UserCohortKebab", studentId: student.id, studentUid: student.uid, cohortId: cohort.id, authUrl: Rails.application.secrets.auth_url + = react_component "cohorts/settings/UserCohortKebab", studentId: student.id, studentUid: student.uid, cohortId: cohort.id, authUrl: "" diff --git a/spec/features/cohorts/management_feature_spec.rb b/spec/features/cohorts/management_feature_spec.rb index 47b8799..84b1dd4 100644 --- a/spec/features/cohorts/management_feature_spec.rb +++ b/spec/features/cohorts/management_feature_spec.rb @@ -202,7 +202,7 @@ describe "Cohorts management", js: true do expect(page).to have_content(cohort.name) expect(page).to have_content(cohort.campus_name) expect(page).to have_content(cohort.starts_on.strftime("%b %e, %Y")) - expect(page).to have_link("Edit", href: "#{Rails.application.secrets.auth_url}/admin/products/#{cohort.uid}/edit") + # expect(page).to have_link("Edit", href: "#{Rails.application.secrets.auth_url}/admin/products/#{cohort.uid}/edit") end end diff --git a/spec/features/home/header_feature_spec.rb b/spec/features/home/header_feature_spec.rb index db82458..4b327d0 100644 --- a/spec/features/home/header_feature_spec.rb +++ b/spec/features/home/header_feature_spec.rb @@ -174,7 +174,7 @@ describe "Header", js: true do it "links out to auth account management" do within(".primary-navigation") do all(".navigation-dropdown").last.hover - expect(page).to have_link("My Account", href: "#{Rails.application.secrets.auth_url}/account") + # expect(page).to have_link("My Account", href: "#{Rails.application.secrets.auth_url}/account") end end end -- GitLab From b627c2855b7f06d9ba88ea096901fabacb7816d9 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 29 Sep 2020 11:57:24 -1000 Subject: [PATCH 109/283] adding startup of sidekiq --- entrypoint-server.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/entrypoint-server.sh b/entrypoint-server.sh index 3df1bbc..23730d1 100755 --- a/entrypoint-server.sh +++ b/entrypoint-server.sh @@ -2,4 +2,5 @@ rm -f tmp/pids/server.pid bundle exec rails db:migrate +bundle exec sidekiq & RAILS_ENV=production rails server -b 0.0.0.0 -p 3000 -- GitLab From aa47ec5803763bab7b9eee6264eb35539919d135 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 29 Sep 2020 12:22:57 -1000 Subject: [PATCH 110/283] changing api app controller current user. --- app/controllers/api/application_controller.rb | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/application_controller.rb b/app/controllers/api/application_controller.rb index 128bcd8..24c4ae6 100644 --- a/app/controllers/api/application_controller.rb +++ b/app/controllers/api/application_controller.rb @@ -37,11 +37,13 @@ class Api::ApplicationController < ActionController::API end def current_user - @current_user ||= if request.headers["Authorization"] - User.find_by(api_token: bearer_token) - else - User.find_by(uid: session[:user_uid]) - end + # @current_user ||= if request.headers["Authorization"] + # User.find_by(api_token: bearer_token) + # else + # User.find_by(uid: session[:user_uid]) + # end + + @current_user ||= User.find_by(uid: session[:user_uid]) end def current_cohort -- GitLab From ac257f92efb162af8d36a3f410a5574c99d14964 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 29 Sep 2020 14:38:58 -1000 Subject: [PATCH 111/283] changing sidekiq to run in production mode and log to file. --- .gitignore | 1 + entrypoint-server.sh | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 7aadd35..6b52443 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ tags .rakeTasks /public/assets/ !/public/assets/images +log.txt \ No newline at end of file diff --git a/entrypoint-server.sh b/entrypoint-server.sh index 23730d1..588f9ad 100755 --- a/entrypoint-server.sh +++ b/entrypoint-server.sh @@ -2,5 +2,5 @@ rm -f tmp/pids/server.pid bundle exec rails db:migrate -bundle exec sidekiq & -RAILS_ENV=production rails server -b 0.0.0.0 -p 3000 +RAILS_ENV=production bundle exec sidekiq > log.txt 2>&1 & +RAILS_ENV=production rails server -b 0.0.0.0 -p 3000 \ No newline at end of file -- GitLab From a9c219b65101d66102f26eb11cdac8c9dfb6ea02 Mon Sep 17 00:00:00 2001 From: Derrin Chong Date: Tue, 29 Sep 2020 15:30:41 -1000 Subject: [PATCH 112/283] Install redis --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 1148353..8439451 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,6 +4,7 @@ ENV count 6 # Install what we can through OS package management RUN apt-get -y update RUN apt-get -y install --no-install-recommends \ + redis-tools \ curl \ software-properties-common \ postgresql-client\ -- GitLab From 61831f2f5c48201835d546080961436860f3463c Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 29 Sep 2020 16:19:27 -1000 Subject: [PATCH 113/283] changes for minio --- config/initializers/aws.rb | 10 +++++++++- config/secrets.yml | 5 +++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/config/initializers/aws.rb b/config/initializers/aws.rb index 9694d1d..b3f02f1 100644 --- a/config/initializers/aws.rb +++ b/config/initializers/aws.rb @@ -35,5 +35,13 @@ end Rails.application.config.aws = if Rails.env.test? AwsMock.new else - Aws::S3::Resource.new(region: Rails.application.secrets.s3_region).bucket(Rails.application.secrets.glearn_bucket_name) + options = { + :region => Rails.application.secrets.s3_region + } + + if !Rails.application.secrets.minio_endpoint_url.nil? + options[:endpoint] = Rails.application.secrets.minio_endpoint_url + end + + Aws::S3::Resource.new(options).bucket(Rails.application.secrets.glearn_bucket_name) end diff --git a/config/secrets.yml b/config/secrets.yml index ce9959d..0898743 100644 --- a/config/secrets.yml +++ b/config/secrets.yml @@ -10,7 +10,7 @@ shared: github_token: <%= ENV["GITHUB_COM_TOKEN"] %> mixpanel_project_token: <%= ENV["MIXPANEL_PROJECT_TOKEN"] %> protocol: <%= ENV['PROTOCOL'] || "http://" %> - s3_bucket_name: <%= ENV["appS3BucketUUID"] %> + s3_bucket_name: <%= ENV["APP_S3_BUCKET"] %> secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> sendgrid_password: <%= ENV['SENDGRID_PASSWORD'] %> sendgrid_username: <%= ENV['SENDGRID_USERNAME'] %> @@ -23,9 +23,10 @@ shared: glearn_access_key_id: <%= ENV['accesskey'] %> glearn_secret_access_key: <%= ENV['secretkey'] %> glearn_key_prefix: <%= ENV['GLEARN_KEY_PREFIX'] || "forge" %> - glearn_bucket_name: <%= ENV["appS3BucketUUID"] %> + glearn_bucket_name: <%= ENV["APP_S3_BUCKET"] %> s3_region: <%= ENV["S3_REGION"] || "us-gov-west-1" %> dev_notify_slack_url: <%= ENV['DEV_NOTIFY_SLACK_URL'] %> + minio_endpoint_url: <%= ENV["MINIO_ENDPOINT_URL"] %> git_download_tokens: github_com: type: github -- GitLab From 261d99f5bf15b7f5f581dd4098d1ab0de1603a01 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 29 Sep 2020 16:40:53 -1000 Subject: [PATCH 114/283] changing sidekiq production mode parameter. --- entrypoint-server.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/entrypoint-server.sh b/entrypoint-server.sh index 588f9ad..42dd16f 100755 --- a/entrypoint-server.sh +++ b/entrypoint-server.sh @@ -2,5 +2,5 @@ rm -f tmp/pids/server.pid bundle exec rails db:migrate -RAILS_ENV=production bundle exec sidekiq > log.txt 2>&1 & +bundle exec sidekiq -e production > log.txt 2>&1 & RAILS_ENV=production rails server -b 0.0.0.0 -p 3000 \ No newline at end of file -- GitLab From 080bf709864f1c763039de8dbf9ff65729811bf6 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 29 Sep 2020 16:45:31 -1000 Subject: [PATCH 115/283] changing sidekiq command --- entrypoint-server.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/entrypoint-server.sh b/entrypoint-server.sh index 42dd16f..1106a52 100755 --- a/entrypoint-server.sh +++ b/entrypoint-server.sh @@ -2,5 +2,5 @@ rm -f tmp/pids/server.pid bundle exec rails db:migrate -bundle exec sidekiq -e production > log.txt 2>&1 & +bundle exec sidekiq -d -e production -L sidekiq.log -C config/sidekiq.yml RAILS_ENV=production rails server -b 0.0.0.0 -p 3000 \ No newline at end of file -- GitLab From 524e8e85c63fe65d645598036ad240158707f7a2 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 29 Sep 2020 18:03:44 -1000 Subject: [PATCH 116/283] fixing aws module setup for minio --- .gitignore | 3 ++- config/initializers/aws.rb | 30 +++++++++++++++++------------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 6b52443..d8bcd2a 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,5 @@ tags .rakeTasks /public/assets/ !/public/assets/images -log.txt \ No newline at end of file +log.txt +sidekiq.log \ No newline at end of file diff --git a/config/initializers/aws.rb b/config/initializers/aws.rb index b3f02f1..6961a43 100644 --- a/config/initializers/aws.rb +++ b/config/initializers/aws.rb @@ -32,16 +32,20 @@ class AwsMock end end -Rails.application.config.aws = if Rails.env.test? - AwsMock.new - else - options = { - :region => Rails.application.secrets.s3_region - } - - if !Rails.application.secrets.minio_endpoint_url.nil? - options[:endpoint] = Rails.application.secrets.minio_endpoint_url - end - - Aws::S3::Resource.new(options).bucket(Rails.application.secrets.glearn_bucket_name) - end +if Rails.env.test? + Rails.application.config.aws = AwsMock.new +else + options = { + :access_key_id => Rails.application.secrets.glearn_access_key_id, + :secret_access_key => Rails.application.secrets.glearn_secret_access_key + } + + if !Rails.application.secrets.minio_endpoint_url.nil? + options[:endpoint] = Rails.application.secrets.minio_endpoint_url + options[:force_path_style] = true + else + options[:region] = Rails.application.secrets.s3_region + end + + Rails.application.config.aws = Aws::S3::Resource.new(options).bucket(Rails.application.secrets.glearn_bucket_name) +end \ No newline at end of file -- GitLab From 0ee42f934cb4078dc2ba97a42b7d2a712737b9b8 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 29 Sep 2020 18:54:06 -1000 Subject: [PATCH 117/283] adding region back in --- config/initializers/aws.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/config/initializers/aws.rb b/config/initializers/aws.rb index 6961a43..bf80004 100644 --- a/config/initializers/aws.rb +++ b/config/initializers/aws.rb @@ -37,14 +37,13 @@ if Rails.env.test? else options = { :access_key_id => Rails.application.secrets.glearn_access_key_id, - :secret_access_key => Rails.application.secrets.glearn_secret_access_key + :secret_access_key => Rails.application.secrets.glearn_secret_access_key, + :region => Rails.application.secrets.s3_region } if !Rails.application.secrets.minio_endpoint_url.nil? options[:endpoint] = Rails.application.secrets.minio_endpoint_url options[:force_path_style] = true - else - options[:region] = Rails.application.secrets.s3_region end Rails.application.config.aws = Aws::S3::Resource.new(options).bucket(Rails.application.secrets.glearn_bucket_name) -- GitLab From cf166164b4fed5c432d6f30c7f24d6a25c780c18 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Wed, 30 Sep 2020 12:45:34 -1000 Subject: [PATCH 118/283] changing to use email again for looking up existing users. --- .../platform_one_auth_resolver_service.rb | 26 +++++-------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/app/services/platform_one_auth_resolver_service.rb b/app/services/platform_one_auth_resolver_service.rb index a32d5d1..d6d45b6 100644 --- a/app/services/platform_one_auth_resolver_service.rb +++ b/app/services/platform_one_auth_resolver_service.rb @@ -9,30 +9,18 @@ class PlatformOneAuthResolverService @payload = JWT.decode(jwt_token, nil, false)[0] puts @payload @uid = @payload["sub"] - @email = @payload["email"] || "" - - if @payload["usercertificate"].nil? || @payload["usercertificate"].empty? - @first_name = "" - @last_name = "" - else - user_certificate = @payload["usercertificate"] - user_parts = user_certificate.split(".") - - if user_parts.nil? || user_parts.length < 3 - raise UserCertificateError - end - - @last_name = user_parts[0].titleize - @first_name = user_parts[1].titleize - end + @email = @payload["email"] + @first_name = @payload["given_name"] + @last_name = @payload["family_name"] end def find_or_create_user - existing_user = User.find_by(uid: @uid) + existing_user = User.find_by(email: @email) if existing_user - existing_user.update(first_name: @first_name, - last_name: @last_name + existing_user.update(uid: @uid, + first_name: @first_name, + last_name: @last_name, ) existing_user -- GitLab From 4a7c32e61d0a8f3d0a4b91b187bf5ceb04362567 Mon Sep 17 00:00:00 2001 From: Derrin Chong Date: Wed, 30 Sep 2020 16:06:06 -1000 Subject: [PATCH 119/283] Revert to old method of starting sidekiq --- entrypoint-server.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/entrypoint-server.sh b/entrypoint-server.sh index 1106a52..95515d9 100755 --- a/entrypoint-server.sh +++ b/entrypoint-server.sh @@ -2,5 +2,5 @@ rm -f tmp/pids/server.pid bundle exec rails db:migrate -bundle exec sidekiq -d -e production -L sidekiq.log -C config/sidekiq.yml +bundle exec sidekiq -e production -L sidekiq.log & RAILS_ENV=production rails server -b 0.0.0.0 -p 3000 \ No newline at end of file -- GitLab From 6195f580668b9bfdbf5d70d1aa4ff44f4f41c499 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Wed, 30 Sep 2020 17:29:12 -1000 Subject: [PATCH 120/283] adding secrets for webhooks url --- config/secrets.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/secrets.yml b/config/secrets.yml index 0898743..890cc21 100644 --- a/config/secrets.yml +++ b/config/secrets.yml @@ -1,5 +1,6 @@ shared: - actionmailer_host: <%= ENV['HEROKU_APP_NAME'].present? ? "#{ENV['HEROKU_APP_NAME']}.herokuapp.com" : ENV['ACTIONMAILER_HOST'] %> + actionmailer_host: <%= ENV['ACTIONMAILER_HOST'] %> + actionmailer_port: <%= ENV['ACTIONMAILER_PORT'] %> assessments_api_key: <%= ENV['ASSESSMENTS_API_KEY'] %> assessments_callback_token: <%= ENV['ASSESSMENTS_CALLBACK_TOKEN'] %> assessments_service_domain: <%= ENV['ASSESSMENTS_SERVICE_DOMAIN'] %> -- GitLab From 11b78e58114ad0e2847fcee0ec69e112919381cd Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Wed, 30 Sep 2020 22:38:21 -1000 Subject: [PATCH 121/283] removing reference to learn base url --- app/controllers/cohorts_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/cohorts_controller.rb b/app/controllers/cohorts_controller.rb index 916e7db..5aa9eff 100644 --- a/app/controllers/cohorts_controller.rb +++ b/app/controllers/cohorts_controller.rb @@ -61,7 +61,7 @@ class CohortsController < ApplicationController all_other_cohorts: all_other_cohorts, own_cohorts: own_cohorts, cohort_id_counts: cohort_id_counts, - learn_base_url: ENV["LEARN_BASE_URL"], + learn_base_url: "", cohort_types: cohort_types, cohort_campuses: cohort_campuses, new_auth_product_url: "" -- GitLab From 3aeec713c463d4ccd71a486abc648f6339aaece0 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Thu, 1 Oct 2020 11:49:58 -1000 Subject: [PATCH 122/283] fixing bug on cohorts where user does not have a name yet --- app/models/user.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index c56665e..a307bbf 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -8,8 +8,8 @@ class User < ApplicationRecord blocks_manager: "forge.blocks_manager" }.freeze - # validates(:email, presence: true) - validates(:uid, uniqueness: true) + validates(:email, presence: true) + validates(:uid, uniqueness: true, allow_nil: true) has_many :cohort_users has_many :cohorts, through: :cohort_users @@ -35,7 +35,11 @@ class User < ApplicationRecord end def initials - "#{first_name[0]}#{last_name[0]}".upcase + if first_name.nil? || last_name.nil? + "" + else + "#{first_name[0]}#{last_name[0]}".upcase + end end def instructor_of?(cohort_id) -- GitLab From c159b84fc7a4167b61671d9655dd9ad82903d485 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Thu, 1 Oct 2020 16:19:11 -1000 Subject: [PATCH 123/283] changing the way the auth header is read. --- app/controllers/sessions_controller.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 9ee7c56..e2f99ce 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -26,12 +26,12 @@ class SessionsController < ActionController::Base def token if Rails.env == 'production' pattern = /^Bearer / - header = request.env["HTTP_AUTHORIZATION"] + header = request.headers["Authorization"] header.gsub(pattern, '') if header&.match(pattern) else - if !request.env["HTTP_AUTHORIZATION"].nil? + if !request.headers["Authorization"].nil? pattern = /^Bearer / - header = request.env["HTTP_AUTHORIZATION"] + header = request.headers["Authorization"] header.gsub(pattern, '') if header&.match(pattern) elsif !request.query_parameters["token"].nil? request.query_parameters["token"] -- GitLab From 982d7edc0984bd1a3aee389e2872218d0ca8f9ba Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Thu, 1 Oct 2020 16:49:49 -1000 Subject: [PATCH 124/283] changing header name for bearer token --- app/controllers/api/application_controller.rb | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/app/controllers/api/application_controller.rb b/app/controllers/api/application_controller.rb index 24c4ae6..8c6e56e 100644 --- a/app/controllers/api/application_controller.rb +++ b/app/controllers/api/application_controller.rb @@ -37,13 +37,11 @@ class Api::ApplicationController < ActionController::API end def current_user - # @current_user ||= if request.headers["Authorization"] - # User.find_by(api_token: bearer_token) - # else - # User.find_by(uid: session[:user_uid]) - # end - - @current_user ||= User.find_by(uid: session[:user_uid]) + @current_user ||= if request.headers["X-LEARN-API-TOKEN"] + User.find_by(api_token: bearer_token) + else + User.find_by(uid: session[:user_uid]) + end end def current_cohort @@ -58,7 +56,7 @@ class Api::ApplicationController < ActionController::API def bearer_token pattern = /^Bearer / - header = request.headers["Authorization"] + header = request.headers["X-LEARN-API-TOKEN"] header.gsub(pattern, "") if header&.match(pattern) end -- GitLab From 69ffa268777101cf7d5e3bb0961b3306833886fb Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Thu, 1 Oct 2020 20:05:56 -1000 Subject: [PATCH 125/283] fixing bug on cohort user edit using wrong user to determine if global roles can be editted. --- app/controllers/users_controller.rb | 2 +- app/views/users/edit.html.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 9339cb6..8ab5b37 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -14,7 +14,7 @@ class UsersController < ApplicationController authorize(current_cohort) current_cohort_user.update(roles: [params[:instructor]].compact) - if (user.admin?) + if (current_user.admin?) user.update(roles:[params[:forge_admin], params[:forge_blocks_manager], params[:auth_product_admin]].compact) end diff --git a/app/views/users/edit.html.haml b/app/views/users/edit.html.haml index cdc6a68..de0f522 100644 --- a/app/views/users/edit.html.haml +++ b/app/views/users/edit.html.haml @@ -15,7 +15,7 @@ .form-check = check_box_tag :instructor, "forge.instructor", @cohort_user.roles.include?("forge.instructor"), class: "form-check-input" = label_tag :instructor, "Instructor" - - if @user.admin? + - if @current_user.admin? %h5 Global Roles: .form-group .form-check -- GitLab From 7b43e50fadab3f855a60bbc713467c7a4e678996 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Mon, 5 Oct 2020 13:45:05 -1000 Subject: [PATCH 126/283] Testing & doc changes for new API authorization key --- config/secrets.yml | 1 - doc/api.md | 2 +- doc/api/cohorts/creating_a_new_cohort.json | 4 ++-- .../cohorts/viewing_curriculum_details.json | 2 +- .../content/update_content_visibility.json | 2 +- .../creating_a_user_and_their_enrollment.json | 2 +- .../unenrolling_a_user_from_a_cohort.json | 4 ++-- .../updating_a_user's_enrollment_roles.json | 4 ++-- .../viewing_cohort_enrollments.json | 4 ++-- doc/api/units/update_unit_visibility.json | 2 +- doc/api/users/regenerate_user_token.json | 2 +- scripts/sh/cohort_curriculum.sh | 2 +- scripts/sh/content_file_mark_hidden.sh | 2 +- scripts/sh/content_file_mark_visible.sh | 2 +- scripts/sh/unit_mark_hidden.sh | 2 +- scripts/sh/unit_mark_visible.sh | 2 +- .../api/v1/blocks/releases_controller_spec.rb | 2 +- .../api/v1/blocks_controller_spec.rb | 6 ++--- .../blocks/content_files_controller_spec.rb | 13 +++++----- .../cohorts/blocks/units_controller_spec.rb | 10 ++++---- .../api/v1/cohorts/cohorts_controller_spec.rb | 8 +++---- .../api/v1/cohorts/users_controller_spec.rb | 12 +++++----- .../api/v1/users_controller_spec.rb | 24 +++++++++---------- 23 files changed, 56 insertions(+), 58 deletions(-) diff --git a/config/secrets.yml b/config/secrets.yml index 890cc21..f66ca92 100644 --- a/config/secrets.yml +++ b/config/secrets.yml @@ -59,7 +59,6 @@ test: auth_url: http://localhost:5000 assessments_callback_token: yep assessments_service_domain: http://test-assessments-server/assessments - auth_url: http://localhost:5000 secret_key_base: 4a87e39a69c39c2d133099a329efab6c39b428b807c3e89601e2196cfa1ca79c2560530283d0a845e95b939bd07acfc3bc3686c36dfde8aaf8fc57ea2d1ca6e4 segment_write_key_server: test_key segment_write_key_client: test_key diff --git a/doc/api.md b/doc/api.md index 02fbd41..7631cd6 100644 --- a/doc/api.md +++ b/doc/api.md @@ -8,7 +8,7 @@ Future work might add the ability to publish curriculum and manage cohort creati Authentication ============== -Each Learn admin and instructor account will have a token that can be used to access the API. The token can be found in the UI under the account dropdown, or by going directly to https://learn-2.galvanize.com/api_token. The token must be passed in the header of API requests as `Authorization: Bearer {token}` +Each Learn admin and instructor account will have a token that can be used to access the API. The token can be found in the UI under the account dropdown, or by going directly to https://learn.apps.il2.dsop.io/api_token. The token must be passed in the header of API requests as `X-LEARN-API-TOKEN: Bearer {token}` The authorization scope for each token will match the user’s permissions. For example, if a user is allowed to update a cohort’s visibility in the UI, that user’s token will be allowed to make API requests to do the same. diff --git a/doc/api/cohorts/creating_a_new_cohort.json b/doc/api/cohorts/creating_a_new_cohort.json index e080c07..d062b17 100644 --- a/doc/api/cohorts/creating_a_new_cohort.json +++ b/doc/api/cohorts/creating_a_new_cohort.json @@ -60,7 +60,7 @@ "request_headers": { "Content-Type": "application/json", "Accept": "application/json", - "Authorization": "Bearer token", + "X-LEARN-API-TOKEN": "Bearer token", "Host": "example.org", "Cookie": "" }, @@ -83,4 +83,4 @@ "curl": null } ] -} \ No newline at end of file +} diff --git a/doc/api/cohorts/viewing_curriculum_details.json b/doc/api/cohorts/viewing_curriculum_details.json index 6b55981..826cf79 100644 --- a/doc/api/cohorts/viewing_curriculum_details.json +++ b/doc/api/cohorts/viewing_curriculum_details.json @@ -24,7 +24,7 @@ "request_headers": { "Content-Type": "application/json", "Accept": "application/json", - "Authorization": "Bearer token", + "X-LEARN-API-TOKEN": "Bearer token", "Host": "example.org", "Cookie": "" }, diff --git a/doc/api/content/update_content_visibility.json b/doc/api/content/update_content_visibility.json index b731347..d8c15a2 100644 --- a/doc/api/content/update_content_visibility.json +++ b/doc/api/content/update_content_visibility.json @@ -42,7 +42,7 @@ "request_headers": { "Content-Type": "application/json", "Accept": "application/json", - "Authorization": "Bearer token", + "X-LEARN-API-TOKEN": "Bearer token", "Host": "example.org", "Cookie": "" }, diff --git a/doc/api/enrollments/creating_a_user_and_their_enrollment.json b/doc/api/enrollments/creating_a_user_and_their_enrollment.json index 2ac9988..73ea749 100644 --- a/doc/api/enrollments/creating_a_user_and_their_enrollment.json +++ b/doc/api/enrollments/creating_a_user_and_their_enrollment.json @@ -54,7 +54,7 @@ "request_headers": { "Content-Type": "application/json", "Accept": "application/json", - "Authorization": "Bearer token", + "X-LEARN-API-TOKEN": "Bearer token", "Host": "example.org", "Cookie": "" }, diff --git a/doc/api/enrollments/unenrolling_a_user_from_a_cohort.json b/doc/api/enrollments/unenrolling_a_user_from_a_cohort.json index fe3e684..e1905e5 100644 --- a/doc/api/enrollments/unenrolling_a_user_from_a_cohort.json +++ b/doc/api/enrollments/unenrolling_a_user_from_a_cohort.json @@ -30,7 +30,7 @@ "request_headers": { "Content-Type": "application/json", "Accept": "application/json", - "Authorization": "Bearer token", + "X-LEARN-API-TOKEN": "Bearer token", "Host": "example.org", "Cookie": "" }, @@ -53,4 +53,4 @@ "curl": null } ] -} \ No newline at end of file +} diff --git a/doc/api/enrollments/updating_a_user's_enrollment_roles.json b/doc/api/enrollments/updating_a_user's_enrollment_roles.json index 7239916..7f547cf 100644 --- a/doc/api/enrollments/updating_a_user's_enrollment_roles.json +++ b/doc/api/enrollments/updating_a_user's_enrollment_roles.json @@ -42,7 +42,7 @@ "request_headers": { "Content-Type": "application/json", "Accept": "application/json", - "Authorization": "Bearer token", + "X-LEARN-API-TOKEN": "Bearer token", "Host": "example.org", "Cookie": "" }, @@ -65,4 +65,4 @@ "curl": null } ] -} \ No newline at end of file +} diff --git a/doc/api/enrollments/viewing_cohort_enrollments.json b/doc/api/enrollments/viewing_cohort_enrollments.json index 5514f83..3ade291 100644 --- a/doc/api/enrollments/viewing_cohort_enrollments.json +++ b/doc/api/enrollments/viewing_cohort_enrollments.json @@ -24,7 +24,7 @@ "request_headers": { "Content-Type": "application/json", "Accept": "application/json", - "Authorization": "Bearer token", + "X-LEARN-API-TOKEN": "Bearer token", "Host": "example.org", "Cookie": "" }, @@ -47,4 +47,4 @@ "curl": null } ] -} \ No newline at end of file +} diff --git a/doc/api/units/update_unit_visibility.json b/doc/api/units/update_unit_visibility.json index ecf0cbf..2afc576 100644 --- a/doc/api/units/update_unit_visibility.json +++ b/doc/api/units/update_unit_visibility.json @@ -42,7 +42,7 @@ "request_headers": { "Content-Type": "application/json", "Accept": "application/json", - "Authorization": "Bearer token", + "X-LEARN-API-TOKEN": "Bearer token", "Host": "example.org", "Cookie": "" }, diff --git a/doc/api/users/regenerate_user_token.json b/doc/api/users/regenerate_user_token.json index c1abe63..8fcfaeb 100644 --- a/doc/api/users/regenerate_user_token.json +++ b/doc/api/users/regenerate_user_token.json @@ -19,7 +19,7 @@ "request_headers": { "Content-Type": "application/json", "Accept": "application/json", - "Authorization": "Bearer token", + "X-LEARN-API-TOKEN": "Bearer token", "Host": "example.org", "Cookie": "" }, diff --git a/scripts/sh/cohort_curriculum.sh b/scripts/sh/cohort_curriculum.sh index e16b457..27ab4f6 100755 --- a/scripts/sh/cohort_curriculum.sh +++ b/scripts/sh/cohort_curriculum.sh @@ -5,6 +5,6 @@ BASE_URL= # Example: http://localhost:3003 or https://galvanize-forge-staging-pr COHORT_ID=1 # Change for different cohorts curl --request GET \ - -H "Authorization: Bearer ${API_TOKEN}" \ + -H "X-LEARN-API-TOKEN: Bearer ${API_TOKEN}" \ -H "Content-Type: application/json" \ -H "Accept: application/json" ${BASE_URL}/api/v1/cohorts/${COHORT_ID}/curriculum -k -v diff --git a/scripts/sh/content_file_mark_hidden.sh b/scripts/sh/content_file_mark_hidden.sh index da46ff2..a9c8c81 100644 --- a/scripts/sh/content_file_mark_hidden.sh +++ b/scripts/sh/content_file_mark_hidden.sh @@ -7,7 +7,7 @@ BLOCK_ID= # Change for different blocks UID= # Change for different content uid curl --request PATCH \ - -H "Authorization: Bearer ${API_TOKEN}" \ + -H "X-LEARN-API-TOKEN: Bearer ${API_TOKEN}" \ -H "Content-Type: application/json" \ -H "Accept: application/json" ${BASE_URL}/api/v1/cohorts/${COHORT_ID}/blocks/${BLOCK_ID}/content_files/${UID} -k -v \ --data '{"visible": false }' diff --git a/scripts/sh/content_file_mark_visible.sh b/scripts/sh/content_file_mark_visible.sh index 909809c..ec4f767 100644 --- a/scripts/sh/content_file_mark_visible.sh +++ b/scripts/sh/content_file_mark_visible.sh @@ -7,7 +7,7 @@ BLOCK_ID= # Change for different blocks UID= # Change for different content uid curl --request PATCH \ - -H "Authorization: Bearer ${API_TOKEN}" \ + -H "X-LEARN-API-TOKEN: Bearer ${API_TOKEN}" \ -H "Content-Type: application/json" \ -H "Accept: application/json" ${BASE_URL}/api/v1/cohorts/${COHORT_ID}/blocks/${BLOCK_ID}/content_files/${UID} -k -v \ --data '{"visible": true }' diff --git a/scripts/sh/unit_mark_hidden.sh b/scripts/sh/unit_mark_hidden.sh index 9864020..f5da9cb 100644 --- a/scripts/sh/unit_mark_hidden.sh +++ b/scripts/sh/unit_mark_hidden.sh @@ -7,7 +7,7 @@ BLOCK_ID= # Change for different blocks UID= # Change for different content uid curl --request PATCH \ - -H "Authorization: Bearer ${API_TOKEN}" \ + -H "X-LEARN-API-TOKEN: Bearer ${API_TOKEN}" \ -H "Content-Type: application/json" \ -H "Accept: application/json" ${BASE_URL}/api/v1/cohorts/${COHORT_ID}/blocks/${BLOCK_ID}/units/${UID} -k -v \ --data '{"visible": false }' diff --git a/scripts/sh/unit_mark_visible.sh b/scripts/sh/unit_mark_visible.sh index dff7750..893027c 100644 --- a/scripts/sh/unit_mark_visible.sh +++ b/scripts/sh/unit_mark_visible.sh @@ -7,7 +7,7 @@ BLOCK_ID= # Change for different blocks UID= # Change for different content uid curl --request PATCH \ - -H "Authorization: Bearer ${API_TOKEN}" \ + -H "X-LEARN-API-TOKEN: Bearer ${API_TOKEN}" \ -H "Content-Type: application/json" \ -H "Accept: application/json" ${BASE_URL}/api/v1/cohorts/${COHORT_ID}/blocks/${BLOCK_ID}/units/${UID} -k -v \ --data '{"visible": true }' diff --git a/spec/controllers/api/v1/blocks/releases_controller_spec.rb b/spec/controllers/api/v1/blocks/releases_controller_spec.rb index 0bae45d..51a9897 100644 --- a/spec/controllers/api/v1/blocks/releases_controller_spec.rb +++ b/spec/controllers/api/v1/blocks/releases_controller_spec.rb @@ -9,7 +9,7 @@ describe Api::V1::Blocks::ReleasesController do context "as a user with blocks_manager rights" do let(:admin) { create(:user, :admin, roles: [User::ROLES[:blocks_manager]]) } before do - request.headers["Authorization"] = "Bearer #{admin.api_token}" + request.headers["X-LEARN-API-TOKEN"] = "Bearer #{admin.api_token}" end it "enqueues a new CreateReleaseJob and yields the pending release id" do diff --git a/spec/controllers/api/v1/blocks_controller_spec.rb b/spec/controllers/api/v1/blocks_controller_spec.rb index 6c8bf92..1b757d4 100644 --- a/spec/controllers/api/v1/blocks_controller_spec.rb +++ b/spec/controllers/api/v1/blocks_controller_spec.rb @@ -11,7 +11,7 @@ describe Api::V1::BlocksController do let!(:release) { create(:release, block: block_1) } before do - request.headers["Authorization"] = "Bearer #{admin.api_token}" + request.headers["X-LEARN-API-TOKEN"] = "Bearer #{admin.api_token}" end it "returns blocks as json" do @@ -50,7 +50,7 @@ describe Api::V1::BlocksController do expect(second_block["sync_errors"]).to eq [] expect(second_block["cohorts_using"]).to eq [] end - + it "selects a block by repo_name if the repo_name param specifies one" do get :index, format: :json, params: { repo_name: "learning-material"} @@ -76,7 +76,7 @@ describe Api::V1::BlocksController do context "when Authorization header matches a user with blocks_manager role" do let(:admin) { create(:user, :admin, roles: [User::ROLES[:blocks_manager]]) } before do - request.headers["Authorization"] = "Bearer #{admin.api_token}" + request.headers["X-LEARN-API-TOKEN"] = "Bearer #{admin.api_token}" end it "creates a block when given a unique repo_name" do diff --git a/spec/controllers/api/v1/cohorts/blocks/content_files_controller_spec.rb b/spec/controllers/api/v1/cohorts/blocks/content_files_controller_spec.rb index 35d636b..3171dd0 100644 --- a/spec/controllers/api/v1/cohorts/blocks/content_files_controller_spec.rb +++ b/spec/controllers/api/v1/cohorts/blocks/content_files_controller_spec.rb @@ -5,12 +5,12 @@ resource "Content" do let(:user) { create(:user, :admin, api_token: "token") } let(:content_file) { create(:content_file) } let(:cohort) { create(:cohort_release, release: content_file.standard.release).cohort } - + header "Content-Type", "application/json" header "Accept", "application/json" let(:api_token) { "Bearer #{user.api_token}" } - header "Authorization", :api_token - + header "X-LEARN-API-TOKEN", :api_token + describe "updating visibility" do explanation <<-MARKDOWN.strip_heredoc Hide or show an individual Lesson or Checkpoint. This is equivalent to clicking the “eye” icon on the cohort visibility page. If you set the content to visible but the parent unit is hidden, the Lesson or Checkpoint will not be shown. @@ -61,7 +61,7 @@ resource "Content" do let!(:checkpoint) { create(:content_file, uid: "abc123", path: "01-instructor.md", position: 1, content_file_type: "checkpoint", standard: standard, max_checkpoint_submissions: 1, time_limit: 1) } let!(:challenge) { create(:challenge, points: 2, content_file: checkpoint) } let!(:user) { create(:cohort_user, cohort: cohort).user } - + describe "POST #take_assessmet" do context "when the content file is not a checkpoint" do let!(:lesson) { create(:content_file, uid: "abc123", path: "01-instructor.md", position: 1, content_file_type: "lesson", standard: standard) } @@ -98,9 +98,9 @@ resource "Content" do xit "gives the new time_limit" do # TODO: No idea why this wont work... post :take_assessment, params: { cohort_id: cohort.id, block_id: release.block_id, id: checkpoint.id }, format: :json, session: { user_uid: user.uid } expect(json_response[:time_limit]).to eq 1 - + CohortRelease.last.update(release: new_release) - + post :take_assessment, params: { cohort_id: cohort.id, block_id: release.block_id, id: checkpoint.id }, format: :json, session: { user_uid: user.uid } expect(json_response[:time_limit]).to eq 10 end @@ -113,7 +113,6 @@ resource "Content" do cohort_id: cohort.id, content_file_uid: checkpoint.uid, content_file_block_id: checkpoint.standard.release.block_id, - content_file_block_id: checkpoint.standard.release.block_id, user_id: user.id, state: CheckpointSubmission::STATES[:started] ) diff --git a/spec/controllers/api/v1/cohorts/blocks/units_controller_spec.rb b/spec/controllers/api/v1/cohorts/blocks/units_controller_spec.rb index 7c1d4a0..a2c7b5f 100644 --- a/spec/controllers/api/v1/cohorts/blocks/units_controller_spec.rb +++ b/spec/controllers/api/v1/cohorts/blocks/units_controller_spec.rb @@ -6,12 +6,12 @@ resource "Units" do let(:content_file) { create(:content_file) } let(:cohort) { create(:cohort_release, release: content_file.standard.release).cohort } let(:unit) { content_file.standard } - + header "Content-Type", "application/json" header "Accept", "application/json" let(:api_token) { "Bearer #{user.api_token}" } - header "Authorization", :api_token - + header "X-LEARN-API-TOKEN", :api_token + describe "updating visibility" do let(:cohort_id) { cohort.id } @@ -32,7 +32,7 @@ resource "Units" do patch "/api/v1/cohorts/:cohort_id/blocks/:block_id/units/:id" do example "Update Unit Visibility" do - header "Authorization", "Bearer #{user.api_token}" + header "X-LEARN-API-TOKEN", "Bearer #{user.api_token}" expect { do_request }.to change { ContentVisibility.count }.by(1) expect(response_json["status"]).to eq("ok") expect(status).to eq 200 @@ -46,7 +46,7 @@ resource "Units" do patch "/api/v1/cohorts/:cohort_id/blocks/:block_id/units/:id" do example "To reveal the Unit", document:false do - header "Authorization", "Bearer #{user.api_token}" + header "X-LEARN-API-TOKEN", "Bearer #{user.api_token}" create(:content_visibility, cohort_id: cohort.id, content_uid: unit.uid, content_type: "Standard", visibility_type: "hidden") expect { do_request }.to change { ContentVisibility.count }.by(-1) expect(response_json["status"]).to eq("ok") diff --git a/spec/controllers/api/v1/cohorts/cohorts_controller_spec.rb b/spec/controllers/api/v1/cohorts/cohorts_controller_spec.rb index fe60333..10411d6 100644 --- a/spec/controllers/api/v1/cohorts/cohorts_controller_spec.rb +++ b/spec/controllers/api/v1/cohorts/cohorts_controller_spec.rb @@ -30,7 +30,7 @@ resource "Cohorts" do explanation <<-MARKDOWN.strip_heredoc Allow users to easily create a cohort. MARKDOWN - header "Authorization", "Bearer #{user.api_token}" + header "X-LEARN-API-TOKEN", "Bearer #{user.api_token}" # Commented out since AuthApi has been removed # dbl = double(AuthApi::Client) # expect(AuthResolverService).to receive(:resolve) @@ -68,7 +68,7 @@ resource "Cohorts" do explanation <<-MARKDOWN.strip_heredoc Responds with a 400 when Required Params: name, product_type, or starts_on are missing. opt_out_for_marketing must be true or false. MARKDOWN - header "Authorization", "Bearer #{user.api_token}" + header "X-LEARN-API-TOKEN", "Bearer #{user.api_token}" expect { do_request }.to have_enqueued_job(CreateApiInteractionJob) @@ -82,7 +82,7 @@ resource "Cohorts" do explanation <<-MARKDOWN.strip_heredoc Responds with a 400 when auth API request fails. MARKDOWN - header "Authorization", "Bearer 'wrong'" + header "X-LEARN-API-TOKEN", "Bearer 'wrong'" # Commented out since AuthApi has been removed # dbl = double(AuthApi::Client) # expect(dbl).to receive(:create_product).and_raise(AuthApi::RequestFailed, "{}") @@ -124,7 +124,7 @@ resource "Cohorts" do let!(:cohort_id) { cohort.id } get "/api/v1/cohorts/:cohort_id/curriculum" do example "Viewing Curriculum Details" do - header "Authorization", "Bearer #{user.api_token}" + header "X-LEARN-API-TOKEN", "Bearer #{user.api_token}" release.block.update(repo_name: "demo-mocking-java") expect { diff --git a/spec/controllers/api/v1/cohorts/users_controller_spec.rb b/spec/controllers/api/v1/cohorts/users_controller_spec.rb index 456be4a..42dd667 100644 --- a/spec/controllers/api/v1/cohorts/users_controller_spec.rb +++ b/spec/controllers/api/v1/cohorts/users_controller_spec.rb @@ -26,7 +26,7 @@ resource "Enrollments" do explanation <<-MARKDOWN.strip_heredoc Lists users currently enrolled in the cohort, including instructors and onboarders. Roles are specific to that cohort, and do not include any global user roles. MARKDOWN - header "Authorization", "Bearer #{user.api_token}" + header "X-LEARN-API-TOKEN", "Bearer #{user.api_token}" expect { do_request }.to have_enqueued_job(CreateApiInteractionJob) @@ -79,7 +79,7 @@ resource "Enrollments" do explanation <<-MARKDOWN.strip_heredoc Invite new users or enroll existing users to a cohort. A user is invited only if they do not exist. Enrolling a user who is already enrolled changes nothing about their enrollment- their roles will not be modified to match the body parameters, and instead must be changed via a PATCH. MARKDOWN - header "Authorization", "Bearer #{user.api_token}" + header "X-LEARN-API-TOKEN", "Bearer #{user.api_token}" # Using double for Keyclaok::Internal does not seem to work # dbl = double(Keycloak::Internal) @@ -111,7 +111,7 @@ resource "Enrollments" do it "finds the user by email in the system" do existing_user = create(:user, email: email, first_name: first_name, last_name: last_name) - header "Authorization", "Bearer #{user.api_token}" + header "X-LEARN-API-TOKEN", "Bearer #{user.api_token}" allow(Keycloak::Internal).to receive(:get_user_info).and_return(OpenStruct.new({ id: "test", firstName: first_name, @@ -133,7 +133,7 @@ resource "Enrollments" do end it "makes a request to KeyCloak even if the user exists and is enrolled" do - header "Authorization", "Bearer #{user.api_token}" + header "X-LEARN-API-TOKEN", "Bearer #{user.api_token}" existing_user = create(:user, email: email, first_name: first_name, last_name: last_name) create(:cohort_user, user: existing_user, cohort: cohort) @@ -162,7 +162,7 @@ resource "Enrollments" do end it "responds with a 400 when the KeyCloak request fails" do - header "Authorization", "Bearer #{user.api_token}" + header "X-LEARN-API-TOKEN", "Bearer #{user.api_token}" expect(Keycloak::Internal).to receive(:get_user_info).and_raise(Keycloak::UserLoginNotFound) @@ -181,7 +181,7 @@ resource "Enrollments" do let(:email) { "" } it "responds with a 400 when an email parameter is missing" do - header "Authorization", "Bearer #{user.api_token}" + header "X-LEARN-API-TOKEN", "Bearer #{user.api_token}" expect { do_request }.to have_enqueued_job(CreateApiInteractionJob) diff --git a/spec/controllers/api/v1/users_controller_spec.rb b/spec/controllers/api/v1/users_controller_spec.rb index 186fd53..4bc6be9 100644 --- a/spec/controllers/api/v1/users_controller_spec.rb +++ b/spec/controllers/api/v1/users_controller_spec.rb @@ -4,14 +4,14 @@ resource "Users" do context "when an a admin/teacher with an api_token" do describe "regenerate_token" do let(:user) { create(:user, :admin, api_token: "token") } - + header "Content-Type", "application/json" header "Accept", "application/json" - + describe "endpoints" do get "/api/v1/users/regenerate_token" do example "Regenerate User Token" do - header "Authorization", "Bearer #{user.api_token}" + header "X-LEARN-API-TOKEN", "Bearer #{user.api_token}" do_request expect(status).to eq 200 @@ -23,13 +23,13 @@ resource "Users" do describe "learn_cli_credentials" do describe "with correct HTTP method" do let(:user) { create(:user, :admin, api_token: "token") } - + header "Content-Type", "application/json" header "Accept", "application/json" get "/api/v1/users/learn_cli_credentials" do example "Access CLI credentials", document:false do - header "Authorization", "Bearer #{user.api_token}" + header "X-LEARN-API-TOKEN", "Bearer #{user.api_token}" do_request expect(status).to eq 200 @@ -39,13 +39,13 @@ resource "Users" do describe "with incorrect HTTP method" do let(:user) { create(:user, :admin, api_token: "token") } - + header "Content-Type", "application/json" header "Accept", "application/json" post "/api/v1/users/learn_cli_credentials" do example "CLI credentials with incorrect method", document:false do - header "Authorization", "Bearer #{user.api_token}" + header "X-LEARN-API-TOKEN", "Bearer #{user.api_token}" do_request expect(status).to eq 405 @@ -58,14 +58,14 @@ resource "Users" do context "with wrong or no credentials" do describe "regenerate_token" do let(:user) { create(:user, :admin) } - + header "Content-Type", "application/json" header "Accept", "application/json" - + describe "endpoints" do get "/api/v1/users/regenerate_token" do example "regenerate token with bad bearer token", document:false do - header "Authorization", "Bearer incorrect_token" + header "X-LEARN-API-TOKEN", "Bearer incorrect_token" do_request expect(status).to eq 401 @@ -76,13 +76,13 @@ resource "Users" do describe "learn_cli_credentials" do let(:user) { create(:user, :admin) } - + header "Content-Type", "application/json" header "Accept", "application/json" get "/api/v1/users/learn_cli_credentials" do example "CLI credentials with bad bearer token", document:false do - header "Authorization", "Bearer incorrect_token" + header "X-LEARN-API-TOKEN", "Bearer incorrect_token" do_request expect(status).to eq 401 -- GitLab From 8eaa5a41d53044e075d002104bbd1107ef5c8ecd Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 5 Oct 2020 17:14:39 -1000 Subject: [PATCH 127/283] upgrading to ruby 2.6.6 and bundler 2.1.4 --- .ruby-version | 2 +- Dockerfile | 27 +++++---------------------- Dockerfile.base | 8 +++----- Gemfile | 2 +- Gemfile.lock | 4 ++-- 5 files changed, 12 insertions(+), 31 deletions(-) diff --git a/.ruby-version b/.ruby-version index e70b452..338a5b5 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.6.0 +2.6.6 diff --git a/Dockerfile b/Dockerfile index 8439451..d35d8b7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,4 @@ -FROM bitnami/ruby:2.6.0 -ENV count 6 +FROM bitnami/ruby:2.6.6 # Install what we can through OS package management RUN apt-get -y update @@ -24,31 +23,16 @@ RUN curl -L https://raw.githubusercontent.com/tj/n/master/bin/n -o n RUN bash n auto RUN npm install -g yarn -# Set the user -#RUN set -ex && \ -# groupadd --gid 950 ruby && \ -# useradd --uid 950 --gid ruby --shell /bin/bash --create-home ruby -#RUN ls -l /home - # Setup our environment WORKDIR /usr/src/app -ENV RAILS_ENV production - -# Stuff that changes -#RUN chown -R ruby:ruby /usr/src/app -#RUN chmod 755 /usr/src/app -#RUN chown -R ruby:ruby /opt/bitnami/ruby -#RUN chmod 755 /opt/bitnami/ruby - -# Copy the files. ADD . . -# Switch to ruby. -#USER ruby +# Set the Rails environment variable. +ENV RAILS_ENV production # Install Rails Dependecies. -RUN gem install bundler:1.17.3 -RUN gem install rake -v '12.3.1' --source 'https://rubygems.org/' +RUN gem install bundler:2.1.4 +RUN gem install rake:13.0.1 --source 'https://rubygems.org/' # Run the bundle install RUN bundle install @@ -66,5 +50,4 @@ RUN bundle exec rake assets:clean ENV PATH /usr/src/app/node_modules/.bin:$PATH # Set the entry point. -#CMD ["tail", "-f", "/dev/null"] CMD ["./entrypoint-server.sh"] diff --git a/Dockerfile.base b/Dockerfile.base index cbbb371..dc797ed 100644 --- a/Dockerfile.base +++ b/Dockerfile.base @@ -1,6 +1,4 @@ -FROM bitnami/ruby:2.6.0 - -ENV count 6 +FROM bitnami/ruby:2.6.6 # Install what we can through OS package management RUN apt-get -y update @@ -42,8 +40,8 @@ ENV RAILS_ENV production ADD . . ADD Gemfile /usr/src/app/Gemfile ADD Gemfile.lock /usr/src/app/Gemfile.lock -# RUN gem install bundler --version 1.17.3 -RUN gem install rake -v '12.3.1' --source 'https://rubygems.org/' +# RUN gem install bundler --version 2.1.4 +RUN gem install rake -v '13.0.1' --source 'https://rubygems.org/' RUN bundle install ENV PATH /usr/src/app/node_modules/.bin:$PATH CMD ["./entrypoint-server.sh"] diff --git a/Gemfile b/Gemfile index 7df3f20..f76b087 100644 --- a/Gemfile +++ b/Gemfile @@ -1,5 +1,5 @@ source "https://rubygems.org" -ruby "2.6.0" +ruby "2.6.6" git_source(:github) do |repo_name| repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/") diff --git a/Gemfile.lock b/Gemfile.lock index b82f726..f0f90e3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -462,7 +462,7 @@ DEPENDENCIES zip-zip RUBY VERSION - ruby 2.6.0p0 + ruby 2.6.6p146 BUNDLED WITH - 1.17.3 + 2.1.4 -- GitLab From 1ec6ea98b5a793d1262d6fc34829f9476b0a5e36 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Mon, 5 Oct 2020 17:43:20 -1000 Subject: [PATCH 128/283] Several changes to testing --- app/controllers/users_controller.rb | 12 ++++++++-- .../platform_one_auth_resolver_service.rb | 1 - .../api/v1/cohorts/users_controller_spec.rb | 22 ++++++++++--------- spec/controllers/cohorts_controller_spec.rb | 5 +++-- spec/controllers/sessions_controller_spec.rb | 19 ++++++++-------- spec/models/block_spec.rb | 6 +++-- spec/models/user_spec.rb | 3 ++- 7 files changed, 41 insertions(+), 27 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 8ab5b37..941c048 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -12,10 +12,18 @@ class UsersController < ApplicationController def update authorize(current_cohort) - current_cohort_user.update(roles: [params[:instructor]].compact) + unless current_cohort_user.update(roles: [params[:instructor]].compact) + flash[:error] = current_cohort_user.errors.full_messages.join(", ") + render :edit + return + end if (current_user.admin?) - user.update(roles:[params[:forge_admin], params[:forge_blocks_manager], params[:auth_product_admin]].compact) + unless user.update(roles:[params[:forge_admin], params[:forge_blocks_manager], params[:auth_product_admin]].compact) + flash[:error] = user.errors.full_messages.join(", ") + render :edit + return + end end redirect_to users_cohort_path(current_cohort) diff --git a/app/services/platform_one_auth_resolver_service.rb b/app/services/platform_one_auth_resolver_service.rb index d6d45b6..7ad8286 100644 --- a/app/services/platform_one_auth_resolver_service.rb +++ b/app/services/platform_one_auth_resolver_service.rb @@ -7,7 +7,6 @@ class PlatformOneAuthResolverService def initialize(jwt_token) @payload = JWT.decode(jwt_token, nil, false)[0] - puts @payload @uid = @payload["sub"] @email = @payload["email"] @first_name = @payload["given_name"] diff --git a/spec/controllers/api/v1/cohorts/users_controller_spec.rb b/spec/controllers/api/v1/cohorts/users_controller_spec.rb index 42dd667..798352b 100644 --- a/spec/controllers/api/v1/cohorts/users_controller_spec.rb +++ b/spec/controllers/api/v1/cohorts/users_controller_spec.rb @@ -84,21 +84,23 @@ resource "Enrollments" do # Using double for Keyclaok::Internal does not seem to work # dbl = double(Keycloak::Internal) - expect(Keycloak::Internal).to receive(:get_user_info).with( - email, - true, - Rails.application.secrets.keycloak_client_id, - Rails.application.secrets.keycloak_client_secret - ).and_return(OpenStruct.new({ id: "4b58555dbbc93c9016f7325ead84667d", - firstName: first_name, - lastName: last_name, - email: email - })) + # expect(Keycloak::Internal).to receive(:get_user_info).with( + # email, + # true, + # Rails.application.secrets.keycloak_client_id, + # Rails.application.secrets.keycloak_client_secret + # ).and_return(OpenStruct.new({ id: "4b58555dbbc93c9016f7325ead84667d", + # firstName: first_name, + # lastName: last_name, + # email: email + # })) expect { do_request }.to have_enqueued_job(CreateApiInteractionJob) + print "email = ", email + new_user = User.find_by(email: email) expect(new_user.first_name).to eq(first_name) expect(new_user.last_name).to eq(last_name) diff --git a/spec/controllers/cohorts_controller_spec.rb b/spec/controllers/cohorts_controller_spec.rb index 7572f53..c7bdfcb 100644 --- a/spec/controllers/cohorts_controller_spec.rb +++ b/spec/controllers/cohorts_controller_spec.rb @@ -90,11 +90,12 @@ describe CohortsController do describe "GET #index" do it "returns locals with a list of all cohorts" do - allow(Rails.application.secrets).to receive(:auth_url).and_return("http://auth.galvanize.com") + # Commenting out since we don't use auth anymore + # allow(Rails.application.secrets).to receive(:auth_url).and_return("http://auth.galvanize.com") allow(controller).to receive(:render) expect(controller).to receive(:render) do |args| expect(args[:locals][:all_other_cohorts]).to eq([cohort]) - expect(args[:locals][:new_auth_product_url]).to eq("http://auth.galvanize.com/admin/products/new") + # expect(args[:locals][:new_auth_product_url]).to eq("http://auth.galvanize.com/admin/products/new") end get :index diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index c2391dc..299edb7 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -2,15 +2,16 @@ require "spec_helper" describe SessionsController do describe "GET #new" do - context "when signing in as a user not authenticated" do - render_views - - it "redirects to KeyCloak" do - get :new - expect(response).to redirect_to '/auth/keycloakopenid' - end - - end + # Commented out since no unauthenticated users should reach site + # context "when signing in as a user not authenticated" do + # render_views + # + # it "redirects to KeyCloak" do + # get :new + # expect(response).to redirect_to '/sign_in' + # end + # + # end context "when signing in as a user already authenticated" do diff --git a/spec/models/block_spec.rb b/spec/models/block_spec.rb index 50ffff4..0753f91 100644 --- a/spec/models/block_spec.rb +++ b/spec/models/block_spec.rb @@ -24,7 +24,7 @@ describe Block do expect(subject.cohorts.map(&:id).sort).to eq([cohort_1.id, cohort_2.id].sort) end end - + describe "#git_url" do it "should include the repo name into the url" do expect(subject.git_url).to eq( @@ -58,8 +58,10 @@ describe Block do context "when repo name is not valid" do context "when given anything other than the repo name" do subject { build(:block, repo_name: "/foo") } - it "fails validation" do + # The check has been removed to allow for gitlab subprojects + xit "fails validation" do subject.save + byebug expect(subject.valid?).to eq false expect(subject.errors[:repo]).to include("URL cannot include a branch") end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index a10197d..42e22cb 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -328,7 +328,8 @@ describe User do end describe "#auth_edit_url" do - it "returns the correct url" do + # This path no longer exists + xit "returns the correct url" do expect(subject.auth_edit_url).to eq("#{Rails.application.secrets.auth_url}/admin/users/#{subject.uid}/edit") end end -- GitLab From ebbbcbf7f1ba5da2f0ea26970c1e43c29e4e900d Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Mon, 5 Oct 2020 22:14:50 -1000 Subject: [PATCH 129/283] Several changes to tests --- .../api/v1/cohorts/users_controller_spec.rb | 2 - .../gitlab-course-yaml-branch-failure.yml | 243 +++-------------- .../gitlab-course-yaml-success.yml | 256 ++++++------------ .../vcr_cassettes/gitlab-not-found.yml | 60 ++-- .../fixtures/vcr_cassettes/gitlab-success.yml | 167 ++++-------- spec/models/block_spec.rb | 1 - spec/services/assessment_service_spec.rb | 11 +- spec/services/course_validator_spec.rb | 15 +- .../download_repository_service_spec.rb | 8 +- 9 files changed, 220 insertions(+), 543 deletions(-) diff --git a/spec/controllers/api/v1/cohorts/users_controller_spec.rb b/spec/controllers/api/v1/cohorts/users_controller_spec.rb index 798352b..cc70a50 100644 --- a/spec/controllers/api/v1/cohorts/users_controller_spec.rb +++ b/spec/controllers/api/v1/cohorts/users_controller_spec.rb @@ -99,8 +99,6 @@ resource "Enrollments" do do_request }.to have_enqueued_job(CreateApiInteractionJob) - print "email = ", email - new_user = User.find_by(email: email) expect(new_user.first_name).to eq(first_name) expect(new_user.last_name).to eq(last_name) diff --git a/spec/fixtures/vcr_cassettes/gitlab-course-yaml-branch-failure.yml b/spec/fixtures/vcr_cassettes/gitlab-course-yaml-branch-failure.yml index 3997da5..bc1ecf6 100644 --- a/spec/fixtures/vcr_cassettes/gitlab-course-yaml-branch-failure.yml +++ b/spec/fixtures/vcr_cassettes/gitlab-course-yaml-branch-failure.yml @@ -2,13 +2,13 @@ http_interactions: - request: method: get - uri: https://gitlab.galvanize.com/api/v4/projects?search=courseyaml + uri: https://code.il2.dsop.io/api/v4/projects?search=p1-test body: encoding: US-ASCII string: '' headers: Private-Token: - - Ky6ZnUeePqstUBSRsuD3 + - WmXSEG8RHyy2ud_esxfF Accept-Encoding: - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 Accept: @@ -22,22 +22,16 @@ http_interactions: headers: Cache-Control: - max-age=0, private, must-revalidate + Content-Length: + - '3280' Content-Type: - application/json - Date: - - Tue, 04 Aug 2020 22:35:41 GMT Etag: - - W/"418e7a65233ea8a3566cff93fac15441" + - W/"905a13fb3b949a706442a5f1b4b540d6" Link: - - ; - rel="first", ; + - ; + rel="first", ; rel="last" - Referrer-Policy: - - strict-origin-when-cross-origin - Server: - - nginx - Strict-Transport-Security: - - max-age=31536000 Vary: - Origin X-Content-Type-Options: @@ -53,34 +47,36 @@ http_interactions: X-Prev-Page: - '' X-Request-Id: - - nHmmOdiiOs6 + - bjd2vFLwMO X-Runtime: - - '0.071233' + - '0.063492' X-Total: - '1' X-Total-Pages: - '1' - Content-Length: - - '3163' - Connection: - - keep-alive + Date: + - Tue, 06 Oct 2020 07:44:25 GMT + X-Envoy-Upstream-Service-Time: + - '66' + Server: + - istio-envoy body: encoding: UTF-8 - string: '[{"id":9,"description":"Course yaml files for testing from self hosted - gitlab","name":"courseyaml","name_with_namespace":"Peter Grunde / courseyaml","path":"courseyaml","path_with_namespace":"peteragrunde/courseyaml","created_at":"2020-07-29T20:14:33.408Z","default_branch":"master","tag_list":[],"ssh_url_to_repo":"git@gitlab.galvanize.com:peteragrunde/courseyaml.git","http_url_to_repo":"https://gitlab.galvanize.com/peteragrunde/courseyaml.git","web_url":"https://gitlab.galvanize.com/peteragrunde/courseyaml","readme_url":null,"avatar_url":null,"star_count":0,"forks_count":0,"last_activity_at":"2020-08-04T18:59:47.516Z","namespace":{"id":10,"name":"Peter - Grunde","path":"peteragrunde","kind":"user","full_path":"peteragrunde","parent_id":null,"avatar_url":"https://secure.gravatar.com/avatar/f2a2c817c588e6c5a914a36815685467?s=80\u0026d=identicon","web_url":"https://gitlab.galvanize.com/peteragrunde"},"_links":{"self":"https://gitlab.galvanize.com/api/v4/projects/9","issues":"https://gitlab.galvanize.com/api/v4/projects/9/issues","merge_requests":"https://gitlab.galvanize.com/api/v4/projects/9/merge_requests","repo_branches":"https://gitlab.galvanize.com/api/v4/projects/9/repository/branches","labels":"https://gitlab.galvanize.com/api/v4/projects/9/labels","events":"https://gitlab.galvanize.com/api/v4/projects/9/events","members":"https://gitlab.galvanize.com/api/v4/projects/9/members"},"empty_repo":false,"archived":false,"visibility":"private","owner":{"id":9,"name":"Peter - Grunde","username":"peteragrunde","state":"active","avatar_url":"https://secure.gravatar.com/avatar/f2a2c817c588e6c5a914a36815685467?s=80\u0026d=identicon","web_url":"https://gitlab.galvanize.com/peteragrunde"},"resolve_outdated_diff_discussions":false,"container_registry_enabled":true,"container_expiration_policy":{"cadence":"7d","enabled":true,"keep_n":null,"older_than":null,"name_regex":null,"name_regex_keep":null,"next_run_at":"2020-08-05T20:14:33.466Z"},"issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"jobs_enabled":true,"snippets_enabled":true,"can_create_merge_request_in":true,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"enabled","wiki_access_level":"enabled","builds_access_level":"enabled","snippets_access_level":"enabled","pages_access_level":"private","emails_disabled":null,"shared_runners_enabled":true,"lfs_enabled":true,"creator_id":9,"import_status":"none","open_issues_count":0,"ci_default_git_depth":50,"public_jobs":true,"build_timeout":3600,"auto_cancel_pending_pipelines":"enabled","build_coverage_regex":null,"ci_config_path":null,"shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"request_access_enabled":true,"only_allow_merge_if_all_discussions_are_resolved":false,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"merge","suggestion_commit_message":null,"auto_devops_enabled":true,"auto_devops_deploy_strategy":"continuous","autoclose_referenced_issues":true,"permissions":{"project_access":{"access_level":40,"notification_level":3},"group_access":null}}]' - http_version: - recorded_at: Tue, 04 Aug 2020 22:35:41 GMT + string: '[{"id":702,"description":"","name":"p1-test","name_with_namespace":"Charlie + Sakamaki / p1-test","path":"p1-test","path_with_namespace":"csakamaki/p1-test","created_at":"2020-09-23T19:53:49.310Z","default_branch":"master","tag_list":[],"ssh_url_to_repo":"git@code.il2.dsop.io:csakamaki/p1-test.git","http_url_to_repo":"https://code.il2.dsop.io/csakamaki/p1-test.git","web_url":"https://code.il2.dsop.io/csakamaki/p1-test","readme_url":null,"avatar_url":null,"star_count":0,"forks_count":0,"last_activity_at":"2020-09-24T00:07:57.336Z","namespace":{"id":288,"name":"Charlie + Sakamaki","path":"csakamaki","kind":"user","full_path":"csakamaki","parent_id":null,"avatar_url":"https://secure.gravatar.com/avatar/ed30ad3597897901ccbd315e731bf100?s=80\u0026d=identicon","web_url":"https://code.il2.dsop.io/csakamaki"},"_links":{"self":"https://code.il2.dsop.io/api/v4/projects/702","issues":"https://code.il2.dsop.io/api/v4/projects/702/issues","merge_requests":"https://code.il2.dsop.io/api/v4/projects/702/merge_requests","repo_branches":"https://code.il2.dsop.io/api/v4/projects/702/repository/branches","labels":"https://code.il2.dsop.io/api/v4/projects/702/labels","events":"https://code.il2.dsop.io/api/v4/projects/702/events","members":"https://code.il2.dsop.io/api/v4/projects/702/members"},"empty_repo":false,"archived":false,"visibility":"private","owner":{"id":238,"name":"Charlie + Sakamaki","username":"csakamaki","state":"active","avatar_url":"https://secure.gravatar.com/avatar/ed30ad3597897901ccbd315e731bf100?s=80\u0026d=identicon","web_url":"https://code.il2.dsop.io/csakamaki"},"resolve_outdated_diff_discussions":false,"container_registry_enabled":true,"container_expiration_policy":{"cadence":"7d","enabled":true,"keep_n":null,"older_than":null,"name_regex":null,"name_regex_keep":null,"next_run_at":"2020-10-07T20:50:13.933Z"},"issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"jobs_enabled":true,"snippets_enabled":true,"can_create_merge_request_in":true,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"enabled","wiki_access_level":"enabled","builds_access_level":"enabled","snippets_access_level":"enabled","pages_access_level":"private","emails_disabled":null,"shared_runners_enabled":true,"lfs_enabled":true,"creator_id":238,"import_status":"none","open_issues_count":0,"ci_default_git_depth":50,"public_jobs":true,"build_timeout":3600,"auto_cancel_pending_pipelines":"enabled","build_coverage_regex":null,"ci_config_path":"","shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"request_access_enabled":true,"only_allow_merge_if_all_discussions_are_resolved":false,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"merge","suggestion_commit_message":null,"auto_devops_enabled":false,"auto_devops_deploy_strategy":"continuous","autoclose_referenced_issues":true,"approvals_before_merge":0,"mirror":false,"external_authorization_classification_label":null,"packages_enabled":true,"service_desk_enabled":false,"service_desk_address":null,"marked_for_deletion_at":null,"marked_for_deletion_on":null,"permissions":{"project_access":{"access_level":40,"notification_level":3},"group_access":null}}]' + http_version: + recorded_at: Tue, 06 Oct 2020 07:44:25 GMT - request: method: get - uri: https://gitlab.galvanize.com/api/v4/projects/9/repository/files/course.yaml?ref=missingfile + uri: https://code.il2.dsop.io/api/v4/projects/702/repository/files/course.yaml?ref=missingfile body: encoding: US-ASCII string: '' headers: Private-Token: - - Ky6ZnUeePqstUBSRsuD3 + - WmXSEG8RHyy2ud_esxfF User-Agent: - Galvanize Forge Accept-Encoding: @@ -89,199 +85,34 @@ http_interactions: - "*/*" response: status: - code: 200 - message: OK + code: 404 + message: Not Found headers: Cache-Control: - - max-age=0, private, must-revalidate + - no-cache + Content-Length: + - '34' Content-Type: - application/json - Date: - - Tue, 04 Aug 2020 22:35:42 GMT - Etag: - - W/"1f3e9dd662b02630914d32e7276fdbc6" - Referrer-Policy: - - strict-origin-when-cross-origin - Server: - - nginx - Strict-Transport-Security: - - max-age=31536000 Vary: - Origin X-Content-Type-Options: - nosniff X-Frame-Options: - SAMEORIGIN - X-Gitlab-Blob-Id: - - 5318521c2ce87c7be7257b9b68e39ede2a188623 - X-Gitlab-Commit-Id: - - 84e9892ffa2516ac447c15bede7d8eb6060cf5c2 - X-Gitlab-Content-Sha256: - - 8cd2063696521123e6caf74048a44614de1a6baacf4705e6143d9f56fc127c46 - X-Gitlab-Encoding: - - base64 - X-Gitlab-File-Name: - - course.yaml - X-Gitlab-File-Path: - - course.yaml - X-Gitlab-Last-Commit-Id: - - 84e9892ffa2516ac447c15bede7d8eb6060cf5c2 - X-Gitlab-Ref: - - missingfile - X-Gitlab-Size: - - '300' X-Request-Id: - - if7O53iyeXa + - lJJgxk2Wz06 X-Runtime: - - '0.041679' - Content-Length: - - '769' - Connection: - - keep-alive - body: - encoding: UTF-8 - string: '{"file_name":"course.yaml","file_path":"course.yaml","size":300,"encoding":"base64","content_sha256":"8cd2063696521123e6caf74048a44614de1a6baacf4705e6143d9f56fc127c46","ref":"missingfile","blob_id":"5318521c2ce87c7be7257b9b68e39ede2a188623","commit_id":"84e9892ffa2516ac447c15bede7d8eb6060cf5c2","last_commit_id":"84e9892ffa2516ac447c15bede7d8eb6060cf5c2","content":"LS0tCkNvdXJzZToKICAtIFNlY3Rpb246IERTSSBBZG1pc3Npb25zIFByZXAKICAgIFJlcG9zOgogICAgICAtIFVSTDogaHR0cHM6Ly9naXRodWIuY29tL2dTY2hvb2wvZHNpLWludHJvLXRvLWRzLXN0YXRzCiAgICAgIC0gVVJMOiBodHRwczovL2dpdGxhYi5nYWx2YW5pemUuY29tL3BldGVyYWdydW5kZS9taXNzaW5nbm8KICAtIFNlY3Rpb246IEFkdmFuY2VkIERTSSBBZG1pc3Npb25zIFByZXAKICAgIFJlcG9zOgogICAgICAtIFVSTDogaHR0cHM6Ly9naXRodWIuY29tL2dTY2hvb2wvZHMtcHl0aG9uLXF1aXp6ZXMtYmxvY2sK"}' - http_version: - recorded_at: Tue, 04 Aug 2020 22:35:42 GMT -- request: - method: head - uri: https://api.github.com/repos/gSchool/dsi-intro-to-ds-stats - body: - encoding: US-ASCII - string: '' - headers: - Authorization: - - token 34ed6e936ee7686b5a6adafb796fe4ad888c813a - User-Agent: - - Galvanize Forge - response: - status: - code: 200 - message: OK - headers: - Server: - - GitHub.com - Date: - - Tue, 04 Aug 2020 22:35:42 GMT - Content-Type: - - application/json; charset=utf-8 - Content-Length: - - '6511' - Status: - - 200 OK - X-Ratelimit-Limit: - - '5000' - X-Ratelimit-Remaining: - - '4995' - X-Ratelimit-Reset: - - '1596583625' - Cache-Control: - - private, max-age=60, s-maxage=60 - Vary: - - Accept, Authorization, Cookie, X-GitHub-OTP - - Accept-Encoding, Accept, X-Requested-With - Etag: - - '"f1e9c158c11303b3d08160e3eaf04662"' - Last-Modified: - - Mon, 10 Jun 2019 21:37:29 GMT - X-Oauth-Scopes: - - repo - X-Accepted-Oauth-Scopes: - - repo - X-Github-Media-Type: - - github.v3; format=json - Access-Control-Expose-Headers: - - ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, - X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, - X-GitHub-Media-Type, Deprecation, Sunset - Access-Control-Allow-Origin: - - "*" - Strict-Transport-Security: - - max-age=31536000; includeSubdomains; preload - X-Frame-Options: - - deny - X-Content-Type-Options: - - nosniff - X-Xss-Protection: - - 1; mode=block - Referrer-Policy: - - origin-when-cross-origin, strict-origin-when-cross-origin - Content-Security-Policy: - - default-src 'none' - X-Github-Request-Id: - - C70B:5B2C:168762C:350F7A1:5F29E2BE - body: - encoding: UTF-8 - string: '' - http_version: - recorded_at: Tue, 04 Aug 2020 22:35:42 GMT -- request: - method: get - uri: https://gitlab.galvanize.com/api/v4/projects?search=missingno - body: - encoding: US-ASCII - string: '' - headers: - Private-Token: - - Ky6ZnUeePqstUBSRsuD3 - Accept-Encoding: - - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 - Accept: - - "*/*" - User-Agent: - - Ruby - response: - status: - code: 200 - message: OK - headers: - Cache-Control: - - max-age=0, private, must-revalidate - Content-Type: - - application/json + - '0.042335' Date: - - Tue, 04 Aug 2020 22:35:43 GMT - Etag: - - W/"4f53cda18c2baa0c0354bb5f9a3ecbe5" - Link: - - ; - rel="first", ; - rel="last" - Referrer-Policy: - - strict-origin-when-cross-origin + - Tue, 06 Oct 2020 07:44:25 GMT + X-Envoy-Upstream-Service-Time: + - '47' Server: - - nginx - Strict-Transport-Security: - - max-age=31536000 - Vary: - - Origin - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - SAMEORIGIN - X-Next-Page: - - '' - X-Page: - - '1' - X-Per-Page: - - '20' - X-Prev-Page: - - '' - X-Request-Id: - - 1i4N2TT4GH9 - X-Runtime: - - '0.031994' - X-Total: - - '0' - X-Total-Pages: - - '1' - Content-Length: - - '2' - Connection: - - keep-alive + - istio-envoy body: encoding: UTF-8 - string: "[]" - http_version: - recorded_at: Tue, 04 Aug 2020 22:35:43 GMT + string: '{"message":"404 Commit Not Found"}' + http_version: + recorded_at: Tue, 06 Oct 2020 07:44:25 GMT recorded_with: VCR 4.0.0 diff --git a/spec/fixtures/vcr_cassettes/gitlab-course-yaml-success.yml b/spec/fixtures/vcr_cassettes/gitlab-course-yaml-success.yml index 42178e0..549e280 100644 --- a/spec/fixtures/vcr_cassettes/gitlab-course-yaml-success.yml +++ b/spec/fixtures/vcr_cassettes/gitlab-course-yaml-success.yml @@ -2,13 +2,13 @@ http_interactions: - request: method: get - uri: https://gitlab.galvanize.com/api/v4/projects?search=courseyaml + uri: https://code.il2.dsop.io/api/v4/projects?search=p1-test body: encoding: US-ASCII string: '' headers: Private-Token: - - Ky6ZnUeePqstUBSRsuD3 + - WmXSEG8RHyy2ud_esxfF Accept-Encoding: - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 Accept: @@ -22,22 +22,16 @@ http_interactions: headers: Cache-Control: - max-age=0, private, must-revalidate + Content-Length: + - '3280' Content-Type: - application/json - Date: - - Tue, 04 Aug 2020 19:26:34 GMT Etag: - - W/"418e7a65233ea8a3566cff93fac15441" + - W/"905a13fb3b949a706442a5f1b4b540d6" Link: - - ; - rel="first", ; + - ; + rel="first", ; rel="last" - Referrer-Policy: - - strict-origin-when-cross-origin - Server: - - nginx - Strict-Transport-Security: - - max-age=31536000 Vary: - Origin X-Content-Type-Options: @@ -53,34 +47,36 @@ http_interactions: X-Prev-Page: - '' X-Request-Id: - - X66R6Bsauu8 + - O1E5nWd8Oa5 X-Runtime: - - '0.086174' + - '0.103785' X-Total: - '1' X-Total-Pages: - '1' - Content-Length: - - '3163' - Connection: - - keep-alive + Date: + - Tue, 06 Oct 2020 07:37:19 GMT + X-Envoy-Upstream-Service-Time: + - '108' + Server: + - istio-envoy body: encoding: UTF-8 - string: '[{"id":9,"description":"Course yaml files for testing from self hosted - gitlab","name":"courseyaml","name_with_namespace":"Peter Grunde / courseyaml","path":"courseyaml","path_with_namespace":"peteragrunde/courseyaml","created_at":"2020-07-29T20:14:33.408Z","default_branch":"master","tag_list":[],"ssh_url_to_repo":"git@gitlab.galvanize.com:peteragrunde/courseyaml.git","http_url_to_repo":"https://gitlab.galvanize.com/peteragrunde/courseyaml.git","web_url":"https://gitlab.galvanize.com/peteragrunde/courseyaml","readme_url":null,"avatar_url":null,"star_count":0,"forks_count":0,"last_activity_at":"2020-08-04T18:59:47.516Z","namespace":{"id":10,"name":"Peter - Grunde","path":"peteragrunde","kind":"user","full_path":"peteragrunde","parent_id":null,"avatar_url":"https://secure.gravatar.com/avatar/f2a2c817c588e6c5a914a36815685467?s=80\u0026d=identicon","web_url":"https://gitlab.galvanize.com/peteragrunde"},"_links":{"self":"https://gitlab.galvanize.com/api/v4/projects/9","issues":"https://gitlab.galvanize.com/api/v4/projects/9/issues","merge_requests":"https://gitlab.galvanize.com/api/v4/projects/9/merge_requests","repo_branches":"https://gitlab.galvanize.com/api/v4/projects/9/repository/branches","labels":"https://gitlab.galvanize.com/api/v4/projects/9/labels","events":"https://gitlab.galvanize.com/api/v4/projects/9/events","members":"https://gitlab.galvanize.com/api/v4/projects/9/members"},"empty_repo":false,"archived":false,"visibility":"private","owner":{"id":9,"name":"Peter - Grunde","username":"peteragrunde","state":"active","avatar_url":"https://secure.gravatar.com/avatar/f2a2c817c588e6c5a914a36815685467?s=80\u0026d=identicon","web_url":"https://gitlab.galvanize.com/peteragrunde"},"resolve_outdated_diff_discussions":false,"container_registry_enabled":true,"container_expiration_policy":{"cadence":"7d","enabled":true,"keep_n":null,"older_than":null,"name_regex":null,"name_regex_keep":null,"next_run_at":"2020-08-05T20:14:33.466Z"},"issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"jobs_enabled":true,"snippets_enabled":true,"can_create_merge_request_in":true,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"enabled","wiki_access_level":"enabled","builds_access_level":"enabled","snippets_access_level":"enabled","pages_access_level":"private","emails_disabled":null,"shared_runners_enabled":true,"lfs_enabled":true,"creator_id":9,"import_status":"none","open_issues_count":0,"ci_default_git_depth":50,"public_jobs":true,"build_timeout":3600,"auto_cancel_pending_pipelines":"enabled","build_coverage_regex":null,"ci_config_path":null,"shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"request_access_enabled":true,"only_allow_merge_if_all_discussions_are_resolved":false,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"merge","suggestion_commit_message":null,"auto_devops_enabled":true,"auto_devops_deploy_strategy":"continuous","autoclose_referenced_issues":true,"permissions":{"project_access":{"access_level":40,"notification_level":3},"group_access":null}}]' - http_version: - recorded_at: Tue, 04 Aug 2020 19:26:34 GMT + string: '[{"id":702,"description":"","name":"p1-test","name_with_namespace":"Charlie + Sakamaki / p1-test","path":"p1-test","path_with_namespace":"csakamaki/p1-test","created_at":"2020-09-23T19:53:49.310Z","default_branch":"master","tag_list":[],"ssh_url_to_repo":"git@code.il2.dsop.io:csakamaki/p1-test.git","http_url_to_repo":"https://code.il2.dsop.io/csakamaki/p1-test.git","web_url":"https://code.il2.dsop.io/csakamaki/p1-test","readme_url":null,"avatar_url":null,"star_count":0,"forks_count":0,"last_activity_at":"2020-09-24T00:07:57.336Z","namespace":{"id":288,"name":"Charlie + Sakamaki","path":"csakamaki","kind":"user","full_path":"csakamaki","parent_id":null,"avatar_url":"https://secure.gravatar.com/avatar/ed30ad3597897901ccbd315e731bf100?s=80\u0026d=identicon","web_url":"https://code.il2.dsop.io/csakamaki"},"_links":{"self":"https://code.il2.dsop.io/api/v4/projects/702","issues":"https://code.il2.dsop.io/api/v4/projects/702/issues","merge_requests":"https://code.il2.dsop.io/api/v4/projects/702/merge_requests","repo_branches":"https://code.il2.dsop.io/api/v4/projects/702/repository/branches","labels":"https://code.il2.dsop.io/api/v4/projects/702/labels","events":"https://code.il2.dsop.io/api/v4/projects/702/events","members":"https://code.il2.dsop.io/api/v4/projects/702/members"},"empty_repo":false,"archived":false,"visibility":"private","owner":{"id":238,"name":"Charlie + Sakamaki","username":"csakamaki","state":"active","avatar_url":"https://secure.gravatar.com/avatar/ed30ad3597897901ccbd315e731bf100?s=80\u0026d=identicon","web_url":"https://code.il2.dsop.io/csakamaki"},"resolve_outdated_diff_discussions":false,"container_registry_enabled":true,"container_expiration_policy":{"cadence":"7d","enabled":true,"keep_n":null,"older_than":null,"name_regex":null,"name_regex_keep":null,"next_run_at":"2020-10-07T20:50:13.933Z"},"issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"jobs_enabled":true,"snippets_enabled":true,"can_create_merge_request_in":true,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"enabled","wiki_access_level":"enabled","builds_access_level":"enabled","snippets_access_level":"enabled","pages_access_level":"private","emails_disabled":null,"shared_runners_enabled":true,"lfs_enabled":true,"creator_id":238,"import_status":"none","open_issues_count":0,"ci_default_git_depth":50,"public_jobs":true,"build_timeout":3600,"auto_cancel_pending_pipelines":"enabled","build_coverage_regex":null,"ci_config_path":"","shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"request_access_enabled":true,"only_allow_merge_if_all_discussions_are_resolved":false,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"merge","suggestion_commit_message":null,"auto_devops_enabled":false,"auto_devops_deploy_strategy":"continuous","autoclose_referenced_issues":true,"approvals_before_merge":0,"mirror":false,"external_authorization_classification_label":null,"packages_enabled":true,"service_desk_enabled":false,"service_desk_address":null,"marked_for_deletion_at":null,"marked_for_deletion_on":null,"permissions":{"project_access":{"access_level":40,"notification_level":3},"group_access":null}}]' + http_version: + recorded_at: Tue, 06 Oct 2020 07:37:19 GMT - request: method: get - uri: https://gitlab.galvanize.com/api/v4/projects/9/repository/files/course.yaml?ref=master + uri: https://code.il2.dsop.io/api/v4/projects/702/repository/files/course.yaml?ref=master body: encoding: US-ASCII string: '' headers: Private-Token: - - Ky6ZnUeePqstUBSRsuD3 + - WmXSEG8RHyy2ud_esxfF User-Agent: - Galvanize Forge Accept-Encoding: @@ -94,18 +90,12 @@ http_interactions: headers: Cache-Control: - max-age=0, private, must-revalidate + Content-Length: + - '648' Content-Type: - application/json - Date: - - Tue, 04 Aug 2020 19:26:35 GMT Etag: - - W/"245457fcb7609cfb441b4e341a231538" - Referrer-Policy: - - strict-origin-when-cross-origin - Server: - - nginx - Strict-Transport-Security: - - max-age=31536000 + - W/"58ce3aa47e9466c129ffaf1a1f8ab1fe" Vary: - Origin X-Content-Type-Options: @@ -113,11 +103,11 @@ http_interactions: X-Frame-Options: - SAMEORIGIN X-Gitlab-Blob-Id: - - 54fd94d6a6e049332901aebd5a0b276d83586b0c + - 696c1f44c7233b2fd1c27c43c2b1106cc06f0eb3 X-Gitlab-Commit-Id: - - 3a2cac8bc9d8fa59adbd683860a159da2745afea + - c114c7afbf65344d93f697f34060ca901b3035df X-Gitlab-Content-Sha256: - - 793ba86b488f88e4274e160be56caed15ba726bb1a4b38f1da7b9028aed633dc + - d537f06b2b5bc5e1e1980872aac58766d2a57578d2f565e53b007debf05feb9f X-Gitlab-Encoding: - base64 X-Gitlab-File-Name: @@ -125,105 +115,35 @@ http_interactions: X-Gitlab-File-Path: - course.yaml X-Gitlab-Last-Commit-Id: - - 3a2cac8bc9d8fa59adbd683860a159da2745afea + - ac0da165cce031bf056866c3629dc7f221748c8f X-Gitlab-Ref: - master X-Gitlab-Size: - - '295' + - '211' X-Request-Id: - - eLbShIRVWja + - UlX7wrEymh2 X-Runtime: - - '0.044831' - Content-Length: - - '760' - Connection: - - keep-alive - body: - encoding: UTF-8 - string: '{"file_name":"course.yaml","file_path":"course.yaml","size":295,"encoding":"base64","content_sha256":"793ba86b488f88e4274e160be56caed15ba726bb1a4b38f1da7b9028aed633dc","ref":"master","blob_id":"54fd94d6a6e049332901aebd5a0b276d83586b0c","commit_id":"3a2cac8bc9d8fa59adbd683860a159da2745afea","last_commit_id":"3a2cac8bc9d8fa59adbd683860a159da2745afea","content":"LS0tCkNvdXJzZToKICAtIFNlY3Rpb246IERTSSBBZG1pc3Npb25zIFByZXAKICAgIFJlcG9zOgogICAgICAtIFVSTDogaHR0cHM6Ly9naXRodWIuY29tL2dTY2hvb2wvZHNpLWludHJvLXRvLWRzLXN0YXRzCiAgICAgIC0gVVJMOiBodHRwczovL2dpdGxhYi5nYWx2YW5pemUuY29tL3BldGVyYWdydW5kZS90ZXN0CiAgLSBTZWN0aW9uOiBBZHZhbmNlZCBEU0kgQWRtaXNzaW9ucyBQcmVwCiAgICBSZXBvczoKICAgICAgLSBVUkw6IGh0dHBzOi8vZ2l0aHViLmNvbS9nU2Nob29sL2RzLXB5dGhvbi1xdWl6emVzLWJsb2NrCg=="}' - http_version: - recorded_at: Tue, 04 Aug 2020 19:26:36 GMT -- request: - method: head - uri: https://api.github.com/repos/gSchool/dsi-intro-to-ds-stats - body: - encoding: US-ASCII - string: '' - headers: - Authorization: - - token 34ed6e936ee7686b5a6adafb796fe4ad888c813a - User-Agent: - - Galvanize Forge - response: - status: - code: 200 - message: OK - headers: - Server: - - GitHub.com + - '0.052112' Date: - - Tue, 04 Aug 2020 19:26:37 GMT - Content-Type: - - application/json; charset=utf-8 - Content-Length: - - '6511' - Status: - - 200 OK - X-Ratelimit-Limit: - - '5000' - X-Ratelimit-Remaining: - - '4996' - X-Ratelimit-Reset: - - '1596572723' - Cache-Control: - - private, max-age=60, s-maxage=60 - Vary: - - Accept, Authorization, Cookie, X-GitHub-OTP - - Accept-Encoding, Accept, X-Requested-With - Etag: - - '"eb1b6de787fdce59365562f3c8942282"' - Last-Modified: - - Mon, 10 Jun 2019 21:37:29 GMT - X-Oauth-Scopes: - - repo - X-Accepted-Oauth-Scopes: - - repo - X-Github-Media-Type: - - github.v3; format=json - Access-Control-Expose-Headers: - - ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, - X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, - X-GitHub-Media-Type, Deprecation, Sunset - Access-Control-Allow-Origin: - - "*" - Strict-Transport-Security: - - max-age=31536000; includeSubdomains; preload - X-Frame-Options: - - deny - X-Content-Type-Options: - - nosniff - X-Xss-Protection: - - 1; mode=block - Referrer-Policy: - - origin-when-cross-origin, strict-origin-when-cross-origin - Content-Security-Policy: - - default-src 'none' - X-Github-Request-Id: - - C25B:465E:1A93A1A:3D7B0B0:5F29B66C + - Tue, 06 Oct 2020 07:37:19 GMT + X-Envoy-Upstream-Service-Time: + - '54' + Server: + - istio-envoy body: encoding: UTF-8 - string: '' - http_version: - recorded_at: Tue, 04 Aug 2020 19:26:37 GMT + string: '{"file_name":"course.yaml","file_path":"course.yaml","size":211,"encoding":"base64","content_sha256":"d537f06b2b5bc5e1e1980872aac58766d2a57578d2f565e53b007debf05feb9f","ref":"master","blob_id":"696c1f44c7233b2fd1c27c43c2b1106cc06f0eb3","commit_id":"c114c7afbf65344d93f697f34060ca901b3035df","last_commit_id":"ac0da165cce031bf056866c3629dc7f221748c8f","content":"LS0tCiAgQ291cnNlOgogICAgLSBTZWN0aW9uOiBEU09QIEdpdExhYgogICAgICBSZXBvczoKICAgICAgICAtIFVSTDogaHR0cHM6Ly9jb2RlLmlsMi5kc29wLmlvL2NzYWthbWFraS9wMS10ZXN0CiAgICAtIFNlY3Rpb246IGdTY2hvb2wgR2l0SHViCiAgICAgIFJlcG9zOgogICAgICAgIC0gVVJMOiBodHRwczovL2dpdGh1Yi5jb20vZ1NjaG9vbC9yZXZhY29tbS10ZXN0Cg=="}' + http_version: + recorded_at: Tue, 06 Oct 2020 07:37:19 GMT - request: method: get - uri: https://gitlab.galvanize.com/api/v4/projects?search=test + uri: https://code.il2.dsop.io/api/v4/projects?search=p1-test body: encoding: US-ASCII string: '' headers: Private-Token: - - Ky6ZnUeePqstUBSRsuD3 + - WmXSEG8RHyy2ud_esxfF Accept-Encoding: - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 Accept: @@ -237,22 +157,16 @@ http_interactions: headers: Cache-Control: - max-age=0, private, must-revalidate + Content-Length: + - '3280' Content-Type: - application/json - Date: - - Tue, 04 Aug 2020 19:26:39 GMT Etag: - - W/"cf52ca39c3207275169449d1bc25ab4a" + - W/"905a13fb3b949a706442a5f1b4b540d6" Link: - - ; - rel="first", ; + - ; + rel="first", ; rel="last" - Referrer-Policy: - - strict-origin-when-cross-origin - Server: - - nginx - Strict-Transport-Security: - - max-age=31536000 Vary: - Origin X-Content-Type-Options: @@ -268,39 +182,36 @@ http_interactions: X-Prev-Page: - '' X-Request-Id: - - ROM5an0LA14 + - kFr194XN4I8 X-Runtime: - - '1.304371' + - '0.065975' X-Total: - - '3' + - '1' X-Total-Pages: - '1' - Content-Length: - - '9426' - Connection: - - keep-alive + Date: + - Tue, 06 Oct 2020 07:37:19 GMT + X-Envoy-Upstream-Service-Time: + - '68' + Server: + - istio-envoy body: encoding: UTF-8 - string: '[{"id":12,"description":"","name":"test","name_with_namespace":"Peter - Grunde / test","path":"test","path_with_namespace":"peteragrunde/test","created_at":"2020-08-04T18:58:35.273Z","default_branch":"master","tag_list":[],"ssh_url_to_repo":"git@gitlab.galvanize.com:peteragrunde/test.git","http_url_to_repo":"https://gitlab.galvanize.com/peteragrunde/test.git","web_url":"https://gitlab.galvanize.com/peteragrunde/test","readme_url":"https://gitlab.galvanize.com/peteragrunde/test/-/blob/master/README.md","avatar_url":null,"star_count":0,"forks_count":0,"last_activity_at":"2020-08-04T18:58:35.273Z","namespace":{"id":10,"name":"Peter - Grunde","path":"peteragrunde","kind":"user","full_path":"peteragrunde","parent_id":null,"avatar_url":"https://secure.gravatar.com/avatar/f2a2c817c588e6c5a914a36815685467?s=80\u0026d=identicon","web_url":"https://gitlab.galvanize.com/peteragrunde"},"_links":{"self":"https://gitlab.galvanize.com/api/v4/projects/12","issues":"https://gitlab.galvanize.com/api/v4/projects/12/issues","merge_requests":"https://gitlab.galvanize.com/api/v4/projects/12/merge_requests","repo_branches":"https://gitlab.galvanize.com/api/v4/projects/12/repository/branches","labels":"https://gitlab.galvanize.com/api/v4/projects/12/labels","events":"https://gitlab.galvanize.com/api/v4/projects/12/events","members":"https://gitlab.galvanize.com/api/v4/projects/12/members"},"empty_repo":false,"archived":false,"visibility":"private","owner":{"id":9,"name":"Peter - Grunde","username":"peteragrunde","state":"active","avatar_url":"https://secure.gravatar.com/avatar/f2a2c817c588e6c5a914a36815685467?s=80\u0026d=identicon","web_url":"https://gitlab.galvanize.com/peteragrunde"},"resolve_outdated_diff_discussions":false,"container_registry_enabled":true,"container_expiration_policy":{"cadence":"7d","enabled":true,"keep_n":null,"older_than":null,"name_regex":null,"name_regex_keep":null,"next_run_at":"2020-08-11T18:58:35.305Z"},"issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"jobs_enabled":true,"snippets_enabled":true,"can_create_merge_request_in":true,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"enabled","wiki_access_level":"enabled","builds_access_level":"enabled","snippets_access_level":"enabled","pages_access_level":"private","emails_disabled":null,"shared_runners_enabled":true,"lfs_enabled":true,"creator_id":9,"import_status":"none","open_issues_count":0,"ci_default_git_depth":50,"public_jobs":true,"build_timeout":3600,"auto_cancel_pending_pipelines":"enabled","build_coverage_regex":null,"ci_config_path":null,"shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"request_access_enabled":true,"only_allow_merge_if_all_discussions_are_resolved":false,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"merge","suggestion_commit_message":null,"auto_devops_enabled":true,"auto_devops_deploy_strategy":"continuous","autoclose_referenced_issues":true,"permissions":{"project_access":{"access_level":40,"notification_level":3},"group_access":null}},{"id":9,"description":"Course - yaml files for testing from self hosted gitlab","name":"courseyaml","name_with_namespace":"Peter - Grunde / courseyaml","path":"courseyaml","path_with_namespace":"peteragrunde/courseyaml","created_at":"2020-07-29T20:14:33.408Z","default_branch":"master","tag_list":[],"ssh_url_to_repo":"git@gitlab.galvanize.com:peteragrunde/courseyaml.git","http_url_to_repo":"https://gitlab.galvanize.com/peteragrunde/courseyaml.git","web_url":"https://gitlab.galvanize.com/peteragrunde/courseyaml","readme_url":null,"avatar_url":null,"star_count":0,"forks_count":0,"last_activity_at":"2020-08-04T18:59:47.516Z","namespace":{"id":10,"name":"Peter - Grunde","path":"peteragrunde","kind":"user","full_path":"peteragrunde","parent_id":null,"avatar_url":"https://secure.gravatar.com/avatar/f2a2c817c588e6c5a914a36815685467?s=80\u0026d=identicon","web_url":"https://gitlab.galvanize.com/peteragrunde"},"_links":{"self":"https://gitlab.galvanize.com/api/v4/projects/9","issues":"https://gitlab.galvanize.com/api/v4/projects/9/issues","merge_requests":"https://gitlab.galvanize.com/api/v4/projects/9/merge_requests","repo_branches":"https://gitlab.galvanize.com/api/v4/projects/9/repository/branches","labels":"https://gitlab.galvanize.com/api/v4/projects/9/labels","events":"https://gitlab.galvanize.com/api/v4/projects/9/events","members":"https://gitlab.galvanize.com/api/v4/projects/9/members"},"empty_repo":false,"archived":false,"visibility":"private","owner":{"id":9,"name":"Peter - Grunde","username":"peteragrunde","state":"active","avatar_url":"https://secure.gravatar.com/avatar/f2a2c817c588e6c5a914a36815685467?s=80\u0026d=identicon","web_url":"https://gitlab.galvanize.com/peteragrunde"},"resolve_outdated_diff_discussions":false,"container_registry_enabled":true,"container_expiration_policy":{"cadence":"7d","enabled":true,"keep_n":null,"older_than":null,"name_regex":null,"name_regex_keep":null,"next_run_at":"2020-08-05T20:14:33.466Z"},"issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"jobs_enabled":true,"snippets_enabled":true,"can_create_merge_request_in":true,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"enabled","wiki_access_level":"enabled","builds_access_level":"enabled","snippets_access_level":"enabled","pages_access_level":"private","emails_disabled":null,"shared_runners_enabled":true,"lfs_enabled":true,"creator_id":9,"import_status":"none","open_issues_count":0,"ci_default_git_depth":50,"public_jobs":true,"build_timeout":3600,"auto_cancel_pending_pipelines":"enabled","build_coverage_regex":null,"ci_config_path":null,"shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"request_access_enabled":true,"only_allow_merge_if_all_discussions_are_resolved":false,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"merge","suggestion_commit_message":null,"auto_devops_enabled":true,"auto_devops_deploy_strategy":"continuous","autoclose_referenced_issues":true,"permissions":{"project_access":{"access_level":40,"notification_level":3},"group_access":null}},{"id":4,"description":"","name":"new-testable-project - ","name_with_namespace":"tori / new-testable-project ","path":"new-testable-project","path_with_namespace":"tori_bo_bori/new-testable-project","created_at":"2020-06-11T18:31:43.774Z","default_branch":"master","tag_list":[],"ssh_url_to_repo":"git@gitlab.galvanize.com:tori_bo_bori/new-testable-project.git","http_url_to_repo":"https://gitlab.galvanize.com/tori_bo_bori/new-testable-project.git","web_url":"https://gitlab.galvanize.com/tori_bo_bori/new-testable-project","readme_url":null,"avatar_url":null,"star_count":0,"forks_count":0,"last_activity_at":"2020-07-28T17:19:15.539Z","namespace":{"id":6,"name":"tori","path":"tori_bo_bori","kind":"user","full_path":"tori_bo_bori","parent_id":null,"avatar_url":"https://secure.gravatar.com/avatar/4016ff16228c054071edacde54159f41?s=80\u0026d=identicon","web_url":"https://gitlab.galvanize.com/tori_bo_bori"},"_links":{"self":"https://gitlab.galvanize.com/api/v4/projects/4","issues":"https://gitlab.galvanize.com/api/v4/projects/4/issues","merge_requests":"https://gitlab.galvanize.com/api/v4/projects/4/merge_requests","repo_branches":"https://gitlab.galvanize.com/api/v4/projects/4/repository/branches","labels":"https://gitlab.galvanize.com/api/v4/projects/4/labels","events":"https://gitlab.galvanize.com/api/v4/projects/4/events","members":"https://gitlab.galvanize.com/api/v4/projects/4/members"},"empty_repo":false,"archived":false,"visibility":"internal","owner":{"id":6,"name":"tori","username":"tori_bo_bori","state":"active","avatar_url":"https://secure.gravatar.com/avatar/4016ff16228c054071edacde54159f41?s=80\u0026d=identicon","web_url":"https://gitlab.galvanize.com/tori_bo_bori"},"resolve_outdated_diff_discussions":false,"container_registry_enabled":true,"container_expiration_policy":{"cadence":"7d","enabled":true,"keep_n":null,"older_than":null,"name_regex":null,"name_regex_keep":null,"next_run_at":"2020-08-06T21:50:31.547Z"},"issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"jobs_enabled":true,"snippets_enabled":true,"can_create_merge_request_in":true,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"enabled","wiki_access_level":"enabled","builds_access_level":"enabled","snippets_access_level":"enabled","pages_access_level":"private","emails_disabled":null,"shared_runners_enabled":true,"lfs_enabled":true,"creator_id":6,"import_status":"none","open_issues_count":0,"ci_default_git_depth":50,"public_jobs":true,"build_timeout":3600,"auto_cancel_pending_pipelines":"enabled","build_coverage_regex":null,"ci_config_path":null,"shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"request_access_enabled":true,"only_allow_merge_if_all_discussions_are_resolved":false,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"merge","suggestion_commit_message":null,"auto_devops_enabled":false,"auto_devops_deploy_strategy":"continuous","autoclose_referenced_issues":true,"permissions":{"project_access":null,"group_access":null}}]' - http_version: - recorded_at: Tue, 04 Aug 2020 19:26:39 GMT + string: '[{"id":702,"description":"","name":"p1-test","name_with_namespace":"Charlie + Sakamaki / p1-test","path":"p1-test","path_with_namespace":"csakamaki/p1-test","created_at":"2020-09-23T19:53:49.310Z","default_branch":"master","tag_list":[],"ssh_url_to_repo":"git@code.il2.dsop.io:csakamaki/p1-test.git","http_url_to_repo":"https://code.il2.dsop.io/csakamaki/p1-test.git","web_url":"https://code.il2.dsop.io/csakamaki/p1-test","readme_url":null,"avatar_url":null,"star_count":0,"forks_count":0,"last_activity_at":"2020-09-24T00:07:57.336Z","namespace":{"id":288,"name":"Charlie + Sakamaki","path":"csakamaki","kind":"user","full_path":"csakamaki","parent_id":null,"avatar_url":"https://secure.gravatar.com/avatar/ed30ad3597897901ccbd315e731bf100?s=80\u0026d=identicon","web_url":"https://code.il2.dsop.io/csakamaki"},"_links":{"self":"https://code.il2.dsop.io/api/v4/projects/702","issues":"https://code.il2.dsop.io/api/v4/projects/702/issues","merge_requests":"https://code.il2.dsop.io/api/v4/projects/702/merge_requests","repo_branches":"https://code.il2.dsop.io/api/v4/projects/702/repository/branches","labels":"https://code.il2.dsop.io/api/v4/projects/702/labels","events":"https://code.il2.dsop.io/api/v4/projects/702/events","members":"https://code.il2.dsop.io/api/v4/projects/702/members"},"empty_repo":false,"archived":false,"visibility":"private","owner":{"id":238,"name":"Charlie + Sakamaki","username":"csakamaki","state":"active","avatar_url":"https://secure.gravatar.com/avatar/ed30ad3597897901ccbd315e731bf100?s=80\u0026d=identicon","web_url":"https://code.il2.dsop.io/csakamaki"},"resolve_outdated_diff_discussions":false,"container_registry_enabled":true,"container_expiration_policy":{"cadence":"7d","enabled":true,"keep_n":null,"older_than":null,"name_regex":null,"name_regex_keep":null,"next_run_at":"2020-10-07T20:50:13.933Z"},"issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"jobs_enabled":true,"snippets_enabled":true,"can_create_merge_request_in":true,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"enabled","wiki_access_level":"enabled","builds_access_level":"enabled","snippets_access_level":"enabled","pages_access_level":"private","emails_disabled":null,"shared_runners_enabled":true,"lfs_enabled":true,"creator_id":238,"import_status":"none","open_issues_count":0,"ci_default_git_depth":50,"public_jobs":true,"build_timeout":3600,"auto_cancel_pending_pipelines":"enabled","build_coverage_regex":null,"ci_config_path":"","shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"request_access_enabled":true,"only_allow_merge_if_all_discussions_are_resolved":false,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"merge","suggestion_commit_message":null,"auto_devops_enabled":false,"auto_devops_deploy_strategy":"continuous","autoclose_referenced_issues":true,"approvals_before_merge":0,"mirror":false,"external_authorization_classification_label":null,"packages_enabled":true,"service_desk_enabled":false,"service_desk_address":null,"marked_for_deletion_at":null,"marked_for_deletion_on":null,"permissions":{"project_access":{"access_level":40,"notification_level":3},"group_access":null}}]' + http_version: + recorded_at: Tue, 06 Oct 2020 07:37:20 GMT - request: method: head - uri: https://api.github.com/repos/gSchool/ds-python-quizzes-block + uri: https://api.github.com/repos/gSchool/revacomm-test body: encoding: US-ASCII string: '' headers: Authorization: - - token 34ed6e936ee7686b5a6adafb796fe4ad888c813a + - token 86f4c1b3eb7417dc81fe87466c5179106a6d213c User-Agent: - Galvanize Forge response: @@ -308,41 +219,44 @@ http_interactions: code: 200 message: OK headers: - Server: - - GitHub.com Date: - - Tue, 04 Aug 2020 19:26:40 GMT + - Tue, 06 Oct 2020 07:37:21 GMT Content-Type: - application/json; charset=utf-8 Content-Length: - - '6523' + - '6092' + Server: + - GitHub.com Status: - 200 OK - X-Ratelimit-Limit: - - '5000' - X-Ratelimit-Remaining: - - '4995' - X-Ratelimit-Reset: - - '1596572723' Cache-Control: - private, max-age=60, s-maxage=60 Vary: - Accept, Authorization, Cookie, X-GitHub-OTP + - Accept-Encoding - Accept-Encoding, Accept, X-Requested-With Etag: - - '"3ed650962861667cb8d370c03098a728"' + - '"2575197bdf1788abeea33fa22b34b5e4e00fe10bb9a22582fbd0a22e3ae43d14"' Last-Modified: - - Tue, 14 Aug 2018 03:34:36 GMT + - Wed, 23 Sep 2020 20:21:08 GMT X-Oauth-Scopes: - repo X-Accepted-Oauth-Scopes: - repo X-Github-Media-Type: - github.v3; format=json + X-Ratelimit-Limit: + - '5000' + X-Ratelimit-Remaining: + - '4999' + X-Ratelimit-Reset: + - '1601973441' + X-Ratelimit-Used: + - '1' Access-Control-Expose-Headers: - ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, - X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, - X-GitHub-Media-Type, Deprecation, Sunset + X-RateLimit-Used, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, + X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset Access-Control-Allow-Origin: - "*" Strict-Transport-Security: @@ -358,10 +272,10 @@ http_interactions: Content-Security-Policy: - default-src 'none' X-Github-Request-Id: - - C25D:6D16:15F1955:32AEC25:5F29B66F + - D9CF:6749:3F7741:4BD406:5F7C1EB0 body: encoding: UTF-8 string: '' - http_version: - recorded_at: Tue, 04 Aug 2020 19:26:40 GMT + http_version: + recorded_at: Tue, 06 Oct 2020 07:37:21 GMT recorded_with: VCR 4.0.0 diff --git a/spec/fixtures/vcr_cassettes/gitlab-not-found.yml b/spec/fixtures/vcr_cassettes/gitlab-not-found.yml index 4e900e7..7d3fbbb 100644 --- a/spec/fixtures/vcr_cassettes/gitlab-not-found.yml +++ b/spec/fixtures/vcr_cassettes/gitlab-not-found.yml @@ -2,13 +2,13 @@ http_interactions: - request: method: get - uri: https://gitlab.galvanize.com/api/v4/projects?membership=true&search=does-not-exist + uri: https://code.il2.dsop.io/api/v4/projects?membership=true&search=does-not-exist body: encoding: US-ASCII string: '' headers: Private-Token: - - blah + - WmXSEG8RHyy2ud_esxfF Accept-Encoding: - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 Accept: @@ -22,22 +22,16 @@ http_interactions: headers: Cache-Control: - max-age=0, private, must-revalidate + Content-Length: + - '2' Content-Type: - application/json - Date: - - Tue, 28 Jul 2020 21:44:22 GMT Etag: - W/"4f53cda18c2baa0c0354bb5f9a3ecbe5" Link: - - ; - rel="first", ; + - ; + rel="first", ; rel="last" - Referrer-Policy: - - strict-origin-when-cross-origin - Server: - - nginx - Strict-Transport-Security: - - max-age=31536000 Vary: - Origin X-Content-Type-Options: @@ -53,31 +47,33 @@ http_interactions: X-Prev-Page: - '' X-Request-Id: - - ydXwSBXdz31 + - 5DtY450BKt2 X-Runtime: - - '0.026346' + - '0.036173' X-Total: - '0' X-Total-Pages: - '1' - Content-Length: - - '2' - Connection: - - keep-alive + Date: + - Tue, 06 Oct 2020 07:49:47 GMT + X-Envoy-Upstream-Service-Time: + - '38' + Server: + - istio-envoy body: encoding: UTF-8 string: "[]" http_version: - recorded_at: Tue, 28 Jul 2020 21:44:23 GMT + recorded_at: Tue, 06 Oct 2020 07:49:47 GMT - request: method: get - uri: https://gitlab.galvanize.com/api/v4/projects//repository/branches/master + uri: https://code.il2.dsop.io/api/v4/projects//repository/branches/master body: encoding: US-ASCII string: '' headers: Private-Token: - - blah + - WmXSEG8RHyy2ud_esxfF Accept-Encoding: - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 Accept: @@ -91,25 +87,25 @@ http_interactions: headers: Cache-Control: - no-cache + Content-Length: + - '25' Content-Type: - application/json - Date: - - Tue, 28 Jul 2020 21:44:23 GMT - Server: - - nginx Vary: - Origin X-Request-Id: - - mBmBjSgTBV5 + - GZZKs8WY2z7 X-Runtime: - - '0.025525' - Content-Length: - - '25' - Connection: - - keep-alive + - '0.007294' + Date: + - Tue, 06 Oct 2020 07:49:47 GMT + X-Envoy-Upstream-Service-Time: + - '9' + Server: + - istio-envoy body: encoding: UTF-8 string: '{"error":"404 Not Found"}' http_version: - recorded_at: Tue, 28 Jul 2020 21:44:23 GMT + recorded_at: Tue, 06 Oct 2020 07:49:47 GMT recorded_with: VCR 4.0.0 diff --git a/spec/fixtures/vcr_cassettes/gitlab-success.yml b/spec/fixtures/vcr_cassettes/gitlab-success.yml index 0ee311f..c701ecf 100644 --- a/spec/fixtures/vcr_cassettes/gitlab-success.yml +++ b/spec/fixtures/vcr_cassettes/gitlab-success.yml @@ -2,13 +2,13 @@ http_interactions: - request: method: get - uri: https://gitlab.galvanize.com/api/v4/projects?membership=true&search=tori-block + uri: https://code.il2.dsop.io/api/v4/projects?membership=true&search=test-20200917 body: encoding: US-ASCII string: '' headers: Private-Token: - - blah + - WmXSEG8RHyy2ud_esxfF Accept-Encoding: - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 Accept: @@ -22,22 +22,16 @@ http_interactions: headers: Cache-Control: - max-age=0, private, must-revalidate + Content-Length: + - '3391' Content-Type: - application/json - Date: - - Tue, 28 Jul 2020 21:41:58 GMT Etag: - - W/"7dc1661449d1e7ae849c3df1b555ab2f" + - W/"94af059ec19294995f506264a0cbc893" Link: - - ; - rel="first", ; + - ; + rel="first", ; rel="last" - Referrer-Policy: - - strict-origin-when-cross-origin - Server: - - nginx - Strict-Transport-Security: - - max-age=31536000 Vary: - Origin X-Content-Type-Options: @@ -53,86 +47,36 @@ http_interactions: X-Prev-Page: - '' X-Request-Id: - - NTDPucrVWZ9 + - 6kMf53dilIa X-Runtime: - - '0.091574' + - '0.069335' X-Total: - '1' X-Total-Pages: - '1' - Content-Length: - - '3085' - Connection: - - keep-alive - body: - encoding: UTF-8 - string: '[{"id":8,"description":"","name":"tori-block","name_with_namespace":"tori - / tori-block","path":"tori-block","path_with_namespace":"tori_bo_bori/tori-block","created_at":"2020-07-28T19:55:46.548Z","default_branch":"master","tag_list":[],"ssh_url_to_repo":"git@gitlab.galvanize.com:tori_bo_bori/tori-block.git","http_url_to_repo":"https://gitlab.galvanize.com/tori_bo_bori/tori-block.git","web_url":"https://gitlab.galvanize.com/tori_bo_bori/tori-block","readme_url":null,"avatar_url":null,"star_count":0,"forks_count":0,"last_activity_at":"2020-07-28T19:55:46.548Z","namespace":{"id":6,"name":"tori","path":"tori_bo_bori","kind":"user","full_path":"tori_bo_bori","parent_id":null,"avatar_url":"https://secure.gravatar.com/avatar/4016ff16228c054071edacde54159f41?s=80\u0026d=identicon","web_url":"https://gitlab.galvanize.com/tori_bo_bori"},"_links":{"self":"https://gitlab.galvanize.com/api/v4/projects/8","issues":"https://gitlab.galvanize.com/api/v4/projects/8/issues","merge_requests":"https://gitlab.galvanize.com/api/v4/projects/8/merge_requests","repo_branches":"https://gitlab.galvanize.com/api/v4/projects/8/repository/branches","labels":"https://gitlab.galvanize.com/api/v4/projects/8/labels","events":"https://gitlab.galvanize.com/api/v4/projects/8/events","members":"https://gitlab.galvanize.com/api/v4/projects/8/members"},"empty_repo":false,"archived":false,"visibility":"private","owner":{"id":6,"name":"tori","username":"tori_bo_bori","state":"active","avatar_url":"https://secure.gravatar.com/avatar/4016ff16228c054071edacde54159f41?s=80\u0026d=identicon","web_url":"https://gitlab.galvanize.com/tori_bo_bori"},"resolve_outdated_diff_discussions":false,"container_registry_enabled":true,"container_expiration_policy":{"cadence":"7d","enabled":true,"keep_n":null,"older_than":null,"name_regex":null,"name_regex_keep":null,"next_run_at":"2020-08-04T19:55:46.573Z"},"issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"jobs_enabled":true,"snippets_enabled":true,"can_create_merge_request_in":true,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"enabled","wiki_access_level":"enabled","builds_access_level":"enabled","snippets_access_level":"enabled","pages_access_level":"private","emails_disabled":null,"shared_runners_enabled":true,"lfs_enabled":true,"creator_id":6,"import_status":"none","open_issues_count":0,"ci_default_git_depth":50,"public_jobs":true,"build_timeout":3600,"auto_cancel_pending_pipelines":"enabled","build_coverage_regex":null,"ci_config_path":null,"shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"request_access_enabled":true,"only_allow_merge_if_all_discussions_are_resolved":false,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"merge","suggestion_commit_message":null,"auto_devops_enabled":true,"auto_devops_deploy_strategy":"continuous","autoclose_referenced_issues":true,"permissions":{"project_access":{"access_level":30,"notification_level":3},"group_access":null}}]' - http_version: - recorded_at: Tue, 28 Jul 2020 21:41:58 GMT -- request: - method: get - uri: https://gitlab.galvanize.com/api/v4/projects/8/repository/branches/master - body: - encoding: US-ASCII - string: '' - headers: - Private-Token: - - blah - Accept-Encoding: - - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 - Accept: - - "*/*" - User-Agent: - - Ruby - response: - status: - code: 200 - message: OK - headers: - Cache-Control: - - max-age=0, private, must-revalidate - Content-Type: - - application/json Date: - - Tue, 28 Jul 2020 21:42:16 GMT - Etag: - - W/"9a7cc4a81299652f190fd62c8081c527" - Referrer-Policy: - - strict-origin-when-cross-origin + - Tue, 06 Oct 2020 07:55:51 GMT + X-Envoy-Upstream-Service-Time: + - '71' Server: - - nginx - Strict-Transport-Security: - - max-age=31536000 - Vary: - - Origin - X-Content-Type-Options: - - nosniff - X-Frame-Options: - - SAMEORIGIN - X-Request-Id: - - MBUj26IyOn4 - X-Runtime: - - '0.052905' - Content-Length: - - '803' - Connection: - - keep-alive + - istio-envoy body: encoding: UTF-8 - string: '{"name":"master","commit":{"id":"c832f0b537cb958223113fed33e581cc88b3666a","short_id":"c832f0b5","created_at":"2020-07-28T19:59:41.000+00:00","parent_ids":["980162b62dc0a315ea155798f7c458b628762536"],"title":"Add - new file","message":"Add new file","author_name":"tori","author_email":"victoria.kafati@galvanize.com","authored_date":"2020-07-28T19:59:41.000+00:00","committer_name":"tori","committer_email":"victoria.kafati@galvanize.com","committed_date":"2020-07-28T19:59:41.000+00:00","web_url":"https://gitlab.galvanize.com/tori_bo_bori/tori-block/-/commit/c832f0b537cb958223113fed33e581cc88b3666a"},"merged":false,"protected":true,"developers_can_push":false,"developers_can_merge":false,"can_push":false,"default":true,"web_url":"https://gitlab.galvanize.com/tori_bo_bori/tori-block/-/tree/master"}' + string: '[{"id":599,"description":"","name":"test-20200917","name_with_namespace":"Charlie + Sakamaki / test-20200917","path":"test-20200917","path_with_namespace":"csakamaki/test-20200917","created_at":"2020-09-18T20:08:10.651Z","default_branch":"master","tag_list":[],"ssh_url_to_repo":"git@code.il2.dsop.io:csakamaki/test-20200917.git","http_url_to_repo":"https://code.il2.dsop.io/csakamaki/test-20200917.git","web_url":"https://code.il2.dsop.io/csakamaki/test-20200917","readme_url":"https://code.il2.dsop.io/csakamaki/test-20200917/-/blob/master/README.md","avatar_url":null,"star_count":0,"forks_count":0,"last_activity_at":"2020-09-30T19:14:19.395Z","namespace":{"id":288,"name":"Charlie + Sakamaki","path":"csakamaki","kind":"user","full_path":"csakamaki","parent_id":null,"avatar_url":"https://secure.gravatar.com/avatar/ed30ad3597897901ccbd315e731bf100?s=80\u0026d=identicon","web_url":"https://code.il2.dsop.io/csakamaki"},"_links":{"self":"https://code.il2.dsop.io/api/v4/projects/599","issues":"https://code.il2.dsop.io/api/v4/projects/599/issues","merge_requests":"https://code.il2.dsop.io/api/v4/projects/599/merge_requests","repo_branches":"https://code.il2.dsop.io/api/v4/projects/599/repository/branches","labels":"https://code.il2.dsop.io/api/v4/projects/599/labels","events":"https://code.il2.dsop.io/api/v4/projects/599/events","members":"https://code.il2.dsop.io/api/v4/projects/599/members"},"empty_repo":false,"archived":false,"visibility":"public","owner":{"id":238,"name":"Charlie + Sakamaki","username":"csakamaki","state":"active","avatar_url":"https://secure.gravatar.com/avatar/ed30ad3597897901ccbd315e731bf100?s=80\u0026d=identicon","web_url":"https://code.il2.dsop.io/csakamaki"},"resolve_outdated_diff_discussions":false,"container_registry_enabled":true,"container_expiration_policy":{"cadence":"7d","enabled":true,"keep_n":null,"older_than":null,"name_regex":null,"name_regex_keep":null,"next_run_at":"2020-10-09T20:50:21.090Z"},"issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"jobs_enabled":true,"snippets_enabled":true,"can_create_merge_request_in":true,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"enabled","wiki_access_level":"enabled","builds_access_level":"enabled","snippets_access_level":"enabled","pages_access_level":"enabled","emails_disabled":null,"shared_runners_enabled":true,"lfs_enabled":true,"creator_id":238,"import_status":"none","open_issues_count":0,"ci_default_git_depth":50,"public_jobs":true,"build_timeout":3600,"auto_cancel_pending_pipelines":"enabled","build_coverage_regex":null,"ci_config_path":"","shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"request_access_enabled":true,"only_allow_merge_if_all_discussions_are_resolved":false,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"merge","suggestion_commit_message":null,"auto_devops_enabled":false,"auto_devops_deploy_strategy":"continuous","autoclose_referenced_issues":true,"approvals_before_merge":0,"mirror":false,"external_authorization_classification_label":null,"packages_enabled":true,"service_desk_enabled":false,"service_desk_address":null,"marked_for_deletion_at":null,"marked_for_deletion_on":null,"permissions":{"project_access":{"access_level":40,"notification_level":3},"group_access":null}}]' http_version: - recorded_at: Tue, 28 Jul 2020 21:42:16 GMT + recorded_at: Tue, 06 Oct 2020 07:55:51 GMT - request: method: get - uri: https://gitlab.galvanize.com/api/v4/projects/8/repository/branches/master + uri: https://code.il2.dsop.io/api/v4/projects/599/repository/branches/master body: encoding: US-ASCII string: '' headers: Private-Token: - - blah + - WmXSEG8RHyy2ud_esxfF Accept-Encoding: - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 Accept: @@ -146,18 +90,12 @@ http_interactions: headers: Cache-Control: - max-age=0, private, must-revalidate + Content-Length: + - '816' Content-Type: - application/json - Date: - - Tue, 28 Jul 2020 21:42:19 GMT Etag: - - W/"9a7cc4a81299652f190fd62c8081c527" - Referrer-Policy: - - strict-origin-when-cross-origin - Server: - - nginx - Strict-Transport-Security: - - max-age=31536000 + - W/"b75c5a8fd1ffffdfc9f75550b7c82847" Vary: - Origin X-Content-Type-Options: @@ -165,28 +103,31 @@ http_interactions: X-Frame-Options: - SAMEORIGIN X-Request-Id: - - 29FbcHD99S8 + - q2T3D9YGCS4 X-Runtime: - - '0.075793' - Content-Length: - - '803' - Connection: - - keep-alive + - '0.053157' + Date: + - Tue, 06 Oct 2020 07:55:51 GMT + X-Envoy-Upstream-Service-Time: + - '57' + Server: + - istio-envoy body: encoding: UTF-8 - string: '{"name":"master","commit":{"id":"c832f0b537cb958223113fed33e581cc88b3666a","short_id":"c832f0b5","created_at":"2020-07-28T19:59:41.000+00:00","parent_ids":["980162b62dc0a315ea155798f7c458b628762536"],"title":"Add - new file","message":"Add new file","author_name":"tori","author_email":"victoria.kafati@galvanize.com","authored_date":"2020-07-28T19:59:41.000+00:00","committer_name":"tori","committer_email":"victoria.kafati@galvanize.com","committed_date":"2020-07-28T19:59:41.000+00:00","web_url":"https://gitlab.galvanize.com/tori_bo_bori/tori-block/-/commit/c832f0b537cb958223113fed33e581cc88b3666a"},"merged":false,"protected":true,"developers_can_push":false,"developers_can_merge":false,"can_push":false,"default":true,"web_url":"https://gitlab.galvanize.com/tori_bo_bori/tori-block/-/tree/master"}' + string: '{"name":"master","commit":{"id":"0d3ccb796757d84e99dcf43ef913821483a248a0","short_id":"0d3ccb79","created_at":"2020-09-30T09:12:44.000-10:00","parent_ids":["1ff934599cfdc0f21efe3d524609aec8c73b0632"],"title":"add + python-simple","message":"add python-simple\n","author_name":"Charlie Sakamaki","author_email":"csakamaki@revacomm.com","authored_date":"2020-09-30T09:12:44.000-10:00","committer_name":"Charlie + Sakamaki","committer_email":"csakamaki@revacomm.com","committed_date":"2020-09-30T09:12:44.000-10:00","web_url":"https://code.il2.dsop.io/csakamaki/test-20200917/-/commit/0d3ccb796757d84e99dcf43ef913821483a248a0"},"merged":false,"protected":true,"developers_can_push":false,"developers_can_merge":false,"can_push":true,"default":true,"web_url":"https://code.il2.dsop.io/csakamaki/test-20200917/-/tree/master"}' http_version: - recorded_at: Tue, 28 Jul 2020 21:42:20 GMT + recorded_at: Tue, 06 Oct 2020 07:55:52 GMT - request: method: get - uri: https://gitlab.galvanize.com/api/v4/projects/8/repository/archive.zip + uri: https://code.il2.dsop.io/api/v4/projects/599/repository/archive.zip body: encoding: US-ASCII string: '' headers: Private-Token: - - blah + - WmXSEG8RHyy2ud_esxfF Accept-Encoding: - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 Accept: @@ -201,39 +142,37 @@ http_interactions: Cache-Control: - max-age=0, private, must-revalidate Content-Disposition: - - attachment; filename="tori-block-master-c832f0b537cb958223113fed33e581cc88b3666a.zip" + - attachment; filename="test-20200917-master-0d3ccb796757d84e99dcf43ef913821483a248a0.zip" Content-Transfer-Encoding: - binary Content-Type: - application/zip - Date: - - Tue, 28 Jul 2020 21:42:20 GMT Etag: - - W/"3f8c16fce1bd7f4c9c219c01dd6b05d2" - Referrer-Policy: - - strict-origin-when-cross-origin - Server: - - nginx - Strict-Transport-Security: - - max-age=31536000 + - W/"f6c043f69a6d473456415d31d209d042" Vary: - Origin + X-Accel-Buffering: + - 'no' X-Content-Type-Options: - nosniff X-Frame-Options: - SAMEORIGIN X-Request-Id: - - X7CSLGrg4Z3 + - fbo9AxdH8r1 X-Runtime: - - '0.041880' - Content-Length: - - '2278' - Connection: - - keep-alive + - '0.153419' + Date: + - Tue, 06 Oct 2020 07:55:52 GMT + X-Envoy-Upstream-Service-Time: + - '160' + Server: + - istio-envoy + Transfer-Encoding: + - chunked body: encoding: ASCII-8BIT string: !binary |- - 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ZTU4MWNjODhiMzY2NmEvVVQFAAGtgyBfUEsBAgAACgAAAAgAdJ/8UFzN5j8jAQAA+wEAAEYACQAAAAAAAQAAAAAAYgAAAHRvcmktYmxvY2stbWFzdGVyLWM4MzJmMGI1MzdjYjk1ODIyMzExM2ZlZDMzZTU4MWNjODhiMzY2NmEvY29uZmlnLnlhbWxVVAUAAa2DIF9QSwECAAAKAAAACAB0n/xQRFby0nYBAAD9AgAATwAJAAAAAAABAAAAAADyAQAAdG9yaS1ibG9jay1tYXN0ZXItYzgzMmYwYjUzN2NiOTU4MjIzMTEzZmVkMzNlNTgxY2M4OGIzNjY2YS9zaW1wbGUtY2hlY2twb2ludC5tZFVUBQABrYMgX1BLAQIAAAoAAAAIAHSf/FAbLfYBWwIAAHQFAABOAAkAAAAAAAEAAAAAAN4DAAB0b3JpLWJsb2NrLW1hc3Rlci1jODMyZjBiNTM3Y2I5NTgyMjMxMTNmZWQzM2U1ODFjYzg4YjM2NjZhL3Rlc3RhYmxlLXByb2plY3QubWRVVAUAAa2DIF9QSwUGAAAAAAQABAD6AQAArgYAACgAYzgzMmYwYjUzN2NiOTU4MjIzMTEzZmVkMzNlNTgxY2M4OGIzNjY2YQ== + UEsDBAoAAAAAAJaZPlEAAAAAAAAAAAAAAAA+AAkAdGVzdC0yMDIwMDkxNy1tYXN0ZXItMGQzY2NiNzk2NzU3ZDg0ZTk5ZGNmNDNlZjkxMzgyMTQ4M2EyNDhhMC9VVAUAAazYdF9QSwMECgAAAAgAlpk+UaIGo9WfBQAAwg8AAF4ACQB0ZXN0LTIwMjAwOTE3LW1hc3Rlci0wZDNjY2I3OTY3NTdkODRlOTlkY2Y0M2VmOTEzODIxNDgzYTI0OGEwL1B5dGhvbi1Db2RlLVNuaXBwZXQtQ2hhbGxlbmdlLm1kVVQFAAGs2HRf7Vffb9s2EH4u/4qr8+BkkFRb+eHUmLOHrsMC7EexpViAIIgpibZZy5QqUnG0Yfvb95GUbblNgw576UPz4FDH493x40fe3QG9acyiUPSqyAT9rmRZCkOvFjzPhZoLzdgnJgiDYk2ctKkzoQyZgtaVNGJjMJOVSE3ekFT0k+CViuhqIUjXyUpqLaEhNYl7ntfciIz4nEulDdVKwpbQRpNZcEO8whph6pK4ppJXhooZZsQulNbuJoyFUFggtFPShquMVxkVtSlrQ7OqWLkJ64GqWilR7QJk7OCALpURFU+NvBf0+oGvylxY+QE9TzceGfv2eRiSaUphN1GJ9zU2mwVegvi2mhSGF065n3M1r/lc9LsraFZUbtGYUsAcag9zRD9AXjocAypKA7S0Q6LvhXE06hN2tvk+js76W1cksz0fW7mRJhcfTbFvHokAwk3AY9r6hFRmYxKng1F6kg1CIYaDEAMRJrNBHI7OZtlJHIvj09G5tWrdjWkmcwBKSUNpzrVusXv+vsYJtCzYj8dhvZlm7NKewKo9WprVKnXLpt7uXdLcObvTMV1ChS8tNWkmuKmB14qbSj4ENL2eBgAMGFa8cSdk1wiNmcbNgIBehn0nIofc/Z9G1qpeFHWeIUzYVJb4Gw5WxVp7Tl3TelFo4VfbPdnpOTikvAjcmk6nHkl2cXGBBRNSZeQCOry5GQYUB3R8G9DNSUCnAZ3Z4Sig84Be2uFwENAQWsP49vbIWWj2LPR4L6Bean/cKOm1ah/gdHgdUOOUjthHzhn5v63jp20kXRt78WGv/hyFysLdWfqjL3OeikWRZ/bu6ZbfHJi3N7ayfLFs9C/AWgLwRBDPMlAEz4xVE5k0uCM7wnSMdqHOxOwT0btjORq7Lff7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Y291cnNlZmlsZXMvVVQFAAGs2HRfUEsDBAoAAAAAAJaZPlEAAAAAAAAAAAAAAABRAAkAdGVzdC0yMDIwMDkxNy1tYXN0ZXItMGQzY2NiNzk2NzU3ZDg0ZTk5ZGNmNDNlZjkxMzgyMTQ4M2EyNDhhMC9jb3Vyc2VmaWxlcy9naXRodWIvVVQFAAGs2HRfUEsDBAoAAAAIAJaZPlHw+naYXQAAAHUAAABcAAkAdGVzdC0yMDIwMDkxNy1tYXN0ZXItMGQzY2NiNzk2NzU3ZDg0ZTk5ZGNmNDNlZjkxMzgyMTQ4M2EyNDhhMC9jb3Vyc2VmaWxlcy9naXRodWIvY291cnNlLnlhbWxVVAUAAazYdF81ijsOgCAQRHtOMRdYie22tlYYD6BmIyQiBFbP7ydazZs3Y4jIAF06ShW+CSAMsmhIO/+A9h0AJzlV/srzHF3P8Kq5srVrUH/MzZKidXJOd8bOT2ULYlWqUvmkuQBQSwMECgAAAAAAlpk+UQAAAAAAAAAAAAAAAFEACQB0ZXN0LTIwMjAwOTE3LW1hc3Rlci0wZDNjY2I3OTY3NTdkODRlOTlkY2Y0M2VmOTEzODIxNDgzYTI0OGEwL2NvdXJzZWZpbGVzL2dpdGxhYi9VVAUAAazYdF9QSwMECgAAAAgAlpk+Uc9Kmm1jAAAAdQAAAFwACQB0ZXN0LTIwMjAwOTE3LW1hc3Rlci0wZDNjY2I3OTY3NTdkODRlOTlkY2Y0M2VmOTEzODIxNDgzYTI0OGEwL2NvdXJzZWZpbGVzL2dpdGxhYi9jb3Vyc2UueWFtbFVUBQABrNh0XzWKOw4CMQwF+5ziXcBJNg3CLS3VIg4QZS0RLeAIe+/PR2w3o5lARAE46fYy4Q8BhIs07/rkHTD9AjDLUOO/fM/rfGbc3IdxSk0Xif1e4mI6YtfUrK71UdeeXMyp5JLzcTqEN1BLAwQKAAAACACWmT5RoKr04p4BAAAfAwAATgAJAHRlc3QtMjAyMDA5MTctbWFzdGVyLTBkM2NjYjc5Njc1N2Q4NGU5OWRjZjQzZWY5MTM4MjE0ODNhMjQ4YTAvcHl0aG9uLXNpbXBsZS5tZFVUBQABrNh0X2VTTXObMBC961dsh+kMzgCTxDZ2fE2bX5BLT0aGxWgqJKKPafn33Q3Y2KkuSG/fvt23QkmSwLe6k1qjOaMQDxDGAQ9Q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c3QtMjAyMDA5MTctbWFzdGVyLTBkM2NjYjc5Njc1N2Q4NGU5OWRjZjQzZWY5MTM4MjE0ODNhMjQ4YTAvY2hlY2twb2ludC5tZFVUBQABrNh0X1BLAQIAAAoAAAAIAJaZPlE+YPWdeAEAANwCAABJAAkAAAAAAAEAAAAAAEgIAAB0ZXN0LTIwMjAwOTE3LW1hc3Rlci0wZDNjY2I3OTY3NTdkODRlOTlkY2Y0M2VmOTEzODIxNDgzYTI0OGEwL2NvbmZpZy55YW1sVVQFAAGs2HRfUEsBAgAACgAAAAAAlpk+UQAAAAAAAAAAAAAAAEoACQAAAAAAAAAQAAAAMAoAAHRlc3QtMjAyMDA5MTctbWFzdGVyLTBkM2NjYjc5Njc1N2Q4NGU5OWRjZjQzZWY5MTM4MjE0ODNhMjQ4YTAvY291cnNlZmlsZXMvVVQFAAGs2HRfUEsBAgAACgAAAAAAlpk+UQAAAAAAAAAAAAAAAFEACQAAAAAAAAAQAAAAoQoAAHRlc3QtMjAyMDA5MTctbWFzdGVyLTBkM2NjYjc5Njc1N2Q4NGU5OWRjZjQzZWY5MTM4MjE0ODNhMjQ4YTAvY291cnNlZmlsZXMvZ2l0aHViL1VUBQABrNh0X1BLAQIAAAoAAAAIAJaZPlHw+naYXQAAAHUAAABcAAkAAAAAAAEAAAAAABkLAAB0ZXN0LTIwMjAwOTE3LW1hc3Rlci0wZDNjY2I3OTY3NTdkODRlOTlkY2Y0M2VmOTEzODIxNDgzYTI0OGEwL2NvdXJzZWZpbGVzL2dpdGh1Yi9jb3Vyc2UueWFtbFVUBQABrNh0X1BLAQIAAAoAAAAAAJaZPlEAAAAAAAAAAAAAAABRAAkAAAAAAAAAEAAAAPkLAAB0ZXN0LTIwMjAwOTE3LW1hc3Rlci0wZDNjY2I3OTY3NTdkODRlOTlkY2Y0M2VmOTEzODIxNDgzYTI0OGEwL2NvdXJzZWZpbGVzL2dpdGxhYi9VVAUAAazYdF9QSwECAAAKAAAACACWmT5Rz0qabWMAAAB1AAAAXAAJAAAAAAABAAAAAABxDAAAdGVzdC0yMDIwMDkxNy1tYXN0ZXItMGQzY2NiNzk2NzU3ZDg0ZTk5ZGNmNDNlZjkxMzgyMTQ4M2EyNDhhMC9jb3Vyc2VmaWxlcy9naXRsYWIvY291cnNlLnlhbWxVVAUAAazYdF9QSwECAAAKAAAACACWmT5RoKr04p4BAAAfAwAATgAJAAAAAAABAAAAAABXDQAAdGVzdC0yMDIwMDkxNy1tYXN0ZXItMGQzY2NiNzk2NzU3ZDg0ZTk5ZGNmNDNlZjkxMzgyMTQ4M2EyNDhhMC9weXRob24tc2ltcGxlLm1kVVQFAAGs2HRfUEsBAgAACgAAAAgAlpk+URN/NXSBAwAAIwgAAE4ACQAAAAAAAQAAAAAAag8AAHRlc3QtMjAyMDA5MTctbWFzdGVyLTBkM2NjYjc5Njc1N2Q4NGU5OWRjZjQzZWY5MTM4MjE0ODNhMjQ4YTAvcmV2YWNvbW0tcXVpei5tZFVUBQABrNh0X1BLBQYAAAAADAAMAEsGAABgEwAAKAAwZDNjY2I3OTY3NTdkODRlOTlkY2Y0M2VmOTEzODIxNDgzYTI0OGEw http_version: - recorded_at: Tue, 28 Jul 2020 21:42:20 GMT + recorded_at: Tue, 06 Oct 2020 07:55:52 GMT recorded_with: VCR 4.0.0 diff --git a/spec/models/block_spec.rb b/spec/models/block_spec.rb index 0753f91..8c0ddf2 100644 --- a/spec/models/block_spec.rb +++ b/spec/models/block_spec.rb @@ -61,7 +61,6 @@ describe Block do # The check has been removed to allow for gitlab subprojects xit "fails validation" do subject.save - byebug expect(subject.valid?).to eq false expect(subject.errors[:repo]).to include("URL cannot include a branch") end diff --git a/spec/services/assessment_service_spec.rb b/spec/services/assessment_service_spec.rb index 6d73f76..db72262 100644 --- a/spec/services/assessment_service_spec.rb +++ b/spec/services/assessment_service_spec.rb @@ -8,13 +8,13 @@ describe AssessmentService do let(:challenge) { create(:challenge, challenge_type: Challenge::TYPES[:code_snippet], tests: "function () {return true;}", setup: "console.log(\"helloWorld\")", language: "javascript") } let(:submitted_challenge_answer) { create(:submitted_challenge_answer, status: "processing", challenge_id: challenge.id, answer: "function repeats() {return true;}") } - it "returns 200 if job created" do - allow_any_instance_of(Faraday::Connection).to receive(:post).and_return(faraday_resp) + it "returns creates a javascript job" do response = described_class.evaluate_code_snippet(challenge, submitted_challenge_answer, "some-callback-url") - expect(response.status).to eq(200) + expect(response.queue_name).to eq("javascript_evaluation") end - it "updates submitted challenge answer with borked status when non-200 is yielded" do + # Code assessments no longer use Faraday requests + xit "updates submitted challenge answer with borked status when non-200 is yielded" do allow_any_instance_of(Faraday::Connection).to receive(:post).and_return(OpenStruct.new(status: 400)) response = described_class.evaluate_code_snippet(challenge, submitted_challenge_answer, "some-callback-url") expect(response.status).to eq(400) @@ -22,7 +22,8 @@ describe AssessmentService do expect(submitted_challenge_answer.reload.test_results).to eq("Connection failed") end - it "updates submitted challenge answer with borked status when Faraday::ConnectionFailed is raised" do + # Code assessments no longer use Faraday requests + xit "updates submitted challenge answer with borked status when Faraday::ConnectionFailed is raised" do allow_any_instance_of(Faraday::Connection).to receive(:post).and_raise(Faraday::ConnectionFailed.new("bork")) described_class.evaluate_code_snippet(challenge, submitted_challenge_answer, "some-callback-url") expect(submitted_challenge_answer.reload.status).to eq("failed") diff --git a/spec/services/course_validator_spec.rb b/spec/services/course_validator_spec.rb index f0216f1..f873719 100644 --- a/spec/services/course_validator_spec.rb +++ b/spec/services/course_validator_spec.rb @@ -29,22 +29,21 @@ describe CourseValidator do it "works when the course yaml file comes from gitlab sources" do VCR.use_cassette("gitlab-course-yaml-success") do - result = described_class.run(url: "https://gitlab.galvanize.com/peteragrunde/courseyaml/blob/master/course.yaml") + result = described_class.run(url: "https://code.il2.dsop.io/csakamaki/p1-test/-/blob/master/course.yaml") expect(result).to be_a_success expect(result.value[:course]).to eq({ default_unit_visibility: false, sections: [ { - title: "DSI Admissions Prep", + title: "DSOP GitLab", repos: [ - {url: "https://github.com/gSchool/dsi-intro-to-ds-stats"}, - {url: "https://gitlab.galvanize.com/peteragrunde/test"}, + { url: "https://code.il2.dsop.io/csakamaki/p1-test" } ] }, { - title: "Advanced DSI Admissions Prep", + title: "gSchool GitHub", repos: [ - {url: "https://github.com/gSchool/ds-python-quizzes-block"}, + { url: "https://github.com/gSchool/revacomm-test" } ] } ] @@ -55,9 +54,9 @@ describe CourseValidator do it "fetches from branches and fails when repos are missing in the yaml" do VCR.use_cassette("gitlab-course-yaml-branch-failure") do - result = described_class.run(url: "https://gitlab.galvanize.com/peteragrunde/courseyaml/-/blob/missingfile/course.yaml") + result = described_class.run(url: "https://code.il2.dsop.io/csakamaki/p1-test/-/blob/missingfile/course.yaml") expect(result).to be_a_failure - expect(result.value.type).to eq :section_course_http_fetch_error + expect(result.value.type).to eq :top_course_http_fetch_error end end diff --git a/spec/services/download_repository_service_spec.rb b/spec/services/download_repository_service_spec.rb index b532230..d08a6bc 100644 --- a/spec/services/download_repository_service_spec.rb +++ b/spec/services/download_repository_service_spec.rb @@ -44,14 +44,14 @@ describe DownloadRepositoryService do end context "when downloading from gitlab" do - let(:block) { create(:block, org: "tori_bo_bori", origin: "gitlab.galvanize.com", repo_name: "tori-block")} + let(:block) { create(:block, org: "csakamaki", origin: "code.il2.dsop.io", repo_name: "test-20200917")} let(:release) { create(:release, block: block)} subject { DownloadGitlabRepositoryService.new(release: release, tmp_path: Rails.root.join("tmp", block.repo_name)).execute } describe ".execute" do context "when provided an invalid gitlab url" do - let(:block) { create(:block, org: "not-found", origin: "gitlab.galvanize.com", repo_name: "does-not-exist")} + let(:block) { create(:block, org: "not-found", origin: "code.il2.dsop.io", repo_name: "does-not-exist")} it "returns an error" do VCR.use_cassette("gitlab-not-found") do @@ -64,8 +64,8 @@ describe DownloadRepositoryService do it "returns no errors" do VCR.use_cassette("gitlab-success") do expect(subject[:errors]).to eq([]) - expect(subject[:repository_path]).to include("tori-block/tori-block-master") - expect(subject[:sha]).to eq("c832f0b537cb958223113fed33e581cc88b3666a") + expect(subject[:repository_path]).to include("test-20200917") + expect(subject[:sha]).to eq("0d3ccb796757d84e99dcf43ef913821483a248a0") end end end -- GitLab From 332751ea379036d0671cc4569b2d654a91247703 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Tue, 6 Oct 2020 08:48:38 -1000 Subject: [PATCH 130/283] Disabled webhook auth tests --- .../webhooks/auth/cohorts_controller_spec.rb | 16 +++++++++------- .../webhooks/auth/users_controller_spec.rb | 14 ++++++++------ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/spec/controllers/webhooks/auth/cohorts_controller_spec.rb b/spec/controllers/webhooks/auth/cohorts_controller_spec.rb index 99ddd50..ca76a70 100644 --- a/spec/controllers/webhooks/auth/cohorts_controller_spec.rb +++ b/spec/controllers/webhooks/auth/cohorts_controller_spec.rb @@ -1,5 +1,7 @@ require "spec_helper" +# Disabling rspec tests here since Auth is no longer used + describe Webhooks::Auth::CohortsController, type: :request do describe "POST #update" do let(:action) do @@ -32,7 +34,7 @@ describe Webhooks::Auth::CohortsController, type: :request do context "when the auth token is incorrect" do before { AuthApi.configuration.webhook_token = "....bad token...." } - it "404s" do + xit "404s" do expect { action }.to raise_error(ActionController::RoutingError) end end @@ -43,7 +45,7 @@ describe Webhooks::Auth::CohortsController, type: :request do context "when resolving a new cohort that is not a valid Forge product type" do let(:product_type) { "" } - it "notifies honeybadger" do + xit "notifies honeybadger" do expect(Honeybadger).to receive(:notify) do |message, options| expect(message).to eq("Provided cohort is not compatible with Learn V2") expect(options[:context][:auth_resource].attributes).to eq(cohort_info[:attributes]) @@ -52,7 +54,7 @@ describe Webhooks::Auth::CohortsController, type: :request do action end - it "responds with errors" do + xit "responds with errors" do action errors = { "cohort" => cohort_info, "errors" => ["Provided cohort is not compatible with Learn V2"] }.to_json @@ -111,7 +113,7 @@ describe Webhooks::Auth::CohortsController, type: :request do before { create(:cohort, label: "00-00-WD-DP", uid: "abc123") } - it "notifies honeybadger" do + xit "notifies honeybadger" do expect(Honeybadger).to receive(:notify) do |_message, options| expect(options[:context][:errors]).to eq(["Uid can't be blank"]) end @@ -119,7 +121,7 @@ describe Webhooks::Auth::CohortsController, type: :request do action end - it "responds with errors" do + xit "responds with errors" do action errors = { "cohort" => cohort_info, "errors" => ["Uid can't be blank"] }.to_json @@ -127,7 +129,7 @@ describe Webhooks::Auth::CohortsController, type: :request do end end - it "creates a cohort with the valid attributes" do + xit "creates a cohort with the valid attributes" do expect { action }.to change { Cohort.count }.by(1) cohort = Cohort.last @@ -142,7 +144,7 @@ describe Webhooks::Auth::CohortsController, type: :request do expect(cohort.ends_on).to eq("2017-08-30T00:00:00.000Z") end - it "updates an existing cohort with the valid attributes" do + xit "updates an existing cohort with the valid attributes" do cohort = create(:cohort, uid: "abc123", label: "foo") expect { action }.to_not(change { Cohort.count }) diff --git a/spec/controllers/webhooks/auth/users_controller_spec.rb b/spec/controllers/webhooks/auth/users_controller_spec.rb index ca51d6c..03fba72 100644 --- a/spec/controllers/webhooks/auth/users_controller_spec.rb +++ b/spec/controllers/webhooks/auth/users_controller_spec.rb @@ -1,5 +1,7 @@ require "spec_helper" +# Disabling rspec tests here since Auth is no longer used + describe Webhooks::Auth::UsersController, type: :request do describe "POST #update" do let(:action) do @@ -27,7 +29,7 @@ describe Webhooks::Auth::UsersController, type: :request do context "when the auth token is incorrect" do before { AuthApi.configuration.webhook_token = "baz" } - it "404s" do + xit "404s" do expect { action }.to raise_error(ActionController::RoutingError) end end @@ -38,7 +40,7 @@ describe Webhooks::Auth::UsersController, type: :request do context "when the user fails validation on update" do before { create(:user, email: "smitty@example.com", uid: "futzybutzy") } - it "notifies honeybadger" do + xit "notifies honeybadger" do expect(Honeybadger).to receive(:notify) do |message, options| expect(message).to eq("Invalid user payload") expect(options[:context][:errors]).to eq(["First name can't be blank"]) @@ -47,7 +49,7 @@ describe Webhooks::Auth::UsersController, type: :request do action end - it "responds with errors" do + xit "responds with errors" do action errors = { "user" => user_info, "errors" => ["First name can't be blank"] }.to_json @@ -56,7 +58,7 @@ describe Webhooks::Auth::UsersController, type: :request do end context "when the user fails validation on create" do - it "responds with errors" do + xit "responds with errors" do action errors = { "user" => user_info, "errors" => ["First name can't be blank"] }.to_json @@ -85,7 +87,7 @@ describe Webhooks::Auth::UsersController, type: :request do } end - it "creates a user with the valid attributes" do + xit "creates a user with the valid attributes" do expect { action }.to change { User.count }.by(1) user = User.last @@ -94,7 +96,7 @@ describe Webhooks::Auth::UsersController, type: :request do expect(user.email).to eq "smooty@exmaple.com" end - it "updates an existing user with the valid attributes" do + xit "updates an existing user with the valid attributes" do user = create(:user, :admin, uid: "futzybutzy", first_name: "FIrst", last_name: "Name", email: "exampleemail@something.com", profile_image: "img.img", timezone: "PST") -- GitLab From f180de1293bbd2c9a0e067e31eae2669b67769ca Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Tue, 6 Oct 2020 11:33:51 -1000 Subject: [PATCH 131/283] Fixes for testing --- .../api/v1/cohorts/users_controller_spec.rb | 58 +++---------------- .../cohorts/management_feature_spec.rb | 19 +++--- 2 files changed, 19 insertions(+), 58 deletions(-) diff --git a/spec/controllers/api/v1/cohorts/users_controller_spec.rb b/spec/controllers/api/v1/cohorts/users_controller_spec.rb index cc70a50..e345933 100644 --- a/spec/controllers/api/v1/cohorts/users_controller_spec.rb +++ b/spec/controllers/api/v1/cohorts/users_controller_spec.rb @@ -77,31 +77,18 @@ resource "Enrollments" do post "/api/v1/cohorts/:cohort_id/users" do example "Creating a user and their enrollment" do explanation <<-MARKDOWN.strip_heredoc - Invite new users or enroll existing users to a cohort. A user is invited only if they do not exist. Enrolling a user who is already enrolled changes nothing about their enrollment- their roles will not be modified to match the body parameters, and instead must be changed via a PATCH. + Invite new users or enroll existing users to a cohort. A user is added only if they do not exist. Enrolling a user who is already enrolled changes nothing about their enrollment- their roles will not be modified to match the body parameters, and instead must be changed via a PATCH. MARKDOWN header "X-LEARN-API-TOKEN", "Bearer #{user.api_token}" - # Using double for Keyclaok::Internal does not seem to work - # dbl = double(Keycloak::Internal) - - # expect(Keycloak::Internal).to receive(:get_user_info).with( - # email, - # true, - # Rails.application.secrets.keycloak_client_id, - # Rails.application.secrets.keycloak_client_secret - # ).and_return(OpenStruct.new({ id: "4b58555dbbc93c9016f7325ead84667d", - # firstName: first_name, - # lastName: last_name, - # email: email - # })) - expect { do_request }.to have_enqueued_job(CreateApiInteractionJob) new_user = User.find_by(email: email) - expect(new_user.first_name).to eq(first_name) - expect(new_user.last_name).to eq(last_name) + # New user only has an email field and no uid or name info + # expect(new_user.first_name).to eq(first_name) + # expect(new_user.last_name).to eq(last_name) expect(new_user.email).to eq(email) expect(status).to eq 200 @@ -113,16 +100,11 @@ resource "Enrollments" do existing_user = create(:user, email: email, first_name: first_name, last_name: last_name) header "X-LEARN-API-TOKEN", "Bearer #{user.api_token}" - allow(Keycloak::Internal).to receive(:get_user_info).and_return(OpenStruct.new({ id: "test", - firstName: first_name, - lastName: last_name, - email: email - })) - expect { do_request }.to have_enqueued_job(CreateApiInteractionJob) + existing_user = User.find_by(email: email) expect(existing_user.first_name).to eq(first_name) expect(existing_user.last_name).to eq(last_name) expect(existing_user.email).to eq(email) @@ -132,47 +114,23 @@ resource "Enrollments" do expect(response_json["status"]).to eq("ok") end - it "makes a request to KeyCloak even if the user exists and is enrolled" do + it "returns an error if the user exists in the cohort" do header "X-LEARN-API-TOKEN", "Bearer #{user.api_token}" existing_user = create(:user, email: email, first_name: first_name, last_name: last_name) create(:cohort_user, user: existing_user, cohort: cohort) - expect(Keycloak::Internal).to receive(:get_user_info).with( - email, - true, - Rails.application.secrets.keycloak_client_id, - Rails.application.secrets.keycloak_client_secret - ).and_return(OpenStruct.new({ id: "test", - firstName: first_name, - lastName: last_name, - email: email - })) - expect { do_request }.to have_enqueued_job(CreateApiInteractionJob) + existing_user = User.find_by(email: email) expect(existing_user.first_name).to eq(first_name) expect(existing_user.last_name).to eq(last_name) expect(existing_user.email).to eq(email) - expect(status).to eq 200 - - expect(response_json["status"]).to eq("ok") - end - - it "responds with a 400 when the KeyCloak request fails" do - header "X-LEARN-API-TOKEN", "Bearer #{user.api_token}" - - expect(Keycloak::Internal).to receive(:get_user_info).and_raise(Keycloak::UserLoginNotFound) - - expect { - do_request - }.to have_enqueued_job(CreateApiInteractionJob) - expect(status).to eq 400 - expect(response_json["error"]).to eq("User does not exist in KeyCloak.") + expect(response_json["error"]).to eq("User is already in the cohort.") end context "malformed body" do diff --git a/spec/features/cohorts/management_feature_spec.rb b/spec/features/cohorts/management_feature_spec.rb index 84b1dd4..4b12ce8 100644 --- a/spec/features/cohorts/management_feature_spec.rb +++ b/spec/features/cohorts/management_feature_spec.rb @@ -539,7 +539,7 @@ describe "Cohorts management", js: true do expect(page).to have_content("Syncing...") expect(page).to have_content("CANCEL") - + find(".lp-style-button").click expect(page).to have_content("RESYNC") end @@ -625,7 +625,9 @@ describe "Cohorts management", js: true do end context "manage external users" do - it "allows users to view an auth Manage Users link if they have auth.admin or the auth.product_admin cohort_user role" do + + # Disabled since this feature currently does not exist + xit "allows users to view an auth Manage Users link if they have auth.admin or the auth.product_admin cohort_user role" do visit(users_cohort_path(cohort)) expect(page).to have_content(cohort.name) expect(page).to_not have_link("Manage Users in Auth") @@ -657,12 +659,13 @@ describe "Cohorts management", js: true do it "allows users to view an individual student's submissions from the cohort users tab" do visit(users_cohort_path(cohort)) - find(".action-kebab").click + all(".action-kebab").last.click find("a", text: "View Submissions").click - assert_current_path(submissions_dashboard_cohort_user_path(cohort.id, cohort.students.first.id)) + assert_current_path(submissions_dashboard_cohort_user_path(cohort.id, cohort.students.last.id)) end - - it "allows users to view an individual in auth from the cohort users tab" do + + # Disabled since this feature currently does not exist + xit "allows users to view an individual in auth from the cohort users tab" do visit(users_cohort_path(cohort)) find(".action-kebab").click expect(page).to have_link("View In Auth") @@ -690,7 +693,7 @@ describe "Cohorts management", js: true do expect(page).to have_content("Secret") expect(page).to have_content("Savvy") expect(page).to have_content("Sinon") - + find(".action-item", text: "Create New").click fill_in "Title", with: "Pair Force One" find('select').find(:xpath, 'option[2]').select_option @@ -726,7 +729,7 @@ describe "Cohorts management", js: true do within first_student do find('.fa-unlock-alt').click end - 5.times do + 5.times do click_button "Random" page.driver.browser.switch_to.alert.dismiss expect(all('.student').first.text).to eq(name) -- GitLab From 564f114f7f0ff8fb8772bc324d0a00305ec4008f Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 6 Oct 2020 12:18:53 -1000 Subject: [PATCH 132/283] adding new users listing and edit for global roles. removing global role edit from cohort user edit form --- app/controllers/users_controller.rb | 32 ++++++++++++++----- app/policies/user_policy.rb | 6 ++++ .../layouts/_primary_navigation.html.haml | 2 ++ app/views/users/edit.html.haml | 12 ------- app/views/users/edit_user.html.haml | 26 +++++++++++++++ app/views/users/index.html.haml | 20 ++++++++++++ config/routes.rb | 7 ++++ 7 files changed, 85 insertions(+), 20 deletions(-) create mode 100644 app/views/users/edit_user.html.haml create mode 100644 app/views/users/index.html.haml diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 941c048..c5cd2e0 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,4 +1,28 @@ class UsersController < ApplicationController + def index + authorize(current_user) + @users = User.all.limit(20) + render :index + end + + def edit_user + authorize(current_user) + user + render :edit_user + end + + def update_user + authorize(current_user) + + unless user.update(roles:[params[:forge_admin], params[:forge_blocks_manager], params[:auth_product_admin]].compact) + flash[:error] = user.errors.full_messages.join(", ") + render :edit + return + end + + redirect_to users_path + end + def new authorize(Cohort) @cohort_id = params[:cohort_id] @@ -18,14 +42,6 @@ class UsersController < ApplicationController return end - if (current_user.admin?) - unless user.update(roles:[params[:forge_admin], params[:forge_blocks_manager], params[:auth_product_admin]].compact) - flash[:error] = user.errors.full_messages.join(", ") - render :edit - return - end - end - redirect_to users_cohort_path(current_cohort) end diff --git a/app/policies/user_policy.rb b/app/policies/user_policy.rb index a0b8ee9..c1b93ba 100644 --- a/app/policies/user_policy.rb +++ b/app/policies/user_policy.rb @@ -3,6 +3,10 @@ class UserPolicy < ApplicationPolicy user == record end + def edit_user? + user.admin? + end + def view_challenges? user.instructor_or_admin?(record.cohort_id) end @@ -19,6 +23,8 @@ class UserPolicy < ApplicationPolicy user.onboarder? end + alias index? edit_user? + alias update_user? edit_user? alias regenerate_api_token? content_file_api? alias release_polling? content_file_api? alias learn_cli_credentials? content_file_api? diff --git a/app/views/layouts/_primary_navigation.html.haml b/app/views/layouts/_primary_navigation.html.haml index d76b7f0..6c55bfb 100644 --- a/app/views/layouts/_primary_navigation.html.haml +++ b/app/views/layouts/_primary_navigation.html.haml @@ -30,6 +30,8 @@ - if current_user.admin? %li.item = link_to("Cohorts", cohorts_path) + %li.item + = link_to("Users", users_path) .notifications= react_component "Notifications", isMobileDevice: @is_mobile_device .item .navigation-dropdown diff --git a/app/views/users/edit.html.haml b/app/views/users/edit.html.haml index de0f522..761e786 100644 --- a/app/views/users/edit.html.haml +++ b/app/views/users/edit.html.haml @@ -15,18 +15,6 @@ .form-check = check_box_tag :instructor, "forge.instructor", @cohort_user.roles.include?("forge.instructor"), class: "form-check-input" = label_tag :instructor, "Instructor" - - if @current_user.admin? - %h5 Global Roles: - .form-group - .form-check - = check_box_tag :forge_admin, "forge.admin", @user.roles.include?("forge.admin"), class: "form-check-input" - = label_tag :forge_admin, "Forge Admin" - .form-check - = check_box_tag :forge_blocks_manager, "forge.blocks_manager", @user.roles.include?("forge.blocks_manager"), class: "form-check-input" - = label_tag :forge_blocks_manager, "Forge Blocks Manager" - .form-check - = check_box_tag :auth_product_admin, "auth.product_admin", @user.roles.include?("auth.product_admin"), class: "form-check-input" - = label_tag :auth_product_admin, "Forge Product Admin" = f.submit "Update Cohort User", class: "btn btn-primary" = link_to "Remove User From Cohort", "#my-modal", class: "btn btn-danger", "data-toggle": "modal", style: "float:right;" .modal{id: "my-modal"} diff --git a/app/views/users/edit_user.html.haml b/app/views/users/edit_user.html.haml new file mode 100644 index 0000000..95a6087 --- /dev/null +++ b/app/views/users/edit_user.html.haml @@ -0,0 +1,26 @@ +.container + %h1 Edit User +%br +.container + = form_for @user, :url => { :controller => 'users', :action => :update_user } do |f| + .form-group + = label :first_name, :title, "First Name" + = text_field_tag :first_name, @user.first_name, class: "form-control", readonly: true + .form-group + = label :last_name, :title, "Last Name" + = text_field_tag :last_name, @user.last_name, class: "form-control", readonly: true + .form-group + = label :email, :title, "Email" + = text_field_tag :email, @user.email, class: "form-control", readonly: true + %h5 Global Roles: + .form-group + .form-check + = check_box_tag :forge_admin, "forge.admin", @user.roles.include?("forge.admin"), class: "form-check-input" + = label_tag :forge_admin, "Forge Admin" + .form-check + = check_box_tag :forge_blocks_manager, "forge.blocks_manager", @user.roles.include?("forge.blocks_manager"), class: "form-check-input" + = label_tag :forge_blocks_manager, "Forge Blocks Manager" + .form-check + = check_box_tag :auth_product_admin, "auth.product_admin", @user.roles.include?("auth.product_admin"), class: "form-check-input" + = label_tag :auth_product_admin, "Forge Product Admin" + = f.submit "Update User", class: "btn btn-primary" \ No newline at end of file diff --git a/app/views/users/index.html.haml b/app/views/users/index.html.haml new file mode 100644 index 0000000..ac9b223 --- /dev/null +++ b/app/views/users/index.html.haml @@ -0,0 +1,20 @@ +.container + %h1 Users + %br + - if @users.present? + %table.table.table-hover + %thead + %tr + %th First + %th Last + %th Email + %th + %tbody + - @users.each do |u| + %tr + %td= u.first_name + %td= u.last_name + %td= u.email + %td{ style: "text-align: right;" } + %a{href: edit_user_user_path(u)} + %button.lp-style-button.-small Edit \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index bf3c21c..b453d74 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -44,6 +44,13 @@ Rails.application.routes.draw do match "*path", via: :all, to: "application#not_found_or_invalid_version" end + resources :users, only: %i[ index ] do + member do + get :edit_user + patch :update_user + end + end + resources :blocks, only: %i[index create new show] do member do get :release_polling -- GitLab From 02e5910796b443ee8ab873b7e0eca3da083cbd4b Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 6 Oct 2020 16:33:26 -1000 Subject: [PATCH 133/283] ordering by email. --- app/controllers/users_controller.rb | 2 +- app/views/users/index.html.haml | 33 ++++++++++++++--------------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index c5cd2e0..659d1d0 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,7 +1,7 @@ class UsersController < ApplicationController def index authorize(current_user) - @users = User.all.limit(20) + @users = User.order('LOWER(email)') render :index end diff --git a/app/views/users/index.html.haml b/app/views/users/index.html.haml index ac9b223..7207085 100644 --- a/app/views/users/index.html.haml +++ b/app/views/users/index.html.haml @@ -1,20 +1,19 @@ .container %h1 Users %br - - if @users.present? - %table.table.table-hover - %thead - %tr - %th First - %th Last - %th Email - %th - %tbody - - @users.each do |u| - %tr - %td= u.first_name - %td= u.last_name - %td= u.email - %td{ style: "text-align: right;" } - %a{href: edit_user_user_path(u)} - %button.lp-style-button.-small Edit \ No newline at end of file + %table.table.table-hover + %thead + %tr + %th First + %th Last + %th Email + %th + %tbody + - @users.each do |u| + %tr + %td= u.first_name + %td= u.last_name + %td= u.email + %td{ style: "text-align: right;" } + %a{href: edit_user_user_path(u)} + %button.lp-style-button.-small Edit \ No newline at end of file -- GitLab From f2e6f4df8ba1e9f81be62d7ee0022df0ca1896b9 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 6 Oct 2020 21:53:45 -1000 Subject: [PATCH 134/283] adding search feature to user listing --- app/javascript/api.d.ts | 8 + .../components/users/UsersIndex.tsx | 200 ++++++++++++++++++ app/models/user.rb | 6 +- app/views/users/index.html.haml | 29 +-- 4 files changed, 223 insertions(+), 20 deletions(-) create mode 100644 app/javascript/components/users/UsersIndex.tsx diff --git a/app/javascript/api.d.ts b/app/javascript/api.d.ts index 51881ec..74b5d40 100644 --- a/app/javascript/api.d.ts +++ b/app/javascript/api.d.ts @@ -28,6 +28,14 @@ declare namespace Api { profile_image: string } + type User = { + id: number, + first_name: string, + last_name: string, + full_name: string, + email: string + } + type ContentFile = { id: number uid: string diff --git a/app/javascript/components/users/UsersIndex.tsx b/app/javascript/components/users/UsersIndex.tsx new file mode 100644 index 0000000..0be44c9 --- /dev/null +++ b/app/javascript/components/users/UsersIndex.tsx @@ -0,0 +1,200 @@ +import React, { Component } from 'react' +import SvgRenderer from '../SvgRenderer' + +type Props = { + users: Api.User[] + arrowDropUpPath: string + arrowDropDownPath: string +} + +type State = { + sort: 'first_name' | 'last_name' | 'email' + sortDirectionInverted: boolean + search: string + users: Api.User[] +} + +export default class UsersIndex extends Component { + constructor(props: Props) { + super(props); + + this.state = { + sort: 'email', + sortDirectionInverted: false, + search: '', + users: this.props.users + }; + + this.sortedUsers = this.sortedUsers.bind(this); + this.userTable = this.userTable.bind(this); + this.updateSortSelection = this.updateSortSelection.bind(this); + this.userSorter = this.userSorter.bind(this); + this.applySort = this.applySort.bind(this); + this.buildSortIcon = this.buildSortIcon.bind(this); + this.searchInput = this.searchInput.bind(this); + this.applySearch = this.applySearch.bind(this); + } + + goToPage = (pageObj: any) => { + window.location.href = + `${window.location.href.split('?')[0]}?page=${pageObj.selected + 1}` + } + + updateSortSelection(sortType: any) { + if (this.state.sort === sortType) { + this.setState({ sortDirectionInverted: !this.state.sortDirectionInverted }); + } else { + this.setState({ sort: sortType }); + } + } + + applySort(userSet: Api.User[]) { + let comparatorFunction = this.userSorter(this.state.sort); + let sortedUsers = userSet.sort(comparatorFunction); + + if (this.state.search !== '') { + sortedUsers = sortedUsers.filter((user) => { + if (!user.first_name) { + user.first_name = ''; + } + + if (!user.last_name) { + user.last_name = ''; + } + + return user.email.toLowerCase().includes(this.state.search.trim().toLowerCase()) + || user.first_name.toLowerCase().includes(this.state.search.trim().toLowerCase()) + || user.last_name.toLowerCase().includes(this.state.search.trim().toLowerCase()); + }); + } + + return sortedUsers; + } + + userSorter(key: string) { + return ( + (a: Api.User, b: Api.User) => { + if (this.state.sortDirectionInverted) { + b = [a, a = b][0]; + } + if ((a as any)[key] === null || (a as any)[key] === '') { + return 1; + } else if ((b as any)[key] === null || (b as any)[key] === '') { + return -1; + } else if ((a as any)[key].toLowerCase() === (b as any)[key].toLowerCase()) { + return 0; + } else if ((a as any)[key].toLowerCase() < (b as any)[key].toLowerCase()) { + return -1; + } else if ((a as any)[key].toLowerCase() > (b as any)[key].toLowerCase()) { + return 1; + } + + return 0 + } + ); + } + + sortedUsers() { + return ( + this.applySort(this.state.users).map((user:Api.User) => { + return ( + + + + + + + ); + }) + ); + } + + userTable(userList: any[]) { + return ( +
    +
    {user.first_name}{user.last_name}{user.email} + Edit +
    + + + + + + + + + + { userList.length == 0 ? this.noUsersMessage() : userList } + +
    + First Name{this.buildSortIcon('first_name')} + + Last Name{this.buildSortIcon('last_name')} + + Email{this.buildSortIcon('email')} +
    + + ); + } + + buildSortIcon(sortType: string) { + if (this.state.sort === sortType) { + if (this.state.sortDirectionInverted) { + return ( + + + + ) + } else { + return ( + + + + ) + } + } + } + + noUsersMessage() { + return ( + + +

    No results match your search

    + + + ); + } + + searchInput() { + return ( +
    +

    Search

    + +
    + ); + } + + applySearch(e: React.ChangeEvent) { + this.setState({ search: (e.target as HTMLInputElement).value }); + } + + render() { + return ( +
    +
    +
    + { this.searchInput() } + { this.userTable(this.sortedUsers())} +
    +
    +
    + ); + } +} diff --git a/app/models/user.rb b/app/models/user.rb index a307bbf..6f3563c 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -31,7 +31,11 @@ class User < ApplicationRecord end def full_name - "#{first_name} #{last_name}" + if first_name.nil? || last_name.nil? + "" + else + "#{first_name} #{last_name}" + end end def initials diff --git a/app/views/users/index.html.haml b/app/views/users/index.html.haml index 7207085..44b30c6 100644 --- a/app/views/users/index.html.haml +++ b/app/views/users/index.html.haml @@ -1,19 +1,10 @@ -.container - %h1 Users - %br - %table.table.table-hover - %thead - %tr - %th First - %th Last - %th Email - %th - %tbody - - @users.each do |u| - %tr - %td= u.first_name - %td= u.last_name - %td= u.email - %td{ style: "text-align: right;" } - %a{href: edit_user_user_path(u)} - %button.lp-style-button.-small Edit \ No newline at end of file +.cohorts + .settingscontainer + .settingsrow + .selectedsettingstab + %h1 + Users + = react_component "users/UsersIndex", + users: @users, + arrowDropDownPath: path_to_image("svg/svg-sprite-navigation-symbol.svg#ic_arrow_drop_down_24px"), + arrowDropUpPath: path_to_image("svg/svg-sprite-navigation-symbol.svg#ic_arrow_drop_up_24px") -- GitLab From 61398e4955d6d4ac169f24b2f445f571cada32b3 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Wed, 7 Oct 2020 12:14:14 -1000 Subject: [PATCH 135/283] Initial work on getting forge to work with new webpacker --- .browserslistrc | 1 + .nvmrc | 2 +- Gemfile | 2 +- Gemfile.lock | 12 +- app/assets/javascripts/application.js | 1 - .../components/blocks/BlocksIndex-v2.tsx | 4 +- .../components/blocks/BlocksNewModal.tsx | 3 +- .../components/blocks/BlocksNewRelease.tsx | 3 +- .../components/blocks/BlocksStats.tsx | 16 +- .../challenge_block/ChallengeBlock.tsx | 32 +- .../checkpoints/CheckpointSubmissionShow.tsx | 8 +- .../cohort_submissions/CohortSubmissions.tsx | 6 +- .../cohorts/pairing/StudentItem.tsx | 2 +- .../cohorts/settings/CohortSettingsResync.tsx | 2 +- .../SubmissionsDashboard.tsx | 2 +- .../components/content_files/PDFRenderer.tsx | 5 +- .../checkpoints/CheckpointActionBar.tsx | 6 +- .../components/shared/Button/Button.tsx | 4 +- .../components/shared/Pill/Pill.tsx | 24 +- .../shared/UniversalList/UniversalList.tsx | 3 +- .../shared/UniversalRow/UniversalRow.tsx | 4 +- .../standards/MasteryScoringBlock.tsx | 2 +- .../standards/StandardScoreButton.tsx | 2 +- .../standards/StandardScoringBlock.tsx | 2 +- babel.config.js | 70 + .babelrc => babelrc.sav | 0 bin/webpack | 7 +- bin/webpack-dev-server | 7 +- config/webpacker.yml | 28 +- package.json | 97 +- package.json.sav | 83 + postcss.config.js | 12 + yarn.lock | 6835 ++++++++++------- 33 files changed, 4526 insertions(+), 2761 deletions(-) create mode 100644 .browserslistrc create mode 100644 babel.config.js rename .babelrc => babelrc.sav (100%) create mode 100644 package.json.sav create mode 100644 postcss.config.js diff --git a/.browserslistrc b/.browserslistrc new file mode 100644 index 0000000..e94f814 --- /dev/null +++ b/.browserslistrc @@ -0,0 +1 @@ +defaults diff --git a/.nvmrc b/.nvmrc index f20cfd9..9306ff9 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -10.15.1 \ No newline at end of file +14.8.0 diff --git a/Gemfile b/Gemfile index 1de72bf..d744d89 100644 --- a/Gemfile +++ b/Gemfile @@ -24,7 +24,7 @@ gem "rack-attack" # assets gem "ts_routes" -gem "webpacker", "~> 3.5" +gem "webpacker", "~> 5.2.1" gem "bootstrap", "4.0.0" gem "font-awesome-rails" gem "sass-rails", "~> 5.0" diff --git a/Gemfile.lock b/Gemfile.lock index 0dbb773..34ea2ba 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -243,7 +243,7 @@ GEM rack (>= 1.2.0) rack-protection (2.0.0) rack - rack-proxy (0.6.4) + rack-proxy (0.6.5) rack rack-test (0.8.2) rack (>= 1.0, < 3) @@ -343,6 +343,7 @@ GEM selenium-webdriver (3.8.0) childprocess (~> 0.5) rubyzip (~> 1.0) + semantic_range (2.3.0) shoulda-matchers (3.1.2) activesupport (>= 4.0.0) sidekiq (5.0.5) @@ -385,10 +386,11 @@ GEM addressable (>= 2.3.6) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) - webpacker (3.5.5) - activesupport (>= 4.2) + webpacker (5.2.1) + activesupport (>= 5.2) rack-proxy (>= 0.6.1) - railties (>= 4.2) + railties (>= 5.2) + semantic_range (>= 2.3.0) websocket-driver (0.7.0) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.3) @@ -464,7 +466,7 @@ DEPENDENCIES underscore-rails (= 1.8.3) vcr webmock - webpacker (~> 3.5) + webpacker (~> 5.2.1) zip-zip RUBY VERSION diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 8cc897f..fb0297b 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -4,4 +4,3 @@ //= require bootstrap-sprockets //= require bootstrap-datepicker //= require hopscotch -//= require gsap diff --git a/app/javascript/components/blocks/BlocksIndex-v2.tsx b/app/javascript/components/blocks/BlocksIndex-v2.tsx index e4d000f..f809c90 100644 --- a/app/javascript/components/blocks/BlocksIndex-v2.tsx +++ b/app/javascript/components/blocks/BlocksIndex-v2.tsx @@ -8,7 +8,7 @@ import BlocksStats from './BlocksStats'; import BlocksNewModal from './BlocksNewModal'; import BlocksNewRelease from './BlocksNewRelease'; -const ReactTooltip = require('react-tooltip'); +import ReactTooltip from "react-tooltip"; export const MODAL_STATE = { NEW_BLOCK: 'newBlockModalVisible', @@ -85,7 +85,7 @@ class BlocksIndex extends React.Component { mainTitleLink={Routes.blockPath(block.id)} rowClickable={true} subTitle={block.repo_url.includes('github') ? block.repo_url && - <> + <> {block.repo_url.split('/').slice(-2).join(' / ')} diff --git a/app/javascript/components/blocks/BlocksNewModal.tsx b/app/javascript/components/blocks/BlocksNewModal.tsx index fb49141..da0e602 100644 --- a/app/javascript/components/blocks/BlocksNewModal.tsx +++ b/app/javascript/components/blocks/BlocksNewModal.tsx @@ -23,7 +23,7 @@ type State = { urlErrorMsg: string } -class BlocksNewModal extends React.Component { +export default class BlocksNewModal extends React.Component { constructor(props: Props) { super(props); @@ -184,4 +184,3 @@ class BlocksNewModal extends React.Component { } } -export default BlocksNewModal; diff --git a/app/javascript/components/blocks/BlocksNewRelease.tsx b/app/javascript/components/blocks/BlocksNewRelease.tsx index 398a923..9dab196 100644 --- a/app/javascript/components/blocks/BlocksNewRelease.tsx +++ b/app/javascript/components/blocks/BlocksNewRelease.tsx @@ -14,7 +14,7 @@ type State = { releaseNotesText: string } -class BlocksNewRelease extends React.Component { +export default class BlocksNewRelease extends React.Component { constructor(props: Props) { super(props); @@ -79,4 +79,3 @@ class BlocksNewRelease extends React.Component { } } -export default BlocksNewRelease; diff --git a/app/javascript/components/blocks/BlocksStats.tsx b/app/javascript/components/blocks/BlocksStats.tsx index e31caf0..440e92e 100644 --- a/app/javascript/components/blocks/BlocksStats.tsx +++ b/app/javascript/components/blocks/BlocksStats.tsx @@ -11,7 +11,7 @@ type statsProps = { verticalAlign?: boolean, } -const BlocksStats = ({ block, displayUser, showTooltip, verbose, verticalAlign }: statsProps) => { +export default ({ block, displayUser = true, showTooltip = true, verbose = false, verticalAlign = false }: statsProps) => { const timezone = window.moment.tz.guess(); const timeAgo = block.last_update ? `published ${window.moment(block.last_update).tz(timezone).fromNow()}` : ''; const classes = verticalAlign ? "block-stats__stats-row vertical" : "block-stats__stats-row"; @@ -49,11 +49,9 @@ const BlocksStats = ({ block, displayUser, showTooltip, verbose, verticalAlign } ) } -export default BlocksStats; - -BlocksStats.defaultProps = { - displayUser: true, - showTooltip: true, - verbose: false, - verticalAlign: false -} +// BlocksStats.defaultProps = { +// displayUser: true, +// showTooltip: true, +// verbose: false, +// verticalAlign: false +// } diff --git a/app/javascript/components/challenges/challenge_block/ChallengeBlock.tsx b/app/javascript/components/challenges/challenge_block/ChallengeBlock.tsx index 5d3cc61..0bfcf1e 100644 --- a/app/javascript/components/challenges/challenge_block/ChallengeBlock.tsx +++ b/app/javascript/components/challenges/challenge_block/ChallengeBlock.tsx @@ -17,7 +17,7 @@ import ChallengeLocalTestResults from './ChallengeLocalTestResults' import Pill from '../../shared/Pill/Pill' import { TestResult } from '../local/run-local-challenge' -const ReactTooltip = require('react-tooltip') +import ReactTooltip from "react-tooltip"; type Props = { challenge: Api.ChallengeWithSubmittedChallengeAnswersPresenter @@ -344,10 +344,10 @@ export default class ChallengeBlock extends React.Component { if (contentFileType === "checkpoint") { if (challenge.challenge_type === "multiple-choice" || challenge.challenge_type === "checkbox") { this.saveDraft(e.target.value) - } else if (challenge.challenge_type === "testable-project" || - challenge.challenge_type === "project" || - challenge.challenge_type === "paragraph" || - challenge.challenge_type === "short-answer" || + } else if (challenge.challenge_type === "testable-project" || + challenge.challenge_type === "project" || + challenge.challenge_type === "paragraph" || + challenge.challenge_type === "short-answer" || challenge.challenge_type === "number" ) { if (this.state.draftTimeout) { clearTimeout(this.state.draftTimeout) @@ -366,7 +366,7 @@ export default class ChallengeBlock extends React.Component { } updateHasUnsavedWork = (inputVal: string) => { - let bool = false; + let bool = false; if (this.currentSubmission()) { bool = this.currentSubmission().answer !== inputVal; @@ -405,7 +405,7 @@ export default class ChallengeBlock extends React.Component { .map(entry => entry[0]); this.setState({draftTimeout: setTimeout(() => { this.saveDraft(answer); }, 100)}); } - + if (!onUpdateAnswered) return; Object.values(this.state.checkboxInputs).forEach((checkValue) => { if (checkValue) { @@ -420,7 +420,7 @@ export default class ChallengeBlock extends React.Component { const { onUpdateAnswered, contentFileType, challenge } = this.props this.setState({ input: value }); if (!onUpdateAnswered) return; - + if (contentFileType === "checkpoint" && challenge.challenge_type === 'code-snippet' && (this.isAnsweredIgnorePlaceholder(value) && this.inputIsChanged(value))) { if (this.state.draftTimeout) { clearTimeout(this.state.draftTimeout); @@ -679,8 +679,8 @@ export default class ChallengeBlock extends React.Component { const { challenge: { topics }, contentFileType, challenge } = this.props const { draftTimestamp } = this.state - const hideSubmit = (contentFileType === "checkpoint" && !(challenge.challenge_type == "testable-project" || - challenge.challenge_type == "code-snippet" || + const hideSubmit = (contentFileType === "checkpoint" && !(challenge.challenge_type == "testable-project" || + challenge.challenge_type == "code-snippet" || challenge.challenge_type == "local-snippet") ) return ( @@ -717,8 +717,8 @@ export default class ChallengeBlock extends React.Component { const { showSaved } = this.state const disabledClass = showSaved && this.buttonText() === 'SAVED' ? '-disabled' : '' // On checkpoints, show the submit button if its "testable-project" || "code-snippet" || "local-snippet" - const hideSubmit = (contentFileType === "checkpoint" && !(challenge.challenge_type == "testable-project" || - challenge.challenge_type == "code-snippet" || + const hideSubmit = (contentFileType === "checkpoint" && !(challenge.challenge_type == "testable-project" || + challenge.challenge_type == "code-snippet" || challenge.challenge_type == "local-snippet") ) specificClass = `${specificClass} ${disabledClass}`; @@ -780,7 +780,7 @@ export default class ChallengeBlock extends React.Component { if ( currentSubmission == undefined) return null let { points, max_points } = currentSubmission; - + // handle legacy submissions which might not have maxPoints or points if (max_points === undefined || max_points === null) max_points = 1; if (points === undefined || points === null) { @@ -807,7 +807,7 @@ export default class ChallengeBlock extends React.Component { } else { // This could possible be removed, "saftey coding" let currentSubmission = this.currentSubmission() let { points, max_points } = currentSubmission; - + // handle legacy submissions which might not have maxPoints or points if (max_points === undefined || max_points === null) max_points = 1; if (points === undefined || points === null) { @@ -959,7 +959,7 @@ export default class ChallengeBlock extends React.Component { challenge.topics.length > 0 && contentFileType === 'checkpoint' - let challengeTopics + let challengeTopics if (challenge.topics) { challengeTopics = challenge.topics.map((topic: any, i: number) => ( { )} {this.timeline()}
    diff --git a/app/javascript/components/checkpoints/CheckpointSubmissionShow.tsx b/app/javascript/components/checkpoints/CheckpointSubmissionShow.tsx index 54e26ac..73d2744 100644 --- a/app/javascript/components/checkpoints/CheckpointSubmissionShow.tsx +++ b/app/javascript/components/checkpoints/CheckpointSubmissionShow.tsx @@ -10,7 +10,7 @@ import ChallengeDetailActivities from '../challenges/challenge_block/ChallengeDe import CheckpointSubmissionChallenges from './CheckpointSubmissionChallenges' import CheckpointSubmissionStudentNameBar from './CheckpointSubmissionStudentNameBar' -const ReactTooltip = require('react-tooltip') +import ReactTooltip from "react-tooltip"; type Props = { challenges: Api.ChallengeWithSubmittedChallengeAnswersPresenter[] @@ -55,7 +55,7 @@ export default class CheckpointSubmissionShow extends React.Component { http('PATCH', submissionUrl,{ - body: { + body: { checkpoint_submission: { state: "done" } @@ -294,7 +294,7 @@ export default class CheckpointSubmissionShow extends React.Component ) } - + return (
    diff --git a/app/javascript/components/cohorts/cohort_submissions/CohortSubmissions.tsx b/app/javascript/components/cohorts/cohort_submissions/CohortSubmissions.tsx index f803bd3..9acd96e 100644 --- a/app/javascript/components/cohorts/cohort_submissions/CohortSubmissions.tsx +++ b/app/javascript/components/cohorts/cohort_submissions/CohortSubmissions.tsx @@ -11,7 +11,7 @@ import ProgressThresholdsModal from '../../shared/ProgressThresholdsModal/Progre import ProgressThresholdsKey from '../../shared/ProgressThresholdsKey/ProgressThresholdsKey' import SettingsCog from '../../shared/Icons/SettingsCog' -const ReactTooltip = require('react-tooltip') +import ReactTooltip from "react-tooltip"; type contentFileId = number type standardId = number @@ -320,7 +320,7 @@ export default class CohortSubmissions extends React.Component { block.standards.forEach((standard) => { if (standard.id === standardId) { if (this.state.open[standard.id]) { - + // TODO: Update to not modify state directly this.state.standardsLoading[standard.id] = false; this.state.open[standard.id] = false; @@ -331,7 +331,7 @@ export default class CohortSubmissions extends React.Component { this.setState({ data: blocks }); } else { const oldContentFilesLength = standard.content_files.length; - + // TODO: Update to not modify state directly this.state.standardsLoading[standard.id] = true; this.state.open[standard.id] = true; diff --git a/app/javascript/components/cohorts/pairing/StudentItem.tsx b/app/javascript/components/cohorts/pairing/StudentItem.tsx index 7984662..b079b89 100644 --- a/app/javascript/components/cohorts/pairing/StudentItem.tsx +++ b/app/javascript/components/cohorts/pairing/StudentItem.tsx @@ -1,7 +1,7 @@ import React, { PureComponent } from 'react' import { DraggableProvided } from 'react-beautiful-dnd' import UserAvatar from '../../UserAvatar'; -const ReactTooltip = require('react-tooltip') +import ReactTooltip from "react-tooltip"; type Props = { index: number diff --git a/app/javascript/components/cohorts/settings/CohortSettingsResync.tsx b/app/javascript/components/cohorts/settings/CohortSettingsResync.tsx index 43ad062..1d37c35 100644 --- a/app/javascript/components/cohorts/settings/CohortSettingsResync.tsx +++ b/app/javascript/components/cohorts/settings/CohortSettingsResync.tsx @@ -1,7 +1,7 @@ import * as React from 'react' import * as Routes from '../../../generated/routes' import http from '../../../lib/http' -const ReactTooltip = require('react-tooltip') +import ReactTooltip from "react-tooltip"; type Job = Api.Setup.ResyncJob type SuccessfulJob = Api.Setup.SuccessfulResyncJob diff --git a/app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboard.tsx b/app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboard.tsx index dd9a4ec..8057255 100644 --- a/app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboard.tsx +++ b/app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboard.tsx @@ -9,7 +9,7 @@ import SortDropdown from '../../SortDropdown' import HeaderStandardContainer from './HeaderStandardContainer' import SubmissionsDashboardTable from './SubmissionsDashboardTable' -const ReactTooltip = require('react-tooltip') +import ReactTooltip from "react-tooltip"; type Props = any type State = any diff --git a/app/javascript/components/content_files/PDFRenderer.tsx b/app/javascript/components/content_files/PDFRenderer.tsx index e75fafe..ecc7265 100644 --- a/app/javascript/components/content_files/PDFRenderer.tsx +++ b/app/javascript/components/content_files/PDFRenderer.tsx @@ -1,5 +1,8 @@ import * as React from 'react'; -import { Document, Page, pdfjs } from 'react-pdf/dist/entry.webpack'; +//import { Document, Page, pdfjs } from 'react-pdf/dist/umd/entry.webpack'; +//import { Document, Page, pdfjs } from 'react-pdf/dist/esm/entry.webpack'; +import { Document, Page } from 'react-pdf/dist/umd/entry.webpack'; +import { pdfjs } from 'react-pdf'; pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`; diff --git a/app/javascript/components/content_files/checkpoints/CheckpointActionBar.tsx b/app/javascript/components/content_files/checkpoints/CheckpointActionBar.tsx index 37a9580..7552538 100644 --- a/app/javascript/components/content_files/checkpoints/CheckpointActionBar.tsx +++ b/app/javascript/components/content_files/checkpoints/CheckpointActionBar.tsx @@ -5,7 +5,7 @@ import { cohortCheckpointSubmissionPath } from '../../../generated/routes' import CheckpointPairs from './CheckpointPairs' import PairAvatars from './PairAvatars' -const ReactTooltip = require('react-tooltip') +import ReactTooltip from "react-tooltip"; type Props = { timeLimit: number | null @@ -112,7 +112,7 @@ export default class CheckpointActionBar extends React.Component { render() { - const { + const { onSubmitCheckpoint, onSaveAndExit, timeLimit, @@ -189,4 +189,4 @@ export default class CheckpointActionBar extends React.Component { ) } -} \ No newline at end of file +} diff --git a/app/javascript/components/shared/Button/Button.tsx b/app/javascript/components/shared/Button/Button.tsx index f1eea72..27b98c9 100644 --- a/app/javascript/components/shared/Button/Button.tsx +++ b/app/javascript/components/shared/Button/Button.tsx @@ -11,7 +11,7 @@ type Props = { className?: string } -const Button = ({ format, color, style, onClick, disabled, text, children, className }: Props) => { +export default Button = ({ format, color, style, onClick, disabled, text, children, className }: Props) => { let classes = `button-wrapper button-${format}-${color} ${(className ? className : '')}`; return (
    ) } } - -- GitLab From f34335aa79822627f1bfb48c7cc395c211c370be Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Wed, 7 Oct 2020 17:31:50 -1000 Subject: [PATCH 137/283] Re-enabled but downgraded react-pdf --- .../components/content_files/PDFRenderer.tsx | 37 +- package-lock.json | 14172 ++++++++++++++++ package.json | 2 +- 3 files changed, 14189 insertions(+), 22 deletions(-) create mode 100644 package-lock.json diff --git a/app/javascript/components/content_files/PDFRenderer.tsx b/app/javascript/components/content_files/PDFRenderer.tsx index 544aaf9..b9ff2c6 100644 --- a/app/javascript/components/content_files/PDFRenderer.tsx +++ b/app/javascript/components/content_files/PDFRenderer.tsx @@ -1,11 +1,7 @@ import React from 'react'; -// TODO: Figure out why the react-pdf stuff is not working -//import { Document, Page, pdfjs } from 'react-pdf/dist/esm/entry.webpack'; -//import { Document, Page, pdfjs } from 'react-pdf/dist/umd/entry.webpack'; -//import { Document, Page, pdfjs } from 'react-pdf'; +import { Document, Page, pdfjs } from 'react-pdf/dist/entry.webpack'; -//pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`; -//pdfjs.GlobalWorkerOptions.workerSrc = "pdfjs-dist/build/pdf.worker.js"; +pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`; type Props = { contentFileHtml: string @@ -37,23 +33,22 @@ export default class PDFRenderer extends React.Component { )}
    - {/*TODO: Figure out why the react-pdf stuff is not working*/} - {/**/} + { - // Array.from( - // new Array(this.state.numPages), - // (_el, index) => ( - // - // ), - // ) + Array.from( + new Array(this.state.numPages), + (_el, index) => ( + + ), + ) } - {/**/} +
    ) diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..382cf49 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,14172 @@ +{ + "name": "forge", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/compat-data": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.11.0.tgz", + "integrity": "sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ==", + "requires": { + "browserslist": "^4.12.0", + "invariant": "^2.2.4", + "semver": "^5.5.0" + } + }, + "@babel/core": { + "version": "7.11.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.6.tgz", + "integrity": "sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg==", + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.6", + "@babel/helper-module-transforms": "^7.11.0", + "@babel/helpers": "^7.10.4", + "@babel/parser": "^7.11.5", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.11.5", + "@babel/types": "^7.11.5", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "requires": { + "ms": "2.1.2" + } + }, + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "requires": { + "minimist": "^1.2.5" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + } + } + }, + "@babel/generator": { + "version": "7.11.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz", + "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==", + "requires": { + "@babel/types": "^7.11.5", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz", + "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==", + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz", + "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==", + "requires": { + "@babel/helper-explode-assignable-expression": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz", + "integrity": "sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ==", + "requires": { + "@babel/compat-data": "^7.10.4", + "browserslist": "^4.12.0", + "invariant": "^2.2.4", + "levenary": "^1.1.1", + "semver": "^5.5.0" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz", + "integrity": "sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A==", + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-member-expression-to-functions": "^7.10.5", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.10.4" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz", + "integrity": "sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-regex": "^7.10.4", + "regexpu-core": "^4.7.0" + } + }, + "@babel/helper-define-map": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz", + "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==", + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/types": "^7.10.5", + "lodash": "^4.17.19" + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.11.4.tgz", + "integrity": "sha512-ux9hm3zR4WV1Y3xXxXkdG/0gxF9nvI0YVmKVhvK9AfMoaQkemL3sJpXw+Xbz65azo8qJiEz2XVDUpK3KYhH3ZQ==", + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz", + "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==", + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz", + "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==", + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz", + "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==", + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-module-transforms": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz", + "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==", + "requires": { + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-simple-access": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/template": "^7.10.4", + "@babel/types": "^7.11.0", + "lodash": "^4.17.19" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", + "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" + }, + "@babel/helper-regex": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz", + "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==", + "requires": { + "lodash": "^4.17.19" + } + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.11.4.tgz", + "integrity": "sha512-tR5vJ/vBa9wFy3m5LLv2faapJLnDFxNWff2SAYkSE4rLUdbp7CdObYFgI7wK4T/Mj4UzpjPwzR8Pzmr5m7MHGA==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-wrap-function": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-replace-supers": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz", + "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==", + "requires": { + "@babel/helper-member-expression-to-functions": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-simple-access": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz", + "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==", + "requires": { + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz", + "integrity": "sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q==", + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==" + }, + "@babel/helper-wrap-function": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz", + "integrity": "sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug==", + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helpers": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz", + "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==", + "requires": { + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==" + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz", + "integrity": "sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.10.4", + "@babel/plugin-syntax-async-generators": "^7.8.0" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz", + "integrity": "sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz", + "integrity": "sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-dynamic-import": "^7.8.0" + } + }, + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz", + "integrity": "sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz", + "integrity": "sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.0" + } + }, + "@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz", + "integrity": "sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz", + "integrity": "sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz", + "integrity": "sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz", + "integrity": "sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-transform-parameters": "^7.10.4" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz", + "integrity": "sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz", + "integrity": "sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0" + } + }, + "@babel/plugin-proposal-private-methods": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz", + "integrity": "sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz", + "integrity": "sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz", + "integrity": "sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz", + "integrity": "sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz", + "integrity": "sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz", + "integrity": "sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ==", + "requires": { + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.10.4" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz", + "integrity": "sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz", + "integrity": "sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz", + "integrity": "sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-define-map": "^7.10.4", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.10.4", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz", + "integrity": "sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz", + "integrity": "sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz", + "integrity": "sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz", + "integrity": "sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz", + "integrity": "sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw==", + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz", + "integrity": "sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz", + "integrity": "sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg==", + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz", + "integrity": "sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz", + "integrity": "sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz", + "integrity": "sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw==", + "requires": { + "@babel/helper-module-transforms": "^7.10.5", + "@babel/helper-plugin-utils": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz", + "integrity": "sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w==", + "requires": { + "@babel/helper-module-transforms": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-simple-access": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz", + "integrity": "sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw==", + "requires": { + "@babel/helper-hoist-variables": "^7.10.4", + "@babel/helper-module-transforms": "^7.10.5", + "@babel/helper-plugin-utils": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz", + "integrity": "sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA==", + "requires": { + "@babel/helper-module-transforms": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz", + "integrity": "sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.10.4" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz", + "integrity": "sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz", + "integrity": "sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz", + "integrity": "sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw==", + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz", + "integrity": "sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz", + "integrity": "sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw==", + "requires": { + "regenerator-transform": "^0.14.2" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz", + "integrity": "sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-runtime": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.11.5.tgz", + "integrity": "sha512-9aIoee+EhjySZ6vY5hnLjigHzunBlscx9ANKutkeWTJTx6m5Rbq6Ic01tLvO54lSusR+BxV7u4UDdCmXv5aagg==", + "requires": { + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "resolve": "^1.8.1", + "semver": "^5.5.1" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz", + "integrity": "sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz", + "integrity": "sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz", + "integrity": "sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-regex": "^7.10.4" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz", + "integrity": "sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz", + "integrity": "sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz", + "integrity": "sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz", + "integrity": "sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/preset-env": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.11.5.tgz", + "integrity": "sha512-kXqmW1jVcnB2cdueV+fyBM8estd5mlNfaQi6lwLgRwCby4edpavgbFhiBNjmWA3JpB/yZGSISa7Srf+TwxDQoA==", + "requires": { + "@babel/compat-data": "^7.11.0", + "@babel/helper-compilation-targets": "^7.10.4", + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-proposal-async-generator-functions": "^7.10.4", + "@babel/plugin-proposal-class-properties": "^7.10.4", + "@babel/plugin-proposal-dynamic-import": "^7.10.4", + "@babel/plugin-proposal-export-namespace-from": "^7.10.4", + "@babel/plugin-proposal-json-strings": "^7.10.4", + "@babel/plugin-proposal-logical-assignment-operators": "^7.11.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4", + "@babel/plugin-proposal-numeric-separator": "^7.10.4", + "@babel/plugin-proposal-object-rest-spread": "^7.11.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.10.4", + "@babel/plugin-proposal-optional-chaining": "^7.11.0", + "@babel/plugin-proposal-private-methods": "^7.10.4", + "@babel/plugin-proposal-unicode-property-regex": "^7.10.4", + "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-class-properties": "^7.10.4", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-top-level-await": "^7.10.4", + "@babel/plugin-transform-arrow-functions": "^7.10.4", + "@babel/plugin-transform-async-to-generator": "^7.10.4", + "@babel/plugin-transform-block-scoped-functions": "^7.10.4", + "@babel/plugin-transform-block-scoping": "^7.10.4", + "@babel/plugin-transform-classes": "^7.10.4", + "@babel/plugin-transform-computed-properties": "^7.10.4", + "@babel/plugin-transform-destructuring": "^7.10.4", + "@babel/plugin-transform-dotall-regex": "^7.10.4", + "@babel/plugin-transform-duplicate-keys": "^7.10.4", + "@babel/plugin-transform-exponentiation-operator": "^7.10.4", + "@babel/plugin-transform-for-of": "^7.10.4", + "@babel/plugin-transform-function-name": "^7.10.4", + "@babel/plugin-transform-literals": "^7.10.4", + "@babel/plugin-transform-member-expression-literals": "^7.10.4", + "@babel/plugin-transform-modules-amd": "^7.10.4", + "@babel/plugin-transform-modules-commonjs": "^7.10.4", + "@babel/plugin-transform-modules-systemjs": "^7.10.4", + "@babel/plugin-transform-modules-umd": "^7.10.4", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.10.4", + "@babel/plugin-transform-new-target": "^7.10.4", + "@babel/plugin-transform-object-super": "^7.10.4", + "@babel/plugin-transform-parameters": "^7.10.4", + "@babel/plugin-transform-property-literals": "^7.10.4", + "@babel/plugin-transform-regenerator": "^7.10.4", + "@babel/plugin-transform-reserved-words": "^7.10.4", + "@babel/plugin-transform-shorthand-properties": "^7.10.4", + "@babel/plugin-transform-spread": "^7.11.0", + "@babel/plugin-transform-sticky-regex": "^7.10.4", + "@babel/plugin-transform-template-literals": "^7.10.4", + "@babel/plugin-transform-typeof-symbol": "^7.10.4", + "@babel/plugin-transform-unicode-escapes": "^7.10.4", + "@babel/plugin-transform-unicode-regex": "^7.10.4", + "@babel/preset-modules": "^0.1.3", + "@babel/types": "^7.11.5", + "browserslist": "^4.12.0", + "core-js-compat": "^3.6.2", + "invariant": "^2.2.2", + "levenary": "^1.1.1", + "semver": "^5.5.0" + } + }, + "@babel/preset-modules": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", + "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/runtime": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", + "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/runtime-corejs3": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.11.2.tgz", + "integrity": "sha512-qh5IR+8VgFz83VBa6OkaET6uN/mJOhHONuy3m1sgF0CV6mXdPSEBdA7e1eUbVvyNtANjMbg22JUv71BaDXLY6A==", + "dev": true, + "requires": { + "core-js-pure": "^3.0.0", + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/traverse": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz", + "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==", + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.5", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.11.5", + "@babel/types": "^7.11.5", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "requires": { + "ms": "2.1.2" + } + } + } + }, + "@babel/types": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "@csstools/convert-colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz", + "integrity": "sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==" + }, + "@eslint/eslintrc": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.3.tgz", + "integrity": "sha512-4YVwPkANLeNtRjMekzux1ci8hIaH5eGKktGqR0d3LWsKNn5B2X/1Z6Trxy7jQXl9EBGE6Yj02O+t09FMeRllaA==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "lodash": "^4.17.19", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + } + } + }, + "@npmcli/move-file": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.0.1.tgz", + "integrity": "sha512-Uv6h1sT+0DrblvIrolFtbvM1FgWm+/sy4B3pvLp67Zys+thcukzS5ekn7HsZFGpWP4Q3fYJCljbWQE/XivMRLw==", + "requires": { + "mkdirp": "^1.0.4" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + } + } + }, + "@rails/webpacker": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@rails/webpacker/-/webpacker-5.2.1.tgz", + "integrity": "sha512-rO0kOv0o4ESB8ZnKX+b54ZKogNJGWSMULGmsJacREfm9SahKEQwXBeHNsqSGtS9NAPsU6YUFhGKRd4i/kbMNrQ==", + "requires": { + "@babel/core": "^7.11.1", + "@babel/plugin-proposal-class-properties": "^7.10.4", + "@babel/plugin-proposal-object-rest-spread": "^7.10.1", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-destructuring": "^7.10.1", + "@babel/plugin-transform-regenerator": "^7.10.1", + "@babel/plugin-transform-runtime": "^7.11.0", + "@babel/preset-env": "^7.11.0", + "@babel/runtime": "^7.11.2", + "babel-loader": "^8.1.0", + "babel-plugin-dynamic-import-node": "^2.3.3", + "babel-plugin-macros": "^2.8.0", + "case-sensitive-paths-webpack-plugin": "^2.3.0", + "compression-webpack-plugin": "^4.0.0", + "core-js": "^3.6.5", + "css-loader": "^3.5.3", + "file-loader": "^6.0.0", + "flatted": "^3.0.4", + "glob": "^7.1.6", + "js-yaml": "^3.14.0", + "mini-css-extract-plugin": "^0.9.0", + "node-sass": "^4.14.1", + "optimize-css-assets-webpack-plugin": "^5.0.3", + "path-complete-extname": "^1.0.0", + "pnp-webpack-plugin": "^1.6.4", + "postcss-flexbugs-fixes": "^4.2.1", + "postcss-import": "^12.0.1", + "postcss-loader": "^3.0.0", + "postcss-preset-env": "^6.7.0", + "postcss-safe-parser": "^4.0.2", + "regenerator-runtime": "^0.13.7", + "sass-loader": "^8.0.2", + "style-loader": "^1.2.1", + "terser-webpack-plugin": "^4.0.0", + "webpack": "^4.44.1", + "webpack-assets-manifest": "^3.1.1", + "webpack-cli": "^3.3.12", + "webpack-sources": "^1.4.3" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + } + } + } + } + }, + "@types/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", + "dev": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/json-schema": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", + "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==" + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, + "@types/lodash": { + "version": "4.14.137", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.137.tgz", + "integrity": "sha512-g4rNK5SRKloO+sUGbuO7aPtwbwzMgjK+bm9BBhLD7jGUiGR7zhwYEhSln/ihgYQBeIJ5j7xjyaYzrWTcu3UotQ==", + "dev": true + }, + "@types/lodash-es": { + "version": "4.17.3", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.3.tgz", + "integrity": "sha512-iHI0i7ZAL1qepz1Y7f3EKg/zUMDwDfTzitx+AlHhJJvXwenP682ZyGbgPSc5Ej3eEAKVbNWKFuwOadCj5vBbYQ==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "@types/node": { + "version": "12.7.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.2.tgz", + "integrity": "sha512-dyYO+f6ihZEtNPDcWNR1fkoTDf3zAK3lAABDze3mz6POyIercH0lEUawUFXlG8xaQZmm1yEBON/4TsYv/laDYg==" + }, + "@types/node-fetch": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz", + "integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==", + "dev": true, + "requires": { + "@types/node": "*", + "form-data": "^3.0.0" + } + }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" + }, + "@types/pdfjs-dist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@types/pdfjs-dist/-/pdfjs-dist-2.1.2.tgz", + "integrity": "sha512-tUMIcX3z8M8EXA0SA4YIZcgZ6r/Rb2wbwvM9AKJhE/MPh5rEC90Sg8lMyVX6hzMaToR4jWEvN7IUA1bvoVpctA==" + }, + "@types/prop-types": { + "version": "15.7.1", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.1.tgz", + "integrity": "sha512-CFzn9idOEpHrgdw8JsoTkaDDyRWk1jrzIV8djzcgpq0y9tG4B4lFT+Nxh52DVpDXV+n4+NPNv7M1Dj5uMp6XFg==" + }, + "@types/q": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz", + "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==" + }, + "@types/rc-slider": { + "version": "8.6.6", + "resolved": "https://registry.npmjs.org/@types/rc-slider/-/rc-slider-8.6.6.tgz", + "integrity": "sha512-2Q3vwKrSm3PbgiMNwzxMkOaMtcAGi0xQ8WPeVKoabk1vNYHiVR44DMC3mr9jC2lhbxCBgGBJWF9sBhmnSDQ8Bg==", + "dev": true, + "requires": { + "@types/rc-tooltip": "*", + "@types/react": "*" + }, + "dependencies": { + "@types/react": { + "version": "16.9.2", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.2.tgz", + "integrity": "sha512-jYP2LWwlh+FTqGd9v7ynUKZzjj98T8x7Yclz479QdRhHfuW9yQ+0jjnD31eXSXutmBpppj5PYNLYLRfnZJvcfg==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "csstype": "^2.2.0" + } + }, + "csstype": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz", + "integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==", + "dev": true + } + } + }, + "@types/rc-tooltip": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@types/rc-tooltip/-/rc-tooltip-3.7.1.tgz", + "integrity": "sha512-H+pW9+H42rlb3PBjcxuXhQre1ldr0gdDVbVfCj0Pf4Mdjd1plti9ekt1yJ+gGig3bRFLpCknWDmfOkAjKY+S+Q==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/react": { + "version": "16.9.51", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.51.tgz", + "integrity": "sha512-lQa12IyO+DMlnSZ3+AGHRUiUcpK47aakMMoBG8f7HGxJT8Yfe+WE128HIXaHOHVPReAW0oDS3KAI0JI2DDe1PQ==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "@types/react-addons-css-transition-group": { + "version": "15.0.5", + "resolved": "https://registry.npmjs.org/@types/react-addons-css-transition-group/-/react-addons-css-transition-group-15.0.5.tgz", + "integrity": "sha512-UIJt5HQDOzRI7AOmnGnc2OZA0N3p7r6yMsxZ3T0+dyGPB3zWiKOPKrMkJr9tyuY3kHKPm26GyihcJKNJdMY8CQ==", + "dev": true, + "requires": { + "@types/react": "*", + "@types/react-addons-transition-group": "*" + }, + "dependencies": { + "@types/react": { + "version": "16.9.2", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.2.tgz", + "integrity": "sha512-jYP2LWwlh+FTqGd9v7ynUKZzjj98T8x7Yclz479QdRhHfuW9yQ+0jjnD31eXSXutmBpppj5PYNLYLRfnZJvcfg==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "csstype": "^2.2.0" + } + }, + "csstype": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz", + "integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==", + "dev": true + } + } + }, + "@types/react-addons-transition-group": { + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@types/react-addons-transition-group/-/react-addons-transition-group-15.0.4.tgz", + "integrity": "sha512-0S2cKn9OLYr6N36oRH4ybzidkgQ0UGhuvrFvU3tdktJfrx3muu7MgfIWG434wKg7rcysBEfpmQaNpGteEtx6vw==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/react-beautiful-dnd": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.0.0.tgz", + "integrity": "sha512-by80tJ8aTTDXT256Gl+RfLRtFjYbUWOnZuEigJgNsJrSEGxvFe5eY6k3g4VIvf0M/6+xoLgfYWoWonlOo6Wqdg==", + "dev": true, + "requires": { + "@types/react": "*" + }, + "dependencies": { + "@types/react": { + "version": "16.9.2", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.2.tgz", + "integrity": "sha512-jYP2LWwlh+FTqGd9v7ynUKZzjj98T8x7Yclz479QdRhHfuW9yQ+0jjnD31eXSXutmBpppj5PYNLYLRfnZJvcfg==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "csstype": "^2.2.0" + } + }, + "csstype": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz", + "integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==", + "dev": true + } + } + }, + "@types/react-copy-to-clipboard": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-4.3.0.tgz", + "integrity": "sha512-iideNPRyroENqsOFh1i2Dv3zkviYS9r/9qD9Uh3Z9NNoAAqqa2x53i7iGndGNnJFIo20wIu7Hgh77tx1io8bgw==", + "dev": true, + "requires": { + "@types/react": "*" + }, + "dependencies": { + "@types/react": { + "version": "16.9.2", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.2.tgz", + "integrity": "sha512-jYP2LWwlh+FTqGd9v7ynUKZzjj98T8x7Yclz479QdRhHfuW9yQ+0jjnD31eXSXutmBpppj5PYNLYLRfnZJvcfg==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "csstype": "^2.2.0" + } + }, + "csstype": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz", + "integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==", + "dev": true + } + } + }, + "@types/react-datepicker": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/react-datepicker/-/react-datepicker-3.1.1.tgz", + "integrity": "sha512-vwNrgaIMJThvvwmtnA8jSVVJZ0FNgljQrq1jDA4MtYJIDmVmd9NNrFaXf9u2JqR2nS+8Kvi8OVs/tnAbUqZhHw==", + "dev": true, + "requires": { + "@types/react": "*", + "date-fns": "^2.0.1", + "popper.js": "^1.14.1" + }, + "dependencies": { + "@types/react": { + "version": "16.9.2", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.2.tgz", + "integrity": "sha512-jYP2LWwlh+FTqGd9v7ynUKZzjj98T8x7Yclz479QdRhHfuW9yQ+0jjnD31eXSXutmBpppj5PYNLYLRfnZJvcfg==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "csstype": "^2.2.0" + } + }, + "csstype": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz", + "integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==", + "dev": true + }, + "popper.js": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.15.0.tgz", + "integrity": "sha512-w010cY1oCUmI+9KwwlWki+r5jxKfTFDVoadl7MSrIujHU5MJ5OR6HTDj6Xo8aoR/QsA56x8jKjA59qGH4ELtrA==", + "dev": true + } + } + }, + "@types/react-dom": { + "version": "16.9.8", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.8.tgz", + "integrity": "sha512-ykkPQ+5nFknnlU6lDd947WbQ6TE3NNzbQAkInC2EKY1qeYdTKp7onFusmYZb+ityzx2YviqT6BXSu+LyWWJwcA==", + "dev": true, + "requires": { + "@types/react": "*" + }, + "dependencies": { + "@types/react": { + "version": "16.9.2", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.2.tgz", + "integrity": "sha512-jYP2LWwlh+FTqGd9v7ynUKZzjj98T8x7Yclz479QdRhHfuW9yQ+0jjnD31eXSXutmBpppj5PYNLYLRfnZJvcfg==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "csstype": "^2.2.0" + } + }, + "csstype": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz", + "integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==", + "dev": true + } + } + }, + "@types/react-paginate": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@types/react-paginate/-/react-paginate-6.2.1.tgz", + "integrity": "sha512-+q8k1N0WzbMyOCsIEH/p5D6/KQD8dXYLzfvSvriYn//94icd2sqhAL2rWXkgwGvqHGCSTU9AoHtsWCJxPfquUQ==", + "requires": { + "@types/react": "*" + }, + "dependencies": { + "@types/react": { + "version": "16.9.2", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.2.tgz", + "integrity": "sha512-jYP2LWwlh+FTqGd9v7ynUKZzjj98T8x7Yclz479QdRhHfuW9yQ+0jjnD31eXSXutmBpppj5PYNLYLRfnZJvcfg==", + "requires": { + "@types/prop-types": "*", + "csstype": "^2.2.0" + } + }, + "csstype": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz", + "integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==" + } + } + }, + "@types/react-pdf": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/react-pdf/-/react-pdf-4.0.6.tgz", + "integrity": "sha512-ZmtUA31L5AaF9PilB8cJ3PuGOHIiyWcHnCir7KOux1cDjfVH6VxiN/j7CcyX98U9hwlyN81bkqxeNWNuEc0a4w==", + "requires": { + "@types/pdfjs-dist": "*", + "@types/react": "*" + }, + "dependencies": { + "@types/react": { + "version": "16.9.2", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.2.tgz", + "integrity": "sha512-jYP2LWwlh+FTqGd9v7ynUKZzjj98T8x7Yclz479QdRhHfuW9yQ+0jjnD31eXSXutmBpppj5PYNLYLRfnZJvcfg==", + "requires": { + "@types/prop-types": "*", + "csstype": "^2.2.0" + } + }, + "csstype": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz", + "integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==" + } + } + }, + "@types/react-textarea-autosize": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@types/react-textarea-autosize/-/react-textarea-autosize-4.3.5.tgz", + "integrity": "sha512-PiDL83kPMTolyZAWW3lyzO6ktooTb9tFTntVy7CA83/qFLWKLJ5bLeRboy6J6j3b1e8h2Eec6gBTEOOJRjV14A==", + "dev": true, + "requires": { + "@types/react": "*" + }, + "dependencies": { + "@types/react": { + "version": "16.9.2", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.2.tgz", + "integrity": "sha512-jYP2LWwlh+FTqGd9v7ynUKZzjj98T8x7Yclz479QdRhHfuW9yQ+0jjnD31eXSXutmBpppj5PYNLYLRfnZJvcfg==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "csstype": "^2.2.0" + } + }, + "csstype": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz", + "integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==", + "dev": true + } + } + }, + "@types/vimeo__player": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/@types/vimeo__player/-/vimeo__player-2.9.1.tgz", + "integrity": "sha512-L6XHWenPkN+WHFWmo/fhA70kTQnNUxOs3bQS3nF/FK3kv+UzEVRqPEkxJNUZWExwrhOKaTKzplZHmxYwmr0SJA==", + "dev": true + }, + "@vimeo/player": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@vimeo/player/-/player-2.14.0.tgz", + "integrity": "sha512-hTeROVnkcyboRjetPi9tasryrjDPVsmr/73clwbYsBpSk8k5q1ygFyvkWXQShv9Rc+hvXM5RJXPd7i7Wh7dqcA==", + "requires": { + "native-promise-only": "0.8.1", + "weakmap-polyfill": "2.0.1" + } + }, + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==" + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==" + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==" + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", + "requires": { + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==" + }, + "@webassemblyjs/helper-module-context": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "requires": { + "@webassemblyjs/ast": "1.9.0" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==" + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==" + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" + }, + "acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true + }, + "acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "requires": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==" + }, + "add-dom-event-listener": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/add-dom-event-listener/-/add-dom-event-listener-1.1.0.tgz", + "integrity": "sha512-WCxx1ixHT0GQU9hb0KI/mhgRQhnU+U3GvwY6ZvVjYq8rsihIGoaIOUbY0yMPBxLH5MDtr0kz3fisWGNcbWW7Jw==", + "requires": { + "object-assign": "4.x" + } + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ajv": { + "version": "6.12.5", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", + "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==" + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" + }, + "alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=" + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "dev": true + }, + "ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "aria-query": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.10.2", + "@babel/runtime-corejs3": "^7.10.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" + }, + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true + }, + "array-includes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", + "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "is-string": "^1.0.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + } + } + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "array.prototype.flat": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", + "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + } + } + }, + "array.prototype.flatmap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.3.tgz", + "integrity": "sha512-OOEk+lkePcg+ODXIpvuU9PAryCikCJyo7GlDG1upleEpQRx6mzL9puEBkozQ5iAx20KV0l3DbyQwqciJtqe5Pg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + } + } + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } + } + }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, + "ast-types": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz", + "integrity": "sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=" + }, + "ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "requires": { + "lodash": "^4.17.14" + } + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" + }, + "async-foreach": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", + "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=" + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + }, + "autoprefixer": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-7.2.6.tgz", + "integrity": "sha512-Iq8TRIB+/9eQ8rbGhcP7ct5cYb/3qjNYAR2SnzLCEcwF6rvVOax8+9+fccgXk4bEhQGjOZd5TLhsksmAdsbGqQ==", + "dev": true, + "requires": { + "browserslist": "^2.11.3", + "caniuse-lite": "^1.0.30000805", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^6.0.17", + "postcss-value-parser": "^3.2.3" + }, + "dependencies": { + "browserslist": { + "version": "2.11.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", + "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000792", + "electron-to-chromium": "^1.3.30" + } + }, + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", + "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==" + }, + "axe-core": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-3.5.5.tgz", + "integrity": "sha512-5P0QZ6J5xGikH780pghEdbEKijCTrruK9KxtPZCFWUpef0f6GipO+xEZ5GKCb020mmqgbiNO6TcA55CriL784Q==", + "dev": true + }, + "axobject-query": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", + "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==", + "dev": true + }, + "babel-helper-builder-react-jsx": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", + "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", + "requires": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "esutils": "^2.0.2" + } + }, + "babel-loader": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.1.0.tgz", + "integrity": "sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw==", + "requires": { + "find-cache-dir": "^2.1.0", + "loader-utils": "^1.4.0", + "mkdirp": "^0.5.3", + "pify": "^4.0.1", + "schema-utils": "^2.6.5" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + } + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-macros": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz", + "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==", + "requires": { + "@babel/runtime": "^7.7.2", + "cosmiconfig": "^6.0.0", + "resolve": "^1.12.0" + } + }, + "babel-plugin-syntax-flow": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=" + }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=" + }, + "babel-plugin-transform-flow-strip-types": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", + "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", + "requires": { + "babel-plugin-syntax-flow": "^6.18.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-react-display-name": { + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", + "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-react-jsx": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", + "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", + "requires": { + "babel-helper-builder-react-jsx": "^6.24.1", + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-react-jsx-self": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", + "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", + "requires": { + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-react-jsx-source": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", + "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", + "requires": { + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-preset-flow": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", + "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", + "requires": { + "babel-plugin-transform-flow-strip-types": "^6.22.0" + } + }, + "babel-preset-react": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", + "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", + "requires": { + "babel-plugin-syntax-jsx": "^6.3.13", + "babel-plugin-transform-react-display-name": "^6.23.0", + "babel-plugin-transform-react-jsx": "^6.24.1", + "babel-plugin-transform-react-jsx-self": "^6.22.0", + "babel-plugin-transform-react-jsx-source": "^6.22.0", + "babel-preset-flow": "^6.23.0" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + }, + "dependencies": { + "core-js": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + } + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + }, + "dependencies": { + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" + } + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "base62": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/base62/-/base62-0.1.1.tgz", + "integrity": "sha1-e0F0wvlESXU7EcJlHAg9qEGnsIQ=" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "requires": { + "inherits": "~2.0.0" + } + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==" + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "dependencies": { + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + } + } + }, + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "dev": true, + "requires": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + }, + "brace": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/brace/-/brace-0.11.1.tgz", + "integrity": "sha1-SJb8ydVE7vRfS7dmDbMg07N5/lg=" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browser-pack": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", + "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==", + "requires": { + "JSONStream": "^1.0.3", + "combine-source-map": "~0.8.0", + "defined": "^1.0.0", + "safe-buffer": "^5.1.1", + "through2": "^2.0.0", + "umd": "^3.0.0" + } + }, + "browser-resolve": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz", + "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==", + "requires": { + "resolve": "^1.17.0" + } + }, + "browserify": { + "version": "16.5.2", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-16.5.2.tgz", + "integrity": "sha512-TkOR1cQGdmXU9zW4YukWzWVSJwrxmNdADFbqbE3HFgQWe5wqZmOawqZ7J/8MPCwk/W8yY7Y0h+7mOtcZxLP23g==", + "requires": { + "JSONStream": "^1.0.3", + "assert": "^1.4.0", + "browser-pack": "^6.0.1", + "browser-resolve": "^2.0.0", + "browserify-zlib": "~0.2.0", + "buffer": "~5.2.1", + "cached-path-relative": "^1.0.0", + "concat-stream": "^1.6.0", + "console-browserify": "^1.1.0", + "constants-browserify": "~1.0.0", + "crypto-browserify": "^3.0.0", + "defined": "^1.0.0", + "deps-sort": "^2.0.0", + "domain-browser": "^1.2.0", + "duplexer2": "~0.1.2", + "events": "^2.0.0", + "glob": "^7.1.0", + "has": "^1.0.0", + "htmlescape": "^1.1.0", + "https-browserify": "^1.0.0", + "inherits": "~2.0.1", + "insert-module-globals": "^7.0.0", + "labeled-stream-splicer": "^2.0.0", + "mkdirp-classic": "^0.5.2", + "module-deps": "^6.2.3", + "os-browserify": "~0.3.0", + "parents": "^1.0.1", + "path-browserify": "~0.0.0", + "process": "~0.11.0", + "punycode": "^1.3.2", + "querystring-es3": "~0.2.0", + "read-only-stream": "^2.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.1.4", + "shasum": "^1.0.0", + "shell-quote": "^1.6.1", + "stream-browserify": "^2.0.0", + "stream-http": "^3.0.0", + "string_decoder": "^1.1.1", + "subarg": "^1.0.0", + "syntax-error": "^1.1.1", + "through2": "^2.0.0", + "timers-browserify": "^1.0.1", + "tty-browserify": "0.0.1", + "url": "~0.11.0", + "util": "~0.10.1", + "vm-browserify": "^1.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cache-api": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/browserify-cache-api/-/browserify-cache-api-3.0.1.tgz", + "integrity": "sha1-liR+hT8Gj9bg1FzHPwuyzZd47wI=", + "requires": { + "async": "^1.5.2", + "through2": "^2.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + } + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-incremental": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/browserify-incremental/-/browserify-incremental-3.1.1.tgz", + "integrity": "sha1-BxPLdYckemMqnwjPG9FpuHi2Koo=", + "requires": { + "JSONStream": "^0.10.0", + "browserify-cache-api": "^3.0.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "JSONStream": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.10.0.tgz", + "integrity": "sha1-dDSdDYlSK3HzDwoD/5vSDKbxKsA=", + "requires": { + "jsonparse": "0.0.5", + "through": ">=2.2.7 <3" + } + }, + "jsonparse": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", + "integrity": "sha1-MwVCrT8KZUZlt3jz6y2an6UHrGQ=" + } + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } + } + }, + "browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "4.14.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.5.tgz", + "integrity": "sha512-Z+vsCZIvCBvqLoYkBFTwEYH3v5MCQbsAjp50ERycpOjnPmolg1Gjy4+KaWWpm8QOJt9GHkhdqAl14NpCX73CWA==", + "requires": { + "caniuse-lite": "^1.0.30001135", + "electron-to-chromium": "^1.3.571", + "escalade": "^3.1.0", + "node-releases": "^1.1.61" + } + }, + "buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, + "cacache": { + "version": "15.0.5", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", + "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", + "requires": { + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.0", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "cached-path-relative": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.2.tgz", + "integrity": "sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg==" + }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "requires": { + "callsites": "^2.0.0" + }, + "dependencies": { + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=" + } + } + }, + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "requires": { + "caller-callsite": "^2.0.0" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + } + } + }, + "caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "requires": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "caniuse-lite": { + "version": "1.0.30001144", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001144.tgz", + "integrity": "sha512-4GQTEWNMnVZVOFG3BK0xvGeaDAtiPAbG2N8yuMXuXzx/c2Vd4XoMPO8+E918zeXn5IF0FRVtGShBfkfQea2wHQ==" + }, + "case-sensitive-paths-webpack-plugin": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.3.0.tgz", + "integrity": "sha512-/4YgnZS8y1UXXmC02xD5rRrBEu6T5ub+mQHLNRj0fzTRbgdBYhsNo2V5EqwgqrExjxsjtF/OpAKAMkKsxbD5XQ==" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "chain-function": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chain-function/-/chain-function-1.0.1.tgz", + "integrity": "sha512-SxltgMwL9uCko5/ZCLiyG2B7R9fY4pDZUw7hJ4MhirdjBLosoDqkWABi3XMucddHdLiFJMb7PD2MZifZriuMTg==" + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "dependencies": { + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "^2.1.0" + } + } + } + } + } + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "requires": { + "tslib": "^1.9.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "classnames": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", + "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "requires": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", + "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", + "dev": true, + "requires": { + "clone": "^1.0.2", + "color-convert": "^1.3.0", + "color-string": "^0.3.0" + }, + "dependencies": { + "color-string": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", + "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", + "dev": true, + "requires": { + "color-name": "^1.0.0" + } + } + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + }, + "dependencies": { + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + } + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "color-string": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", + "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "colorette": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", + "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==" + }, + "combine-source-map": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", + "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", + "requires": { + "convert-source-map": "~1.1.0", + "inline-source-map": "~0.6.0", + "lodash.memoize": "~3.0.3", + "source-map": "~0.5.3" + }, + "dependencies": { + "convert-source-map": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=" + }, + "lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=" + } + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, + "commoner": { + "version": "0.10.8", + "resolved": "https://registry.npmjs.org/commoner/-/commoner-0.10.8.tgz", + "integrity": "sha1-NPw2cs0kOT6LtH5wyqApOBH08sU=", + "requires": { + "commander": "^2.5.0", + "detective": "^4.3.1", + "glob": "^5.0.15", + "graceful-fs": "^4.1.2", + "iconv-lite": "^0.4.5", + "mkdirp": "^0.5.0", + "private": "^0.1.6", + "q": "^1.1.2", + "recast": "^0.11.17" + }, + "dependencies": { + "acorn": { + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", + "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==" + }, + "detective": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", + "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", + "requires": { + "acorn": "^5.2.1", + "defined": "^1.0.0" + } + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "component-classes": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/component-classes/-/component-classes-1.2.6.tgz", + "integrity": "sha1-xkI5TDYYpNiwuJGe/Mu9kw5c1pE=", + "requires": { + "component-indexof": "0.0.3" + } + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "component-indexof": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-indexof/-/component-indexof-0.0.3.tgz", + "integrity": "sha1-EdCRMSI5648yyPJa6csAL/6NPCQ=" + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "requires": { + "mime-db": ">= 1.43.0 < 2" + }, + "dependencies": { + "mime-db": { + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", + "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", + "dev": true + } + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "compression-webpack-plugin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/compression-webpack-plugin/-/compression-webpack-plugin-4.0.1.tgz", + "integrity": "sha512-0mg6PgwTsUe5LEcUrOu3ob32vraDx2VdbMGAT1PARcOV+UJWDYZFdkSo6RbHoGQ061mmmkC7XpRKOlvwm/gzJQ==", + "requires": { + "cacache": "^15.0.5", + "find-cache-dir": "^3.3.1", + "schema-utils": "^2.7.0", + "serialize-javascript": "^4.0.0", + "webpack-sources": "^1.4.3" + }, + "dependencies": { + "find-cache-dir": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", + "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "requires": { + "find-up": "^4.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "confusing-browser-globals": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz", + "integrity": "sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw==", + "dev": true + }, + "connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "dev": true + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "requires": { + "date-now": "^0.1.4" + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "requires": { + "safe-buffer": "~5.1.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, + "copy-to-clipboard": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.2.0.tgz", + "integrity": "sha512-eOZERzvCmxS8HWzugj4Uxl8OJxa7T2k1Gi0X5qavwydHIfuSHq2dTD09LOg/XyGq4Zpb5IsR/2OJ5lbOegz78w==", + "requires": { + "toggle-selection": "^1.0.6" + } + }, + "core-js": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", + "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==" + }, + "core-js-compat": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz", + "integrity": "sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng==", + "requires": { + "browserslist": "^4.8.5", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==" + } + } + }, + "core-js-pure": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.5.tgz", + "integrity": "sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + }, + "dependencies": { + "parse-json": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", + "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" + } + } + }, + "create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "create-react-context": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/create-react-context/-/create-react-context-0.3.0.tgz", + "integrity": "sha512-dNldIoSuNSvlTJ7slIKC/ZFGKexBMBrrcc+TTe1NdmROnaASuLPvqpwj9v4XS4uXZ8+YPu0sNmShX2rXI5LNsw==", + "requires": { + "gud": "^1.0.0", + "warning": "^4.0.3" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "css-animation": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/css-animation/-/css-animation-1.6.1.tgz", + "integrity": "sha512-/48+/BaEaHRY6kNQ2OIPzKf9A6g8WjZYjhiNDNuIVbsm5tXCGIAsHDjB4Xu1C4vXJtUWZo26O68OQkDpNBaPog==", + "requires": { + "babel-runtime": "6.x", + "component-classes": "^1.2.5" + } + }, + "css-blank-pseudo": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz", + "integrity": "sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w==", + "requires": { + "postcss": "^7.0.5" + } + }, + "css-box-model": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz", + "integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==", + "requires": { + "tiny-invariant": "^1.0.6" + } + }, + "css-color-function": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/css-color-function/-/css-color-function-1.3.3.tgz", + "integrity": "sha1-jtJMLAIFBzM5+voAS8jBQfzLKC4=", + "dev": true, + "requires": { + "balanced-match": "0.1.0", + "color": "^0.11.0", + "debug": "^3.1.0", + "rgb": "~0.1.0" + }, + "dependencies": { + "balanced-match": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.1.0.tgz", + "integrity": "sha1-tQS9BYabOSWd0MXvw12EMXbczEo=", + "dev": true + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=" + }, + "css-declaration-sorter": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz", + "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==", + "requires": { + "postcss": "^7.0.1", + "timsort": "^0.3.0" + } + }, + "css-has-pseudo": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz", + "integrity": "sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ==", + "requires": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^5.0.0-rc.4" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==" + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "css-loader": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", + "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", + "requires": { + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.32", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^3.0.2", + "postcss-modules-scope": "^2.2.0", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^2.7.0", + "semver": "^6.3.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-value-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", + "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==" + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "css-prefers-color-scheme": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz", + "integrity": "sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg==", + "requires": { + "postcss": "^7.0.5" + } + }, + "css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" + }, + "css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "requires": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "css-unit-converter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz", + "integrity": "sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==", + "dev": true + }, + "css-what": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.1.tgz", + "integrity": "sha512-wHOppVDKl4vTAOWzJt5Ek37Sgd9qq1Bmj/T1OjvicWbU5W7ru7Pqbn0Jdqii3Drx/h+dixHKXNhZYx7blthL7g==" + }, + "cssdb": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-4.4.0.tgz", + "integrity": "sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ==" + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" + }, + "cssnano": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz", + "integrity": "sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==", + "requires": { + "cosmiconfig": "^5.0.0", + "cssnano-preset-default": "^4.0.7", + "is-resolvable": "^1.0.0", + "postcss": "^7.0.0" + }, + "dependencies": { + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + } + } + }, + "cssnano-preset-default": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz", + "integrity": "sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==", + "requires": { + "css-declaration-sorter": "^4.0.1", + "cssnano-util-raw-cache": "^4.0.1", + "postcss": "^7.0.0", + "postcss-calc": "^7.0.1", + "postcss-colormin": "^4.0.3", + "postcss-convert-values": "^4.0.1", + "postcss-discard-comments": "^4.0.2", + "postcss-discard-duplicates": "^4.0.2", + "postcss-discard-empty": "^4.0.1", + "postcss-discard-overridden": "^4.0.1", + "postcss-merge-longhand": "^4.0.11", + "postcss-merge-rules": "^4.0.3", + "postcss-minify-font-values": "^4.0.2", + "postcss-minify-gradients": "^4.0.2", + "postcss-minify-params": "^4.0.2", + "postcss-minify-selectors": "^4.0.2", + "postcss-normalize-charset": "^4.0.1", + "postcss-normalize-display-values": "^4.0.2", + "postcss-normalize-positions": "^4.0.2", + "postcss-normalize-repeat-style": "^4.0.2", + "postcss-normalize-string": "^4.0.2", + "postcss-normalize-timing-functions": "^4.0.2", + "postcss-normalize-unicode": "^4.0.1", + "postcss-normalize-url": "^4.0.1", + "postcss-normalize-whitespace": "^4.0.2", + "postcss-ordered-values": "^4.1.2", + "postcss-reduce-initial": "^4.0.3", + "postcss-reduce-transforms": "^4.0.2", + "postcss-svgo": "^4.0.2", + "postcss-unique-selectors": "^4.0.1" + }, + "dependencies": { + "postcss-calc": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.5.tgz", + "integrity": "sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg==", + "requires": { + "postcss": "^7.0.27", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.2" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + } + } + }, + "postcss-value-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", + "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "cssnano-util-get-arguments": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz", + "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=" + }, + "cssnano-util-get-match": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz", + "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=" + }, + "cssnano-util-raw-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz", + "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==", + "requires": { + "postcss": "^7.0.0" + } + }, + "cssnano-util-same-parent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz", + "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==" + }, + "csso": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.0.3.tgz", + "integrity": "sha512-NL3spysxUkcrOgnpsT4Xdl2aiEiBG6bXswAABQVHcMrfjjBisFOKwLDOmf4wf32aPdcJws1zds2B0Rg+jqMyHQ==", + "requires": { + "css-tree": "1.0.0-alpha.39" + }, + "dependencies": { + "css-tree": { + "version": "1.0.0-alpha.39", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.39.tgz", + "integrity": "sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA==", + "requires": { + "mdn-data": "2.0.6", + "source-map": "^0.6.1" + } + }, + "mdn-data": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.6.tgz", + "integrity": "sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "csstype": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.3.tgz", + "integrity": "sha512-jPl+wbWPOWJ7SXsWyqGRk3lGecbar0Cb0OvZF/r/ZU011R4YqiRehgkQ9p4eQfo9DSDLqLL3wHwfxeJiuIsNag==", + "dev": true + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "requires": { + "array-find-index": "^1.0.1" + } + }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=" + }, + "damerau-levenshtein": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz", + "integrity": "sha512-JVrozIeElnj3QzfUIt8tB8YMluBJom4Vw9qTPpjGYQ9fYlB3D/rb6OordUxf3xeFB35LKWs0xqcO5U6ySvBtug==", + "dev": true + }, + "dash-ast": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", + "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "date-fns": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.16.1.tgz", + "integrity": "sha512-sAJVKx/FqrLYHAQeN7VpJrPhagZc9R4ImZIWYRFZaaohR3KzmuK88touwsSwSVT8Qcbd4zoDsnGfX4GFB4imyQ==" + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "dev": true, + "requires": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "default-gateway": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", + "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "ip-regex": "^2.1.0" + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" + }, + "del": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "dependencies": { + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "deps-sort": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", + "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=", + "requires": { + "JSONStream": "^1.0.3", + "shasum": "^1.0.0", + "subarg": "^1.0.0", + "through2": "^2.0.0" + } + }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=" + }, + "detect-node": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", + "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", + "dev": true + }, + "detective": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", + "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", + "requires": { + "acorn-node": "^1.6.1", + "defined": "^1.0.0", + "minimist": "^1.1.1" + } + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } + } + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", + "dev": true + }, + "dns-packet": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", + "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", + "dev": true, + "requires": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "dev": true, + "requires": { + "buffer-indexof": "^1.0.0" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "dom-align": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.0.tgz", + "integrity": "sha512-YkoezQuhp3SLFGdOlr5xkqZ640iXrnHAwVYcDg8ZKRUtO7mSzSC2BA5V0VuyAwPSJA4CLIc6EDDJh4bEsD2+zA==" + }, + "dom-helpers": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz", + "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==", + "requires": { + "@babel/runtime": "^7.1.2" + } + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.2.tgz", + "integrity": "sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA==" + } + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "requires": { + "is-obj": "^2.0.0" + } + }, + "dropzone": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/dropzone/-/dropzone-5.7.2.tgz", + "integrity": "sha512-m217bJHtf0J1IiKn4Tv6mnu1h5QvQNBnKZ39gma7hzGQhIZMxYq1vYEHs4AVd4ThFwmALys+52NAOD4zdLTG4w==" + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "requires": { + "readable-stream": "^2.0.2" + } + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.578", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.578.tgz", + "integrity": "sha512-z4gU6dA1CbBJsAErW5swTGAaU2TBzc2mPAonJb00zqW1rOraDo2zfBMDRvaz9cVic+0JEZiYbHWPw/fTaZlG2Q==" + }, + "elliptic": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } + } + }, + "email-addresses": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-3.1.0.tgz", + "integrity": "sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg==" + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "^1.4.0" + } + }, + "enhanced-resolve": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz", + "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==", + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } + } + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + }, + "dependencies": { + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + } + } + }, + "entities": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==" + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "dependencies": { + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "requires": { + "has-symbols": "^1.0.1" + } + } + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escalade": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.0.tgz", + "integrity": "sha512-mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig==" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "eslint": { + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.10.0.tgz", + "integrity": "sha512-BDVffmqWl7JJXqCjAK6lWtcQThZB/aP1HXSH1JKwGwv0LQEdvpR7qzNrUT487RM39B5goWuboFad5ovMBmD8yA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@eslint/eslintrc": "^0.1.3", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^1.3.0", + "espree": "^7.3.0", + "esquery": "^1.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash": "^4.17.19", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "eslint-config-airbnb": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-18.2.0.tgz", + "integrity": "sha512-Fz4JIUKkrhO0du2cg5opdyPKQXOI2MvF8KUvN2710nJMT6jaRUpRE2swrJftAjVGL7T1otLM5ieo5RqS1v9Udg==", + "dev": true, + "requires": { + "eslint-config-airbnb-base": "^14.2.0", + "object.assign": "^4.1.0", + "object.entries": "^1.1.2" + } + }, + "eslint-config-airbnb-base": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.0.tgz", + "integrity": "sha512-Snswd5oC6nJaevs3nZoLSTvGJBvzTfnBqOIArkf3cbyTyq9UD79wOk8s+RiL6bhca0p/eRO6veczhf6A/7Jy8Q==", + "dev": true, + "requires": { + "confusing-browser-globals": "^1.0.9", + "object.assign": "^4.1.0", + "object.entries": "^1.1.2" + } + }, + "eslint-import-resolver-node": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", + "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.13.1" + } + }, + "eslint-module-utils": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", + "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "pkg-dir": "^2.0.0" + }, + "dependencies": { + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + } + } + }, + "eslint-plugin-import": { + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", + "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", + "dev": true, + "requires": { + "array-includes": "^3.1.1", + "array.prototype.flat": "^1.2.3", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.4", + "eslint-module-utils": "^2.6.0", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.1", + "read-pkg-up": "^2.0.0", + "resolve": "^1.17.0", + "tsconfig-paths": "^3.9.0" + } + }, + "eslint-plugin-jsx-a11y": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.3.1.tgz", + "integrity": "sha512-i1S+P+c3HOlBJzMFORRbC58tHa65Kbo8b52/TwCwSKLohwvpfT5rm2GjGWzOHTEuq4xxf2aRlHHTtmExDQOP+g==", + "dev": true, + "requires": { + "@babel/runtime": "^7.10.2", + "aria-query": "^4.2.2", + "array-includes": "^3.1.1", + "ast-types-flow": "^0.0.7", + "axe-core": "^3.5.4", + "axobject-query": "^2.1.2", + "damerau-levenshtein": "^1.0.6", + "emoji-regex": "^9.0.0", + "has": "^1.0.3", + "jsx-ast-utils": "^2.4.1", + "language-tags": "^1.0.5" + }, + "dependencies": { + "emoji-regex": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.0.0.tgz", + "integrity": "sha512-6p1NII1Vm62wni/VR/cUMauVQoxmLVb9csqQlvLz+hO2gk8U2UYDfXHQSUYIBKmZwAKz867IDqG7B+u0mj+M6w==", + "dev": true + } + } + }, + "eslint-plugin-promise": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz", + "integrity": "sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==", + "dev": true + }, + "eslint-plugin-react": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.21.3.tgz", + "integrity": "sha512-OI4GwTCqyIb4ipaOEGLWdaOHCXZZydStAsBEPB2e1ZfNM37bojpgO1BoOQbFb0eLVz3QLDx7b+6kYcrxCuJfhw==", + "dev": true, + "requires": { + "array-includes": "^3.1.1", + "array.prototype.flatmap": "^1.2.3", + "doctrine": "^2.1.0", + "has": "^1.0.3", + "jsx-ast-utils": "^2.4.1", + "object.entries": "^1.1.2", + "object.fromentries": "^2.0.2", + "object.values": "^1.1.1", + "prop-types": "^15.7.2", + "resolve": "^1.17.0", + "string.prototype.matchall": "^4.0.2" + }, + "dependencies": { + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dev": true, + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + } + } + }, + "eslint-plugin-standard": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.1.tgz", + "integrity": "sha512-v/KBnfyaOMPmZc/dmc6ozOdWqekGp7bBGq4jLAecEfPGmfKiWS4sA8sC0LqiV9w5qmXAtXVn4M3p1jSyhY85SQ==", + "dev": true + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "espree": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz", + "integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.3.0" + } + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + }, + "esquery": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "events": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/events/-/events-2.1.0.tgz", + "integrity": "sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg==" + }, + "eventsource": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz", + "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==", + "dev": true, + "requires": { + "original": "^1.0.0" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==" + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "file-loader": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.1.0.tgz", + "integrity": "sha512-26qPdHyTsArQ6gU4P1HJbAbnFTyT2r0pG7czh1GFAd9TZbj0n94wWbupgixZH/ET/meqi2/5+F7DhW4OAXD+Lg==", + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^2.7.1" + }, + "dependencies": { + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "requires": { + "minimist": "^1.2.5" + } + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + } + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true + }, + "filename-reserved-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-1.0.0.tgz", + "integrity": "sha1-5hz4BfDeHJhFZ9A4bcXfUO5a9+Q=" + }, + "filenamify": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-1.2.1.tgz", + "integrity": "sha1-qfL/0RxQO+0wABUCknI3jx8TZaU=", + "requires": { + "filename-reserved-regex": "^1.0.0", + "strip-outer": "^1.0.0", + "trim-repeated": "^1.0.0" + } + }, + "filenamify-url": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/filenamify-url/-/filenamify-url-1.0.0.tgz", + "integrity": "sha1-syvYExnvWGO3MHi+1Q9GpPeXX1A=", + "requires": { + "filenamify": "^1.0.0", + "humanize-url": "^1.0.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + }, + "dependencies": { + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "flatted": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.0.tgz", + "integrity": "sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA==" + }, + "flatten": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", + "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=" + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "follow-redirects": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", + "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", + "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "requires": { + "minipass": "^3.0.0" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "optional": true + }, + "fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "requires": { + "globule": "^1.0.0" + } + }, + "gensync": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", + "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==" + }, + "get-assigned-identifiers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", + "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==" + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "gh-pages": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-2.2.0.tgz", + "integrity": "sha512-c+yPkNOPMFGNisYg9r4qvsMIjVYikJv7ImFOhPIVPt0+AcRUamZ7zkGRLHz7FKB0xrlZ+ddSOJsZv9XAFVXLmA==", + "requires": { + "async": "^2.6.1", + "commander": "^2.18.0", + "email-addresses": "^3.0.1", + "filenamify-url": "^1.0.0", + "fs-extra": "^8.1.0", + "globby": "^6.1.0" + } + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "requires": { + "is-glob": "^4.0.1" + } + }, + "global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "requires": { + "global-prefix": "^3.0.0" + }, + "dependencies": { + "global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "requires": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + } + } + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "globule": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz", + "integrity": "sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==", + "requires": { + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + } + }, + "graceful-fs": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", + "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==" + }, + "gud": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz", + "integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw==" + }, + "handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hex-color-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", + "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==" + }, + "highlightjs": { + "version": "9.16.2", + "resolved": "https://registry.npmjs.org/highlightjs/-/highlightjs-9.16.2.tgz", + "integrity": "sha512-FK1vmMj8BbEipEy8DLIvp71t5UsC7n2D6En/UfM/91PCwmOpj6f2iu0Y0coRC62KSRHHC+dquM2xMULV/X7NFg==" + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "hsl-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz", + "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=" + }, + "hsla-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", + "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=" + }, + "html-comment-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", + "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==" + }, + "html-entities": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz", + "integrity": "sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA==", + "dev": true + }, + "htmlescape": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", + "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=" + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", + "dev": true + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-middleware": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", + "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", + "dev": true, + "requires": { + "http-proxy": "^1.17.0", + "is-glob": "^4.0.0", + "lodash": "^4.17.11", + "micromatch": "^3.1.10" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" + }, + "humanize-url": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/humanize-url/-/humanize-url-1.0.1.tgz", + "integrity": "sha1-9KuZ4NKIF0yk4eUEB8VfuuRk7/8=", + "requires": { + "normalize-url": "^1.0.0", + "strip-url-auth": "^1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "icss-utils": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", + "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", + "requires": { + "postcss": "^7.0.14" + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "immutability-helper": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/immutability-helper/-/immutability-helper-3.1.1.tgz", + "integrity": "sha512-Q0QaXjPjwIju/28TsugCHNEASwoCcJSyJV3uO1sOIQGI0jKgm9f41Lvz0DZj3n46cNCyAZTsEYoY4C2bVRUzyQ==" + }, + "import-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", + "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", + "requires": { + "import-from": "^2.1.0" + } + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + } + } + }, + "import-from": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", + "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", + "requires": { + "resolve-from": "^3.0.0" + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "in-publish": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.1.tgz", + "integrity": "sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ==" + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=" + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "inline-source-map": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", + "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", + "requires": { + "source-map": "~0.5.3" + } + }, + "insert-module-globals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.0.tgz", + "integrity": "sha512-VE6NlW+WGn2/AeOMd496AHFYmE7eLKkUY6Ty31k4og5vmA3Fjuwe9v6ifH6Xx/Hz27QvdoMoviw1/pqWRB09Sw==", + "requires": { + "JSONStream": "^1.0.3", + "acorn-node": "^1.5.2", + "combine-source-map": "^0.8.0", + "concat-stream": "^1.6.1", + "is-buffer": "^1.1.0", + "path-is-absolute": "^1.0.1", + "process": "~0.11.0", + "through2": "^2.0.0", + "undeclared-identifiers": "^1.1.2", + "xtend": "^4.0.0" + } + }, + "internal-ip": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", + "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", + "dev": true, + "requires": { + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" + } + }, + "internal-slot": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.2.tgz", + "integrity": "sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g==", + "dev": true, + "requires": { + "es-abstract": "^1.17.0-next.1", + "has": "^1.0.3", + "side-channel": "^1.0.2" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + } + } + }, + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "dev": true + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true + }, + "is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-callable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==" + }, + "is-color-stop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", + "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=", + "requires": { + "css-color-names": "^0.0.4", + "hex-color-regex": "^1.1.0", + "hsl-regex": "^1.0.0", + "hsla-regex": "^1.0.0", + "rgb-regex": "^1.0.1", + "rgba-regex": "^1.0.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=" + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-finite": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=" + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" + }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true + }, + "is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "dev": true, + "requires": { + "is-path-inside": "^2.1.0" + } + }, + "is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, + "requires": { + "path-is-inside": "^1.0.2" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==" + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, + "is-svg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz", + "integrity": "sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ==", + "requires": { + "html-comment-regex": "^1.1.0" + } + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isnumeric": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/isnumeric/-/isnumeric-0.2.0.tgz", + "integrity": "sha1-ojR7o2DeGeM9D/1ZD933dVy/LmQ=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jest-worker": { + "version": "26.5.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.5.0.tgz", + "integrity": "sha512-kTw66Dn4ZX7WpjZ7T/SUDgRhapFRKWmisVAF0Rv4Fu8SLFD7eLbqpLvbxVqYhSgaWa7I+bW7pHnbyfNsH6stug==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "js-base64": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", + "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==" + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + } + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stable-stringify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", + "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", + "requires": { + "jsonify": "~0.0.0" + } + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "json3": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", + "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "requires": { + "minimist": "^1.2.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jstransform": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/jstransform/-/jstransform-10.1.0.tgz", + "integrity": "sha1-tMSb9j8WLBCLA0g5moc3xxOwqDo=", + "requires": { + "base62": "0.1.1", + "esprima-fb": "13001.1001.0-dev-harmony-fb", + "source-map": "0.1.31" + }, + "dependencies": { + "esprima-fb": { + "version": "13001.1001.0-dev-harmony-fb", + "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-13001.1001.0-dev-harmony-fb.tgz", + "integrity": "sha1-YzrNtA2b1NuKHB1owGqUKVn60rA=" + }, + "source-map": { + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.31.tgz", + "integrity": "sha1-n3BNDWnZ4TioG63267T94z0VHGE=", + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "jsx-ast-utils": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz", + "integrity": "sha512-z1xSldJ6imESSzOjd3NNkieVJKRlKYSOtMG8SFyCj2FIrvSaSuli/WjpBkEzCBoR9bYYYFgqJw61Xhu7Lcgk+w==", + "dev": true, + "requires": { + "array-includes": "^3.1.1", + "object.assign": "^4.1.0" + } + }, + "killable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", + "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", + "dev": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "labeled-stream-splicer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz", + "integrity": "sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==", + "requires": { + "inherits": "^2.0.1", + "stream-splicer": "^2.0.0" + } + }, + "language-subtag-registry": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.20.tgz", + "integrity": "sha512-KPMwROklF4tEx283Xw0pNKtfTj1gZ4UByp4EsIFWLgBavJltF4TiYPc39k06zSTsLzxTVXXDSpbwaQXaFB4Qeg==", + "dev": true + }, + "language-tags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", + "integrity": "sha1-0yHbxNowuovzAk4ED6XBRmH5GTo=", + "dev": true, + "requires": { + "language-subtag-registry": "~0.3.2" + } + }, + "last-call-webpack-plugin": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz", + "integrity": "sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w==", + "requires": { + "lodash": "^4.17.5", + "webpack-sources": "^1.1.0" + } + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" + }, + "levenary": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz", + "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==", + "requires": { + "leven": "^3.1.0" + } + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==" + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + }, + "lodash-es": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.15.tgz", + "integrity": "sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ==" + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, + "lodash.has": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz", + "integrity": "sha1-0Z9NwQlQWMzL4rDN9O4P5Ko3yGI=" + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" + }, + "lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "requires": { + "lodash._reinterpolate": "^3.0.0" + } + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" + }, + "loglevel": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.0.tgz", + "integrity": "sha512-i2sY04nal5jDcagM3FMfG++T69GEEM8CYuOfeOIvmXzOIcwE9a/CJPR0MFM97pYMj/u10lzz7/zd7+qwhrBTqQ==", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "make-cancellable-promise": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/make-cancellable-promise/-/make-cancellable-promise-1.0.0.tgz", + "integrity": "sha512-+YO6Grg2uy/z8Mv3uV90OP6yAUHIF43YGgEFbejmBrK9VWFsVO6DvzFMcopXr9wCNg3/QIltIKiSCROC7zFB2g==" + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + } + } + }, + "make-event-props": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/make-event-props/-/make-event-props-1.2.0.tgz", + "integrity": "sha512-BmWFkm/jZzVH9A0tEBdkjAARUz/eha+5IRyfOndeSMKRadkgR5DawoBHoRwLxkYmjJOI5bHkXKpaZocxj+dKgg==" + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "requires": { + "object-visit": "^1.0.0" + } + }, + "marked": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-1.2.0.tgz", + "integrity": "sha512-tiRxakgbNPBr301ihe/785NntvYyhxlqcL3YaC8CaxJQh7kiaEtrN9B/eK2I2943Yjkh5gw25chYFDQhOMCwMA==" + }, + "math-expression-evaluator": { + "version": "1.2.22", + "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.22.tgz", + "integrity": "sha512-L0j0tFVZBQQLeEjmWOvDLoRciIY8gQGWahvkztXUal8jH8R5Rlqo9GCvgqvXcy9LQhEWdQCVvzqAbxgYNt4blQ==", + "dev": true + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "memoize-one": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.1.1.tgz", + "integrity": "sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA==" + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "^0.2.0" + } + } + } + }, + "merge-class-names": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/merge-class-names/-/merge-class-names-1.3.0.tgz", + "integrity": "sha512-k0Qaj36VBpKgdc8c188LEZvo6v/zzry/FUufwopWbMSp6/knfVFU/KIB55/hJjeIpg18IH2WskXJCRnM/1BrdQ==" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "mime-db": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" + }, + "mime-types": { + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "requires": { + "mime-db": "1.40.0" + } + }, + "mini-css-extract-plugin": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz", + "integrity": "sha512-lp3GeY7ygcgAmVIcRPBVhIkf8Us7FZjA+ILpal44qLdSu11wmjKQ3d9k15lfD7pO4esu9eUIAW7qiYIBppv40A==", + "requires": { + "loader-utils": "^1.1.0", + "normalize-url": "1.9.1", + "schema-utils": "^1.0.0", + "webpack-sources": "^1.1.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "requires": { + "yallist": "^4.0.0" + } + }, + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "requires": { + "minipass": "^3.0.0" + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + } + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "module-deps": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.3.tgz", + "integrity": "sha512-fg7OZaQBcL4/L+AK5f4iVqf9OMbCclXfy/znXRxTVhJSeW5AIlS9AwheYwDaXM3lVW7OBeaeUEY3gbaC6cLlSA==", + "requires": { + "JSONStream": "^1.0.3", + "browser-resolve": "^2.0.0", + "cached-path-relative": "^1.0.2", + "concat-stream": "~1.6.0", + "defined": "^1.0.0", + "detective": "^5.2.0", + "duplexer2": "^0.1.2", + "inherits": "^2.0.1", + "parents": "^1.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.4.0", + "stream-combiner2": "^1.1.1", + "subarg": "^1.0.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "moment": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" + }, + "moment-timezone": { + "version": "0.5.31", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.31.tgz", + "integrity": "sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==", + "requires": { + "moment": ">= 2.9.0" + }, + "dependencies": { + "moment": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", + "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" + } + } + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dev": true, + "requires": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + } + }, + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "dev": true + }, + "nan": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", + "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==" + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "native-promise-only": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", + "integrity": "sha1-IKMYwwy0X3H+et+/eyHJnBRy7xE=" + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + }, + "node-ensure": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/node-ensure/-/node-ensure-0.0.0.tgz", + "integrity": "sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc=" + }, + "node-forge": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", + "dev": true + }, + "node-gyp": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", + "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": "^2.87.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + }, + "tar": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", + "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", + "requires": { + "block-stream": "*", + "fstream": "^1.0.12", + "inherits": "2" + } + } + } + }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + }, + "dependencies": { + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "events": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", + "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==" + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "timers-browserify": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", + "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==", + "requires": { + "setimmediate": "^1.0.4" + } + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + } + } + } + } + }, + "node-releases": { + "version": "1.1.61", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.61.tgz", + "integrity": "sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g==" + }, + "node-sass": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.14.1.tgz", + "integrity": "sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g==", + "requires": { + "async-foreach": "^0.1.3", + "chalk": "^1.1.1", + "cross-spawn": "^3.0.0", + "gaze": "^1.0.0", + "get-stdin": "^4.0.1", + "glob": "^7.0.3", + "in-publish": "^2.0.0", + "lodash": "^4.17.15", + "meow": "^3.7.0", + "mkdirp": "^0.5.1", + "nan": "^2.13.2", + "node-gyp": "^3.8.0", + "npmlog": "^4.0.0", + "request": "^2.88.0", + "sass-graph": "2.2.5", + "stdout-stream": "^1.4.0", + "true-case-path": "^1.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "cross-spawn": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", + "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + } + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "requires": { + "abbrev": "1" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=" + }, + "normalize-url": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", + "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", + "requires": { + "object-assign": "^4.0.1", + "prepend-http": "^1.0.0", + "query-string": "^4.1.0", + "sort-keys": "^1.0.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "requires": { + "boolbase": "~1.0.0" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=" + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==" + }, + "object-is": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.3.tgz", + "integrity": "sha512-teyqLvFWzLkq5B9ki8FVWA902UER2qkxmdA4nLf+wjOLAWgxzCWZNCxpDq9MvE8MmhWNr+I8w3BN49Vx36Y6Xg==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", + "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.0", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "object.entries": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.2.tgz", + "integrity": "sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "has": "^1.0.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + } + } + }, + "object.fromentries": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.2.tgz", + "integrity": "sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + } + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "requires": { + "has-symbols": "^1.0.1" + } + } + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "^3.0.1" + } + }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "requires": { + "has-symbols": "^1.0.1" + } + } + } + }, + "objectify-array": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/objectify-array/-/objectify-array-2.1.0.tgz", + "integrity": "sha512-tG8ndq75CyLdsVSB5e3Xp6ajVi0oC3LsR0lMiGx3imtYWrGNnpdPzP/Tv3UQsRO2OCvpqUedQyZAv20OrlK2WA==" + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "onecolor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/onecolor/-/onecolor-3.1.0.tgz", + "integrity": "sha512-YZSypViXzu3ul5LMu/m6XjJ9ol8qAy9S2VjHl5E6UlhUH1KGKWabyEJifn0Jjpw23bYDzC2ucKMPGiH5kfwSGQ==", + "dev": true + }, + "opn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + } + }, + "optimize-css-assets-webpack-plugin": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.4.tgz", + "integrity": "sha512-wqd6FdI2a5/FdoiCNNkEvLeA//lHHfG24Ln2Xm2qqdIk4aOlsR18jwpyOihqQ8849W3qu2DX8fOYxpvTMj+93A==", + "requires": { + "cssnano": "^4.1.10", + "last-call-webpack-plugin": "^3.0.0" + } + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "original": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", + "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", + "dev": true, + "requires": { + "url-parse": "^1.4.3" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + }, + "dependencies": { + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + } + } + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "dev": true, + "requires": { + "retry": "^0.12.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "requires": { + "callsites": "^3.0.0" + } + }, + "parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "requires": { + "path-platform": "~0.11.15" + } + }, + "parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "requires": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==" + }, + "path-complete-extname": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-complete-extname/-/path-complete-extname-1.0.0.tgz", + "integrity": "sha512-CVjiWcMRdGU8ubs08YQVzhutOR5DEfO97ipRIlOGMK5Bek5nQySknBpuxVAVJ36hseTNs+vdIcv57ZrWxH7zvg==" + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "pdfjs-dist": { + "version": "2.1.266", + "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.1.266.tgz", + "integrity": "sha512-Jy7o1wE3NezPxozexSbq4ltuLT0Z21ew/qrEiAEeUZzHxMHGk4DUV1D7RuCXg5vJDvHmjX1YssN+we9QfRRgXQ==", + "requires": { + "node-ensure": "^0.0.0", + "worker-loader": "^2.0.0" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "^2.0.0" + } + }, + "pixrem": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pixrem/-/pixrem-4.0.1.tgz", + "integrity": "sha1-LaSh3m7EQjxfw3lOkwuB1EkOxoY=", + "dev": true, + "requires": { + "browserslist": "^2.0.0", + "postcss": "^6.0.0", + "reduce-css-calc": "^1.2.7" + }, + "dependencies": { + "browserslist": { + "version": "2.11.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", + "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000792", + "electron-to-chromium": "^1.3.30" + } + }, + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "requires": { + "find-up": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + } + } + }, + "pleeease-filters": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pleeease-filters/-/pleeease-filters-4.0.0.tgz", + "integrity": "sha1-ZjKy+wVkjSdY2GU4T7zteeHMrsc=", + "dev": true, + "requires": { + "onecolor": "^3.0.4", + "postcss": "^6.0.1" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "pnp-webpack-plugin": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz", + "integrity": "sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg==", + "requires": { + "ts-pnp": "^1.1.6" + } + }, + "popper.js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==" + }, + "portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "dev": true, + "requires": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + }, + "postcss": { + "version": "7.0.17", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz", + "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==", + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-apply": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/postcss-apply/-/postcss-apply-0.8.0.tgz", + "integrity": "sha1-FOVEu7XLbxweBIhXll15rgZrE0M=", + "dev": true, + "requires": { + "babel-runtime": "^6.23.0", + "balanced-match": "^0.4.2", + "postcss": "^6.0.0" + }, + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", + "dev": true + }, + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-attribute-case-insensitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-2.0.0.tgz", + "integrity": "sha1-lNxCLI+QmX8WvTOjZUu77AhJY7Q=", + "dev": true, + "requires": { + "postcss": "^6.0.0", + "postcss-selector-parser": "^2.2.3" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "postcss-selector-parser": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", + "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", + "dev": true, + "requires": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-calc": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-6.0.2.tgz", + "integrity": "sha512-fiznXjEN5T42Qm7qqMCVJXS3roaj9r4xsSi+meaBVe7CJBl8t/QLOXu02Z2E6oWAMWIvCuF6JrvzFekmVEbOKA==", + "dev": true, + "requires": { + "css-unit-converter": "^1.1.1", + "postcss": "^7.0.2", + "postcss-selector-parser": "^2.2.2", + "reduce-css-calc": "^2.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", + "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", + "dev": true, + "requires": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "reduce-css-calc": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-2.1.7.tgz", + "integrity": "sha512-fDnlZ+AybAS3C7Q9xDq5y8A2z+lT63zLbynew/lur/IR24OQF5x98tfNwf79mzEdfywZ0a2wpM860FhFfMxZlA==", + "dev": true, + "requires": { + "css-unit-converter": "^1.1.1", + "postcss-value-parser": "^3.3.0" + } + } + } + }, + "postcss-color-function": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-color-function/-/postcss-color-function-4.1.0.tgz", + "integrity": "sha512-2/fuv6mP5Lt03XbRpVfMdGC8lRP1sykme+H1bR4ARyOmSMB8LPSjcL6EAI1iX6dqUF+jNEvKIVVXhan1w/oFDQ==", + "dev": true, + "requires": { + "css-color-function": "~1.3.3", + "postcss": "^6.0.23", + "postcss-message-helpers": "^2.0.0", + "postcss-value-parser": "^3.3.1" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-color-functional-notation": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz", + "integrity": "sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g==", + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-color-gray": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-color-gray/-/postcss-color-gray-4.1.0.tgz", + "integrity": "sha512-L4iLKQLdqChz6ZOgGb6dRxkBNw78JFYcJmBz1orHpZoeLtuhDDGegRtX9gSyfoCIM7rWZ3VNOyiqqvk83BEN+w==", + "dev": true, + "requires": { + "color": "^2.0.1", + "postcss": "^6.0.14", + "postcss-message-helpers": "^2.0.0", + "reduce-function-call": "^1.0.2" + }, + "dependencies": { + "color": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color/-/color-2.0.1.tgz", + "integrity": "sha512-ubUCVVKfT7r2w2D3qtHakj8mbmKms+tThR8gI8zEYCbUBl8/voqFGt3kgBqGwXAopgXybnkuOq+qMYCRrp4cXw==", + "dev": true, + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + } + }, + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-color-hex-alpha": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-3.0.0.tgz", + "integrity": "sha1-HlPmyKyyN5Vej9CLfs2xuLgwn5U=", + "dev": true, + "requires": { + "color": "^1.0.3", + "postcss": "^6.0.1", + "postcss-message-helpers": "^2.0.0" + }, + "dependencies": { + "color": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/color/-/color-1.0.3.tgz", + "integrity": "sha1-5I6DLYXxTvaU+0aIEcLVz+cptV0=", + "dev": true, + "requires": { + "color-convert": "^1.8.2", + "color-string": "^1.4.0" + } + }, + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-color-hsl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-hsl/-/postcss-color-hsl-2.0.0.tgz", + "integrity": "sha1-EnA2ZvoxBDDj8wpFTawThjF9WEQ=", + "dev": true, + "requires": { + "postcss": "^6.0.1", + "postcss-value-parser": "^3.3.0", + "units-css": "^0.4.0" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-color-hwb": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-hwb/-/postcss-color-hwb-3.0.0.tgz", + "integrity": "sha1-NAKxnvTYSXVAwftQcr6YY8qVVx4=", + "dev": true, + "requires": { + "color": "^1.0.3", + "postcss": "^6.0.1", + "postcss-message-helpers": "^2.0.0", + "reduce-function-call": "^1.0.2" + }, + "dependencies": { + "color": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/color/-/color-1.0.3.tgz", + "integrity": "sha1-5I6DLYXxTvaU+0aIEcLVz+cptV0=", + "dev": true, + "requires": { + "color-convert": "^1.8.2", + "color-string": "^1.4.0" + } + }, + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-color-mod-function": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz", + "integrity": "sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ==", + "requires": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-color-rebeccapurple": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-3.1.0.tgz", + "integrity": "sha512-212hJUk9uSsbwO5ECqVjmh/iLsmiVL1xy9ce9TVf+X3cK/ZlUIlaMdoxje/YpsL9cmUH3I7io+/G2LyWx5rg1g==", + "dev": true, + "requires": { + "postcss": "^6.0.22", + "postcss-values-parser": "^1.5.0" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "postcss-values-parser": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-1.5.0.tgz", + "integrity": "sha512-3M3p+2gMp0AH3da530TlX8kiO1nxdTnc3C6vr8dMxRLIlh8UYkz0/wcwptSXjhtx2Fr0TySI7a+BHDQ8NL7LaQ==", + "dev": true, + "requires": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-color-rgb": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-rgb/-/postcss-color-rgb-2.0.0.tgz", + "integrity": "sha1-FFOcinExSUtILg3RzCZf9lFLUmM=", + "dev": true, + "requires": { + "postcss": "^6.0.1", + "postcss-value-parser": "^3.3.0" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-color-rgba-fallback": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-rgba-fallback/-/postcss-color-rgba-fallback-3.0.0.tgz", + "integrity": "sha1-N9XJNToHoJJwkSqCYGu0Kg1wLAQ=", + "dev": true, + "requires": { + "postcss": "^6.0.6", + "postcss-value-parser": "^3.3.0", + "rgb-hex": "^2.1.0" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-colormin": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz", + "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==", + "requires": { + "browserslist": "^4.0.0", + "color": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/color/-/color-3.1.2.tgz", + "integrity": "sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg==", + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + } + } + } + }, + "postcss-convert-values": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz", + "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==", + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-cssnext": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-cssnext/-/postcss-cssnext-3.1.0.tgz", + "integrity": "sha512-awPDhI4OKetcHCr560iVCoDuP6e/vn0r6EAqdWPpAavJMvkBSZ6kDpSN4b3mB3Ti57hQMunHHM8Wvx9PeuYXtA==", + "dev": true, + "requires": { + "autoprefixer": "^7.1.1", + "caniuse-api": "^2.0.0", + "chalk": "^2.0.1", + "pixrem": "^4.0.0", + "pleeease-filters": "^4.0.0", + "postcss": "^6.0.5", + "postcss-apply": "^0.8.0", + "postcss-attribute-case-insensitive": "^2.0.0", + "postcss-calc": "^6.0.0", + "postcss-color-function": "^4.0.0", + "postcss-color-gray": "^4.0.0", + "postcss-color-hex-alpha": "^3.0.0", + "postcss-color-hsl": "^2.0.0", + "postcss-color-hwb": "^3.0.0", + "postcss-color-rebeccapurple": "^3.0.0", + "postcss-color-rgb": "^2.0.0", + "postcss-color-rgba-fallback": "^3.0.0", + "postcss-custom-media": "^6.0.0", + "postcss-custom-properties": "^6.1.0", + "postcss-custom-selectors": "^4.0.1", + "postcss-font-family-system-ui": "^3.0.0", + "postcss-font-variant": "^3.0.0", + "postcss-image-set-polyfill": "^0.3.5", + "postcss-initial": "^2.0.0", + "postcss-media-minmax": "^3.0.0", + "postcss-nesting": "^4.0.1", + "postcss-pseudo-class-any-link": "^4.0.0", + "postcss-pseudoelements": "^5.0.0", + "postcss-replace-overflow-wrap": "^2.0.0", + "postcss-selector-matches": "^3.0.1", + "postcss-selector-not": "^3.0.1" + }, + "dependencies": { + "browserslist": { + "version": "2.11.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", + "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000792", + "electron-to-chromium": "^1.3.30" + } + }, + "caniuse-api": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-2.0.0.tgz", + "integrity": "sha1-sd21pZZrFvSNxJmERNS7xsfZ2DQ=", + "dev": true, + "requires": { + "browserslist": "^2.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-custom-media": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-6.0.0.tgz", + "integrity": "sha1-vlMnhBEOyylQRPtTlaGABushpzc=", + "dev": true, + "requires": { + "postcss": "^6.0.1" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-custom-properties": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-6.3.1.tgz", + "integrity": "sha512-zoiwn4sCiUFbr4KcgcNZLFkR6gVQom647L+z1p/KBVHZ1OYwT87apnS42atJtx6XlX2yI7N5fjXbFixShQO2QQ==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "postcss": "^6.0.18" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-custom-selectors": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-4.0.1.tgz", + "integrity": "sha1-eBOC+UxS5yfvXKR3bqKt9JphE4I=", + "dev": true, + "requires": { + "postcss": "^6.0.1", + "postcss-selector-matches": "^3.0.0" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-dir-pseudo-class": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz", + "integrity": "sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw==", + "requires": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==" + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-discard-comments": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz", + "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==", + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-duplicates": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz", + "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==", + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-empty": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz", + "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==", + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-overridden": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz", + "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==", + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-double-position-gradients": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz", + "integrity": "sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA==", + "requires": { + "postcss": "^7.0.5", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-env-function": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-2.0.2.tgz", + "integrity": "sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw==", + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-flexbugs-fixes": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-4.2.1.tgz", + "integrity": "sha512-9SiofaZ9CWpQWxOwRh1b/r85KD5y7GgvsNt1056k6OYLvWUun0czCvogfJgylC22uJTwW1KzY3Gz65NZRlvoiQ==", + "requires": { + "postcss": "^7.0.26" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-focus-visible": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz", + "integrity": "sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g==", + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-focus-within": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz", + "integrity": "sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w==", + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-font-family-system-ui": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-family-system-ui/-/postcss-font-family-system-ui-3.0.0.tgz", + "integrity": "sha512-58G/hTxMSSKlIRpcPUjlyo6hV2MEzvcVO2m4L/T7Bb2fJTG4DYYfQjQeRvuimKQh1V1sOzCIz99g+H2aFNtlQw==", + "dev": true, + "requires": { + "postcss": "^6.0" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-font-variant": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-3.0.0.tgz", + "integrity": "sha1-CMzIj2BQuoLtjvLMdsDGprQfGD4=", + "dev": true, + "requires": { + "postcss": "^6.0.1" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-gap-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz", + "integrity": "sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg==", + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-image-set-function": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz", + "integrity": "sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw==", + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-image-set-polyfill": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/postcss-image-set-polyfill/-/postcss-image-set-polyfill-0.3.5.tgz", + "integrity": "sha1-Dxk0E3AM8fgr05Bm7wFtZaShgYE=", + "dev": true, + "requires": { + "postcss": "^6.0.1", + "postcss-media-query-parser": "^0.2.3" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-import": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-12.0.1.tgz", + "integrity": "sha512-3Gti33dmCjyKBgimqGxL3vcV8w9+bsHwO5UrBawp796+jdardbcFl4RP5w/76BwNL7aGzpKstIfF9I+kdE8pTw==", + "requires": { + "postcss": "^7.0.1", + "postcss-value-parser": "^3.2.3", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + } + }, + "postcss-initial": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-2.0.0.tgz", + "integrity": "sha1-cnFfczbgu3k1HZnuZcSiU6hEG6Q=", + "dev": true, + "requires": { + "lodash.template": "^4.2.4", + "postcss": "^6.0.1" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-lab-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz", + "integrity": "sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg==", + "requires": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-load-config": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.2.tgz", + "integrity": "sha512-/rDeGV6vMUo3mwJZmeHfEDvwnTKKqQ0S7OHUi/kJvvtx3aWtyWG2/0ZWnzCt2keEclwN6Tf0DST2v9kITdOKYw==", + "requires": { + "cosmiconfig": "^5.0.0", + "import-cwd": "^2.0.0" + }, + "dependencies": { + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + } + } + }, + "postcss-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", + "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", + "requires": { + "loader-utils": "^1.1.0", + "postcss": "^7.0.0", + "postcss-load-config": "^2.0.0", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "postcss-logical": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-3.0.0.tgz", + "integrity": "sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA==", + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-media-minmax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-3.0.0.tgz", + "integrity": "sha1-Z1JWA3pD70C8Twdgv9BtTcadSNI=", + "dev": true, + "requires": { + "postcss": "^6.0.1" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=", + "dev": true + }, + "postcss-merge-longhand": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", + "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==", + "requires": { + "css-color-names": "0.0.4", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "stylehacks": "^4.0.0" + } + }, + "postcss-merge-rules": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", + "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==", + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "cssnano-util-same-parent": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0", + "vendors": "^1.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-message-helpers": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz", + "integrity": "sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4=", + "dev": true + }, + "postcss-minify-font-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz", + "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==", + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-minify-gradients": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz", + "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==", + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "is-color-stop": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-minify-params": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz", + "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==", + "requires": { + "alphanum-sort": "^1.0.0", + "browserslist": "^4.0.0", + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "uniqs": "^2.0.0" + } + }, + "postcss-minify-selectors": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz", + "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==", + "requires": { + "alphanum-sort": "^1.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-modules-extract-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", + "requires": { + "postcss": "^7.0.5" + } + }, + "postcss-modules-local-by-default": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", + "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", + "requires": { + "icss-utils": "^4.1.1", + "postcss": "^7.0.32", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-value-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", + "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-modules-scope": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", + "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", + "requires": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" + } + }, + "postcss-modules-values": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", + "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", + "requires": { + "icss-utils": "^4.0.0", + "postcss": "^7.0.6" + } + }, + "postcss-nesting": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-4.2.1.tgz", + "integrity": "sha512-IkyWXICwagCnlaviRexi7qOdwPw3+xVVjgFfGsxmztvRVaNxAlrypOIKqDE5mxY+BVxnId1rnUKBRQoNE2VDaA==", + "dev": true, + "requires": { + "postcss": "^6.0.11" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-normalize-charset": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", + "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==", + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-normalize-display-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", + "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==", + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-positions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", + "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==", + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-repeat-style": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", + "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==", + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-string": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", + "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==", + "requires": { + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-timing-functions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", + "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==", + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-unicode": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", + "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", + "requires": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-url": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz", + "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==", + "requires": { + "is-absolute-url": "^2.0.0", + "normalize-url": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", + "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=" + }, + "normalize-url": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", + "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==" + } + } + }, + "postcss-normalize-whitespace": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz", + "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==", + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-ordered-values": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz", + "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==", + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-overflow-shorthand": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz", + "integrity": "sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g==", + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-page-break": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-2.0.0.tgz", + "integrity": "sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ==", + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-place": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-4.0.1.tgz", + "integrity": "sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg==", + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-preset-env": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz", + "integrity": "sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg==", + "requires": { + "autoprefixer": "^9.6.1", + "browserslist": "^4.6.4", + "caniuse-lite": "^1.0.30000981", + "css-blank-pseudo": "^0.1.4", + "css-has-pseudo": "^0.10.0", + "css-prefers-color-scheme": "^3.1.1", + "cssdb": "^4.4.0", + "postcss": "^7.0.17", + "postcss-attribute-case-insensitive": "^4.0.1", + "postcss-color-functional-notation": "^2.0.1", + "postcss-color-gray": "^5.0.0", + "postcss-color-hex-alpha": "^5.0.3", + "postcss-color-mod-function": "^3.0.3", + "postcss-color-rebeccapurple": "^4.0.1", + "postcss-custom-media": "^7.0.8", + "postcss-custom-properties": "^8.0.11", + "postcss-custom-selectors": "^5.1.2", + "postcss-dir-pseudo-class": "^5.0.0", + "postcss-double-position-gradients": "^1.0.0", + "postcss-env-function": "^2.0.2", + "postcss-focus-visible": "^4.0.0", + "postcss-focus-within": "^3.0.0", + "postcss-font-variant": "^4.0.0", + "postcss-gap-properties": "^2.0.0", + "postcss-image-set-function": "^3.0.1", + "postcss-initial": "^3.0.0", + "postcss-lab-function": "^2.0.1", + "postcss-logical": "^3.0.0", + "postcss-media-minmax": "^4.0.0", + "postcss-nesting": "^7.0.0", + "postcss-overflow-shorthand": "^2.0.0", + "postcss-page-break": "^2.0.0", + "postcss-place": "^4.0.1", + "postcss-pseudo-class-any-link": "^6.0.0", + "postcss-replace-overflow-wrap": "^3.0.0", + "postcss-selector-matches": "^4.0.0", + "postcss-selector-not": "^4.0.0" + }, + "dependencies": { + "autoprefixer": { + "version": "9.8.6", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.6.tgz", + "integrity": "sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==", + "requires": { + "browserslist": "^4.12.0", + "caniuse-lite": "^1.0.30001109", + "colorette": "^1.2.1", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^7.0.32", + "postcss-value-parser": "^4.1.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + } + } + }, + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==" + }, + "postcss-attribute-case-insensitive": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz", + "integrity": "sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA==", + "requires": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^6.0.2" + } + }, + "postcss-color-gray": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz", + "integrity": "sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw==", + "requires": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.5", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-color-hex-alpha": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz", + "integrity": "sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw==", + "requires": { + "postcss": "^7.0.14", + "postcss-values-parser": "^2.0.1" + } + }, + "postcss-color-rebeccapurple": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz", + "integrity": "sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g==", + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-custom-media": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz", + "integrity": "sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg==", + "requires": { + "postcss": "^7.0.14" + } + }, + "postcss-custom-properties": { + "version": "8.0.11", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz", + "integrity": "sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA==", + "requires": { + "postcss": "^7.0.17", + "postcss-values-parser": "^2.0.1" + } + }, + "postcss-custom-selectors": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz", + "integrity": "sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w==", + "requires": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-font-variant": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-4.0.0.tgz", + "integrity": "sha512-M8BFYKOvCrI2aITzDad7kWuXXTm0YhGdP9Q8HanmN4EF1Hmcgs1KK5rSHylt/lUJe8yLxiSwWAHdScoEiIxztg==", + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-initial": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-3.0.2.tgz", + "integrity": "sha512-ugA2wKonC0xeNHgirR4D3VWHs2JcU08WAi1KFLVcnb7IN89phID6Qtg2RIctWbnvp1TM2BOmDtX8GGLCKdR8YA==", + "requires": { + "lodash.template": "^4.5.0", + "postcss": "^7.0.2" + } + }, + "postcss-media-minmax": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz", + "integrity": "sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw==", + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-nesting": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-7.0.1.tgz", + "integrity": "sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg==", + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-pseudo-class-any-link": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz", + "integrity": "sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew==", + "requires": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-replace-overflow-wrap": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz", + "integrity": "sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw==", + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-selector-matches": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz", + "integrity": "sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww==", + "requires": { + "balanced-match": "^1.0.0", + "postcss": "^7.0.2" + } + }, + "postcss-selector-not": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-4.0.0.tgz", + "integrity": "sha512-W+bkBZRhqJaYN8XAnbbZPLWMvZD1wKTu0UxtFKdhtGjWYmxhkUneoeOhRJKdAE5V7ZTlnbHfCR+6bNwK9e1dTQ==", + "requires": { + "balanced-match": "^1.0.0", + "postcss": "^7.0.2" + } + }, + "postcss-value-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", + "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-pseudo-class-any-link": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-4.0.0.tgz", + "integrity": "sha1-kVKgYT00UHIFE+iJKFS65C0O5o4=", + "dev": true, + "requires": { + "postcss": "^6.0.1", + "postcss-selector-parser": "^2.2.3" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "postcss-selector-parser": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", + "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", + "dev": true, + "requires": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-pseudoelements": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-pseudoelements/-/postcss-pseudoelements-5.0.0.tgz", + "integrity": "sha1-7vGU6NUkZFylIKlJ6V5RjoEkAss=", + "dev": true, + "requires": { + "postcss": "^6.0.0" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-reduce-initial": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", + "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==", + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0" + } + }, + "postcss-reduce-transforms": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz", + "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==", + "requires": { + "cssnano-util-get-match": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-replace-overflow-wrap": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-2.0.0.tgz", + "integrity": "sha1-eU22+qVPjbEAhUOSqTr0V2i04ls=", + "dev": true, + "requires": { + "postcss": "^6.0.1" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-safe-parser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-4.0.2.tgz", + "integrity": "sha512-Uw6ekxSWNLCPesSv/cmqf2bY/77z11O7jZGPax3ycZMFU/oi2DMH9i89AdHc1tRwFg/arFoEwX0IS3LCUxJh1g==", + "requires": { + "postcss": "^7.0.26" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-selector-matches": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-matches/-/postcss-selector-matches-3.0.1.tgz", + "integrity": "sha1-5WNAEeE5UIgYYbvdWMLQER/8lqs=", + "dev": true, + "requires": { + "balanced-match": "^0.4.2", + "postcss": "^6.0.1" + }, + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", + "dev": true + }, + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-selector-not": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-3.0.1.tgz", + "integrity": "sha1-Lk2y8JZTNsAefOx9tsYN/3ZzNdk=", + "dev": true, + "requires": { + "balanced-match": "^0.4.2", + "postcss": "^6.0.1" + }, + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", + "dev": true + }, + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-selector-parser": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz", + "integrity": "sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw==", + "requires": { + "cssesc": "^3.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1", + "util-deprecate": "^1.0.2" + } + }, + "postcss-svgo": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz", + "integrity": "sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==", + "requires": { + "is-svg": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "svgo": "^1.0.0" + } + }, + "postcss-unique-selectors": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", + "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", + "requires": { + "alphanum-sort": "^1.0.0", + "postcss": "^7.0.0", + "uniqs": "^2.0.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "postcss-values-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", + "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", + "requires": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "dev": true, + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + }, + "query-string": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "requires": { + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" + }, + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, + "raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "requires": { + "performance-now": "^2.1.0" + } + }, + "raf-schd": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.2.tgz", + "integrity": "sha512-VhlMZmGy6A6hrkJWHLNTGl5gtgMUm+xfGza6wbwnE914yeQ5Ybm18vgM734RZhMgfw4tacUrWseGZlpUrrakEQ==" + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + } + } + }, + "rc-align": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/rc-align/-/rc-align-2.4.5.tgz", + "integrity": "sha512-nv9wYUYdfyfK+qskThf4BQUSIadeI/dCsfaMZfNEoxm9HwOIioQ+LyqmMK6jWHAZQgOzMLaqawhuBXlF63vgjw==", + "requires": { + "babel-runtime": "^6.26.0", + "dom-align": "^1.7.0", + "prop-types": "^15.5.8", + "rc-util": "^4.0.4" + } + }, + "rc-animate": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-2.11.1.tgz", + "integrity": "sha512-1NyuCGFJG/0Y+9RKh5y/i/AalUCA51opyyS/jO2seELpgymZm2u9QV3xwODwEuzkmeQ1BDPxMLmYLcTJedPlkQ==", + "requires": { + "babel-runtime": "6.x", + "classnames": "^2.2.6", + "css-animation": "^1.3.2", + "prop-types": "15.x", + "raf": "^3.4.0", + "rc-util": "^4.15.3", + "react-lifecycles-compat": "^3.0.4" + } + }, + "rc-slider": { + "version": "github:Galvanize-IT/slider#c569ca3b11979aced8306e6c02f37466cb7cd365", + "from": "github:Galvanize-IT/slider#c569ca3b11979aced8306e6c02f37466cb7cd365", + "requires": { + "babel-runtime": "6.x", + "classnames": "^2.2.5", + "gh-pages": "^2.0.1", + "prop-types": "^15.5.4", + "rc-tooltip": "^3.7.0", + "rc-util": "^4.0.4", + "shallowequal": "^1.0.1", + "warning": "^4.0.3" + } + }, + "rc-tooltip": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-3.7.3.tgz", + "integrity": "sha512-dE2ibukxxkrde7wH9W8ozHKUO4aQnPZ6qBHtrTH9LoO836PjDdiaWO73fgPB05VfJs9FbZdmGPVEbXCeOP99Ww==", + "requires": { + "babel-runtime": "6.x", + "prop-types": "^15.5.8", + "rc-trigger": "^2.2.2" + } + }, + "rc-trigger": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-2.6.5.tgz", + "integrity": "sha512-m6Cts9hLeZWsTvWnuMm7oElhf+03GOjOLfTuU0QmdB9ZrW7jR2IpI5rpNM7i9MvAAlMAmTx5Zr7g3uu/aMvZAw==", + "requires": { + "babel-runtime": "6.x", + "classnames": "^2.2.6", + "prop-types": "15.x", + "rc-align": "^2.4.0", + "rc-animate": "2.x", + "rc-util": "^4.4.0", + "react-lifecycles-compat": "^3.0.4" + } + }, + "rc-util": { + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-4.21.1.tgz", + "integrity": "sha512-Z+vlkSQVc1l8O2UjR3WQ+XdWlhj5q9BMQNLk2iOBch75CqPfrJyGtcWMcnhRlNuDu0Ndtt4kLVO8JI8BrABobg==", + "requires": { + "add-dom-event-listener": "^1.1.0", + "prop-types": "^15.5.10", + "react-is": "^16.12.0", + "react-lifecycles-compat": "^3.0.4", + "shallowequal": "^1.1.0" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } + } + }, + "react": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz", + "integrity": "sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2" + }, + "dependencies": { + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + } + } + }, + "react-addons-css-transition-group": { + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/react-addons-css-transition-group/-/react-addons-css-transition-group-15.6.2.tgz", + "integrity": "sha1-nkN2vPQLUhfRTsaFUwgc7ksIptY=", + "requires": { + "react-transition-group": "^1.2.0" + } + }, + "react-addons-test-utils": { + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/react-addons-test-utils/-/react-addons-test-utils-15.6.2.tgz", + "integrity": "sha1-wStu/cIkfBDae4dw0YUICnsEcVY=" + }, + "react-beautiful-dnd": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.0.0.tgz", + "integrity": "sha512-87It8sN0ineoC3nBW0SbQuTFXM6bUqM62uJGY4BtTf0yzPl8/3+bHMWkgIe0Z6m8e+gJgjWxefGRVfpE3VcdEg==", + "requires": { + "@babel/runtime": "^7.8.4", + "css-box-model": "^1.2.0", + "memoize-one": "^5.1.1", + "raf-schd": "^4.0.2", + "react-redux": "^7.1.1", + "redux": "^4.0.4", + "use-memo-one": "^1.1.1" + } + }, + "react-copy-to-clipboard": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.2.tgz", + "integrity": "sha512-/2t5mLMMPuN5GmdXo6TebFa8IoFxZ+KTDDqYhcDm0PhkgEzSxVvIX26G20s1EB02A4h2UZgwtfymZ3lGJm0OLg==", + "requires": { + "copy-to-clipboard": "^3", + "prop-types": "^15.5.8" + }, + "dependencies": { + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + } + } + }, + "react-datepicker": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-3.2.2.tgz", + "integrity": "sha512-/3D6hfhXcCNCbO8LICuQeoNDItWFyitGo+aLcsi0tAyJLtCInamYRwPIXhsEF+N6/qWim1yNyr71mqjj4YEBmg==", + "requires": { + "classnames": "^2.2.6", + "date-fns": "^2.0.1", + "prop-types": "^15.7.2", + "react-onclickoutside": "^6.9.0", + "react-popper": "^1.3.4" + }, + "dependencies": { + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + } + } + }, + "react-dom": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.13.1.tgz", + "integrity": "sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.19.1" + }, + "dependencies": { + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + } + } + }, + "react-is": { + "version": "16.9.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.9.0.tgz", + "integrity": "sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw==" + }, + "react-json-pretty": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/react-json-pretty/-/react-json-pretty-2.2.0.tgz", + "integrity": "sha512-3UMzlAXkJ4R8S4vmkRKtvJHTewG4/rn1Q18n0zqdu/ipZbUPLVZD+QwC7uVcD/IAY3s8iNVHlgR2dMzIUS0n1A==", + "requires": { + "prop-types": "^15.6.2" + }, + "dependencies": { + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + } + } + }, + "react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "react-onclickoutside": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.9.0.tgz", + "integrity": "sha512-8ltIY3bC7oGhj2nPAvWOGi+xGFybPNhJM0V1H8hY/whNcXgmDeaeoCMPPd8VatrpTsUWjb/vGzrmu6SrXVty3A==" + }, + "react-paginate": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/react-paginate/-/react-paginate-6.5.0.tgz", + "integrity": "sha512-H7xSi9jyiJzgfaj+2nNhQcjZfwzJ/Mxb64V2RiyDctjZyCWojwsaGwMqhLBpQ58iAuMVtBMRQ7ECqMcUKG9QSQ==", + "requires": { + "prop-types": "^15.6.1" + }, + "dependencies": { + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + } + } + }, + "react-pdf": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/react-pdf/-/react-pdf-4.2.0.tgz", + "integrity": "sha512-Ao44mZszfPwtCUsrXHtXnhM+czTvPxfG5wqssbWgj2onL70TKSOKGzQfCH4csCnNDOKji/Pc/s0Og70/VOE+Rg==", + "requires": { + "@babel/runtime": "^7.0.0", + "make-cancellable-promise": "^1.0.0", + "make-event-props": "^1.1.0", + "merge-class-names": "^1.1.1", + "pdfjs-dist": "2.1.266", + "prop-types": "^15.6.2" + } + }, + "react-popper": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.7.tgz", + "integrity": "sha512-nmqYTx7QVjCm3WUZLeuOomna138R1luC4EqkW3hxJUrAe+3eNz3oFCLYdnPwILfn0mX1Ew2c3wctrjlUMYYUww==", + "requires": { + "@babel/runtime": "^7.1.2", + "create-react-context": "^0.3.0", + "deep-equal": "^1.1.1", + "popper.js": "^1.14.4", + "prop-types": "^15.6.1", + "typed-styles": "^0.0.7", + "warning": "^4.0.2" + }, + "dependencies": { + "deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "requires": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + } + }, + "popper.js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==" + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + } + } + }, + "react-redux": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.1.tgz", + "integrity": "sha512-T+VfD/bvgGTUA74iW9d2i5THrDQWbweXP0AVNI8tNd1Rk5ch1rnMiJkDD67ejw7YBKM4+REvcvqRuWJb7BLuEg==", + "requires": { + "@babel/runtime": "^7.5.5", + "hoist-non-react-statics": "^3.3.0", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^16.9.0" + }, + "dependencies": { + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + } + } + }, + "react-scroll-sync": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/react-scroll-sync/-/react-scroll-sync-0.8.0.tgz", + "integrity": "sha512-Ms9srm41UM+lWexuqdocXjqaqqt6ZRSFxcudgB0sYhC7Or+m12WemTwY8BaQCRf7hA8zHDk55FHvMkqsH7gF+w==" + }, + "react-textarea-autosize": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.2.0.tgz", + "integrity": "sha512-grajUlVbkx6VdtSxCgzloUIphIZF5bKr21OYMceWPKkniy7H0mRAT/AXPrRtObAe+zUePnNlBwUc4ivVjUGIjw==", + "requires": { + "@babel/runtime": "^7.10.2", + "use-composed-ref": "^1.0.0", + "use-latest": "^1.0.0" + } + }, + "react-tools": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/react-tools/-/react-tools-0.13.3.tgz", + "integrity": "sha1-2mrH1Nd3elml6VHPRucv1La0Ciw=", + "requires": { + "commoner": "^0.10.0", + "jstransform": "^10.1.0" + } + }, + "react-tooltip": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-4.2.10.tgz", + "integrity": "sha512-D7ZLx6/QwpUl0SZRek3IZy/HWpsEEp0v3562tcT8IwZgu8IgV7hY5ZzniTkHyRcuL+IQnljpjj7A7zCgl2+T3w==", + "requires": { + "prop-types": "^15.7.2", + "uuid": "^7.0.3" + }, + "dependencies": { + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==" + } + } + }, + "react-transition-group": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-1.2.1.tgz", + "integrity": "sha512-CWaL3laCmgAFdxdKbhhps+c0HRGF4c+hdM4H23+FI1QBNUyx/AMeIJGWorehPNSaKnQNOAxL7PQmqMu78CDj3Q==", + "requires": { + "chain-function": "^1.0.0", + "dom-helpers": "^3.2.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.5.6", + "warning": "^3.0.0" + }, + "dependencies": { + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", + "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", + "requires": { + "loose-envify": "^1.0.0" + } + } + } + }, + "react_ujs": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/react_ujs/-/react_ujs-2.6.1.tgz", + "integrity": "sha512-9M33/A8cubStkZ2cpJSimcTD0RlCWiqXF6e90IQmMw/Caf/W0dtAzOtHtiQE3JjLbt/nhRR7NLPxMfnlm141ig==", + "requires": { + "react_ujs": "^2.6.0" + } + }, + "reactify": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/reactify/-/reactify-1.1.1.tgz", + "integrity": "sha1-qPEZWWJzwNS/savqDBTCYB6gO7o=", + "requires": { + "react-tools": "~0.13.0", + "through": "~2.3.4" + } + }, + "read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", + "requires": { + "pify": "^2.3.0" + } + }, + "read-only-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", + "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", + "requires": { + "readable-stream": "^2.0.2" + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "recast": { + "version": "0.11.23", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz", + "integrity": "sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=", + "requires": { + "ast-types": "0.9.6", + "esprima": "~3.1.0", + "private": "~0.1.5", + "source-map": "~0.5.0" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + }, + "dependencies": { + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "requires": { + "repeating": "^2.0.0" + } + } + } + }, + "reduce-css-calc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", + "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", + "dev": true, + "requires": { + "balanced-match": "^0.4.2", + "math-expression-evaluator": "^1.2.14", + "reduce-function-call": "^1.0.1" + }, + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", + "dev": true + } + } + }, + "reduce-function-call": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.3.tgz", + "integrity": "sha512-Hl/tuV2VDgWgCSEeWMLwxLZqX7OK59eU1guxXsRKTAyeYimivsKdtcV4fu3r710tpG5GmDKDhQ0HSZLExnNmyQ==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "redux": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz", + "integrity": "sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==", + "requires": { + "loose-envify": "^1.4.0", + "symbol-observable": "^1.2.0" + } + }, + "regenerate": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", + "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==" + }, + "regenerate-unicode-properties": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", + "requires": { + "regenerate": "^1.4.0" + } + }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" + }, + "regenerator-transform": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "requires": { + "@babel/runtime": "^7.8.4" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexp.prototype.flags": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "requires": { + "has-symbols": "^1.0.1" + } + } + } + }, + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true + }, + "regexpu-core": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", + "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==", + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.2.0", + "regjsgen": "^0.5.1", + "regjsparser": "^0.6.4", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.2.0" + } + }, + "regjsgen": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==" + }, + "regjsparser": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", + "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" + } + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "requires": { + "is-finite": "^1.0.0" + } + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + } + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "dependencies": { + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + } + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "dev": true + }, + "rgb": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/rgb/-/rgb-0.1.0.tgz", + "integrity": "sha1-vieykej+/+rBvZlylyG/pA/AN7U=", + "dev": true + }, + "rgb-hex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/rgb-hex/-/rgb-hex-2.1.0.tgz", + "integrity": "sha1-x3PF/iJoolV42SU5qCp6XOU77aY=", + "dev": true + }, + "rgb-regex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", + "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=" + }, + "rgba-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", + "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=" + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "requires": { + "aproba": "^1.1.1" + } + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sass-graph": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.5.tgz", + "integrity": "sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag==", + "requires": { + "glob": "^7.0.0", + "lodash": "^4.0.0", + "scss-tokenizer": "^0.2.3", + "yargs": "^13.3.2" + } + }, + "sass-loader": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-8.0.2.tgz", + "integrity": "sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ==", + "requires": { + "clone-deep": "^4.0.1", + "loader-utils": "^1.2.3", + "neo-async": "^2.6.1", + "schema-utils": "^2.6.1", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "scheduler": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", + "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + }, + "scss-tokenizer": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", + "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", + "requires": { + "js-base64": "^2.1.8", + "source-map": "^0.4.2" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", + "dev": true + }, + "selfsigned": { + "version": "1.10.8", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.8.tgz", + "integrity": "sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w==", + "dev": true, + "requires": { + "node-forge": "^0.10.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "requires": { + "randombytes": "^2.1.0" + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "requires": { + "kind-of": "^6.0.2" + } + }, + "shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, + "shasum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", + "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", + "requires": { + "json-stable-stringify": "~0.0.0", + "sha.js": "~2.4.4" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "shell-quote": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.1.tgz", + "integrity": "sha512-2kUqeAGnMAu6YrTPX4E3LfxacH9gKljzVjlkUeSqY0soGwK4KLl7TURXCem712tkhBCeeaFP9QK4dKn88s3Icg==" + }, + "side-channel": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.3.tgz", + "integrity": "sha512-A6+ByhlLkksFoUepsGxfj5x1gTSrs+OydsRptUxeNCabQpCFUvcwIczgOigI8vhY/OJCnPnyE9rGiwgvr9cS1g==", + "dev": true, + "requires": { + "es-abstract": "^1.18.0-next.0", + "object-inspect": "^1.8.0" + } + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + } + } + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "sockjs": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.20.tgz", + "integrity": "sha512-SpmVOVpdq0DJc0qArhF3E5xsxvaiqGNb73XfgBpK1y3UD5gs8DSo8aCTsuT5pX8rssdc2NDIzANwP9eCAiSdTA==", + "dev": true, + "requires": { + "faye-websocket": "^0.10.0", + "uuid": "^3.4.0", + "websocket-driver": "0.6.5" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } + } + }, + "sockjs-client": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.4.0.tgz", + "integrity": "sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g==", + "dev": true, + "requires": { + "debug": "^3.2.5", + "eventsource": "^1.0.7", + "faye-websocket": "~0.11.1", + "inherits": "^2.0.3", + "json3": "^3.3.2", + "url-parse": "^1.4.3" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "faye-websocket": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", + "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + } + } + }, + "sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "requires": { + "is-plain-obj": "^1.0.0" + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", + "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==" + }, + "spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + } + } + }, + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.0.tgz", + "integrity": "sha512-aq/pz989nxVYwn16Tsbj1TqFpD5LLrQxHf5zaHuieFV+R0Bbr4y8qUsOA45hXT/N4/9UNXTarBjnjVmjSOVaAA==", + "requires": { + "minipass": "^3.1.1" + } + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==" + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "stdout-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", + "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", + "requires": { + "readable-stream": "^2.0.1" + } + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", + "requires": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-http": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.1.1.tgz", + "integrity": "sha512-S7OqaYu0EkFpgeGFb/NPOoPLxFko7TPqtEeFg5DXPB4v/KETHG0Ln6fRFrNezoelpaDKmycEmmZ81cC9DAwgYg==", + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "stream-splicer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz", + "integrity": "sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.2" + } + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "string.prototype.matchall": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz", + "integrity": "sha512-N/jp6O5fMf9os0JU3E72Qhf590RSRZU/ungsL/qJUYVTNv7hTG0P/dbPjxINVN9jpscu3nzYwKESU3P3RY5tOg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "has-symbols": "^1.0.1", + "internal-slot": "^1.0.2", + "regexp.prototype.flags": "^1.3.0", + "side-channel": "^1.0.2" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + } + } + }, + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "requires": { + "has-symbols": "^1.0.1" + } + } + } + }, + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "requires": { + "has-symbols": "^1.0.1" + } + } + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "requires": { + "get-stdin": "^4.0.1" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, + "strip-url-auth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-url-auth/-/strip-url-auth-1.0.1.tgz", + "integrity": "sha1-IrD6OkE4WzO+PzMVUbu4N/oM164=" + }, + "style-loader": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz", + "integrity": "sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==", + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^2.7.0" + }, + "dependencies": { + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "requires": { + "minimist": "^1.2.5" + } + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + } + } + }, + "stylehacks": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", + "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==", + "requires": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", + "requires": { + "minimist": "^1.1.0" + } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "requires": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + } + }, + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" + }, + "syntax-error": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", + "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", + "requires": { + "acorn-node": "^1.2.0" + } + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" + }, + "tar": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.0.5.tgz", + "integrity": "sha512-0b4HOimQHj9nXNEAA7zWwMM91Zhhba3pspja6sQbgTpynOJf+bkjBnfybNYzbpLbnwXnbyB4LOREvlyXLkCHSg==", + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + } + } + }, + "terser": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.3.4.tgz", + "integrity": "sha512-dxuB8KQo8Gt6OVOeLg/rxfcxdNZI/V1G6ze1czFUzPeCFWZRtvZMgSzlZZ5OYBZ4HoG607F6pFPNLekJyV+yVw==", + "requires": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + }, + "dependencies": { + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" + } + } + }, + "terser-webpack-plugin": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-4.2.2.tgz", + "integrity": "sha512-3qAQpykRTD5DReLu5/cwpsg7EZFzP3Q0Hp2XUWJUw2mpq2jfgOKTZr8IZKKnNieRVVo1UauROTdhbQJZveGKtQ==", + "requires": { + "cacache": "^15.0.5", + "find-cache-dir": "^3.3.1", + "jest-worker": "^26.3.0", + "p-limit": "^3.0.2", + "schema-utils": "^2.7.1", + "serialize-javascript": "^5.0.1", + "source-map": "^0.6.1", + "terser": "^5.3.2", + "webpack-sources": "^1.4.3" + }, + "dependencies": { + "find-cache-dir": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", + "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + } + }, + "p-limit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", + "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + }, + "dependencies": { + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + } + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "requires": { + "find-up": "^4.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + }, + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "requires": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "timers-browserify": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", + "requires": { + "process": "~0.11.0" + } + }, + "timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" + }, + "tiny-invariant": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", + "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha1-bkWxJj8gF/oKzH2J14sVuL932jI=" + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + } + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" + }, + "trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, + "true-case-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", + "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", + "requires": { + "glob": "^7.1.2" + } + }, + "ts-essentials": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-2.0.12.tgz", + "integrity": "sha512-3IVX4nI6B5cc31/GFFE+i8ey/N2eA0CZDbo6n0yrz0zDX8ZJ8djmU1p+XRz7G3is0F3bB3pu2pAroFdAWQKU3w==" + }, + "ts-loader": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-8.0.4.tgz", + "integrity": "sha512-5u8KF1SW8eCUb/Ff7At81e3wznPmT/27fvaGRO9CziVy+6NlPVRvrzSox4OwU0/e6OflOUB32Err4VquysCSAQ==", + "requires": { + "chalk": "^2.3.0", + "enhanced-resolve": "^4.0.0", + "loader-utils": "^1.0.2", + "micromatch": "^4.0.0", + "semver": "^6.0.0" + }, + "dependencies": { + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" + } + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "ts-pnp": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz", + "integrity": "sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==" + }, + "tsconfig-paths": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", + "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, + "tslib": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.0.tgz", + "integrity": "sha512-+Zw5lu0D9tvBMjGP8LpvMb0u2WW2QV3y+D8mO6J+cNzCYIN4sVy43Bf9vl92nqFahutN0I8zHa7cc4vihIshnw==" + }, + "tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typed-styles": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/typed-styles/-/typed-styles-0.0.7.tgz", + "integrity": "sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q==" + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "typescript": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.3.tgz", + "integrity": "sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg==" + }, + "umd": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", + "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==" + }, + "undeclared-identifiers": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz", + "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==", + "requires": { + "acorn-node": "^1.3.0", + "dash-ast": "^1.0.0", + "get-assigned-identifiers": "^1.2.0", + "simple-concat": "^1.0.0", + "xtend": "^4.0.1" + } + }, + "unfetch": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz", + "integrity": "sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==" + }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==" + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==" + }, + "unicode-property-aliases-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", + "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==" + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" + }, + "uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=" + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "units-css": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/units-css/-/units-css-0.4.0.tgz", + "integrity": "sha1-1iKGU6UZg9fBb/KPi53Dsf/tOgc=", + "dev": true, + "requires": { + "isnumeric": "^0.2.0", + "viewport-dimensions": "^0.2.0" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=" + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + } + } + }, + "url-parse": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", + "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", + "dev": true, + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + }, + "use-composed-ref": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.0.0.tgz", + "integrity": "sha512-RVqY3NFNjZa0xrmK3bIMWNmQ01QjKPDc7DeWR3xa/N8aliVppuutOE5bZzPkQfvL+5NRWMMp0DJ99Trd974FIw==", + "requires": { + "ts-essentials": "^2.0.3" + } + }, + "use-isomorphic-layout-effect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.0.0.tgz", + "integrity": "sha512-JMwJ7Vd86NwAt1jH7q+OIozZSIxA4ND0fx6AsOe2q1H8ooBUp5aN6DvVCqZiIaYU6JaMRJGyR0FO7EBCIsb/Rg==" + }, + "use-latest": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.1.0.tgz", + "integrity": "sha512-gF04d0ZMV3AMB8Q7HtfkAWe+oq1tFXP6dZKwBHQF5nVXtGsh2oAYeeqma5ZzxtlpOcW8Ro/tLcfmEodjDeqtuw==", + "requires": { + "use-isomorphic-layout-effect": "^1.0.0" + } + }, + "use-memo-one": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.1.tgz", + "integrity": "sha512-oFfsyun+bP7RX8X2AskHNTxu+R3QdE/RC5IefMbqptmACAA/gfol1KDD5KRzPsGMa62sWxGZw+Ui43u6x4ddoQ==" + }, + "util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "requires": { + "has-symbols": "^1.0.1" + } + } + } + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "uuid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" + }, + "v8-compile-cache": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", + "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==" + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, + "vendors": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", + "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "viewport-dimensions": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/viewport-dimensions/-/viewport-dimensions-0.2.0.tgz", + "integrity": "sha1-3nQHR9tTh/0XJfUXXpG6x2r982w=", + "dev": true + }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" + }, + "warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "watchpack": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz", + "integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==", + "requires": { + "chokidar": "^3.4.1", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.0" + }, + "dependencies": { + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "optional": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "optional": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "optional": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chokidar": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", + "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", + "optional": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.4.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "optional": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "optional": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "optional": true + }, + "readdirp": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", + "optional": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "optional": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "watchpack-chokidar2": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz", + "integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==", + "optional": true, + "requires": { + "chokidar": "^2.1.8" + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, + "weakmap-polyfill": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/weakmap-polyfill/-/weakmap-polyfill-2.0.1.tgz", + "integrity": "sha512-Jy177Lvb1LCrPQDWJsXyyqf4eOhcdvQHFGoCqSv921kVF5i42MVbr4e2WEwetuTLBn1NX0IhPzTmMu0N3cURqQ==" + }, + "webpack": { + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz", + "integrity": "sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.3.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==" + }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + } + } + }, + "webpack-assets-manifest": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/webpack-assets-manifest/-/webpack-assets-manifest-3.1.1.tgz", + "integrity": "sha512-JV9V2QKc5wEWQptdIjvXDUL1ucbPLH2f27toAY3SNdGZp+xSaStAgpoMcvMZmqtFrBc9a5pTS1058vxyMPOzRQ==", + "requires": { + "chalk": "^2.0", + "lodash.get": "^4.0", + "lodash.has": "^4.0", + "mkdirp": "^0.5", + "schema-utils": "^1.0.0", + "tapable": "^1.0.0", + "webpack-sources": "^1.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "webpack-cli": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.12.tgz", + "integrity": "sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag==", + "requires": { + "chalk": "^2.4.2", + "cross-spawn": "^6.0.5", + "enhanced-resolve": "^4.1.1", + "findup-sync": "^3.0.0", + "global-modules": "^2.0.0", + "import-local": "^2.0.0", + "interpret": "^1.4.0", + "loader-utils": "^1.4.0", + "supports-color": "^6.1.0", + "v8-compile-cache": "^2.1.1", + "yargs": "^13.3.2" + } + }, + "webpack-dev-middleware": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz", + "integrity": "sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==", + "dev": true, + "requires": { + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + }, + "dependencies": { + "mime": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", + "dev": true + } + } + }, + "webpack-dev-server": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.0.tgz", + "integrity": "sha512-PUxZ+oSTxogFQgkTtFndEtJIPNmml7ExwufBZ9L2/Xyyd5PnOL5UreWe5ZT7IU25DSdykL9p1MLQzmLh2ljSeg==", + "dev": true, + "requires": { + "ansi-html": "0.0.7", + "bonjour": "^3.5.0", + "chokidar": "^2.1.8", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "debug": "^4.1.1", + "del": "^4.1.1", + "express": "^4.17.1", + "html-entities": "^1.3.1", + "http-proxy-middleware": "0.19.1", + "import-local": "^2.0.0", + "internal-ip": "^4.3.0", + "ip": "^1.1.5", + "is-absolute-url": "^3.0.3", + "killable": "^1.0.1", + "loglevel": "^1.6.8", + "opn": "^5.5.0", + "p-retry": "^3.0.1", + "portfinder": "^1.0.26", + "schema-utils": "^1.0.0", + "selfsigned": "^1.10.7", + "semver": "^6.3.0", + "serve-index": "^1.9.1", + "sockjs": "0.3.20", + "sockjs-client": "1.4.0", + "spdy": "^4.0.2", + "strip-ansi": "^3.0.1", + "supports-color": "^6.1.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^3.7.2", + "webpack-log": "^2.0.0", + "ws": "^6.2.1", + "yargs": "^13.3.2" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "websocket-driver": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz", + "integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=", + "dev": true, + "requires": { + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "requires": { + "string-width": "^1.0.2 || 2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "requires": { + "errno": "~0.1.7" + } + }, + "worker-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-2.0.0.tgz", + "integrity": "sha512-tnvNp4K3KQOpfRnD20m8xltE3eWh89Ye+5oj7wXEEHKac1P4oZ6p9oTj8/8ExqoSBnk9nu5Pr4nKfQ1hn2APJw==", + "requires": { + "loader-utils": "^1.0.0", + "schema-utils": "^0.4.0" + }, + "dependencies": { + "schema-utils": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", + "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==", + "requires": { + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "yaml": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", + "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==" + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + } + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } +} diff --git a/package.json b/package.json index 7db9399..6b46e51 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "react-dom": "^16.13.1", "react-json-pretty": "^2.2.0", "react-paginate": "^6.5.0", - "react-pdf": "^5.0.0", + "react-pdf": "^4.2.0", "react-scroll-sync": "^0.8.0", "react-textarea-autosize": "^8.2.0", "react-tooltip": "^4.2.10", -- GitLab From ed28d0215ba24602b2cc2f37fe39459ee586d0c9 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Wed, 7 Oct 2020 17:43:51 -1000 Subject: [PATCH 138/283] removing old files. removing package lock file. updating yarn lock file --- babelrc.sav | 18 - package-lock.json | 14172 -------------------------------------------- package.json.sav | 83 - yarn.lock | 65 +- 4 files changed, 40 insertions(+), 14298 deletions(-) delete mode 100644 babelrc.sav delete mode 100644 package-lock.json delete mode 100644 package.json.sav diff --git a/babelrc.sav b/babelrc.sav deleted file mode 100644 index ded31c0..0000000 --- a/babelrc.sav +++ /dev/null @@ -1,18 +0,0 @@ -{ - "presets": [ - ["env", { - "modules": false, - "targets": { - "browsers": "> 1%", - "uglify": true - }, - "useBuiltIns": true - }] - ], - - "plugins": [ - "syntax-dynamic-import", - "transform-object-rest-spread", - ["transform-class-properties", { "spec": true }] - ] -} diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 382cf49..0000000 --- a/package-lock.json +++ /dev/null @@ -1,14172 +0,0 @@ -{ - "name": "forge", - "version": "1.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/compat-data": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.11.0.tgz", - "integrity": "sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ==", - "requires": { - "browserslist": "^4.12.0", - "invariant": "^2.2.4", - "semver": "^5.5.0" - } - }, - "@babel/core": { - "version": "7.11.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.6.tgz", - "integrity": "sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg==", - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.6", - "@babel/helper-module-transforms": "^7.11.0", - "@babel/helpers": "^7.10.4", - "@babel/parser": "^7.11.5", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.11.5", - "@babel/types": "^7.11.5", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.2", - "lodash": "^4.17.19", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "requires": { - "ms": "2.1.2" - } - }, - "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", - "requires": { - "minimist": "^1.2.5" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - } - } - }, - "@babel/generator": { - "version": "7.11.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz", - "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==", - "requires": { - "@babel/types": "^7.11.5", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz", - "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==", - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz", - "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==", - "requires": { - "@babel/helper-explode-assignable-expression": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-compilation-targets": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz", - "integrity": "sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ==", - "requires": { - "@babel/compat-data": "^7.10.4", - "browserslist": "^4.12.0", - "invariant": "^2.2.4", - "levenary": "^1.1.1", - "semver": "^5.5.0" - } - }, - "@babel/helper-create-class-features-plugin": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz", - "integrity": "sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A==", - "requires": { - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-member-expression-to-functions": "^7.10.5", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-replace-supers": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.10.4" - } - }, - "@babel/helper-create-regexp-features-plugin": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz", - "integrity": "sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-regex": "^7.10.4", - "regexpu-core": "^4.7.0" - } - }, - "@babel/helper-define-map": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz", - "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==", - "requires": { - "@babel/helper-function-name": "^7.10.4", - "@babel/types": "^7.10.5", - "lodash": "^4.17.19" - } - }, - "@babel/helper-explode-assignable-expression": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.11.4.tgz", - "integrity": "sha512-ux9hm3zR4WV1Y3xXxXkdG/0gxF9nvI0YVmKVhvK9AfMoaQkemL3sJpXw+Xbz65azo8qJiEz2XVDUpK3KYhH3ZQ==", - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-function-name": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", - "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", - "requires": { - "@babel/helper-get-function-arity": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", - "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz", - "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==", - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz", - "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==", - "requires": { - "@babel/types": "^7.11.0" - } - }, - "@babel/helper-module-imports": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz", - "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==", - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-module-transforms": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz", - "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==", - "requires": { - "@babel/helper-module-imports": "^7.10.4", - "@babel/helper-replace-supers": "^7.10.4", - "@babel/helper-simple-access": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/template": "^7.10.4", - "@babel/types": "^7.11.0", - "lodash": "^4.17.19" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", - "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", - "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" - }, - "@babel/helper-regex": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz", - "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==", - "requires": { - "lodash": "^4.17.19" - } - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.11.4.tgz", - "integrity": "sha512-tR5vJ/vBa9wFy3m5LLv2faapJLnDFxNWff2SAYkSE4rLUdbp7CdObYFgI7wK4T/Mj4UzpjPwzR8Pzmr5m7MHGA==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-wrap-function": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-replace-supers": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz", - "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==", - "requires": { - "@babel/helper-member-expression-to-functions": "^7.10.4", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/traverse": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-simple-access": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz", - "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==", - "requires": { - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz", - "integrity": "sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q==", - "requires": { - "@babel/types": "^7.11.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", - "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", - "requires": { - "@babel/types": "^7.11.0" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==" - }, - "@babel/helper-wrap-function": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz", - "integrity": "sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug==", - "requires": { - "@babel/helper-function-name": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helpers": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz", - "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==", - "requires": { - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", - "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==" - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz", - "integrity": "sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-remap-async-to-generator": "^7.10.4", - "@babel/plugin-syntax-async-generators": "^7.8.0" - } - }, - "@babel/plugin-proposal-class-properties": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz", - "integrity": "sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg==", - "requires": { - "@babel/helper-create-class-features-plugin": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-proposal-dynamic-import": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz", - "integrity": "sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-dynamic-import": "^7.8.0" - } - }, - "@babel/plugin-proposal-export-namespace-from": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz", - "integrity": "sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - } - }, - "@babel/plugin-proposal-json-strings": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz", - "integrity": "sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.0" - } - }, - "@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz", - "integrity": "sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - } - }, - "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz", - "integrity": "sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" - } - }, - "@babel/plugin-proposal-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz", - "integrity": "sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - } - }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz", - "integrity": "sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0", - "@babel/plugin-transform-parameters": "^7.10.4" - } - }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz", - "integrity": "sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" - } - }, - "@babel/plugin-proposal-optional-chaining": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz", - "integrity": "sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.0" - } - }, - "@babel/plugin-proposal-private-methods": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz", - "integrity": "sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw==", - "requires": { - "@babel/helper-create-class-features-plugin": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz", - "integrity": "sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA==", - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz", - "integrity": "sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz", - "integrity": "sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz", - "integrity": "sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz", - "integrity": "sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ==", - "requires": { - "@babel/helper-module-imports": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-remap-async-to-generator": "^7.10.4" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz", - "integrity": "sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.11.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz", - "integrity": "sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-classes": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz", - "integrity": "sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-define-map": "^7.10.4", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-replace-supers": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.10.4", - "globals": "^11.1.0" - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz", - "integrity": "sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz", - "integrity": "sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz", - "integrity": "sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA==", - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz", - "integrity": "sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz", - "integrity": "sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw==", - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz", - "integrity": "sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz", - "integrity": "sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg==", - "requires": { - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-literals": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz", - "integrity": "sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-member-expression-literals": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz", - "integrity": "sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz", - "integrity": "sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw==", - "requires": { - "@babel/helper-module-transforms": "^7.10.5", - "@babel/helper-plugin-utils": "^7.10.4", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz", - "integrity": "sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w==", - "requires": { - "@babel/helper-module-transforms": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-simple-access": "^7.10.4", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz", - "integrity": "sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw==", - "requires": { - "@babel/helper-hoist-variables": "^7.10.4", - "@babel/helper-module-transforms": "^7.10.5", - "@babel/helper-plugin-utils": "^7.10.4", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz", - "integrity": "sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA==", - "requires": { - "@babel/helper-module-transforms": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz", - "integrity": "sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA==", - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.10.4" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz", - "integrity": "sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz", - "integrity": "sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-replace-supers": "^7.10.4" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz", - "integrity": "sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw==", - "requires": { - "@babel/helper-get-function-arity": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-property-literals": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz", - "integrity": "sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz", - "integrity": "sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw==", - "requires": { - "regenerator-transform": "^0.14.2" - } - }, - "@babel/plugin-transform-reserved-words": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz", - "integrity": "sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-runtime": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.11.5.tgz", - "integrity": "sha512-9aIoee+EhjySZ6vY5hnLjigHzunBlscx9ANKutkeWTJTx6m5Rbq6Ic01tLvO54lSusR+BxV7u4UDdCmXv5aagg==", - "requires": { - "@babel/helper-module-imports": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4", - "resolve": "^1.8.1", - "semver": "^5.5.1" - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz", - "integrity": "sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz", - "integrity": "sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz", - "integrity": "sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-regex": "^7.10.4" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz", - "integrity": "sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz", - "integrity": "sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-unicode-escapes": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz", - "integrity": "sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz", - "integrity": "sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A==", - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/preset-env": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.11.5.tgz", - "integrity": "sha512-kXqmW1jVcnB2cdueV+fyBM8estd5mlNfaQi6lwLgRwCby4edpavgbFhiBNjmWA3JpB/yZGSISa7Srf+TwxDQoA==", - "requires": { - "@babel/compat-data": "^7.11.0", - "@babel/helper-compilation-targets": "^7.10.4", - "@babel/helper-module-imports": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-proposal-async-generator-functions": "^7.10.4", - "@babel/plugin-proposal-class-properties": "^7.10.4", - "@babel/plugin-proposal-dynamic-import": "^7.10.4", - "@babel/plugin-proposal-export-namespace-from": "^7.10.4", - "@babel/plugin-proposal-json-strings": "^7.10.4", - "@babel/plugin-proposal-logical-assignment-operators": "^7.11.0", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4", - "@babel/plugin-proposal-numeric-separator": "^7.10.4", - "@babel/plugin-proposal-object-rest-spread": "^7.11.0", - "@babel/plugin-proposal-optional-catch-binding": "^7.10.4", - "@babel/plugin-proposal-optional-chaining": "^7.11.0", - "@babel/plugin-proposal-private-methods": "^7.10.4", - "@babel/plugin-proposal-unicode-property-regex": "^7.10.4", - "@babel/plugin-syntax-async-generators": "^7.8.0", - "@babel/plugin-syntax-class-properties": "^7.10.4", - "@babel/plugin-syntax-dynamic-import": "^7.8.0", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.0", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.0", - "@babel/plugin-syntax-top-level-await": "^7.10.4", - "@babel/plugin-transform-arrow-functions": "^7.10.4", - "@babel/plugin-transform-async-to-generator": "^7.10.4", - "@babel/plugin-transform-block-scoped-functions": "^7.10.4", - "@babel/plugin-transform-block-scoping": "^7.10.4", - "@babel/plugin-transform-classes": "^7.10.4", - "@babel/plugin-transform-computed-properties": "^7.10.4", - "@babel/plugin-transform-destructuring": "^7.10.4", - "@babel/plugin-transform-dotall-regex": "^7.10.4", - "@babel/plugin-transform-duplicate-keys": "^7.10.4", - "@babel/plugin-transform-exponentiation-operator": "^7.10.4", - "@babel/plugin-transform-for-of": "^7.10.4", - "@babel/plugin-transform-function-name": "^7.10.4", - "@babel/plugin-transform-literals": "^7.10.4", - "@babel/plugin-transform-member-expression-literals": "^7.10.4", - "@babel/plugin-transform-modules-amd": "^7.10.4", - "@babel/plugin-transform-modules-commonjs": "^7.10.4", - "@babel/plugin-transform-modules-systemjs": "^7.10.4", - "@babel/plugin-transform-modules-umd": "^7.10.4", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.10.4", - "@babel/plugin-transform-new-target": "^7.10.4", - "@babel/plugin-transform-object-super": "^7.10.4", - "@babel/plugin-transform-parameters": "^7.10.4", - "@babel/plugin-transform-property-literals": "^7.10.4", - "@babel/plugin-transform-regenerator": "^7.10.4", - "@babel/plugin-transform-reserved-words": "^7.10.4", - "@babel/plugin-transform-shorthand-properties": "^7.10.4", - "@babel/plugin-transform-spread": "^7.11.0", - "@babel/plugin-transform-sticky-regex": "^7.10.4", - "@babel/plugin-transform-template-literals": "^7.10.4", - "@babel/plugin-transform-typeof-symbol": "^7.10.4", - "@babel/plugin-transform-unicode-escapes": "^7.10.4", - "@babel/plugin-transform-unicode-regex": "^7.10.4", - "@babel/preset-modules": "^0.1.3", - "@babel/types": "^7.11.5", - "browserslist": "^4.12.0", - "core-js-compat": "^3.6.2", - "invariant": "^2.2.2", - "levenary": "^1.1.1", - "semver": "^5.5.0" - } - }, - "@babel/preset-modules": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", - "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - } - }, - "@babel/runtime": { - "version": "7.11.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", - "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, - "@babel/runtime-corejs3": { - "version": "7.11.2", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.11.2.tgz", - "integrity": "sha512-qh5IR+8VgFz83VBa6OkaET6uN/mJOhHONuy3m1sgF0CV6mXdPSEBdA7e1eUbVvyNtANjMbg22JUv71BaDXLY6A==", - "dev": true, - "requires": { - "core-js-pure": "^3.0.0", - "regenerator-runtime": "^0.13.4" - } - }, - "@babel/template": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", - "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/parser": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/traverse": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz", - "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==", - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.5", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.11.5", - "@babel/types": "^7.11.5", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.19" - }, - "dependencies": { - "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "requires": { - "ms": "2.1.2" - } - } - } - }, - "@babel/types": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", - "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "lodash": "^4.17.19", - "to-fast-properties": "^2.0.0" - } - }, - "@csstools/convert-colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz", - "integrity": "sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==" - }, - "@eslint/eslintrc": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.3.tgz", - "integrity": "sha512-4YVwPkANLeNtRjMekzux1ci8hIaH5eGKktGqR0d3LWsKNn5B2X/1Z6Trxy7jQXl9EBGE6Yj02O+t09FMeRllaA==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "lodash": "^4.17.19", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "requires": { - "type-fest": "^0.8.1" - } - } - } - }, - "@npmcli/move-file": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.0.1.tgz", - "integrity": "sha512-Uv6h1sT+0DrblvIrolFtbvM1FgWm+/sy4B3pvLp67Zys+thcukzS5ekn7HsZFGpWP4Q3fYJCljbWQE/XivMRLw==", - "requires": { - "mkdirp": "^1.0.4" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - } - } - }, - "@rails/webpacker": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/@rails/webpacker/-/webpacker-5.2.1.tgz", - "integrity": "sha512-rO0kOv0o4ESB8ZnKX+b54ZKogNJGWSMULGmsJacREfm9SahKEQwXBeHNsqSGtS9NAPsU6YUFhGKRd4i/kbMNrQ==", - "requires": { - "@babel/core": "^7.11.1", - "@babel/plugin-proposal-class-properties": "^7.10.4", - "@babel/plugin-proposal-object-rest-spread": "^7.10.1", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-destructuring": "^7.10.1", - "@babel/plugin-transform-regenerator": "^7.10.1", - "@babel/plugin-transform-runtime": "^7.11.0", - "@babel/preset-env": "^7.11.0", - "@babel/runtime": "^7.11.2", - "babel-loader": "^8.1.0", - "babel-plugin-dynamic-import-node": "^2.3.3", - "babel-plugin-macros": "^2.8.0", - "case-sensitive-paths-webpack-plugin": "^2.3.0", - "compression-webpack-plugin": "^4.0.0", - "core-js": "^3.6.5", - "css-loader": "^3.5.3", - "file-loader": "^6.0.0", - "flatted": "^3.0.4", - "glob": "^7.1.6", - "js-yaml": "^3.14.0", - "mini-css-extract-plugin": "^0.9.0", - "node-sass": "^4.14.1", - "optimize-css-assets-webpack-plugin": "^5.0.3", - "path-complete-extname": "^1.0.0", - "pnp-webpack-plugin": "^1.6.4", - "postcss-flexbugs-fixes": "^4.2.1", - "postcss-import": "^12.0.1", - "postcss-loader": "^3.0.0", - "postcss-preset-env": "^6.7.0", - "postcss-safe-parser": "^4.0.2", - "regenerator-runtime": "^0.13.7", - "sass-loader": "^8.0.2", - "style-loader": "^1.2.1", - "terser-webpack-plugin": "^4.0.0", - "webpack": "^4.44.1", - "webpack-assets-manifest": "^3.1.1", - "webpack-cli": "^3.3.12", - "webpack-sources": "^1.4.3" - }, - "dependencies": { - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "dependencies": { - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" - } - } - } - } - }, - "@types/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", - "dev": true, - "requires": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/json-schema": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", - "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==" - }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", - "dev": true - }, - "@types/lodash": { - "version": "4.14.137", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.137.tgz", - "integrity": "sha512-g4rNK5SRKloO+sUGbuO7aPtwbwzMgjK+bm9BBhLD7jGUiGR7zhwYEhSln/ihgYQBeIJ5j7xjyaYzrWTcu3UotQ==", - "dev": true - }, - "@types/lodash-es": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.3.tgz", - "integrity": "sha512-iHI0i7ZAL1qepz1Y7f3EKg/zUMDwDfTzitx+AlHhJJvXwenP682ZyGbgPSc5Ej3eEAKVbNWKFuwOadCj5vBbYQ==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "@types/node": { - "version": "12.7.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.2.tgz", - "integrity": "sha512-dyYO+f6ihZEtNPDcWNR1fkoTDf3zAK3lAABDze3mz6POyIercH0lEUawUFXlG8xaQZmm1yEBON/4TsYv/laDYg==" - }, - "@types/node-fetch": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz", - "integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==", - "dev": true, - "requires": { - "@types/node": "*", - "form-data": "^3.0.0" - } - }, - "@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" - }, - "@types/pdfjs-dist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@types/pdfjs-dist/-/pdfjs-dist-2.1.2.tgz", - "integrity": "sha512-tUMIcX3z8M8EXA0SA4YIZcgZ6r/Rb2wbwvM9AKJhE/MPh5rEC90Sg8lMyVX6hzMaToR4jWEvN7IUA1bvoVpctA==" - }, - "@types/prop-types": { - "version": "15.7.1", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.1.tgz", - "integrity": "sha512-CFzn9idOEpHrgdw8JsoTkaDDyRWk1jrzIV8djzcgpq0y9tG4B4lFT+Nxh52DVpDXV+n4+NPNv7M1Dj5uMp6XFg==" - }, - "@types/q": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz", - "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==" - }, - "@types/rc-slider": { - "version": "8.6.6", - "resolved": "https://registry.npmjs.org/@types/rc-slider/-/rc-slider-8.6.6.tgz", - "integrity": "sha512-2Q3vwKrSm3PbgiMNwzxMkOaMtcAGi0xQ8WPeVKoabk1vNYHiVR44DMC3mr9jC2lhbxCBgGBJWF9sBhmnSDQ8Bg==", - "dev": true, - "requires": { - "@types/rc-tooltip": "*", - "@types/react": "*" - }, - "dependencies": { - "@types/react": { - "version": "16.9.2", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.2.tgz", - "integrity": "sha512-jYP2LWwlh+FTqGd9v7ynUKZzjj98T8x7Yclz479QdRhHfuW9yQ+0jjnD31eXSXutmBpppj5PYNLYLRfnZJvcfg==", - "dev": true, - "requires": { - "@types/prop-types": "*", - "csstype": "^2.2.0" - } - }, - "csstype": { - "version": "2.6.13", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz", - "integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==", - "dev": true - } - } - }, - "@types/rc-tooltip": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@types/rc-tooltip/-/rc-tooltip-3.7.1.tgz", - "integrity": "sha512-H+pW9+H42rlb3PBjcxuXhQre1ldr0gdDVbVfCj0Pf4Mdjd1plti9ekt1yJ+gGig3bRFLpCknWDmfOkAjKY+S+Q==", - "dev": true, - "requires": { - "@types/react": "*" - } - }, - "@types/react": { - "version": "16.9.51", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.51.tgz", - "integrity": "sha512-lQa12IyO+DMlnSZ3+AGHRUiUcpK47aakMMoBG8f7HGxJT8Yfe+WE128HIXaHOHVPReAW0oDS3KAI0JI2DDe1PQ==", - "dev": true, - "requires": { - "@types/prop-types": "*", - "csstype": "^3.0.2" - } - }, - "@types/react-addons-css-transition-group": { - "version": "15.0.5", - "resolved": "https://registry.npmjs.org/@types/react-addons-css-transition-group/-/react-addons-css-transition-group-15.0.5.tgz", - "integrity": "sha512-UIJt5HQDOzRI7AOmnGnc2OZA0N3p7r6yMsxZ3T0+dyGPB3zWiKOPKrMkJr9tyuY3kHKPm26GyihcJKNJdMY8CQ==", - "dev": true, - "requires": { - "@types/react": "*", - "@types/react-addons-transition-group": "*" - }, - "dependencies": { - "@types/react": { - "version": "16.9.2", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.2.tgz", - "integrity": "sha512-jYP2LWwlh+FTqGd9v7ynUKZzjj98T8x7Yclz479QdRhHfuW9yQ+0jjnD31eXSXutmBpppj5PYNLYLRfnZJvcfg==", - "dev": true, - "requires": { - "@types/prop-types": "*", - "csstype": "^2.2.0" - } - }, - "csstype": { - "version": "2.6.13", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz", - "integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==", - "dev": true - } - } - }, - "@types/react-addons-transition-group": { - "version": "15.0.4", - "resolved": "https://registry.npmjs.org/@types/react-addons-transition-group/-/react-addons-transition-group-15.0.4.tgz", - "integrity": "sha512-0S2cKn9OLYr6N36oRH4ybzidkgQ0UGhuvrFvU3tdktJfrx3muu7MgfIWG434wKg7rcysBEfpmQaNpGteEtx6vw==", - "dev": true, - "requires": { - "@types/react": "*" - } - }, - "@types/react-beautiful-dnd": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.0.0.tgz", - "integrity": "sha512-by80tJ8aTTDXT256Gl+RfLRtFjYbUWOnZuEigJgNsJrSEGxvFe5eY6k3g4VIvf0M/6+xoLgfYWoWonlOo6Wqdg==", - "dev": true, - "requires": { - "@types/react": "*" - }, - "dependencies": { - "@types/react": { - "version": "16.9.2", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.2.tgz", - "integrity": "sha512-jYP2LWwlh+FTqGd9v7ynUKZzjj98T8x7Yclz479QdRhHfuW9yQ+0jjnD31eXSXutmBpppj5PYNLYLRfnZJvcfg==", - "dev": true, - "requires": { - "@types/prop-types": "*", - "csstype": "^2.2.0" - } - }, - "csstype": { - "version": "2.6.13", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz", - "integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==", - "dev": true - } - } - }, - "@types/react-copy-to-clipboard": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-4.3.0.tgz", - "integrity": "sha512-iideNPRyroENqsOFh1i2Dv3zkviYS9r/9qD9Uh3Z9NNoAAqqa2x53i7iGndGNnJFIo20wIu7Hgh77tx1io8bgw==", - "dev": true, - "requires": { - "@types/react": "*" - }, - "dependencies": { - "@types/react": { - "version": "16.9.2", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.2.tgz", - "integrity": "sha512-jYP2LWwlh+FTqGd9v7ynUKZzjj98T8x7Yclz479QdRhHfuW9yQ+0jjnD31eXSXutmBpppj5PYNLYLRfnZJvcfg==", - "dev": true, - "requires": { - "@types/prop-types": "*", - "csstype": "^2.2.0" - } - }, - "csstype": { - "version": "2.6.13", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz", - "integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==", - "dev": true - } - } - }, - "@types/react-datepicker": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@types/react-datepicker/-/react-datepicker-3.1.1.tgz", - "integrity": "sha512-vwNrgaIMJThvvwmtnA8jSVVJZ0FNgljQrq1jDA4MtYJIDmVmd9NNrFaXf9u2JqR2nS+8Kvi8OVs/tnAbUqZhHw==", - "dev": true, - "requires": { - "@types/react": "*", - "date-fns": "^2.0.1", - "popper.js": "^1.14.1" - }, - "dependencies": { - "@types/react": { - "version": "16.9.2", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.2.tgz", - "integrity": "sha512-jYP2LWwlh+FTqGd9v7ynUKZzjj98T8x7Yclz479QdRhHfuW9yQ+0jjnD31eXSXutmBpppj5PYNLYLRfnZJvcfg==", - "dev": true, - "requires": { - "@types/prop-types": "*", - "csstype": "^2.2.0" - } - }, - "csstype": { - "version": "2.6.13", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz", - "integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==", - "dev": true - }, - "popper.js": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.15.0.tgz", - "integrity": "sha512-w010cY1oCUmI+9KwwlWki+r5jxKfTFDVoadl7MSrIujHU5MJ5OR6HTDj6Xo8aoR/QsA56x8jKjA59qGH4ELtrA==", - "dev": true - } - } - }, - "@types/react-dom": { - "version": "16.9.8", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.8.tgz", - "integrity": "sha512-ykkPQ+5nFknnlU6lDd947WbQ6TE3NNzbQAkInC2EKY1qeYdTKp7onFusmYZb+ityzx2YviqT6BXSu+LyWWJwcA==", - "dev": true, - "requires": { - "@types/react": "*" - }, - "dependencies": { - "@types/react": { - "version": "16.9.2", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.2.tgz", - "integrity": "sha512-jYP2LWwlh+FTqGd9v7ynUKZzjj98T8x7Yclz479QdRhHfuW9yQ+0jjnD31eXSXutmBpppj5PYNLYLRfnZJvcfg==", - "dev": true, - "requires": { - "@types/prop-types": "*", - "csstype": "^2.2.0" - } - }, - "csstype": { - "version": "2.6.13", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz", - "integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==", - "dev": true - } - } - }, - "@types/react-paginate": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@types/react-paginate/-/react-paginate-6.2.1.tgz", - "integrity": "sha512-+q8k1N0WzbMyOCsIEH/p5D6/KQD8dXYLzfvSvriYn//94icd2sqhAL2rWXkgwGvqHGCSTU9AoHtsWCJxPfquUQ==", - "requires": { - "@types/react": "*" - }, - "dependencies": { - "@types/react": { - "version": "16.9.2", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.2.tgz", - "integrity": "sha512-jYP2LWwlh+FTqGd9v7ynUKZzjj98T8x7Yclz479QdRhHfuW9yQ+0jjnD31eXSXutmBpppj5PYNLYLRfnZJvcfg==", - "requires": { - "@types/prop-types": "*", - "csstype": "^2.2.0" - } - }, - "csstype": { - "version": "2.6.13", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz", - "integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==" - } - } - }, - "@types/react-pdf": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/react-pdf/-/react-pdf-4.0.6.tgz", - "integrity": "sha512-ZmtUA31L5AaF9PilB8cJ3PuGOHIiyWcHnCir7KOux1cDjfVH6VxiN/j7CcyX98U9hwlyN81bkqxeNWNuEc0a4w==", - "requires": { - "@types/pdfjs-dist": "*", - "@types/react": "*" - }, - "dependencies": { - "@types/react": { - "version": "16.9.2", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.2.tgz", - "integrity": "sha512-jYP2LWwlh+FTqGd9v7ynUKZzjj98T8x7Yclz479QdRhHfuW9yQ+0jjnD31eXSXutmBpppj5PYNLYLRfnZJvcfg==", - "requires": { - "@types/prop-types": "*", - "csstype": "^2.2.0" - } - }, - "csstype": { - "version": "2.6.13", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz", - "integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==" - } - } - }, - "@types/react-textarea-autosize": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@types/react-textarea-autosize/-/react-textarea-autosize-4.3.5.tgz", - "integrity": "sha512-PiDL83kPMTolyZAWW3lyzO6ktooTb9tFTntVy7CA83/qFLWKLJ5bLeRboy6J6j3b1e8h2Eec6gBTEOOJRjV14A==", - "dev": true, - "requires": { - "@types/react": "*" - }, - "dependencies": { - "@types/react": { - "version": "16.9.2", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.2.tgz", - "integrity": "sha512-jYP2LWwlh+FTqGd9v7ynUKZzjj98T8x7Yclz479QdRhHfuW9yQ+0jjnD31eXSXutmBpppj5PYNLYLRfnZJvcfg==", - "dev": true, - "requires": { - "@types/prop-types": "*", - "csstype": "^2.2.0" - } - }, - "csstype": { - "version": "2.6.13", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz", - "integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==", - "dev": true - } - } - }, - "@types/vimeo__player": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/@types/vimeo__player/-/vimeo__player-2.9.1.tgz", - "integrity": "sha512-L6XHWenPkN+WHFWmo/fhA70kTQnNUxOs3bQS3nF/FK3kv+UzEVRqPEkxJNUZWExwrhOKaTKzplZHmxYwmr0SJA==", - "dev": true - }, - "@vimeo/player": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/@vimeo/player/-/player-2.14.0.tgz", - "integrity": "sha512-hTeROVnkcyboRjetPi9tasryrjDPVsmr/73clwbYsBpSk8k5q1ygFyvkWXQShv9Rc+hvXM5RJXPd7i7Wh7dqcA==", - "requires": { - "native-promise-only": "0.8.1", - "weakmap-polyfill": "2.0.1" - } - }, - "@webassemblyjs/ast": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", - "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", - "requires": { - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", - "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==" - }, - "@webassemblyjs/helper-api-error": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", - "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==" - }, - "@webassemblyjs/helper-buffer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", - "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==" - }, - "@webassemblyjs/helper-code-frame": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", - "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", - "requires": { - "@webassemblyjs/wast-printer": "1.9.0" - } - }, - "@webassemblyjs/helper-fsm": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", - "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==" - }, - "@webassemblyjs/helper-module-context": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", - "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", - "requires": { - "@webassemblyjs/ast": "1.9.0" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", - "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==" - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", - "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", - "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", - "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", - "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==" - }, - "@webassemblyjs/wasm-edit": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", - "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/helper-wasm-section": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0", - "@webassemblyjs/wasm-opt": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0", - "@webassemblyjs/wast-printer": "1.9.0" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", - "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/ieee754": "1.9.0", - "@webassemblyjs/leb128": "1.9.0", - "@webassemblyjs/utf8": "1.9.0" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", - "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", - "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-api-error": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/ieee754": "1.9.0", - "@webassemblyjs/leb128": "1.9.0", - "@webassemblyjs/utf8": "1.9.0" - } - }, - "@webassemblyjs/wast-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", - "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/floating-point-hex-parser": "1.9.0", - "@webassemblyjs/helper-api-error": "1.9.0", - "@webassemblyjs/helper-code-frame": "1.9.0", - "@webassemblyjs/helper-fsm": "1.9.0", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", - "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0", - "@xtuc/long": "4.2.2" - } - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" - }, - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "dev": true, - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } - }, - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" - }, - "acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true - }, - "acorn-node": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", - "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", - "requires": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "xtend": "^4.0.2" - } - }, - "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==" - }, - "add-dom-event-listener": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/add-dom-event-listener/-/add-dom-event-listener-1.1.0.tgz", - "integrity": "sha512-WCxx1ixHT0GQU9hb0KI/mhgRQhnU+U3GvwY6ZvVjYq8rsihIGoaIOUbY0yMPBxLH5MDtr0kz3fisWGNcbWW7Jw==", - "requires": { - "object-assign": "4.x" - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "6.12.5", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", - "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==" - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" - }, - "alphanum-sort": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", - "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=" - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" - }, - "ansi-colors": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", - "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", - "dev": true - }, - "ansi-html": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", - "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" - }, - "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.10.2", - "@babel/runtime-corejs3": "^7.10.2" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" - }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" - }, - "array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", - "dev": true - }, - "array-includes": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", - "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0", - "is-string": "^1.0.5" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - } - } - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "requires": { - "array-uniq": "^1.0.1" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" - }, - "array.prototype.flat": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", - "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - } - } - }, - "array.prototype.flatmap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.3.tgz", - "integrity": "sha512-OOEk+lkePcg+ODXIpvuU9PAryCikCJyo7GlDG1upleEpQRx6mzL9puEBkozQ5iAx20KV0l3DbyQwqciJtqe5Pg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - } - } - }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" - } - } - }, - "assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", - "requires": { - "object-assign": "^4.1.1", - "util": "0.10.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "requires": { - "inherits": "2.0.1" - } - } - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" - }, - "ast-types": { - "version": "0.9.6", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz", - "integrity": "sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=" - }, - "ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", - "dev": true - }, - "astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", - "dev": true - }, - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "requires": { - "lodash": "^4.17.14" - } - }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" - }, - "async-foreach": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", - "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=" - }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" - }, - "autoprefixer": { - "version": "7.2.6", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-7.2.6.tgz", - "integrity": "sha512-Iq8TRIB+/9eQ8rbGhcP7ct5cYb/3qjNYAR2SnzLCEcwF6rvVOax8+9+fccgXk4bEhQGjOZd5TLhsksmAdsbGqQ==", - "dev": true, - "requires": { - "browserslist": "^2.11.3", - "caniuse-lite": "^1.0.30000805", - "normalize-range": "^0.1.2", - "num2fraction": "^1.2.2", - "postcss": "^6.0.17", - "postcss-value-parser": "^3.2.3" - }, - "dependencies": { - "browserslist": { - "version": "2.11.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", - "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000792", - "electron-to-chromium": "^1.3.30" - } - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", - "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==" - }, - "axe-core": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-3.5.5.tgz", - "integrity": "sha512-5P0QZ6J5xGikH780pghEdbEKijCTrruK9KxtPZCFWUpef0f6GipO+xEZ5GKCb020mmqgbiNO6TcA55CriL784Q==", - "dev": true - }, - "axobject-query": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", - "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==", - "dev": true - }, - "babel-helper-builder-react-jsx": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", - "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", - "requires": { - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "esutils": "^2.0.2" - } - }, - "babel-loader": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.1.0.tgz", - "integrity": "sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw==", - "requires": { - "find-cache-dir": "^2.1.0", - "loader-utils": "^1.4.0", - "mkdirp": "^0.5.3", - "pify": "^4.0.1", - "schema-utils": "^2.6.5" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - } - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" - } - } - }, - "babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "requires": { - "object.assign": "^4.1.0" - } - }, - "babel-plugin-macros": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz", - "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==", - "requires": { - "@babel/runtime": "^7.7.2", - "cosmiconfig": "^6.0.0", - "resolve": "^1.12.0" - } - }, - "babel-plugin-syntax-flow": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", - "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=" - }, - "babel-plugin-syntax-jsx": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=" - }, - "babel-plugin-transform-flow-strip-types": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", - "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", - "requires": { - "babel-plugin-syntax-flow": "^6.18.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-react-display-name": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", - "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-react-jsx": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", - "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", - "requires": { - "babel-helper-builder-react-jsx": "^6.24.1", - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-react-jsx-self": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", - "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", - "requires": { - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-react-jsx-source": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", - "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", - "requires": { - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-preset-flow": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", - "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", - "requires": { - "babel-plugin-transform-flow-strip-types": "^6.22.0" - } - }, - "babel-preset-react": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", - "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", - "requires": { - "babel-plugin-syntax-jsx": "^6.3.13", - "babel-plugin-transform-react-display-name": "^6.23.0", - "babel-plugin-transform-react-jsx": "^6.24.1", - "babel-plugin-transform-react-jsx-self": "^6.22.0", - "babel-plugin-transform-react-jsx-source": "^6.22.0", - "babel-preset-flow": "^6.23.0" - } - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - }, - "dependencies": { - "core-js": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" - }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" - } - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - }, - "dependencies": { - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" - } - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "base62": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/base62/-/base62-0.1.1.tgz", - "integrity": "sha1-e0F0wvlESXU7EcJlHAg9qEGnsIQ=" - }, - "base64-js": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", - "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" - }, - "batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==" - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "block-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "requires": { - "inherits": "~2.0.0" - } - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, - "bn.js": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==" - }, - "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "dev": true, - "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - }, - "dependencies": { - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true - } - } - }, - "bonjour": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", - "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", - "dev": true, - "requires": { - "array-flatten": "^2.1.0", - "deep-equal": "^1.0.1", - "dns-equal": "^1.0.0", - "dns-txt": "^2.0.2", - "multicast-dns": "^6.0.1", - "multicast-dns-service-types": "^1.1.0" - } - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" - }, - "brace": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/brace/-/brace-0.11.1.tgz", - "integrity": "sha1-SJb8ydVE7vRfS7dmDbMg07N5/lg=" - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" - }, - "browser-pack": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", - "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==", - "requires": { - "JSONStream": "^1.0.3", - "combine-source-map": "~0.8.0", - "defined": "^1.0.0", - "safe-buffer": "^5.1.1", - "through2": "^2.0.0", - "umd": "^3.0.0" - } - }, - "browser-resolve": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz", - "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==", - "requires": { - "resolve": "^1.17.0" - } - }, - "browserify": { - "version": "16.5.2", - "resolved": "https://registry.npmjs.org/browserify/-/browserify-16.5.2.tgz", - "integrity": "sha512-TkOR1cQGdmXU9zW4YukWzWVSJwrxmNdADFbqbE3HFgQWe5wqZmOawqZ7J/8MPCwk/W8yY7Y0h+7mOtcZxLP23g==", - "requires": { - "JSONStream": "^1.0.3", - "assert": "^1.4.0", - "browser-pack": "^6.0.1", - "browser-resolve": "^2.0.0", - "browserify-zlib": "~0.2.0", - "buffer": "~5.2.1", - "cached-path-relative": "^1.0.0", - "concat-stream": "^1.6.0", - "console-browserify": "^1.1.0", - "constants-browserify": "~1.0.0", - "crypto-browserify": "^3.0.0", - "defined": "^1.0.0", - "deps-sort": "^2.0.0", - "domain-browser": "^1.2.0", - "duplexer2": "~0.1.2", - "events": "^2.0.0", - "glob": "^7.1.0", - "has": "^1.0.0", - "htmlescape": "^1.1.0", - "https-browserify": "^1.0.0", - "inherits": "~2.0.1", - "insert-module-globals": "^7.0.0", - "labeled-stream-splicer": "^2.0.0", - "mkdirp-classic": "^0.5.2", - "module-deps": "^6.2.3", - "os-browserify": "~0.3.0", - "parents": "^1.0.1", - "path-browserify": "~0.0.0", - "process": "~0.11.0", - "punycode": "^1.3.2", - "querystring-es3": "~0.2.0", - "read-only-stream": "^2.0.0", - "readable-stream": "^2.0.2", - "resolve": "^1.1.4", - "shasum": "^1.0.0", - "shell-quote": "^1.6.1", - "stream-browserify": "^2.0.0", - "stream-http": "^3.0.0", - "string_decoder": "^1.1.1", - "subarg": "^1.0.0", - "syntax-error": "^1.1.1", - "through2": "^2.0.0", - "timers-browserify": "^1.0.1", - "tty-browserify": "0.0.1", - "url": "~0.11.0", - "util": "~0.10.1", - "vm-browserify": "^1.0.0", - "xtend": "^4.0.0" - }, - "dependencies": { - "resolve": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", - "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", - "requires": { - "path-parse": "^1.0.6" - } - } - } - }, - "browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "requires": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "browserify-cache-api": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/browserify-cache-api/-/browserify-cache-api-3.0.1.tgz", - "integrity": "sha1-liR+hT8Gj9bg1FzHPwuyzZd47wI=", - "requires": { - "async": "^1.5.2", - "through2": "^2.0.0", - "xtend": "^4.0.0" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" - } - } - }, - "browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "browserify-incremental": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/browserify-incremental/-/browserify-incremental-3.1.1.tgz", - "integrity": "sha1-BxPLdYckemMqnwjPG9FpuHi2Koo=", - "requires": { - "JSONStream": "^0.10.0", - "browserify-cache-api": "^3.0.0", - "through2": "^2.0.0", - "xtend": "^4.0.0" - }, - "dependencies": { - "JSONStream": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.10.0.tgz", - "integrity": "sha1-dDSdDYlSK3HzDwoD/5vSDKbxKsA=", - "requires": { - "jsonparse": "0.0.5", - "through": ">=2.2.7 <3" - } - }, - "jsonparse": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", - "integrity": "sha1-MwVCrT8KZUZlt3jz6y2an6UHrGQ=" - } - } - }, - "browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "requires": { - "bn.js": "^4.1.0", - "randombytes": "^2.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" - } - } - }, - "browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", - "requires": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "requires": { - "pako": "~1.0.5" - } - }, - "browserslist": { - "version": "4.14.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.5.tgz", - "integrity": "sha512-Z+vsCZIvCBvqLoYkBFTwEYH3v5MCQbsAjp50ERycpOjnPmolg1Gjy4+KaWWpm8QOJt9GHkhdqAl14NpCX73CWA==", - "requires": { - "caniuse-lite": "^1.0.30001135", - "electron-to-chromium": "^1.3.571", - "escalade": "^3.1.0", - "node-releases": "^1.1.61" - } - }, - "buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", - "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" - }, - "buffer-indexof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", - "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", - "dev": true - }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" - }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true - }, - "cacache": { - "version": "15.0.5", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", - "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", - "requires": { - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.0", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "cached-path-relative": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.2.tgz", - "integrity": "sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg==" - }, - "caller-callsite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", - "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", - "requires": { - "callsites": "^2.0.0" - }, - "dependencies": { - "callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=" - } - } - }, - "caller-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", - "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", - "requires": { - "caller-callsite": "^2.0.0" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" - }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - }, - "dependencies": { - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" - } - } - }, - "caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "requires": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, - "caniuse-lite": { - "version": "1.0.30001144", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001144.tgz", - "integrity": "sha512-4GQTEWNMnVZVOFG3BK0xvGeaDAtiPAbG2N8yuMXuXzx/c2Vd4XoMPO8+E918zeXn5IF0FRVtGShBfkfQea2wHQ==" - }, - "case-sensitive-paths-webpack-plugin": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.3.0.tgz", - "integrity": "sha512-/4YgnZS8y1UXXmC02xD5rRrBEu6T5ub+mQHLNRj0fzTRbgdBYhsNo2V5EqwgqrExjxsjtF/OpAKAMkKsxbD5XQ==" - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "chain-function": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/chain-function/-/chain-function-1.0.1.tgz", - "integrity": "sha512-SxltgMwL9uCko5/ZCLiyG2B7R9fY4pDZUw7hJ4MhirdjBLosoDqkWABi3XMucddHdLiFJMb7PD2MZifZriuMTg==" - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - }, - "dependencies": { - "fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "requires": { - "is-extglob": "^2.1.0" - } - } - } - } - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" - }, - "chrome-trace-event": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", - "requires": { - "tslib": "^1.9.0" - } - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "classnames": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", - "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - } - }, - "coa": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", - "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", - "requires": { - "@types/q": "^1.5.1", - "chalk": "^2.4.1", - "q": "^1.1.2" - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", - "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", - "dev": true, - "requires": { - "clone": "^1.0.2", - "color-convert": "^1.3.0", - "color-string": "^0.3.0" - }, - "dependencies": { - "color-string": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", - "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", - "dev": true, - "requires": { - "color-name": "^1.0.0" - } - } - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - }, - "dependencies": { - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - } - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "color-string": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", - "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", - "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "colorette": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", - "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==" - }, - "combine-source-map": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", - "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", - "requires": { - "convert-source-map": "~1.1.0", - "inline-source-map": "~0.6.0", - "lodash.memoize": "~3.0.3", - "source-map": "~0.5.3" - }, - "dependencies": { - "convert-source-map": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", - "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=" - }, - "lodash.memoize": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", - "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=" - } - } - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==" - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" - }, - "commoner": { - "version": "0.10.8", - "resolved": "https://registry.npmjs.org/commoner/-/commoner-0.10.8.tgz", - "integrity": "sha1-NPw2cs0kOT6LtH5wyqApOBH08sU=", - "requires": { - "commander": "^2.5.0", - "detective": "^4.3.1", - "glob": "^5.0.15", - "graceful-fs": "^4.1.2", - "iconv-lite": "^0.4.5", - "mkdirp": "^0.5.0", - "private": "^0.1.6", - "q": "^1.1.2", - "recast": "^0.11.17" - }, - "dependencies": { - "acorn": { - "version": "5.7.4", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", - "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==" - }, - "detective": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", - "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", - "requires": { - "acorn": "^5.2.1", - "defined": "^1.0.0" - } - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "component-classes": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/component-classes/-/component-classes-1.2.6.tgz", - "integrity": "sha1-xkI5TDYYpNiwuJGe/Mu9kw5c1pE=", - "requires": { - "component-indexof": "0.0.3" - } - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" - }, - "component-indexof": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-indexof/-/component-indexof-0.0.3.tgz", - "integrity": "sha1-EdCRMSI5648yyPJa6csAL/6NPCQ=" - }, - "compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, - "requires": { - "mime-db": ">= 1.43.0 < 2" - }, - "dependencies": { - "mime-db": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", - "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", - "dev": true - } - } - }, - "compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, - "requires": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "compression-webpack-plugin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/compression-webpack-plugin/-/compression-webpack-plugin-4.0.1.tgz", - "integrity": "sha512-0mg6PgwTsUe5LEcUrOu3ob32vraDx2VdbMGAT1PARcOV+UJWDYZFdkSo6RbHoGQ061mmmkC7XpRKOlvwm/gzJQ==", - "requires": { - "cacache": "^15.0.5", - "find-cache-dir": "^3.3.1", - "schema-utils": "^2.7.0", - "serialize-javascript": "^4.0.0", - "webpack-sources": "^1.4.3" - }, - "dependencies": { - "find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "requires": { - "p-locate": "^4.1.0" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "requires": { - "semver": "^6.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "requires": { - "p-limit": "^2.2.0" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "requires": { - "find-up": "^4.0.0" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "confusing-browser-globals": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz", - "integrity": "sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw==", - "dev": true - }, - "connect-history-api-fallback": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", - "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", - "dev": true - }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "requires": { - "date-now": "^0.1.4" - } - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" - }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" - }, - "contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true - }, - "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "dev": true, - "requires": { - "safe-buffer": "5.1.2" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true - }, - "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "requires": { - "safe-buffer": "~5.1.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, - "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", - "dev": true - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true - }, - "copy-concurrently": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", - "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - } - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" - }, - "copy-to-clipboard": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.2.0.tgz", - "integrity": "sha512-eOZERzvCmxS8HWzugj4Uxl8OJxa7T2k1Gi0X5qavwydHIfuSHq2dTD09LOg/XyGq4Zpb5IsR/2OJ5lbOegz78w==", - "requires": { - "toggle-selection": "^1.0.6" - } - }, - "core-js": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", - "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==" - }, - "core-js-compat": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz", - "integrity": "sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng==", - "requires": { - "browserslist": "^4.8.5", - "semver": "7.0.0" - }, - "dependencies": { - "semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==" - } - } - }, - "core-js-pure": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.5.tgz", - "integrity": "sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" - }, - "dependencies": { - "parse-json": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", - "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" - } - } - }, - "create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", - "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" - } - } - }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "create-react-context": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/create-react-context/-/create-react-context-0.3.0.tgz", - "integrity": "sha512-dNldIoSuNSvlTJ7slIKC/ZFGKexBMBrrcc+TTe1NdmROnaASuLPvqpwj9v4XS4uXZ8+YPu0sNmShX2rXI5LNsw==", - "requires": { - "gud": "^1.0.0", - "warning": "^4.0.3" - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - } - }, - "css-animation": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/css-animation/-/css-animation-1.6.1.tgz", - "integrity": "sha512-/48+/BaEaHRY6kNQ2OIPzKf9A6g8WjZYjhiNDNuIVbsm5tXCGIAsHDjB4Xu1C4vXJtUWZo26O68OQkDpNBaPog==", - "requires": { - "babel-runtime": "6.x", - "component-classes": "^1.2.5" - } - }, - "css-blank-pseudo": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz", - "integrity": "sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w==", - "requires": { - "postcss": "^7.0.5" - } - }, - "css-box-model": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz", - "integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==", - "requires": { - "tiny-invariant": "^1.0.6" - } - }, - "css-color-function": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/css-color-function/-/css-color-function-1.3.3.tgz", - "integrity": "sha1-jtJMLAIFBzM5+voAS8jBQfzLKC4=", - "dev": true, - "requires": { - "balanced-match": "0.1.0", - "color": "^0.11.0", - "debug": "^3.1.0", - "rgb": "~0.1.0" - }, - "dependencies": { - "balanced-match": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.1.0.tgz", - "integrity": "sha1-tQS9BYabOSWd0MXvw12EMXbczEo=", - "dev": true - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "css-color-names": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", - "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=" - }, - "css-declaration-sorter": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz", - "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==", - "requires": { - "postcss": "^7.0.1", - "timsort": "^0.3.0" - } - }, - "css-has-pseudo": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz", - "integrity": "sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ==", - "requires": { - "postcss": "^7.0.6", - "postcss-selector-parser": "^5.0.0-rc.4" - }, - "dependencies": { - "cssesc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", - "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==" - }, - "postcss-selector-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", - "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", - "requires": { - "cssesc": "^2.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - } - } - }, - "css-loader": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", - "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", - "requires": { - "camelcase": "^5.3.1", - "cssesc": "^3.0.0", - "icss-utils": "^4.1.1", - "loader-utils": "^1.2.3", - "normalize-path": "^3.0.0", - "postcss": "^7.0.32", - "postcss-modules-extract-imports": "^2.0.0", - "postcss-modules-local-by-default": "^3.0.2", - "postcss-modules-scope": "^2.2.0", - "postcss-modules-values": "^3.0.0", - "postcss-value-parser": "^4.1.0", - "schema-utils": "^2.7.0", - "semver": "^6.3.0" - }, - "dependencies": { - "postcss": { - "version": "7.0.35", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", - "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - } - }, - "postcss-value-parser": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", - "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==" - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "css-prefers-color-scheme": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz", - "integrity": "sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg==", - "requires": { - "postcss": "^7.0.5" - } - }, - "css-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", - "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", - "requires": { - "boolbase": "^1.0.0", - "css-what": "^3.2.1", - "domutils": "^1.7.0", - "nth-check": "^1.0.2" - } - }, - "css-select-base-adapter": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", - "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" - }, - "css-tree": { - "version": "1.0.0-alpha.37", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", - "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", - "requires": { - "mdn-data": "2.0.4", - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "css-unit-converter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz", - "integrity": "sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==", - "dev": true - }, - "css-what": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.1.tgz", - "integrity": "sha512-wHOppVDKl4vTAOWzJt5Ek37Sgd9qq1Bmj/T1OjvicWbU5W7ru7Pqbn0Jdqii3Drx/h+dixHKXNhZYx7blthL7g==" - }, - "cssdb": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-4.4.0.tgz", - "integrity": "sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ==" - }, - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" - }, - "cssnano": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz", - "integrity": "sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==", - "requires": { - "cosmiconfig": "^5.0.0", - "cssnano-preset-default": "^4.0.7", - "is-resolvable": "^1.0.0", - "postcss": "^7.0.0" - }, - "dependencies": { - "cosmiconfig": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", - "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", - "requires": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.13.1", - "parse-json": "^4.0.0" - } - }, - "import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", - "requires": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" - } - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - } - } - }, - "cssnano-preset-default": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz", - "integrity": "sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==", - "requires": { - "css-declaration-sorter": "^4.0.1", - "cssnano-util-raw-cache": "^4.0.1", - "postcss": "^7.0.0", - "postcss-calc": "^7.0.1", - "postcss-colormin": "^4.0.3", - "postcss-convert-values": "^4.0.1", - "postcss-discard-comments": "^4.0.2", - "postcss-discard-duplicates": "^4.0.2", - "postcss-discard-empty": "^4.0.1", - "postcss-discard-overridden": "^4.0.1", - "postcss-merge-longhand": "^4.0.11", - "postcss-merge-rules": "^4.0.3", - "postcss-minify-font-values": "^4.0.2", - "postcss-minify-gradients": "^4.0.2", - "postcss-minify-params": "^4.0.2", - "postcss-minify-selectors": "^4.0.2", - "postcss-normalize-charset": "^4.0.1", - "postcss-normalize-display-values": "^4.0.2", - "postcss-normalize-positions": "^4.0.2", - "postcss-normalize-repeat-style": "^4.0.2", - "postcss-normalize-string": "^4.0.2", - "postcss-normalize-timing-functions": "^4.0.2", - "postcss-normalize-unicode": "^4.0.1", - "postcss-normalize-url": "^4.0.1", - "postcss-normalize-whitespace": "^4.0.2", - "postcss-ordered-values": "^4.1.2", - "postcss-reduce-initial": "^4.0.3", - "postcss-reduce-transforms": "^4.0.2", - "postcss-svgo": "^4.0.2", - "postcss-unique-selectors": "^4.0.1" - }, - "dependencies": { - "postcss-calc": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.5.tgz", - "integrity": "sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg==", - "requires": { - "postcss": "^7.0.27", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.0.2" - }, - "dependencies": { - "postcss": { - "version": "7.0.35", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", - "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - } - } - } - }, - "postcss-value-parser": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", - "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==" - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "cssnano-util-get-arguments": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz", - "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=" - }, - "cssnano-util-get-match": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz", - "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=" - }, - "cssnano-util-raw-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz", - "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==", - "requires": { - "postcss": "^7.0.0" - } - }, - "cssnano-util-same-parent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz", - "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==" - }, - "csso": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.0.3.tgz", - "integrity": "sha512-NL3spysxUkcrOgnpsT4Xdl2aiEiBG6bXswAABQVHcMrfjjBisFOKwLDOmf4wf32aPdcJws1zds2B0Rg+jqMyHQ==", - "requires": { - "css-tree": "1.0.0-alpha.39" - }, - "dependencies": { - "css-tree": { - "version": "1.0.0-alpha.39", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.39.tgz", - "integrity": "sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA==", - "requires": { - "mdn-data": "2.0.6", - "source-map": "^0.6.1" - } - }, - "mdn-data": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.6.tgz", - "integrity": "sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA==" - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "csstype": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.3.tgz", - "integrity": "sha512-jPl+wbWPOWJ7SXsWyqGRk3lGecbar0Cb0OvZF/r/ZU011R4YqiRehgkQ9p4eQfo9DSDLqLL3wHwfxeJiuIsNag==", - "dev": true - }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "requires": { - "array-find-index": "^1.0.1" - } - }, - "cyclist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", - "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=" - }, - "damerau-levenshtein": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz", - "integrity": "sha512-JVrozIeElnj3QzfUIt8tB8YMluBJom4Vw9qTPpjGYQ9fYlB3D/rb6OordUxf3xeFB35LKWs0xqcO5U6ySvBtug==", - "dev": true - }, - "dash-ast": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", - "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==" - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "date-fns": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.16.1.tgz", - "integrity": "sha512-sAJVKx/FqrLYHAQeN7VpJrPhagZc9R4ImZIWYRFZaaohR3KzmuK88touwsSwSVT8Qcbd4zoDsnGfX4GFB4imyQ==" - }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" - }, - "deep-equal": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", - "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", - "dev": true, - "requires": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" - } - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "default-gateway": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", - "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", - "dev": true, - "requires": { - "execa": "^1.0.0", - "ip-regex": "^2.1.0" - } - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" - }, - "del": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "globby": "^6.1.0", - "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", - "p-map": "^2.0.0", - "pify": "^4.0.1", - "rimraf": "^2.6.3" - }, - "dependencies": { - "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - } - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "deps-sort": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", - "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=", - "requires": { - "JSONStream": "^1.0.3", - "shasum": "^1.0.0", - "subarg": "^1.0.0", - "through2": "^2.0.0" - } - }, - "des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=" - }, - "detect-node": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", - "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", - "dev": true - }, - "detective": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", - "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", - "requires": { - "acorn-node": "^1.6.1", - "defined": "^1.0.0", - "minimist": "^1.1.1" - } - }, - "diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" - } - } - }, - "dns-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", - "dev": true - }, - "dns-packet": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", - "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", - "dev": true, - "requires": { - "ip": "^1.1.0", - "safe-buffer": "^5.0.1" - } - }, - "dns-txt": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", - "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", - "dev": true, - "requires": { - "buffer-indexof": "^1.0.0" - } - }, - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - }, - "dom-align": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.0.tgz", - "integrity": "sha512-YkoezQuhp3SLFGdOlr5xkqZ640iXrnHAwVYcDg8ZKRUtO7mSzSC2BA5V0VuyAwPSJA4CLIc6EDDJh4bEsD2+zA==" - }, - "dom-helpers": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz", - "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==", - "requires": { - "@babel/runtime": "^7.1.2" - } - }, - "dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", - "requires": { - "domelementtype": "^2.0.1", - "entities": "^2.0.0" - }, - "dependencies": { - "domelementtype": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.2.tgz", - "integrity": "sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA==" - } - } - }, - "domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" - }, - "domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" - }, - "domutils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", - "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "requires": { - "is-obj": "^2.0.0" - } - }, - "dropzone": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/dropzone/-/dropzone-5.7.2.tgz", - "integrity": "sha512-m217bJHtf0J1IiKn4Tv6mnu1h5QvQNBnKZ39gma7hzGQhIZMxYq1vYEHs4AVd4ThFwmALys+52NAOD4zdLTG4w==" - }, - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "requires": { - "readable-stream": "^2.0.2" - } - }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.578", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.578.tgz", - "integrity": "sha512-z4gU6dA1CbBJsAErW5swTGAaU2TBzc2mPAonJb00zqW1rOraDo2zfBMDRvaz9cVic+0JEZiYbHWPw/fTaZlG2Q==" - }, - "elliptic": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", - "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" - } - } - }, - "email-addresses": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-3.1.0.tgz", - "integrity": "sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg==" - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" - }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true - }, - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "requires": { - "once": "^1.4.0" - } - }, - "enhanced-resolve": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz", - "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==", - "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.5.0", - "tapable": "^1.0.0" - }, - "dependencies": { - "memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - } - } - }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1" - }, - "dependencies": { - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - } - } - }, - "entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==" - }, - "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "requires": { - "prr": "~1.0.1" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - }, - "dependencies": { - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "requires": { - "has-symbols": "^1.0.1" - } - } - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "escalade": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.0.tgz", - "integrity": "sha512-mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig==" - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "eslint": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.10.0.tgz", - "integrity": "sha512-BDVffmqWl7JJXqCjAK6lWtcQThZB/aP1HXSH1JKwGwv0LQEdvpR7qzNrUT487RM39B5goWuboFad5ovMBmD8yA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@eslint/eslintrc": "^0.1.3", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^1.3.0", - "espree": "^7.3.0", - "esquery": "^1.2.0", - "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash": "^4.17.19", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^5.2.3", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "requires": { - "type-fest": "^0.8.1" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "eslint-config-airbnb": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-18.2.0.tgz", - "integrity": "sha512-Fz4JIUKkrhO0du2cg5opdyPKQXOI2MvF8KUvN2710nJMT6jaRUpRE2swrJftAjVGL7T1otLM5ieo5RqS1v9Udg==", - "dev": true, - "requires": { - "eslint-config-airbnb-base": "^14.2.0", - "object.assign": "^4.1.0", - "object.entries": "^1.1.2" - } - }, - "eslint-config-airbnb-base": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.0.tgz", - "integrity": "sha512-Snswd5oC6nJaevs3nZoLSTvGJBvzTfnBqOIArkf3cbyTyq9UD79wOk8s+RiL6bhca0p/eRO6veczhf6A/7Jy8Q==", - "dev": true, - "requires": { - "confusing-browser-globals": "^1.0.9", - "object.assign": "^4.1.0", - "object.entries": "^1.1.2" - } - }, - "eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "resolve": "^1.13.1" - } - }, - "eslint-module-utils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", - "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "pkg-dir": "^2.0.0" - }, - "dependencies": { - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - } - } - } - }, - "eslint-plugin-import": { - "version": "2.22.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", - "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", - "dev": true, - "requires": { - "array-includes": "^3.1.1", - "array.prototype.flat": "^1.2.3", - "contains-path": "^0.1.0", - "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.4", - "eslint-module-utils": "^2.6.0", - "has": "^1.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.1", - "read-pkg-up": "^2.0.0", - "resolve": "^1.17.0", - "tsconfig-paths": "^3.9.0" - } - }, - "eslint-plugin-jsx-a11y": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.3.1.tgz", - "integrity": "sha512-i1S+P+c3HOlBJzMFORRbC58tHa65Kbo8b52/TwCwSKLohwvpfT5rm2GjGWzOHTEuq4xxf2aRlHHTtmExDQOP+g==", - "dev": true, - "requires": { - "@babel/runtime": "^7.10.2", - "aria-query": "^4.2.2", - "array-includes": "^3.1.1", - "ast-types-flow": "^0.0.7", - "axe-core": "^3.5.4", - "axobject-query": "^2.1.2", - "damerau-levenshtein": "^1.0.6", - "emoji-regex": "^9.0.0", - "has": "^1.0.3", - "jsx-ast-utils": "^2.4.1", - "language-tags": "^1.0.5" - }, - "dependencies": { - "emoji-regex": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.0.0.tgz", - "integrity": "sha512-6p1NII1Vm62wni/VR/cUMauVQoxmLVb9csqQlvLz+hO2gk8U2UYDfXHQSUYIBKmZwAKz867IDqG7B+u0mj+M6w==", - "dev": true - } - } - }, - "eslint-plugin-promise": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz", - "integrity": "sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==", - "dev": true - }, - "eslint-plugin-react": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.21.3.tgz", - "integrity": "sha512-OI4GwTCqyIb4ipaOEGLWdaOHCXZZydStAsBEPB2e1ZfNM37bojpgO1BoOQbFb0eLVz3QLDx7b+6kYcrxCuJfhw==", - "dev": true, - "requires": { - "array-includes": "^3.1.1", - "array.prototype.flatmap": "^1.2.3", - "doctrine": "^2.1.0", - "has": "^1.0.3", - "jsx-ast-utils": "^2.4.1", - "object.entries": "^1.1.2", - "object.fromentries": "^2.0.2", - "object.values": "^1.1.1", - "prop-types": "^15.7.2", - "resolve": "^1.17.0", - "string.prototype.matchall": "^4.0.2" - }, - "dependencies": { - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", - "dev": true, - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.8.1" - } - } - } - }, - "eslint-plugin-standard": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.1.tgz", - "integrity": "sha512-v/KBnfyaOMPmZc/dmc6ozOdWqekGp7bBGq4jLAecEfPGmfKiWS4sA8sC0LqiV9w5qmXAtXVn4M3p1jSyhY85SQ==", - "dev": true - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - } - }, - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - }, - "espree": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz", - "integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==", - "dev": true, - "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.2.0", - "eslint-visitor-keys": "^1.3.0" - } - }, - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" - }, - "esquery": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", - "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true - }, - "eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "events": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/events/-/events-2.1.0.tgz", - "integrity": "sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg==" - }, - "eventsource": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz", - "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==", - "dev": true, - "requires": { - "original": "^1.0.0" - } - }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "dev": true, - "requires": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "faye-websocket": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - }, - "figgy-pudding": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", - "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==" - }, - "file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", - "dev": true, - "requires": { - "flat-cache": "^2.0.1" - } - }, - "file-loader": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.1.0.tgz", - "integrity": "sha512-26qPdHyTsArQ6gU4P1HJbAbnFTyT2r0pG7czh1GFAd9TZbj0n94wWbupgixZH/ET/meqi2/5+F7DhW4OAXD+Lg==", - "requires": { - "loader-utils": "^2.0.0", - "schema-utils": "^2.7.1" - }, - "dependencies": { - "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", - "requires": { - "minimist": "^1.2.5" - } - }, - "loader-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", - "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - } - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "optional": true - }, - "filename-reserved-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-1.0.0.tgz", - "integrity": "sha1-5hz4BfDeHJhFZ9A4bcXfUO5a9+Q=" - }, - "filenamify": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-1.2.1.tgz", - "integrity": "sha1-qfL/0RxQO+0wABUCknI3jx8TZaU=", - "requires": { - "filename-reserved-regex": "^1.0.0", - "strip-outer": "^1.0.0", - "trim-repeated": "^1.0.0" - } - }, - "filenamify-url": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/filenamify-url/-/filenamify-url-1.0.0.tgz", - "integrity": "sha1-syvYExnvWGO3MHi+1Q9GpPeXX1A=", - "requires": { - "filenamify": "^1.0.0", - "humanize-url": "^1.0.0" - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - } - }, - "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", - "dev": true, - "requires": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - }, - "dependencies": { - "flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", - "dev": true - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "flatted": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.0.tgz", - "integrity": "sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA==" - }, - "flatten": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", - "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=" - }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "follow-redirects": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", - "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==", - "dev": true - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", - "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", - "dev": true - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "requires": { - "map-cache": "^0.2.2" - } - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true - }, - "from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "requires": { - "minipass": "^3.0.0" - } - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "optional": true - }, - "fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } - } - }, - "gaze": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", - "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", - "requires": { - "globule": "^1.0.0" - } - }, - "gensync": { - "version": "1.0.0-beta.1", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", - "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==" - }, - "get-assigned-identifiers": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", - "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==" - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" - }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "gh-pages": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-2.2.0.tgz", - "integrity": "sha512-c+yPkNOPMFGNisYg9r4qvsMIjVYikJv7ImFOhPIVPt0+AcRUamZ7zkGRLHz7FKB0xrlZ+ddSOJsZv9XAFVXLmA==", - "requires": { - "async": "^2.6.1", - "commander": "^2.18.0", - "email-addresses": "^3.0.1", - "filenamify-url": "^1.0.0", - "fs-extra": "^8.1.0", - "globby": "^6.1.0" - } - }, - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "requires": { - "is-glob": "^4.0.1" - } - }, - "global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "requires": { - "global-prefix": "^3.0.0" - }, - "dependencies": { - "global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "requires": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - } - } - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" - }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "globule": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz", - "integrity": "sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==", - "requires": { - "glob": "~7.1.1", - "lodash": "~4.17.10", - "minimatch": "~3.0.2" - } - }, - "graceful-fs": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", - "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==" - }, - "gud": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz", - "integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw==" - }, - "handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "requires": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "hex-color-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", - "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==" - }, - "highlightjs": { - "version": "9.16.2", - "resolved": "https://registry.npmjs.org/highlightjs/-/highlightjs-9.16.2.tgz", - "integrity": "sha512-FK1vmMj8BbEipEy8DLIvp71t5UsC7n2D6En/UfM/91PCwmOpj6f2iu0Y0coRC62KSRHHC+dquM2xMULV/X7NFg==" - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "requires": { - "react-is": "^16.7.0" - } - }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" - }, - "hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - } - }, - "hsl-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz", - "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=" - }, - "hsla-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", - "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=" - }, - "html-comment-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", - "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==" - }, - "html-entities": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz", - "integrity": "sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA==", - "dev": true - }, - "htmlescape": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", - "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=" - }, - "http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", - "dev": true - }, - "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - } - } - }, - "http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "requires": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-proxy-middleware": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", - "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", - "dev": true, - "requires": { - "http-proxy": "^1.17.0", - "is-glob": "^4.0.0", - "lodash": "^4.17.11", - "micromatch": "^3.1.10" - } - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" - }, - "humanize-url": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/humanize-url/-/humanize-url-1.0.1.tgz", - "integrity": "sha1-9KuZ4NKIF0yk4eUEB8VfuuRk7/8=", - "requires": { - "normalize-url": "^1.0.0", - "strip-url-auth": "^1.0.0" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "icss-utils": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", - "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", - "requires": { - "postcss": "^7.0.14" - } - }, - "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" - }, - "iferr": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "immutability-helper": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/immutability-helper/-/immutability-helper-3.1.1.tgz", - "integrity": "sha512-Q0QaXjPjwIju/28TsugCHNEASwoCcJSyJV3uO1sOIQGI0jKgm9f41Lvz0DZj3n46cNCyAZTsEYoY4C2bVRUzyQ==" - }, - "import-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", - "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", - "requires": { - "import-from": "^2.1.0" - } - }, - "import-fresh": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", - "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" - } - } - }, - "import-from": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", - "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", - "requires": { - "resolve-from": "^3.0.0" - } - }, - "import-local": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", - "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", - "requires": { - "pkg-dir": "^3.0.0", - "resolve-cwd": "^2.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" - }, - "in-publish": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.1.tgz", - "integrity": "sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ==" - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" - }, - "indexes-of": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", - "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=" - }, - "infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" - }, - "inline-source-map": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", - "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", - "requires": { - "source-map": "~0.5.3" - } - }, - "insert-module-globals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.0.tgz", - "integrity": "sha512-VE6NlW+WGn2/AeOMd496AHFYmE7eLKkUY6Ty31k4og5vmA3Fjuwe9v6ifH6Xx/Hz27QvdoMoviw1/pqWRB09Sw==", - "requires": { - "JSONStream": "^1.0.3", - "acorn-node": "^1.5.2", - "combine-source-map": "^0.8.0", - "concat-stream": "^1.6.1", - "is-buffer": "^1.1.0", - "path-is-absolute": "^1.0.1", - "process": "~0.11.0", - "through2": "^2.0.0", - "undeclared-identifiers": "^1.1.2", - "xtend": "^4.0.0" - } - }, - "internal-ip": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", - "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", - "dev": true, - "requires": { - "default-gateway": "^4.2.0", - "ipaddr.js": "^1.9.0" - } - }, - "internal-slot": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.2.tgz", - "integrity": "sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g==", - "dev": true, - "requires": { - "es-abstract": "^1.17.0-next.1", - "has": "^1.0.3", - "side-channel": "^1.0.2" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - } - } - }, - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" - }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "requires": { - "loose-envify": "^1.0.0" - } - }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - }, - "ip-regex": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", - "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", - "dev": true - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true - }, - "is-absolute-url": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", - "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", - "dev": true - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==" - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, - "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==" - }, - "is-color-stop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", - "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=", - "requires": { - "css-color-names": "^0.0.4", - "hex-color-regex": "^1.1.0", - "hsl-regex": "^1.0.0", - "hsla-regex": "^1.0.0", - "rgb-regex": "^1.0.1", - "rgba-regex": "^1.0.0" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, - "is-directory": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=" - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, - "is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==" - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-negative-zero": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", - "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=" - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" - }, - "is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true - }, - "is-path-in-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", - "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", - "dev": true, - "requires": { - "is-path-inside": "^2.1.0" - } - }, - "is-path-inside": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", - "dev": true, - "requires": { - "path-is-inside": "^1.0.2" - } - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "requires": { - "isobject": "^3.0.1" - } - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==" - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true - }, - "is-svg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz", - "integrity": "sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ==", - "requires": { - "html-comment-regex": "^1.1.0" - } - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" - }, - "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "isnumeric": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/isnumeric/-/isnumeric-0.2.0.tgz", - "integrity": "sha1-ojR7o2DeGeM9D/1ZD933dVy/LmQ=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "jest-worker": { - "version": "26.5.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.5.0.tgz", - "integrity": "sha512-kTw66Dn4ZX7WpjZ7T/SUDgRhapFRKWmisVAF0Rv4Fu8SLFD7eLbqpLvbxVqYhSgaWa7I+bW7pHnbyfNsH6stug==", - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "js-base64": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", - "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==" - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "dependencies": { - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" - } - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "json-stable-stringify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", - "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", - "requires": { - "jsonify": "~0.0.0" - } - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "json3": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", - "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==", - "dev": true - }, - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "requires": { - "minimist": "^1.2.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "jstransform": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/jstransform/-/jstransform-10.1.0.tgz", - "integrity": "sha1-tMSb9j8WLBCLA0g5moc3xxOwqDo=", - "requires": { - "base62": "0.1.1", - "esprima-fb": "13001.1001.0-dev-harmony-fb", - "source-map": "0.1.31" - }, - "dependencies": { - "esprima-fb": { - "version": "13001.1001.0-dev-harmony-fb", - "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-13001.1001.0-dev-harmony-fb.tgz", - "integrity": "sha1-YzrNtA2b1NuKHB1owGqUKVn60rA=" - }, - "source-map": { - "version": "0.1.31", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.31.tgz", - "integrity": "sha1-n3BNDWnZ4TioG63267T94z0VHGE=", - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, - "jsx-ast-utils": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz", - "integrity": "sha512-z1xSldJ6imESSzOjd3NNkieVJKRlKYSOtMG8SFyCj2FIrvSaSuli/WjpBkEzCBoR9bYYYFgqJw61Xhu7Lcgk+w==", - "dev": true, - "requires": { - "array-includes": "^3.1.1", - "object.assign": "^4.1.0" - } - }, - "killable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", - "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", - "dev": true - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" - }, - "labeled-stream-splicer": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz", - "integrity": "sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==", - "requires": { - "inherits": "^2.0.1", - "stream-splicer": "^2.0.0" - } - }, - "language-subtag-registry": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.20.tgz", - "integrity": "sha512-KPMwROklF4tEx283Xw0pNKtfTj1gZ4UByp4EsIFWLgBavJltF4TiYPc39k06zSTsLzxTVXXDSpbwaQXaFB4Qeg==", - "dev": true - }, - "language-tags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha1-0yHbxNowuovzAk4ED6XBRmH5GTo=", - "dev": true, - "requires": { - "language-subtag-registry": "~0.3.2" - } - }, - "last-call-webpack-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz", - "integrity": "sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w==", - "requires": { - "lodash": "^4.17.5", - "webpack-sources": "^1.1.0" - } - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" - }, - "levenary": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz", - "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==", - "requires": { - "leven": "^3.1.0" - } - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "lines-and-columns": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", - "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" - }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - } - }, - "loader-runner": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", - "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==" - }, - "loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" - }, - "lodash-es": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.15.tgz", - "integrity": "sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ==" - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" - }, - "lodash.has": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz", - "integrity": "sha1-0Z9NwQlQWMzL4rDN9O4P5Ko3yGI=" - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" - }, - "lodash.template": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", - "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", - "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.templatesettings": "^4.0.0" - } - }, - "lodash.templatesettings": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", - "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", - "requires": { - "lodash._reinterpolate": "^3.0.0" - } - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" - }, - "loglevel": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.0.tgz", - "integrity": "sha512-i2sY04nal5jDcagM3FMfG++T69GEEM8CYuOfeOIvmXzOIcwE9a/CJPR0MFM97pYMj/u10lzz7/zd7+qwhrBTqQ==", - "dev": true - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "make-cancellable-promise": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/make-cancellable-promise/-/make-cancellable-promise-1.0.0.tgz", - "integrity": "sha512-+YO6Grg2uy/z8Mv3uV90OP6yAUHIF43YGgEFbejmBrK9VWFsVO6DvzFMcopXr9wCNg3/QIltIKiSCROC7zFB2g==" - }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "dependencies": { - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" - } - } - }, - "make-event-props": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/make-event-props/-/make-event-props-1.2.0.tgz", - "integrity": "sha512-BmWFkm/jZzVH9A0tEBdkjAARUz/eha+5IRyfOndeSMKRadkgR5DawoBHoRwLxkYmjJOI5bHkXKpaZocxj+dKgg==" - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "requires": { - "object-visit": "^1.0.0" - } - }, - "marked": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-1.2.0.tgz", - "integrity": "sha512-tiRxakgbNPBr301ihe/785NntvYyhxlqcL3YaC8CaxJQh7kiaEtrN9B/eK2I2943Yjkh5gw25chYFDQhOMCwMA==" - }, - "math-expression-evaluator": { - "version": "1.2.22", - "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.22.tgz", - "integrity": "sha512-L0j0tFVZBQQLeEjmWOvDLoRciIY8gQGWahvkztXUal8jH8R5Rlqo9GCvgqvXcy9LQhEWdQCVvzqAbxgYNt4blQ==", - "dev": true - }, - "md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "mdn-data": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", - "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==" - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true - }, - "memoize-one": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.1.1.tgz", - "integrity": "sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA==" - }, - "memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - }, - "dependencies": { - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "requires": { - "is-utf8": "^0.2.0" - } - } - } - }, - "merge-class-names": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/merge-class-names/-/merge-class-names-1.3.0.tgz", - "integrity": "sha512-k0Qaj36VBpKgdc8c188LEZvo6v/zzry/FUufwopWbMSp6/knfVFU/KIB55/hJjeIpg18IH2WskXJCRnM/1BrdQ==" - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" - } - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" - }, - "mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", - "requires": { - "mime-db": "1.40.0" - } - }, - "mini-css-extract-plugin": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz", - "integrity": "sha512-lp3GeY7ygcgAmVIcRPBVhIkf8Us7FZjA+ILpal44qLdSu11wmjKQ3d9k15lfD7pO4esu9eUIAW7qiYIBppv40A==", - "requires": { - "loader-utils": "^1.1.0", - "normalize-url": "1.9.1", - "schema-utils": "^1.0.0", - "webpack-sources": "^1.1.0" - }, - "dependencies": { - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - } - } - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - }, - "minipass": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", - "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", - "requires": { - "yallist": "^4.0.0" - } - }, - "minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "requires": { - "minipass": "^3.0.0" - } - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - } - }, - "mississippi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - } - }, - "mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" - }, - "module-deps": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.3.tgz", - "integrity": "sha512-fg7OZaQBcL4/L+AK5f4iVqf9OMbCclXfy/znXRxTVhJSeW5AIlS9AwheYwDaXM3lVW7OBeaeUEY3gbaC6cLlSA==", - "requires": { - "JSONStream": "^1.0.3", - "browser-resolve": "^2.0.0", - "cached-path-relative": "^1.0.2", - "concat-stream": "~1.6.0", - "defined": "^1.0.0", - "detective": "^5.2.0", - "duplexer2": "^0.1.2", - "inherits": "^2.0.1", - "parents": "^1.0.0", - "readable-stream": "^2.0.2", - "resolve": "^1.4.0", - "stream-combiner2": "^1.1.1", - "subarg": "^1.0.0", - "through2": "^2.0.0", - "xtend": "^4.0.0" - } - }, - "moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" - }, - "moment-timezone": { - "version": "0.5.31", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.31.tgz", - "integrity": "sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==", - "requires": { - "moment": ">= 2.9.0" - }, - "dependencies": { - "moment": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", - "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" - } - } - }, - "move-concurrently": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", - "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "multicast-dns": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", - "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", - "dev": true, - "requires": { - "dns-packet": "^1.3.1", - "thunky": "^1.0.2" - } - }, - "multicast-dns-service-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", - "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", - "dev": true - }, - "nan": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==" - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "native-promise-only": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", - "integrity": "sha1-IKMYwwy0X3H+et+/eyHJnBRy7xE=" - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "dev": true - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" - }, - "node-ensure": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/node-ensure/-/node-ensure-0.0.0.tgz", - "integrity": "sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc=" - }, - "node-forge": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", - "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", - "dev": true - }, - "node-gyp": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", - "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", - "requires": { - "fstream": "^1.0.0", - "glob": "^7.0.3", - "graceful-fs": "^4.1.2", - "mkdirp": "^0.5.0", - "nopt": "2 || 3", - "npmlog": "0 || 1 || 2 || 3 || 4", - "osenv": "0", - "request": "^2.87.0", - "rimraf": "2", - "semver": "~5.3.0", - "tar": "^2.0.0", - "which": "1" - }, - "dependencies": { - "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" - }, - "tar": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", - "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", - "requires": { - "block-stream": "*", - "fstream": "^1.0.12", - "inherits": "2" - } - } - } - }, - "node-libs-browser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", - "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", - "requires": { - "assert": "^1.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^3.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "0.0.1", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.11.0", - "vm-browserify": "^1.0.1" - }, - "dependencies": { - "buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "events": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", - "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==" - }, - "stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - } - }, - "timers-browserify": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", - "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==", - "requires": { - "setimmediate": "^1.0.4" - } - }, - "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" - }, - "util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", - "requires": { - "inherits": "2.0.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - } - } - } - } - }, - "node-releases": { - "version": "1.1.61", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.61.tgz", - "integrity": "sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g==" - }, - "node-sass": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.14.1.tgz", - "integrity": "sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g==", - "requires": { - "async-foreach": "^0.1.3", - "chalk": "^1.1.1", - "cross-spawn": "^3.0.0", - "gaze": "^1.0.0", - "get-stdin": "^4.0.1", - "glob": "^7.0.3", - "in-publish": "^2.0.0", - "lodash": "^4.17.15", - "meow": "^3.7.0", - "mkdirp": "^0.5.1", - "nan": "^2.13.2", - "node-gyp": "^3.8.0", - "npmlog": "^4.0.0", - "request": "^2.88.0", - "sass-graph": "2.2.5", - "stdout-stream": "^1.4.0", - "true-case-path": "^1.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "cross-spawn": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", - "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", - "requires": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" - } - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" - } - } - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "requires": { - "abbrev": "1" - } - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=" - }, - "normalize-url": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", - "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", - "requires": { - "object-assign": "^4.0.1", - "prepend-http": "^1.0.0", - "query-string": "^4.1.0", - "sort-keys": "^1.0.0" - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "requires": { - "boolbase": "~1.0.0" - } - }, - "num2fraction": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", - "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=" - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==" - }, - "object-is": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.3.tgz", - "integrity": "sha512-teyqLvFWzLkq5B9ki8FVWA902UER2qkxmdA4nLf+wjOLAWgxzCWZNCxpDq9MvE8MmhWNr+I8w3BN49Vx36Y6Xg==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - } - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "requires": { - "isobject": "^3.0.0" - } - }, - "object.assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", - "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.0", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - }, - "object.entries": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.2.tgz", - "integrity": "sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5", - "has": "^1.0.3" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - } - } - }, - "object.fromentries": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.2.tgz", - "integrity": "sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "has": "^1.0.3" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - } - } - }, - "object.getownpropertydescriptors": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", - "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "requires": { - "has-symbols": "^1.0.1" - } - } - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "requires": { - "isobject": "^3.0.1" - } - }, - "object.values": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", - "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "has": "^1.0.3" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "requires": { - "has-symbols": "^1.0.1" - } - } - } - }, - "objectify-array": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/objectify-array/-/objectify-array-2.1.0.tgz", - "integrity": "sha512-tG8ndq75CyLdsVSB5e3Xp6ajVi0oC3LsR0lMiGx3imtYWrGNnpdPzP/Tv3UQsRO2OCvpqUedQyZAv20OrlK2WA==" - }, - "obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "onecolor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/onecolor/-/onecolor-3.1.0.tgz", - "integrity": "sha512-YZSypViXzu3ul5LMu/m6XjJ9ol8qAy9S2VjHl5E6UlhUH1KGKWabyEJifn0Jjpw23bYDzC2ucKMPGiH5kfwSGQ==", - "dev": true - }, - "opn": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", - "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", - "dev": true, - "requires": { - "is-wsl": "^1.1.0" - } - }, - "optimize-css-assets-webpack-plugin": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.4.tgz", - "integrity": "sha512-wqd6FdI2a5/FdoiCNNkEvLeA//lHHfG24Ln2Xm2qqdIk4aOlsR18jwpyOihqQ8849W3qu2DX8fOYxpvTMj+93A==", - "requires": { - "cssnano": "^4.1.10", - "last-call-webpack-plugin": "^3.0.0" - } - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "original": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", - "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", - "dev": true, - "requires": { - "url-parse": "^1.4.3" - } - }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - }, - "dependencies": { - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - } - } - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-retry": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", - "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", - "dev": true, - "requires": { - "retry": "^0.12.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" - }, - "pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" - }, - "parallel-transform": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", - "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", - "requires": { - "cyclist": "^1.0.1", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "requires": { - "callsites": "^3.0.0" - } - }, - "parents": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", - "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", - "requires": { - "path-platform": "~0.11.15" - } - }, - "parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "requires": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "requires": { - "error-ex": "^1.2.0" - } - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" - }, - "path-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", - "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==" - }, - "path-complete-extname": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-complete-extname/-/path-complete-extname-1.0.0.tgz", - "integrity": "sha512-CVjiWcMRdGU8ubs08YQVzhutOR5DEfO97ipRIlOGMK5Bek5nQySknBpuxVAVJ36hseTNs+vdIcv57ZrWxH7zvg==" - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" - }, - "path-platform": { - "version": "0.11.15", - "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", - "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } - }, - "pbkdf2": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", - "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "pdfjs-dist": { - "version": "2.1.266", - "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.1.266.tgz", - "integrity": "sha512-Jy7o1wE3NezPxozexSbq4ltuLT0Z21ew/qrEiAEeUZzHxMHGk4DUV1D7RuCXg5vJDvHmjX1YssN+we9QfRRgXQ==", - "requires": { - "node-ensure": "^0.0.0", - "worker-loader": "^2.0.0" - } - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "requires": { - "pinkie": "^2.0.0" - } - }, - "pixrem": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pixrem/-/pixrem-4.0.1.tgz", - "integrity": "sha1-LaSh3m7EQjxfw3lOkwuB1EkOxoY=", - "dev": true, - "requires": { - "browserslist": "^2.0.0", - "postcss": "^6.0.0", - "reduce-css-calc": "^1.2.7" - }, - "dependencies": { - "browserslist": { - "version": "2.11.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", - "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000792", - "electron-to-chromium": "^1.3.30" - } - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "requires": { - "find-up": "^3.0.0" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "requires": { - "p-limit": "^2.0.0" - } - } - } - }, - "pleeease-filters": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pleeease-filters/-/pleeease-filters-4.0.0.tgz", - "integrity": "sha1-ZjKy+wVkjSdY2GU4T7zteeHMrsc=", - "dev": true, - "requires": { - "onecolor": "^3.0.4", - "postcss": "^6.0.1" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "pnp-webpack-plugin": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz", - "integrity": "sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg==", - "requires": { - "ts-pnp": "^1.1.6" - } - }, - "popper.js": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", - "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==" - }, - "portfinder": { - "version": "1.0.28", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", - "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", - "dev": true, - "requires": { - "async": "^2.6.2", - "debug": "^3.1.1", - "mkdirp": "^0.5.5" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - } - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" - }, - "postcss": { - "version": "7.0.17", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz", - "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==", - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "postcss-apply": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/postcss-apply/-/postcss-apply-0.8.0.tgz", - "integrity": "sha1-FOVEu7XLbxweBIhXll15rgZrE0M=", - "dev": true, - "requires": { - "babel-runtime": "^6.23.0", - "balanced-match": "^0.4.2", - "postcss": "^6.0.0" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-attribute-case-insensitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-2.0.0.tgz", - "integrity": "sha1-lNxCLI+QmX8WvTOjZUu77AhJY7Q=", - "dev": true, - "requires": { - "postcss": "^6.0.0", - "postcss-selector-parser": "^2.2.3" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "postcss-selector-parser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", - "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", - "dev": true, - "requires": { - "flatten": "^1.0.2", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-calc": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-6.0.2.tgz", - "integrity": "sha512-fiznXjEN5T42Qm7qqMCVJXS3roaj9r4xsSi+meaBVe7CJBl8t/QLOXu02Z2E6oWAMWIvCuF6JrvzFekmVEbOKA==", - "dev": true, - "requires": { - "css-unit-converter": "^1.1.1", - "postcss": "^7.0.2", - "postcss-selector-parser": "^2.2.2", - "reduce-css-calc": "^2.0.0" - }, - "dependencies": { - "postcss-selector-parser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", - "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", - "dev": true, - "requires": { - "flatten": "^1.0.2", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - }, - "reduce-css-calc": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-2.1.7.tgz", - "integrity": "sha512-fDnlZ+AybAS3C7Q9xDq5y8A2z+lT63zLbynew/lur/IR24OQF5x98tfNwf79mzEdfywZ0a2wpM860FhFfMxZlA==", - "dev": true, - "requires": { - "css-unit-converter": "^1.1.1", - "postcss-value-parser": "^3.3.0" - } - } - } - }, - "postcss-color-function": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-color-function/-/postcss-color-function-4.1.0.tgz", - "integrity": "sha512-2/fuv6mP5Lt03XbRpVfMdGC8lRP1sykme+H1bR4ARyOmSMB8LPSjcL6EAI1iX6dqUF+jNEvKIVVXhan1w/oFDQ==", - "dev": true, - "requires": { - "css-color-function": "~1.3.3", - "postcss": "^6.0.23", - "postcss-message-helpers": "^2.0.0", - "postcss-value-parser": "^3.3.1" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-color-functional-notation": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz", - "integrity": "sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g==", - "requires": { - "postcss": "^7.0.2", - "postcss-values-parser": "^2.0.0" - } - }, - "postcss-color-gray": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-color-gray/-/postcss-color-gray-4.1.0.tgz", - "integrity": "sha512-L4iLKQLdqChz6ZOgGb6dRxkBNw78JFYcJmBz1orHpZoeLtuhDDGegRtX9gSyfoCIM7rWZ3VNOyiqqvk83BEN+w==", - "dev": true, - "requires": { - "color": "^2.0.1", - "postcss": "^6.0.14", - "postcss-message-helpers": "^2.0.0", - "reduce-function-call": "^1.0.2" - }, - "dependencies": { - "color": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color/-/color-2.0.1.tgz", - "integrity": "sha512-ubUCVVKfT7r2w2D3qtHakj8mbmKms+tThR8gI8zEYCbUBl8/voqFGt3kgBqGwXAopgXybnkuOq+qMYCRrp4cXw==", - "dev": true, - "requires": { - "color-convert": "^1.9.1", - "color-string": "^1.5.2" - } - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-color-hex-alpha": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-3.0.0.tgz", - "integrity": "sha1-HlPmyKyyN5Vej9CLfs2xuLgwn5U=", - "dev": true, - "requires": { - "color": "^1.0.3", - "postcss": "^6.0.1", - "postcss-message-helpers": "^2.0.0" - }, - "dependencies": { - "color": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/color/-/color-1.0.3.tgz", - "integrity": "sha1-5I6DLYXxTvaU+0aIEcLVz+cptV0=", - "dev": true, - "requires": { - "color-convert": "^1.8.2", - "color-string": "^1.4.0" - } - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-color-hsl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-color-hsl/-/postcss-color-hsl-2.0.0.tgz", - "integrity": "sha1-EnA2ZvoxBDDj8wpFTawThjF9WEQ=", - "dev": true, - "requires": { - "postcss": "^6.0.1", - "postcss-value-parser": "^3.3.0", - "units-css": "^0.4.0" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-color-hwb": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-color-hwb/-/postcss-color-hwb-3.0.0.tgz", - "integrity": "sha1-NAKxnvTYSXVAwftQcr6YY8qVVx4=", - "dev": true, - "requires": { - "color": "^1.0.3", - "postcss": "^6.0.1", - "postcss-message-helpers": "^2.0.0", - "reduce-function-call": "^1.0.2" - }, - "dependencies": { - "color": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/color/-/color-1.0.3.tgz", - "integrity": "sha1-5I6DLYXxTvaU+0aIEcLVz+cptV0=", - "dev": true, - "requires": { - "color-convert": "^1.8.2", - "color-string": "^1.4.0" - } - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-color-mod-function": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz", - "integrity": "sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ==", - "requires": { - "@csstools/convert-colors": "^1.4.0", - "postcss": "^7.0.2", - "postcss-values-parser": "^2.0.0" - } - }, - "postcss-color-rebeccapurple": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-3.1.0.tgz", - "integrity": "sha512-212hJUk9uSsbwO5ECqVjmh/iLsmiVL1xy9ce9TVf+X3cK/ZlUIlaMdoxje/YpsL9cmUH3I7io+/G2LyWx5rg1g==", - "dev": true, - "requires": { - "postcss": "^6.0.22", - "postcss-values-parser": "^1.5.0" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "postcss-values-parser": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-1.5.0.tgz", - "integrity": "sha512-3M3p+2gMp0AH3da530TlX8kiO1nxdTnc3C6vr8dMxRLIlh8UYkz0/wcwptSXjhtx2Fr0TySI7a+BHDQ8NL7LaQ==", - "dev": true, - "requires": { - "flatten": "^1.0.2", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-color-rgb": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-color-rgb/-/postcss-color-rgb-2.0.0.tgz", - "integrity": "sha1-FFOcinExSUtILg3RzCZf9lFLUmM=", - "dev": true, - "requires": { - "postcss": "^6.0.1", - "postcss-value-parser": "^3.3.0" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-color-rgba-fallback": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-color-rgba-fallback/-/postcss-color-rgba-fallback-3.0.0.tgz", - "integrity": "sha1-N9XJNToHoJJwkSqCYGu0Kg1wLAQ=", - "dev": true, - "requires": { - "postcss": "^6.0.6", - "postcss-value-parser": "^3.3.0", - "rgb-hex": "^2.1.0" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-colormin": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz", - "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==", - "requires": { - "browserslist": "^4.0.0", - "color": "^3.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "dependencies": { - "color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/color/-/color-3.1.2.tgz", - "integrity": "sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg==", - "requires": { - "color-convert": "^1.9.1", - "color-string": "^1.5.2" - } - } - } - }, - "postcss-convert-values": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz", - "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==", - "requires": { - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - } - }, - "postcss-cssnext": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/postcss-cssnext/-/postcss-cssnext-3.1.0.tgz", - "integrity": "sha512-awPDhI4OKetcHCr560iVCoDuP6e/vn0r6EAqdWPpAavJMvkBSZ6kDpSN4b3mB3Ti57hQMunHHM8Wvx9PeuYXtA==", - "dev": true, - "requires": { - "autoprefixer": "^7.1.1", - "caniuse-api": "^2.0.0", - "chalk": "^2.0.1", - "pixrem": "^4.0.0", - "pleeease-filters": "^4.0.0", - "postcss": "^6.0.5", - "postcss-apply": "^0.8.0", - "postcss-attribute-case-insensitive": "^2.0.0", - "postcss-calc": "^6.0.0", - "postcss-color-function": "^4.0.0", - "postcss-color-gray": "^4.0.0", - "postcss-color-hex-alpha": "^3.0.0", - "postcss-color-hsl": "^2.0.0", - "postcss-color-hwb": "^3.0.0", - "postcss-color-rebeccapurple": "^3.0.0", - "postcss-color-rgb": "^2.0.0", - "postcss-color-rgba-fallback": "^3.0.0", - "postcss-custom-media": "^6.0.0", - "postcss-custom-properties": "^6.1.0", - "postcss-custom-selectors": "^4.0.1", - "postcss-font-family-system-ui": "^3.0.0", - "postcss-font-variant": "^3.0.0", - "postcss-image-set-polyfill": "^0.3.5", - "postcss-initial": "^2.0.0", - "postcss-media-minmax": "^3.0.0", - "postcss-nesting": "^4.0.1", - "postcss-pseudo-class-any-link": "^4.0.0", - "postcss-pseudoelements": "^5.0.0", - "postcss-replace-overflow-wrap": "^2.0.0", - "postcss-selector-matches": "^3.0.1", - "postcss-selector-not": "^3.0.1" - }, - "dependencies": { - "browserslist": { - "version": "2.11.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", - "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000792", - "electron-to-chromium": "^1.3.30" - } - }, - "caniuse-api": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-2.0.0.tgz", - "integrity": "sha1-sd21pZZrFvSNxJmERNS7xsfZ2DQ=", - "dev": true, - "requires": { - "browserslist": "^2.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-custom-media": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-6.0.0.tgz", - "integrity": "sha1-vlMnhBEOyylQRPtTlaGABushpzc=", - "dev": true, - "requires": { - "postcss": "^6.0.1" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-custom-properties": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-6.3.1.tgz", - "integrity": "sha512-zoiwn4sCiUFbr4KcgcNZLFkR6gVQom647L+z1p/KBVHZ1OYwT87apnS42atJtx6XlX2yI7N5fjXbFixShQO2QQ==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "postcss": "^6.0.18" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-custom-selectors": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-4.0.1.tgz", - "integrity": "sha1-eBOC+UxS5yfvXKR3bqKt9JphE4I=", - "dev": true, - "requires": { - "postcss": "^6.0.1", - "postcss-selector-matches": "^3.0.0" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-dir-pseudo-class": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz", - "integrity": "sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw==", - "requires": { - "postcss": "^7.0.2", - "postcss-selector-parser": "^5.0.0-rc.3" - }, - "dependencies": { - "cssesc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", - "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==" - }, - "postcss-selector-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", - "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", - "requires": { - "cssesc": "^2.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - } - } - }, - "postcss-discard-comments": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz", - "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==", - "requires": { - "postcss": "^7.0.0" - } - }, - "postcss-discard-duplicates": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz", - "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==", - "requires": { - "postcss": "^7.0.0" - } - }, - "postcss-discard-empty": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz", - "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==", - "requires": { - "postcss": "^7.0.0" - } - }, - "postcss-discard-overridden": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz", - "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==", - "requires": { - "postcss": "^7.0.0" - } - }, - "postcss-double-position-gradients": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz", - "integrity": "sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA==", - "requires": { - "postcss": "^7.0.5", - "postcss-values-parser": "^2.0.0" - } - }, - "postcss-env-function": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-2.0.2.tgz", - "integrity": "sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw==", - "requires": { - "postcss": "^7.0.2", - "postcss-values-parser": "^2.0.0" - } - }, - "postcss-flexbugs-fixes": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-4.2.1.tgz", - "integrity": "sha512-9SiofaZ9CWpQWxOwRh1b/r85KD5y7GgvsNt1056k6OYLvWUun0czCvogfJgylC22uJTwW1KzY3Gz65NZRlvoiQ==", - "requires": { - "postcss": "^7.0.26" - }, - "dependencies": { - "postcss": { - "version": "7.0.35", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", - "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "postcss-focus-visible": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz", - "integrity": "sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g==", - "requires": { - "postcss": "^7.0.2" - } - }, - "postcss-focus-within": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz", - "integrity": "sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w==", - "requires": { - "postcss": "^7.0.2" - } - }, - "postcss-font-family-system-ui": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-font-family-system-ui/-/postcss-font-family-system-ui-3.0.0.tgz", - "integrity": "sha512-58G/hTxMSSKlIRpcPUjlyo6hV2MEzvcVO2m4L/T7Bb2fJTG4DYYfQjQeRvuimKQh1V1sOzCIz99g+H2aFNtlQw==", - "dev": true, - "requires": { - "postcss": "^6.0" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-font-variant": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-3.0.0.tgz", - "integrity": "sha1-CMzIj2BQuoLtjvLMdsDGprQfGD4=", - "dev": true, - "requires": { - "postcss": "^6.0.1" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-gap-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz", - "integrity": "sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg==", - "requires": { - "postcss": "^7.0.2" - } - }, - "postcss-image-set-function": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz", - "integrity": "sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw==", - "requires": { - "postcss": "^7.0.2", - "postcss-values-parser": "^2.0.0" - } - }, - "postcss-image-set-polyfill": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/postcss-image-set-polyfill/-/postcss-image-set-polyfill-0.3.5.tgz", - "integrity": "sha1-Dxk0E3AM8fgr05Bm7wFtZaShgYE=", - "dev": true, - "requires": { - "postcss": "^6.0.1", - "postcss-media-query-parser": "^0.2.3" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-import": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-12.0.1.tgz", - "integrity": "sha512-3Gti33dmCjyKBgimqGxL3vcV8w9+bsHwO5UrBawp796+jdardbcFl4RP5w/76BwNL7aGzpKstIfF9I+kdE8pTw==", - "requires": { - "postcss": "^7.0.1", - "postcss-value-parser": "^3.2.3", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - } - }, - "postcss-initial": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-2.0.0.tgz", - "integrity": "sha1-cnFfczbgu3k1HZnuZcSiU6hEG6Q=", - "dev": true, - "requires": { - "lodash.template": "^4.2.4", - "postcss": "^6.0.1" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-lab-function": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz", - "integrity": "sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg==", - "requires": { - "@csstools/convert-colors": "^1.4.0", - "postcss": "^7.0.2", - "postcss-values-parser": "^2.0.0" - } - }, - "postcss-load-config": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.2.tgz", - "integrity": "sha512-/rDeGV6vMUo3mwJZmeHfEDvwnTKKqQ0S7OHUi/kJvvtx3aWtyWG2/0ZWnzCt2keEclwN6Tf0DST2v9kITdOKYw==", - "requires": { - "cosmiconfig": "^5.0.0", - "import-cwd": "^2.0.0" - }, - "dependencies": { - "cosmiconfig": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", - "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", - "requires": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.13.1", - "parse-json": "^4.0.0" - } - }, - "import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", - "requires": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" - } - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - } - } - }, - "postcss-loader": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", - "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", - "requires": { - "loader-utils": "^1.1.0", - "postcss": "^7.0.0", - "postcss-load-config": "^2.0.0", - "schema-utils": "^1.0.0" - }, - "dependencies": { - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - } - } - }, - "postcss-logical": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-3.0.0.tgz", - "integrity": "sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA==", - "requires": { - "postcss": "^7.0.2" - } - }, - "postcss-media-minmax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-3.0.0.tgz", - "integrity": "sha1-Z1JWA3pD70C8Twdgv9BtTcadSNI=", - "dev": true, - "requires": { - "postcss": "^6.0.1" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-media-query-parser": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", - "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=", - "dev": true - }, - "postcss-merge-longhand": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", - "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==", - "requires": { - "css-color-names": "0.0.4", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0", - "stylehacks": "^4.0.0" - } - }, - "postcss-merge-rules": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", - "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==", - "requires": { - "browserslist": "^4.0.0", - "caniuse-api": "^3.0.0", - "cssnano-util-same-parent": "^4.0.0", - "postcss": "^7.0.0", - "postcss-selector-parser": "^3.0.0", - "vendors": "^1.0.0" - }, - "dependencies": { - "postcss-selector-parser": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", - "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", - "requires": { - "dot-prop": "^5.2.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - } - } - }, - "postcss-message-helpers": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz", - "integrity": "sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4=", - "dev": true - }, - "postcss-minify-font-values": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz", - "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==", - "requires": { - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - } - }, - "postcss-minify-gradients": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz", - "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==", - "requires": { - "cssnano-util-get-arguments": "^4.0.0", - "is-color-stop": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - } - }, - "postcss-minify-params": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz", - "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==", - "requires": { - "alphanum-sort": "^1.0.0", - "browserslist": "^4.0.0", - "cssnano-util-get-arguments": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0", - "uniqs": "^2.0.0" - } - }, - "postcss-minify-selectors": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz", - "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==", - "requires": { - "alphanum-sort": "^1.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-selector-parser": "^3.0.0" - }, - "dependencies": { - "postcss-selector-parser": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", - "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", - "requires": { - "dot-prop": "^5.2.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - } - } - }, - "postcss-modules-extract-imports": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", - "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", - "requires": { - "postcss": "^7.0.5" - } - }, - "postcss-modules-local-by-default": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", - "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", - "requires": { - "icss-utils": "^4.1.1", - "postcss": "^7.0.32", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - }, - "dependencies": { - "postcss": { - "version": "7.0.35", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", - "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - } - }, - "postcss-value-parser": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", - "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==" - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "postcss-modules-scope": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", - "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", - "requires": { - "postcss": "^7.0.6", - "postcss-selector-parser": "^6.0.0" - } - }, - "postcss-modules-values": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", - "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", - "requires": { - "icss-utils": "^4.0.0", - "postcss": "^7.0.6" - } - }, - "postcss-nesting": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-4.2.1.tgz", - "integrity": "sha512-IkyWXICwagCnlaviRexi7qOdwPw3+xVVjgFfGsxmztvRVaNxAlrypOIKqDE5mxY+BVxnId1rnUKBRQoNE2VDaA==", - "dev": true, - "requires": { - "postcss": "^6.0.11" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-normalize-charset": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", - "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==", - "requires": { - "postcss": "^7.0.0" - } - }, - "postcss-normalize-display-values": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", - "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==", - "requires": { - "cssnano-util-get-match": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - } - }, - "postcss-normalize-positions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", - "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==", - "requires": { - "cssnano-util-get-arguments": "^4.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - } - }, - "postcss-normalize-repeat-style": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", - "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==", - "requires": { - "cssnano-util-get-arguments": "^4.0.0", - "cssnano-util-get-match": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - } - }, - "postcss-normalize-string": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", - "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==", - "requires": { - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - } - }, - "postcss-normalize-timing-functions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", - "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==", - "requires": { - "cssnano-util-get-match": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - } - }, - "postcss-normalize-unicode": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", - "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", - "requires": { - "browserslist": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - } - }, - "postcss-normalize-url": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz", - "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==", - "requires": { - "is-absolute-url": "^2.0.0", - "normalize-url": "^3.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "dependencies": { - "is-absolute-url": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", - "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=" - }, - "normalize-url": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", - "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==" - } - } - }, - "postcss-normalize-whitespace": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz", - "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==", - "requires": { - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - } - }, - "postcss-ordered-values": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz", - "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==", - "requires": { - "cssnano-util-get-arguments": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - } - }, - "postcss-overflow-shorthand": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz", - "integrity": "sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g==", - "requires": { - "postcss": "^7.0.2" - } - }, - "postcss-page-break": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-2.0.0.tgz", - "integrity": "sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ==", - "requires": { - "postcss": "^7.0.2" - } - }, - "postcss-place": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-4.0.1.tgz", - "integrity": "sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg==", - "requires": { - "postcss": "^7.0.2", - "postcss-values-parser": "^2.0.0" - } - }, - "postcss-preset-env": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz", - "integrity": "sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg==", - "requires": { - "autoprefixer": "^9.6.1", - "browserslist": "^4.6.4", - "caniuse-lite": "^1.0.30000981", - "css-blank-pseudo": "^0.1.4", - "css-has-pseudo": "^0.10.0", - "css-prefers-color-scheme": "^3.1.1", - "cssdb": "^4.4.0", - "postcss": "^7.0.17", - "postcss-attribute-case-insensitive": "^4.0.1", - "postcss-color-functional-notation": "^2.0.1", - "postcss-color-gray": "^5.0.0", - "postcss-color-hex-alpha": "^5.0.3", - "postcss-color-mod-function": "^3.0.3", - "postcss-color-rebeccapurple": "^4.0.1", - "postcss-custom-media": "^7.0.8", - "postcss-custom-properties": "^8.0.11", - "postcss-custom-selectors": "^5.1.2", - "postcss-dir-pseudo-class": "^5.0.0", - "postcss-double-position-gradients": "^1.0.0", - "postcss-env-function": "^2.0.2", - "postcss-focus-visible": "^4.0.0", - "postcss-focus-within": "^3.0.0", - "postcss-font-variant": "^4.0.0", - "postcss-gap-properties": "^2.0.0", - "postcss-image-set-function": "^3.0.1", - "postcss-initial": "^3.0.0", - "postcss-lab-function": "^2.0.1", - "postcss-logical": "^3.0.0", - "postcss-media-minmax": "^4.0.0", - "postcss-nesting": "^7.0.0", - "postcss-overflow-shorthand": "^2.0.0", - "postcss-page-break": "^2.0.0", - "postcss-place": "^4.0.1", - "postcss-pseudo-class-any-link": "^6.0.0", - "postcss-replace-overflow-wrap": "^3.0.0", - "postcss-selector-matches": "^4.0.0", - "postcss-selector-not": "^4.0.0" - }, - "dependencies": { - "autoprefixer": { - "version": "9.8.6", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.6.tgz", - "integrity": "sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==", - "requires": { - "browserslist": "^4.12.0", - "caniuse-lite": "^1.0.30001109", - "colorette": "^1.2.1", - "normalize-range": "^0.1.2", - "num2fraction": "^1.2.2", - "postcss": "^7.0.32", - "postcss-value-parser": "^4.1.0" - }, - "dependencies": { - "postcss": { - "version": "7.0.35", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", - "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - } - } - } - }, - "cssesc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", - "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==" - }, - "postcss-attribute-case-insensitive": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz", - "integrity": "sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA==", - "requires": { - "postcss": "^7.0.2", - "postcss-selector-parser": "^6.0.2" - } - }, - "postcss-color-gray": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz", - "integrity": "sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw==", - "requires": { - "@csstools/convert-colors": "^1.4.0", - "postcss": "^7.0.5", - "postcss-values-parser": "^2.0.0" - } - }, - "postcss-color-hex-alpha": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz", - "integrity": "sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw==", - "requires": { - "postcss": "^7.0.14", - "postcss-values-parser": "^2.0.1" - } - }, - "postcss-color-rebeccapurple": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz", - "integrity": "sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g==", - "requires": { - "postcss": "^7.0.2", - "postcss-values-parser": "^2.0.0" - } - }, - "postcss-custom-media": { - "version": "7.0.8", - "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz", - "integrity": "sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg==", - "requires": { - "postcss": "^7.0.14" - } - }, - "postcss-custom-properties": { - "version": "8.0.11", - "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz", - "integrity": "sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA==", - "requires": { - "postcss": "^7.0.17", - "postcss-values-parser": "^2.0.1" - } - }, - "postcss-custom-selectors": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz", - "integrity": "sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w==", - "requires": { - "postcss": "^7.0.2", - "postcss-selector-parser": "^5.0.0-rc.3" - }, - "dependencies": { - "postcss-selector-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", - "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", - "requires": { - "cssesc": "^2.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - } - } - }, - "postcss-font-variant": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-4.0.0.tgz", - "integrity": "sha512-M8BFYKOvCrI2aITzDad7kWuXXTm0YhGdP9Q8HanmN4EF1Hmcgs1KK5rSHylt/lUJe8yLxiSwWAHdScoEiIxztg==", - "requires": { - "postcss": "^7.0.2" - } - }, - "postcss-initial": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-3.0.2.tgz", - "integrity": "sha512-ugA2wKonC0xeNHgirR4D3VWHs2JcU08WAi1KFLVcnb7IN89phID6Qtg2RIctWbnvp1TM2BOmDtX8GGLCKdR8YA==", - "requires": { - "lodash.template": "^4.5.0", - "postcss": "^7.0.2" - } - }, - "postcss-media-minmax": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz", - "integrity": "sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw==", - "requires": { - "postcss": "^7.0.2" - } - }, - "postcss-nesting": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-7.0.1.tgz", - "integrity": "sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg==", - "requires": { - "postcss": "^7.0.2" - } - }, - "postcss-pseudo-class-any-link": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz", - "integrity": "sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew==", - "requires": { - "postcss": "^7.0.2", - "postcss-selector-parser": "^5.0.0-rc.3" - }, - "dependencies": { - "postcss-selector-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", - "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", - "requires": { - "cssesc": "^2.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - } - } - }, - "postcss-replace-overflow-wrap": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz", - "integrity": "sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw==", - "requires": { - "postcss": "^7.0.2" - } - }, - "postcss-selector-matches": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz", - "integrity": "sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww==", - "requires": { - "balanced-match": "^1.0.0", - "postcss": "^7.0.2" - } - }, - "postcss-selector-not": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-4.0.0.tgz", - "integrity": "sha512-W+bkBZRhqJaYN8XAnbbZPLWMvZD1wKTu0UxtFKdhtGjWYmxhkUneoeOhRJKdAE5V7ZTlnbHfCR+6bNwK9e1dTQ==", - "requires": { - "balanced-match": "^1.0.0", - "postcss": "^7.0.2" - } - }, - "postcss-value-parser": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", - "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==" - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "postcss-pseudo-class-any-link": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-4.0.0.tgz", - "integrity": "sha1-kVKgYT00UHIFE+iJKFS65C0O5o4=", - "dev": true, - "requires": { - "postcss": "^6.0.1", - "postcss-selector-parser": "^2.2.3" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "postcss-selector-parser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", - "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", - "dev": true, - "requires": { - "flatten": "^1.0.2", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-pseudoelements": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-pseudoelements/-/postcss-pseudoelements-5.0.0.tgz", - "integrity": "sha1-7vGU6NUkZFylIKlJ6V5RjoEkAss=", - "dev": true, - "requires": { - "postcss": "^6.0.0" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-reduce-initial": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", - "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==", - "requires": { - "browserslist": "^4.0.0", - "caniuse-api": "^3.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0" - } - }, - "postcss-reduce-transforms": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz", - "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==", - "requires": { - "cssnano-util-get-match": "^4.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - } - }, - "postcss-replace-overflow-wrap": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-2.0.0.tgz", - "integrity": "sha1-eU22+qVPjbEAhUOSqTr0V2i04ls=", - "dev": true, - "requires": { - "postcss": "^6.0.1" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-safe-parser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-4.0.2.tgz", - "integrity": "sha512-Uw6ekxSWNLCPesSv/cmqf2bY/77z11O7jZGPax3ycZMFU/oi2DMH9i89AdHc1tRwFg/arFoEwX0IS3LCUxJh1g==", - "requires": { - "postcss": "^7.0.26" - }, - "dependencies": { - "postcss": { - "version": "7.0.35", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", - "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "postcss-selector-matches": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/postcss-selector-matches/-/postcss-selector-matches-3.0.1.tgz", - "integrity": "sha1-5WNAEeE5UIgYYbvdWMLQER/8lqs=", - "dev": true, - "requires": { - "balanced-match": "^0.4.2", - "postcss": "^6.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-selector-not": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-3.0.1.tgz", - "integrity": "sha1-Lk2y8JZTNsAefOx9tsYN/3ZzNdk=", - "dev": true, - "requires": { - "balanced-match": "^0.4.2", - "postcss": "^6.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-selector-parser": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz", - "integrity": "sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw==", - "requires": { - "cssesc": "^3.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1", - "util-deprecate": "^1.0.2" - } - }, - "postcss-svgo": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz", - "integrity": "sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==", - "requires": { - "is-svg": "^3.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0", - "svgo": "^1.0.0" - } - }, - "postcss-unique-selectors": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", - "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", - "requires": { - "alphanum-sort": "^1.0.0", - "postcss": "^7.0.0", - "uniqs": "^2.0.0" - } - }, - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" - }, - "postcss-values-parser": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", - "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", - "requires": { - "flatten": "^1.0.2", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" - }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" - }, - "prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.8.1" - } - }, - "proxy-addr": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", - "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", - "dev": true, - "requires": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.1" - } - }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" - }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" - }, - "public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" - } - } - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - }, - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "dev": true - }, - "query-string": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", - "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", - "requires": { - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" - } - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" - }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" - }, - "querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, - "raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", - "requires": { - "performance-now": "^2.1.0" - } - }, - "raf-schd": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.2.tgz", - "integrity": "sha512-VhlMZmGy6A6hrkJWHLNTGl5gtgMUm+xfGza6wbwnE914yeQ5Ybm18vgM734RZhMgfw4tacUrWseGZlpUrrakEQ==" - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "requires": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true - }, - "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "dev": true, - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true - } - } - }, - "rc-align": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/rc-align/-/rc-align-2.4.5.tgz", - "integrity": "sha512-nv9wYUYdfyfK+qskThf4BQUSIadeI/dCsfaMZfNEoxm9HwOIioQ+LyqmMK6jWHAZQgOzMLaqawhuBXlF63vgjw==", - "requires": { - "babel-runtime": "^6.26.0", - "dom-align": "^1.7.0", - "prop-types": "^15.5.8", - "rc-util": "^4.0.4" - } - }, - "rc-animate": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-2.11.1.tgz", - "integrity": "sha512-1NyuCGFJG/0Y+9RKh5y/i/AalUCA51opyyS/jO2seELpgymZm2u9QV3xwODwEuzkmeQ1BDPxMLmYLcTJedPlkQ==", - "requires": { - "babel-runtime": "6.x", - "classnames": "^2.2.6", - "css-animation": "^1.3.2", - "prop-types": "15.x", - "raf": "^3.4.0", - "rc-util": "^4.15.3", - "react-lifecycles-compat": "^3.0.4" - } - }, - "rc-slider": { - "version": "github:Galvanize-IT/slider#c569ca3b11979aced8306e6c02f37466cb7cd365", - "from": "github:Galvanize-IT/slider#c569ca3b11979aced8306e6c02f37466cb7cd365", - "requires": { - "babel-runtime": "6.x", - "classnames": "^2.2.5", - "gh-pages": "^2.0.1", - "prop-types": "^15.5.4", - "rc-tooltip": "^3.7.0", - "rc-util": "^4.0.4", - "shallowequal": "^1.0.1", - "warning": "^4.0.3" - } - }, - "rc-tooltip": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-3.7.3.tgz", - "integrity": "sha512-dE2ibukxxkrde7wH9W8ozHKUO4aQnPZ6qBHtrTH9LoO836PjDdiaWO73fgPB05VfJs9FbZdmGPVEbXCeOP99Ww==", - "requires": { - "babel-runtime": "6.x", - "prop-types": "^15.5.8", - "rc-trigger": "^2.2.2" - } - }, - "rc-trigger": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-2.6.5.tgz", - "integrity": "sha512-m6Cts9hLeZWsTvWnuMm7oElhf+03GOjOLfTuU0QmdB9ZrW7jR2IpI5rpNM7i9MvAAlMAmTx5Zr7g3uu/aMvZAw==", - "requires": { - "babel-runtime": "6.x", - "classnames": "^2.2.6", - "prop-types": "15.x", - "rc-align": "^2.4.0", - "rc-animate": "2.x", - "rc-util": "^4.4.0", - "react-lifecycles-compat": "^3.0.4" - } - }, - "rc-util": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-4.21.1.tgz", - "integrity": "sha512-Z+vlkSQVc1l8O2UjR3WQ+XdWlhj5q9BMQNLk2iOBch75CqPfrJyGtcWMcnhRlNuDu0Ndtt4kLVO8JI8BrABobg==", - "requires": { - "add-dom-event-listener": "^1.1.0", - "prop-types": "^15.5.10", - "react-is": "^16.12.0", - "react-lifecycles-compat": "^3.0.4", - "shallowequal": "^1.1.0" - }, - "dependencies": { - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - } - } - }, - "react": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz", - "integrity": "sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==", - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2" - }, - "dependencies": { - "prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.8.1" - } - } - } - }, - "react-addons-css-transition-group": { - "version": "15.6.2", - "resolved": "https://registry.npmjs.org/react-addons-css-transition-group/-/react-addons-css-transition-group-15.6.2.tgz", - "integrity": "sha1-nkN2vPQLUhfRTsaFUwgc7ksIptY=", - "requires": { - "react-transition-group": "^1.2.0" - } - }, - "react-addons-test-utils": { - "version": "15.6.2", - "resolved": "https://registry.npmjs.org/react-addons-test-utils/-/react-addons-test-utils-15.6.2.tgz", - "integrity": "sha1-wStu/cIkfBDae4dw0YUICnsEcVY=" - }, - "react-beautiful-dnd": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.0.0.tgz", - "integrity": "sha512-87It8sN0ineoC3nBW0SbQuTFXM6bUqM62uJGY4BtTf0yzPl8/3+bHMWkgIe0Z6m8e+gJgjWxefGRVfpE3VcdEg==", - "requires": { - "@babel/runtime": "^7.8.4", - "css-box-model": "^1.2.0", - "memoize-one": "^5.1.1", - "raf-schd": "^4.0.2", - "react-redux": "^7.1.1", - "redux": "^4.0.4", - "use-memo-one": "^1.1.1" - } - }, - "react-copy-to-clipboard": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.2.tgz", - "integrity": "sha512-/2t5mLMMPuN5GmdXo6TebFa8IoFxZ+KTDDqYhcDm0PhkgEzSxVvIX26G20s1EB02A4h2UZgwtfymZ3lGJm0OLg==", - "requires": { - "copy-to-clipboard": "^3", - "prop-types": "^15.5.8" - }, - "dependencies": { - "prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.8.1" - } - } - } - }, - "react-datepicker": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-3.2.2.tgz", - "integrity": "sha512-/3D6hfhXcCNCbO8LICuQeoNDItWFyitGo+aLcsi0tAyJLtCInamYRwPIXhsEF+N6/qWim1yNyr71mqjj4YEBmg==", - "requires": { - "classnames": "^2.2.6", - "date-fns": "^2.0.1", - "prop-types": "^15.7.2", - "react-onclickoutside": "^6.9.0", - "react-popper": "^1.3.4" - }, - "dependencies": { - "prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.8.1" - } - } - } - }, - "react-dom": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.13.1.tgz", - "integrity": "sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag==", - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" - }, - "dependencies": { - "prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.8.1" - } - } - } - }, - "react-is": { - "version": "16.9.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.9.0.tgz", - "integrity": "sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw==" - }, - "react-json-pretty": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/react-json-pretty/-/react-json-pretty-2.2.0.tgz", - "integrity": "sha512-3UMzlAXkJ4R8S4vmkRKtvJHTewG4/rn1Q18n0zqdu/ipZbUPLVZD+QwC7uVcD/IAY3s8iNVHlgR2dMzIUS0n1A==", - "requires": { - "prop-types": "^15.6.2" - }, - "dependencies": { - "prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.8.1" - } - } - } - }, - "react-lifecycles-compat": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", - "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" - }, - "react-onclickoutside": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.9.0.tgz", - "integrity": "sha512-8ltIY3bC7oGhj2nPAvWOGi+xGFybPNhJM0V1H8hY/whNcXgmDeaeoCMPPd8VatrpTsUWjb/vGzrmu6SrXVty3A==" - }, - "react-paginate": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/react-paginate/-/react-paginate-6.5.0.tgz", - "integrity": "sha512-H7xSi9jyiJzgfaj+2nNhQcjZfwzJ/Mxb64V2RiyDctjZyCWojwsaGwMqhLBpQ58iAuMVtBMRQ7ECqMcUKG9QSQ==", - "requires": { - "prop-types": "^15.6.1" - }, - "dependencies": { - "prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.8.1" - } - } - } - }, - "react-pdf": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/react-pdf/-/react-pdf-4.2.0.tgz", - "integrity": "sha512-Ao44mZszfPwtCUsrXHtXnhM+czTvPxfG5wqssbWgj2onL70TKSOKGzQfCH4csCnNDOKji/Pc/s0Og70/VOE+Rg==", - "requires": { - "@babel/runtime": "^7.0.0", - "make-cancellable-promise": "^1.0.0", - "make-event-props": "^1.1.0", - "merge-class-names": "^1.1.1", - "pdfjs-dist": "2.1.266", - "prop-types": "^15.6.2" - } - }, - "react-popper": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.7.tgz", - "integrity": "sha512-nmqYTx7QVjCm3WUZLeuOomna138R1luC4EqkW3hxJUrAe+3eNz3oFCLYdnPwILfn0mX1Ew2c3wctrjlUMYYUww==", - "requires": { - "@babel/runtime": "^7.1.2", - "create-react-context": "^0.3.0", - "deep-equal": "^1.1.1", - "popper.js": "^1.14.4", - "prop-types": "^15.6.1", - "typed-styles": "^0.0.7", - "warning": "^4.0.2" - }, - "dependencies": { - "deep-equal": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", - "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", - "requires": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" - } - }, - "popper.js": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", - "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==" - }, - "prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.8.1" - } - } - } - }, - "react-redux": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.1.tgz", - "integrity": "sha512-T+VfD/bvgGTUA74iW9d2i5THrDQWbweXP0AVNI8tNd1Rk5ch1rnMiJkDD67ejw7YBKM4+REvcvqRuWJb7BLuEg==", - "requires": { - "@babel/runtime": "^7.5.5", - "hoist-non-react-statics": "^3.3.0", - "loose-envify": "^1.4.0", - "prop-types": "^15.7.2", - "react-is": "^16.9.0" - }, - "dependencies": { - "prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.8.1" - } - } - } - }, - "react-scroll-sync": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/react-scroll-sync/-/react-scroll-sync-0.8.0.tgz", - "integrity": "sha512-Ms9srm41UM+lWexuqdocXjqaqqt6ZRSFxcudgB0sYhC7Or+m12WemTwY8BaQCRf7hA8zHDk55FHvMkqsH7gF+w==" - }, - "react-textarea-autosize": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.2.0.tgz", - "integrity": "sha512-grajUlVbkx6VdtSxCgzloUIphIZF5bKr21OYMceWPKkniy7H0mRAT/AXPrRtObAe+zUePnNlBwUc4ivVjUGIjw==", - "requires": { - "@babel/runtime": "^7.10.2", - "use-composed-ref": "^1.0.0", - "use-latest": "^1.0.0" - } - }, - "react-tools": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/react-tools/-/react-tools-0.13.3.tgz", - "integrity": "sha1-2mrH1Nd3elml6VHPRucv1La0Ciw=", - "requires": { - "commoner": "^0.10.0", - "jstransform": "^10.1.0" - } - }, - "react-tooltip": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-4.2.10.tgz", - "integrity": "sha512-D7ZLx6/QwpUl0SZRek3IZy/HWpsEEp0v3562tcT8IwZgu8IgV7hY5ZzniTkHyRcuL+IQnljpjj7A7zCgl2+T3w==", - "requires": { - "prop-types": "^15.7.2", - "uuid": "^7.0.3" - }, - "dependencies": { - "prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.8.1" - } - }, - "uuid": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", - "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==" - } - } - }, - "react-transition-group": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-1.2.1.tgz", - "integrity": "sha512-CWaL3laCmgAFdxdKbhhps+c0HRGF4c+hdM4H23+FI1QBNUyx/AMeIJGWorehPNSaKnQNOAxL7PQmqMu78CDj3Q==", - "requires": { - "chain-function": "^1.0.0", - "dom-helpers": "^3.2.0", - "loose-envify": "^1.3.1", - "prop-types": "^15.5.6", - "warning": "^3.0.0" - }, - "dependencies": { - "prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.8.1" - } - }, - "warning": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", - "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", - "requires": { - "loose-envify": "^1.0.0" - } - } - } - }, - "react_ujs": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/react_ujs/-/react_ujs-2.6.1.tgz", - "integrity": "sha512-9M33/A8cubStkZ2cpJSimcTD0RlCWiqXF6e90IQmMw/Caf/W0dtAzOtHtiQE3JjLbt/nhRR7NLPxMfnlm141ig==", - "requires": { - "react_ujs": "^2.6.0" - } - }, - "reactify": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/reactify/-/reactify-1.1.1.tgz", - "integrity": "sha1-qPEZWWJzwNS/savqDBTCYB6gO7o=", - "requires": { - "react-tools": "~0.13.0", - "through": "~2.3.4" - } - }, - "read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", - "requires": { - "pify": "^2.3.0" - } - }, - "read-only-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", - "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", - "requires": { - "readable-stream": "^2.0.2" - } - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - } - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - }, - "recast": { - "version": "0.11.23", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz", - "integrity": "sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=", - "requires": { - "ast-types": "0.9.6", - "esprima": "~3.1.0", - "private": "~0.1.5", - "source-map": "~0.5.0" - } - }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - }, - "dependencies": { - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "requires": { - "repeating": "^2.0.0" - } - } - } - }, - "reduce-css-calc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", - "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", - "dev": true, - "requires": { - "balanced-match": "^0.4.2", - "math-expression-evaluator": "^1.2.14", - "reduce-function-call": "^1.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - } - } - }, - "reduce-function-call": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.3.tgz", - "integrity": "sha512-Hl/tuV2VDgWgCSEeWMLwxLZqX7OK59eU1guxXsRKTAyeYimivsKdtcV4fu3r710tpG5GmDKDhQ0HSZLExnNmyQ==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "redux": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz", - "integrity": "sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==", - "requires": { - "loose-envify": "^1.4.0", - "symbol-observable": "^1.2.0" - } - }, - "regenerate": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", - "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==" - }, - "regenerate-unicode-properties": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", - "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", - "requires": { - "regenerate": "^1.4.0" - } - }, - "regenerator-runtime": { - "version": "0.13.7", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", - "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" - }, - "regenerator-transform": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", - "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", - "requires": { - "@babel/runtime": "^7.8.4" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "regexp.prototype.flags": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", - "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "requires": { - "has-symbols": "^1.0.1" - } - } - } - }, - "regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", - "dev": true - }, - "regexpu-core": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", - "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==", - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.2.0", - "regjsgen": "^0.5.1", - "regjsparser": "^0.6.4", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.2.0" - } - }, - "regjsgen": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", - "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==" - }, - "regjsparser": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", - "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" - } - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "requires": { - "is-finite": "^1.0.0" - } - }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" - } - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "requires": { - "path-parse": "^1.0.6" - } - }, - "resolve-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", - "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", - "requires": { - "resolve-from": "^3.0.0" - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - }, - "dependencies": { - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - } - } - }, - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" - }, - "retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", - "dev": true - }, - "rgb": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/rgb/-/rgb-0.1.0.tgz", - "integrity": "sha1-vieykej+/+rBvZlylyG/pA/AN7U=", - "dev": true - }, - "rgb-hex": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/rgb-hex/-/rgb-hex-2.1.0.tgz", - "integrity": "sha1-x3PF/iJoolV42SU5qCp6XOU77aY=", - "dev": true - }, - "rgb-regex": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", - "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=" - }, - "rgba-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", - "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=" - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "requires": { - "glob": "^7.1.3" - } - }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "run-queue": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", - "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", - "requires": { - "aproba": "^1.1.1" - } - }, - "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "requires": { - "ret": "~0.1.10" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "sass-graph": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.5.tgz", - "integrity": "sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag==", - "requires": { - "glob": "^7.0.0", - "lodash": "^4.0.0", - "scss-tokenizer": "^0.2.3", - "yargs": "^13.3.2" - } - }, - "sass-loader": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-8.0.2.tgz", - "integrity": "sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ==", - "requires": { - "clone-deep": "^4.0.1", - "loader-utils": "^1.2.3", - "neo-async": "^2.6.1", - "schema-utils": "^2.6.1", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } - } - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, - "schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "requires": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - } - }, - "scss-tokenizer": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", - "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", - "requires": { - "js-base64": "^2.1.8", - "source-map": "^0.4.2" - }, - "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, - "select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", - "dev": true - }, - "selfsigned": { - "version": "1.10.8", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.8.tgz", - "integrity": "sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w==", - "dev": true, - "requires": { - "node-forge": "^0.10.0" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - }, - "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "requires": { - "randombytes": "^2.1.0" - } - }, - "serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "dependencies": { - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - } - } - }, - "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", - "dev": true - }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "requires": { - "kind-of": "^6.0.2" - } - }, - "shallowequal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", - "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" - }, - "shasum": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", - "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", - "requires": { - "json-stable-stringify": "~0.0.0", - "sha.js": "~2.4.4" - } - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" - }, - "shell-quote": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.1.tgz", - "integrity": "sha512-2kUqeAGnMAu6YrTPX4E3LfxacH9gKljzVjlkUeSqY0soGwK4KLl7TURXCem712tkhBCeeaFP9QK4dKn88s3Icg==" - }, - "side-channel": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.3.tgz", - "integrity": "sha512-A6+ByhlLkksFoUepsGxfj5x1gTSrs+OydsRptUxeNCabQpCFUvcwIczgOigI8vhY/OJCnPnyE9rGiwgvr9cS1g==", - "dev": true, - "requires": { - "es-abstract": "^1.18.0-next.0", - "object-inspect": "^1.8.0" - } - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" - }, - "simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" - }, - "simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", - "requires": { - "is-arrayish": "^0.3.1" - }, - "dependencies": { - "is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" - } - } - }, - "slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" - } - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "sockjs": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.20.tgz", - "integrity": "sha512-SpmVOVpdq0DJc0qArhF3E5xsxvaiqGNb73XfgBpK1y3UD5gs8DSo8aCTsuT5pX8rssdc2NDIzANwP9eCAiSdTA==", - "dev": true, - "requires": { - "faye-websocket": "^0.10.0", - "uuid": "^3.4.0", - "websocket-driver": "0.6.5" - }, - "dependencies": { - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - } - } - }, - "sockjs-client": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.4.0.tgz", - "integrity": "sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g==", - "dev": true, - "requires": { - "debug": "^3.2.5", - "eventsource": "^1.0.7", - "faye-websocket": "~0.11.1", - "inherits": "^2.0.3", - "json3": "^3.3.2", - "url-parse": "^1.4.3" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "faye-websocket": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", - "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - } - } - }, - "sort-keys": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", - "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", - "requires": { - "is-plain-obj": "^1.0.0" - } - }, - "source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", - "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==" - }, - "spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - }, - "dependencies": { - "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - } - } - }, - "spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - }, - "dependencies": { - "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" - }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "ssri": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.0.tgz", - "integrity": "sha512-aq/pz989nxVYwn16Tsbj1TqFpD5LLrQxHf5zaHuieFV+R0Bbr4y8qUsOA45hXT/N4/9UNXTarBjnjVmjSOVaAA==", - "requires": { - "minipass": "^3.1.1" - } - }, - "stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==" - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - }, - "stdout-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", - "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", - "requires": { - "readable-stream": "^2.0.1" - } - }, - "stream-browserify": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", - "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", - "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } - }, - "stream-combiner2": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", - "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", - "requires": { - "duplexer2": "~0.1.0", - "readable-stream": "^2.0.2" - } - }, - "stream-each": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", - "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } - }, - "stream-http": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.1.1.tgz", - "integrity": "sha512-S7OqaYu0EkFpgeGFb/NPOoPLxFko7TPqtEeFg5DXPB4v/KETHG0Ln6fRFrNezoelpaDKmycEmmZ81cC9DAwgYg==", - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "xtend": "^4.0.2" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" - }, - "stream-splicer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz", - "integrity": "sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==", - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.2" - } - }, - "strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "string.prototype.matchall": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz", - "integrity": "sha512-N/jp6O5fMf9os0JU3E72Qhf590RSRZU/ungsL/qJUYVTNv7hTG0P/dbPjxINVN9jpscu3nzYwKESU3P3RY5tOg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0", - "has-symbols": "^1.0.1", - "internal-slot": "^1.0.2", - "regexp.prototype.flags": "^1.3.0", - "side-channel": "^1.0.2" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - } - } - }, - "string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "requires": { - "has-symbols": "^1.0.1" - } - } - } - }, - "string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "requires": { - "has-symbols": "^1.0.1" - } - } - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "requires": { - "get-stdin": "^4.0.1" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "strip-outer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", - "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", - "requires": { - "escape-string-regexp": "^1.0.2" - } - }, - "strip-url-auth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-url-auth/-/strip-url-auth-1.0.1.tgz", - "integrity": "sha1-IrD6OkE4WzO+PzMVUbu4N/oM164=" - }, - "style-loader": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz", - "integrity": "sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==", - "requires": { - "loader-utils": "^2.0.0", - "schema-utils": "^2.7.0" - }, - "dependencies": { - "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", - "requires": { - "minimist": "^1.2.5" - } - }, - "loader-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", - "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - } - } - }, - "stylehacks": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", - "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==", - "requires": { - "browserslist": "^4.0.0", - "postcss": "^7.0.0", - "postcss-selector-parser": "^3.0.0" - }, - "dependencies": { - "postcss-selector-parser": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", - "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", - "requires": { - "dot-prop": "^5.2.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - } - } - }, - "subarg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", - "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", - "requires": { - "minimist": "^1.1.0" - } - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "requires": { - "has-flag": "^3.0.0" - } - }, - "svgo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", - "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", - "requires": { - "chalk": "^2.4.1", - "coa": "^2.0.2", - "css-select": "^2.0.0", - "css-select-base-adapter": "^0.1.1", - "css-tree": "1.0.0-alpha.37", - "csso": "^4.0.2", - "js-yaml": "^3.13.1", - "mkdirp": "~0.5.1", - "object.values": "^1.1.0", - "sax": "~1.2.4", - "stable": "^0.1.8", - "unquote": "~1.1.1", - "util.promisify": "~1.0.0" - } - }, - "symbol-observable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", - "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" - }, - "syntax-error": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", - "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", - "requires": { - "acorn-node": "^1.2.0" - } - }, - "table": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", - "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", - "dev": true, - "requires": { - "ajv": "^6.10.2", - "lodash": "^4.17.14", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" - } - }, - "tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" - }, - "tar": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.0.5.tgz", - "integrity": "sha512-0b4HOimQHj9nXNEAA7zWwMM91Zhhba3pspja6sQbgTpynOJf+bkjBnfybNYzbpLbnwXnbyB4LOREvlyXLkCHSg==", - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - } - } - }, - "terser": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.3.4.tgz", - "integrity": "sha512-dxuB8KQo8Gt6OVOeLg/rxfcxdNZI/V1G6ze1czFUzPeCFWZRtvZMgSzlZZ5OYBZ4HoG607F6pFPNLekJyV+yVw==", - "requires": { - "commander": "^2.20.0", - "source-map": "~0.7.2", - "source-map-support": "~0.5.19" - }, - "dependencies": { - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" - } - } - }, - "terser-webpack-plugin": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-4.2.2.tgz", - "integrity": "sha512-3qAQpykRTD5DReLu5/cwpsg7EZFzP3Q0Hp2XUWJUw2mpq2jfgOKTZr8IZKKnNieRVVo1UauROTdhbQJZveGKtQ==", - "requires": { - "cacache": "^15.0.5", - "find-cache-dir": "^3.3.1", - "jest-worker": "^26.3.0", - "p-limit": "^3.0.2", - "schema-utils": "^2.7.1", - "serialize-javascript": "^5.0.1", - "source-map": "^0.6.1", - "terser": "^5.3.2", - "webpack-sources": "^1.4.3" - }, - "dependencies": { - "find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "requires": { - "p-locate": "^4.1.0" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "requires": { - "semver": "^6.0.0" - } - }, - "p-limit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", - "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "requires": { - "p-limit": "^2.2.0" - }, - "dependencies": { - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "requires": { - "p-try": "^2.0.0" - } - } - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "requires": { - "find-up": "^4.0.0" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - }, - "serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", - "requires": { - "randombytes": "^2.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true - }, - "timers-browserify": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", - "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", - "requires": { - "process": "~0.11.0" - } - }, - "timsort": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", - "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" - }, - "tiny-invariant": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", - "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" - }, - "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "toggle-selection": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", - "integrity": "sha1-bkWxJj8gF/oKzH2J14sVuL932jI=" - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "dev": true - }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "dependencies": { - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - } - } - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" - }, - "trim-repeated": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", - "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", - "requires": { - "escape-string-regexp": "^1.0.2" - } - }, - "true-case-path": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", - "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", - "requires": { - "glob": "^7.1.2" - } - }, - "ts-essentials": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-2.0.12.tgz", - "integrity": "sha512-3IVX4nI6B5cc31/GFFE+i8ey/N2eA0CZDbo6n0yrz0zDX8ZJ8djmU1p+XRz7G3is0F3bB3pu2pAroFdAWQKU3w==" - }, - "ts-loader": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-8.0.4.tgz", - "integrity": "sha512-5u8KF1SW8eCUb/Ff7At81e3wznPmT/27fvaGRO9CziVy+6NlPVRvrzSox4OwU0/e6OflOUB32Err4VquysCSAQ==", - "requires": { - "chalk": "^2.3.0", - "enhanced-resolve": "^4.0.0", - "loader-utils": "^1.0.2", - "micromatch": "^4.0.0", - "semver": "^6.0.0" - }, - "dependencies": { - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "requires": { - "fill-range": "^7.0.1" - } - }, - "emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "loader-utils": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", - "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^2.0.0", - "json5": "^1.0.1" - } - }, - "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "requires": { - "is-number": "^7.0.0" - } - } - } - }, - "ts-pnp": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz", - "integrity": "sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==" - }, - "tsconfig-paths": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", - "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", - "dev": true, - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.0", - "strip-bom": "^3.0.0" - } - }, - "tslib": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.0.tgz", - "integrity": "sha512-+Zw5lu0D9tvBMjGP8LpvMb0u2WW2QV3y+D8mO6J+cNzCYIN4sVy43Bf9vl92nqFahutN0I8zHa7cc4vihIshnw==" - }, - "tty-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", - "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==" - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "typed-styles": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/typed-styles/-/typed-styles-0.0.7.tgz", - "integrity": "sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q==" - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" - }, - "typescript": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.3.tgz", - "integrity": "sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg==" - }, - "umd": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", - "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==" - }, - "undeclared-identifiers": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz", - "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==", - "requires": { - "acorn-node": "^1.3.0", - "dash-ast": "^1.0.0", - "get-assigned-identifiers": "^1.2.0", - "simple-concat": "^1.0.0", - "xtend": "^4.0.1" - } - }, - "unfetch": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz", - "integrity": "sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==" - }, - "unicode-canonical-property-names-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", - "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==" - }, - "unicode-match-property-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", - "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", - "requires": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" - } - }, - "unicode-match-property-value-ecmascript": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", - "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==" - }, - "unicode-property-aliases-ecmascript": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", - "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==" - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" - }, - "uniqs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", - "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=" - }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "units-css": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/units-css/-/units-css-0.4.0.tgz", - "integrity": "sha1-1iKGU6UZg9fBb/KPi53Dsf/tOgc=", - "dev": true, - "requires": { - "isnumeric": "^0.2.0", - "viewport-dimensions": "^0.2.0" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true - }, - "unquote": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", - "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=" - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" - } - } - }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "requires": { - "punycode": "^2.1.0" - }, - "dependencies": { - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - } - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" - }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" - } - } - }, - "url-parse": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", - "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", - "dev": true, - "requires": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" - }, - "use-composed-ref": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.0.0.tgz", - "integrity": "sha512-RVqY3NFNjZa0xrmK3bIMWNmQ01QjKPDc7DeWR3xa/N8aliVppuutOE5bZzPkQfvL+5NRWMMp0DJ99Trd974FIw==", - "requires": { - "ts-essentials": "^2.0.3" - } - }, - "use-isomorphic-layout-effect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.0.0.tgz", - "integrity": "sha512-JMwJ7Vd86NwAt1jH7q+OIozZSIxA4ND0fx6AsOe2q1H8ooBUp5aN6DvVCqZiIaYU6JaMRJGyR0FO7EBCIsb/Rg==" - }, - "use-latest": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.1.0.tgz", - "integrity": "sha512-gF04d0ZMV3AMB8Q7HtfkAWe+oq1tFXP6dZKwBHQF5nVXtGsh2oAYeeqma5ZzxtlpOcW8Ro/tLcfmEodjDeqtuw==", - "requires": { - "use-isomorphic-layout-effect": "^1.0.0" - } - }, - "use-memo-one": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.1.tgz", - "integrity": "sha512-oFfsyun+bP7RX8X2AskHNTxu+R3QdE/RC5IefMbqptmACAA/gfol1KDD5KRzPsGMa62sWxGZw+Ui43u6x4ddoQ==" - }, - "util": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", - "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", - "requires": { - "inherits": "2.0.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - } - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "util.promisify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", - "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.2", - "has-symbols": "^1.0.1", - "object.getownpropertydescriptors": "^2.1.0" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "requires": { - "has-symbols": "^1.0.1" - } - } - } - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true - }, - "uuid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", - "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" - }, - "v8-compile-cache": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", - "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==" - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true - }, - "vendors": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", - "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==" - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "viewport-dimensions": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/viewport-dimensions/-/viewport-dimensions-0.2.0.tgz", - "integrity": "sha1-3nQHR9tTh/0XJfUXXpG6x2r982w=", - "dev": true - }, - "vm-browserify": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", - "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" - }, - "warning": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", - "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", - "requires": { - "loose-envify": "^1.0.0" - } - }, - "watchpack": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz", - "integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==", - "requires": { - "chokidar": "^3.4.1", - "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0", - "watchpack-chokidar2": "^2.0.0" - }, - "dependencies": { - "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "optional": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "optional": true - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "optional": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "chokidar": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", - "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", - "optional": true, - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.4.0" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "optional": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "optional": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "optional": true - }, - "readdirp": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", - "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", - "optional": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "optional": true, - "requires": { - "is-number": "^7.0.0" - } - } - } - }, - "watchpack-chokidar2": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz", - "integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==", - "optional": true, - "requires": { - "chokidar": "^2.1.8" - } - }, - "wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "requires": { - "minimalistic-assert": "^1.0.0" - } - }, - "weakmap-polyfill": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/weakmap-polyfill/-/weakmap-polyfill-2.0.1.tgz", - "integrity": "sha512-Jy177Lvb1LCrPQDWJsXyyqf4eOhcdvQHFGoCqSv921kVF5i42MVbr4e2WEwetuTLBn1NX0IhPzTmMu0N3cURqQ==" - }, - "webpack": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz", - "integrity": "sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q==", - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/wasm-edit": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0", - "acorn": "^6.4.1", - "ajv": "^6.10.2", - "ajv-keywords": "^3.4.1", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^4.3.0", - "eslint-scope": "^4.0.3", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.4.0", - "loader-utils": "^1.2.3", - "memory-fs": "^0.4.1", - "micromatch": "^3.1.10", - "mkdirp": "^0.5.3", - "neo-async": "^2.6.1", - "node-libs-browser": "^2.2.1", - "schema-utils": "^1.0.0", - "tapable": "^1.1.3", - "terser-webpack-plugin": "^1.4.3", - "watchpack": "^1.7.4", - "webpack-sources": "^1.4.1" - }, - "dependencies": { - "acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==" - }, - "cacache": { - "version": "12.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", - "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", - "requires": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", - "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "infer-owner": "^1.0.3", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" - } - }, - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" - }, - "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "requires": { - "yallist": "^3.0.2" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - } - }, - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", - "requires": { - "figgy-pudding": "^3.5.1" - } - }, - "terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", - "requires": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - } - }, - "terser-webpack-plugin": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", - "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", - "requires": { - "cacache": "^12.0.2", - "find-cache-dir": "^2.1.0", - "is-wsl": "^1.1.0", - "schema-utils": "^1.0.0", - "serialize-javascript": "^4.0.0", - "source-map": "^0.6.1", - "terser": "^4.1.2", - "webpack-sources": "^1.4.0", - "worker-farm": "^1.7.0" - } - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - } - } - }, - "webpack-assets-manifest": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/webpack-assets-manifest/-/webpack-assets-manifest-3.1.1.tgz", - "integrity": "sha512-JV9V2QKc5wEWQptdIjvXDUL1ucbPLH2f27toAY3SNdGZp+xSaStAgpoMcvMZmqtFrBc9a5pTS1058vxyMPOzRQ==", - "requires": { - "chalk": "^2.0", - "lodash.get": "^4.0", - "lodash.has": "^4.0", - "mkdirp": "^0.5", - "schema-utils": "^1.0.0", - "tapable": "^1.0.0", - "webpack-sources": "^1.0.0" - }, - "dependencies": { - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - } - } - }, - "webpack-cli": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.12.tgz", - "integrity": "sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag==", - "requires": { - "chalk": "^2.4.2", - "cross-spawn": "^6.0.5", - "enhanced-resolve": "^4.1.1", - "findup-sync": "^3.0.0", - "global-modules": "^2.0.0", - "import-local": "^2.0.0", - "interpret": "^1.4.0", - "loader-utils": "^1.4.0", - "supports-color": "^6.1.0", - "v8-compile-cache": "^2.1.1", - "yargs": "^13.3.2" - } - }, - "webpack-dev-middleware": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz", - "integrity": "sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==", - "dev": true, - "requires": { - "memory-fs": "^0.4.1", - "mime": "^2.4.4", - "mkdirp": "^0.5.1", - "range-parser": "^1.2.1", - "webpack-log": "^2.0.0" - }, - "dependencies": { - "mime": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", - "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", - "dev": true - } - } - }, - "webpack-dev-server": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.0.tgz", - "integrity": "sha512-PUxZ+oSTxogFQgkTtFndEtJIPNmml7ExwufBZ9L2/Xyyd5PnOL5UreWe5ZT7IU25DSdykL9p1MLQzmLh2ljSeg==", - "dev": true, - "requires": { - "ansi-html": "0.0.7", - "bonjour": "^3.5.0", - "chokidar": "^2.1.8", - "compression": "^1.7.4", - "connect-history-api-fallback": "^1.6.0", - "debug": "^4.1.1", - "del": "^4.1.1", - "express": "^4.17.1", - "html-entities": "^1.3.1", - "http-proxy-middleware": "0.19.1", - "import-local": "^2.0.0", - "internal-ip": "^4.3.0", - "ip": "^1.1.5", - "is-absolute-url": "^3.0.3", - "killable": "^1.0.1", - "loglevel": "^1.6.8", - "opn": "^5.5.0", - "p-retry": "^3.0.1", - "portfinder": "^1.0.26", - "schema-utils": "^1.0.0", - "selfsigned": "^1.10.7", - "semver": "^6.3.0", - "serve-index": "^1.9.1", - "sockjs": "0.3.20", - "sockjs-client": "1.4.0", - "spdy": "^4.0.2", - "strip-ansi": "^3.0.1", - "supports-color": "^6.1.0", - "url": "^0.11.0", - "webpack-dev-middleware": "^3.7.2", - "webpack-log": "^2.0.0", - "ws": "^6.2.1", - "yargs": "^13.3.2" - }, - "dependencies": { - "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "webpack-log": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", - "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", - "dev": true, - "requires": { - "ansi-colors": "^3.0.0", - "uuid": "^3.3.2" - } - }, - "webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "websocket-driver": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz", - "integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=", - "dev": true, - "requires": { - "websocket-extensions": ">=0.1.1" - } - }, - "websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "requires": { - "string-width": "^1.0.2 || 2" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, - "worker-farm": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", - "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", - "requires": { - "errno": "~0.1.7" - } - }, - "worker-loader": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-2.0.0.tgz", - "integrity": "sha512-tnvNp4K3KQOpfRnD20m8xltE3eWh89Ye+5oj7wXEEHKac1P4oZ6p9oTj8/8ExqoSBnk9nu5Pr4nKfQ1hn2APJw==", - "requires": { - "loader-utils": "^1.0.0", - "schema-utils": "^0.4.0" - }, - "dependencies": { - "schema-utils": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", - "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==", - "requires": { - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0" - } - } - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "write": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", - "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } - }, - "ws": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", - "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0" - } - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "yaml": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", - "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==" - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "requires": { - "p-limit": "^2.0.0" - } - } - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } -} diff --git a/package.json.sav b/package.json.sav deleted file mode 100644 index af9f46c..0000000 --- a/package.json.sav +++ /dev/null @@ -1,83 +0,0 @@ -{ - "name": "forge", - "version": "1.0.0", - "description": "Forge [![Build](http://circleci-badges-max.herokuapp.com/img/Galvanize-IT/forge/master?token=d736af2111a26f129d732b6d9696386619328cd5)](https://circleci.com/gh/Galvanize-IT/forge/tree/master) =====", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/Galvanize-IT/forge.git" - }, - "author": "", - "license": "MIT", - "bugs": { - "url": "https://github.com/Galvanize-IT/forge/issues" - }, - "homepage": "https://github.com/Galvanize-IT/forge#readme", - "dependencies": { - "@rails/webpacker": "3.5", - "@types/react-paginate": "^6.2.1", - "@types/react-pdf": "^4.0.3", - "@vimeo/player": "^2.2.1", - "babel-preset-react": "^6.24.1", - "brace": "^0.9.1", - "browserify": "^13.1.0", - "browserify-incremental": "^3.1.1", - "dropzone": "^4.3.0", - "gsap": "^2.0.1", - "highlightjs": "^9.16.2", - "immutability-helper": "^2.7.1", - "lodash-es": "^4.17.10", - "marked": "^0.5.0", - "moment": "2.19.2", - "moment-timezone": "0.5.14", - "objectify-array": "^2.1.0", - "popper.js": "^1.12.6", - "prop-types": "^15.7.2", - "rc-slider": "Galvanize-IT/slider#c569ca3b11979aced8306e6c02f37466cb7cd365", - "react": "^16.4.2", - "react-addons-css-transition-group": "^15.6.2", - "react-addons-test-utils": "^15.6.0", - "react-beautiful-dnd": "^10.0.0", - "react-copy-to-clipboard": "^5.0.1", - "react-datepicker": "^2.0.0", - "react-dom": "^16.4.2", - "react-json-pretty": "^2.2.0", - "react-paginate": "^6.3.2", - "react-pdf": "^4.1.0", - "react-scroll-sync": "^0.5.0", - "react-textarea-autosize": "^5.1.0", - "react-tooltip": "^3.4.0", - "react_ujs": "^2.4.4", - "reactify": "^1.1.1", - "ts-loader": "3.5.0", - "typescript": "^3.4.5", - "unfetch": "^3.1.1" - }, - "devDependencies": { - "@types/lodash-es": "^4.17.1", - "@types/node-fetch": "^2.1.2", - "@types/rc-slider": "^8.6.5", - "@types/react": "^16.8.24", - "@types/react-addons-css-transition-group": "^15.0.5", - "@types/react-beautiful-dnd": "^10.1.1", - "@types/react-copy-to-clipboard": "^4.2.6", - "@types/react-datepicker": "^2.0.2", - "@types/react-dom": "^16.0.7", - "@types/react-textarea-autosize": "^4.3.3", - "@types/vimeo__player": "^2.6.2", - "eslint": "3.19.0", - "eslint-config-airbnb": "14.1.0", - "eslint-plugin-import": "2.2.0", - "eslint-plugin-jsx-a11y": "4.0.0", - "eslint-plugin-promise": "3.5.0", - "eslint-plugin-react": "6.10.3", - "eslint-plugin-standard": "3.0.1", - "webpack-dev-server": "2.11.2" - }, - "engines": { - "node": "10.15.1" - } -} diff --git a/yarn.lock b/yarn.lock index 5e31736..fc3bc6f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5227,15 +5227,7 @@ loader-runner@^2.4.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== -loader-utils@^1.0.2, loader-utils@^1.1.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" - dependencies: - big.js "^5.2.2" - emojis-list "^2.0.0" - json5 "^1.0.1" - -loader-utils@^1.2.3, loader-utils@^1.4.0: +loader-utils@^1.0.0, loader-utils@^1.2.3, loader-utils@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== @@ -5244,6 +5236,14 @@ loader-utils@^1.2.3, loader-utils@^1.4.0: emojis-list "^3.0.0" json5 "^1.0.1" +loader-utils@^1.0.2, loader-utils@^1.1.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" + dependencies: + big.js "^5.2.2" + emojis-list "^2.0.0" + json5 "^1.0.1" + loader-utils@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" @@ -5819,6 +5819,11 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +node-ensure@^0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/node-ensure/-/node-ensure-0.0.0.tgz#ecae764150de99861ec5c810fd5d096b183932a7" + integrity sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc= + node-forge@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" @@ -6422,10 +6427,13 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" -pdfjs-dist@2.4.456: - version "2.4.456" - resolved "https://registry.yarnpkg.com/pdfjs-dist/-/pdfjs-dist-2.4.456.tgz#0eaad2906cda866bbb393e79a0e5b4e68bd75520" - integrity sha512-yckJEHq3F48hcp6wStEpbN9McOj328Ib09UrBlGAKxvN2k+qYPN5iq6TH6jD1C0pso7zTep+g/CKsYgdrQd5QA== +pdfjs-dist@2.1.266: + version "2.1.266" + resolved "https://registry.yarnpkg.com/pdfjs-dist/-/pdfjs-dist-2.1.266.tgz#cded02268b389559e807f410d2a729db62160026" + integrity sha512-Jy7o1wE3NezPxozexSbq4ltuLT0Z21ew/qrEiAEeUZzHxMHGk4DUV1D7RuCXg5vJDvHmjX1YssN+we9QfRRgXQ== + dependencies: + node-ensure "^0.0.0" + worker-loader "^2.0.0" performance-now@^2.1.0: version "2.1.0" @@ -7752,18 +7760,17 @@ react-paginate@^6.5.0: dependencies: prop-types "^15.6.1" -react-pdf@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/react-pdf/-/react-pdf-5.0.0.tgz#baddeecd5c5ef92ae57aed1ee141203ad14d4b5d" - integrity sha512-VpqZjpZGEevmotLYl6acU6GYQeJ0dxn9+5sth5QjWLFhKu0xy3zSZgt3U3m97zW6UWzQ/scvw5drfPyun5l4eA== +react-pdf@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/react-pdf/-/react-pdf-4.2.0.tgz#b83a01eb070912522075b7a51aee7d63b2c912ed" + integrity sha512-Ao44mZszfPwtCUsrXHtXnhM+czTvPxfG5wqssbWgj2onL70TKSOKGzQfCH4csCnNDOKji/Pc/s0Og70/VOE+Rg== dependencies: "@babel/runtime" "^7.0.0" make-cancellable-promise "^1.0.0" make-event-props "^1.1.0" merge-class-names "^1.1.1" - pdfjs-dist "2.4.456" + pdfjs-dist "2.1.266" prop-types "^15.6.2" - worker-loader "^3.0.0" react-popper@^1.3.4: version "1.3.7" @@ -8266,6 +8273,14 @@ scheduler@^0.19.1: loose-envify "^1.1.0" object-assign "^4.1.1" +schema-utils@^0.4.0: + version "0.4.7" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.7.tgz#ba74f597d2be2ea880131746ee17d0a093c68187" + integrity sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ== + dependencies: + ajv "^6.1.0" + ajv-keywords "^3.1.0" + schema-utils@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" @@ -9717,13 +9732,13 @@ worker-farm@^1.7.0: dependencies: errno "~0.1.7" -worker-loader@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/worker-loader/-/worker-loader-3.0.3.tgz#a9e3a1840589bd2d279da74c9e0e4acdadecbeec" - integrity sha512-yLUJqzloOnoh2/9OisTrUbUHd2a3Tfx8o8ilXHEQJ9Z/x/O/Ll+yZZOoVLT8G33IT2oCrjsIZ6jNB3OVIYCllA== +worker-loader@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/worker-loader/-/worker-loader-2.0.0.tgz#45fda3ef76aca815771a89107399ee4119b430ac" + integrity sha512-tnvNp4K3KQOpfRnD20m8xltE3eWh89Ye+5oj7wXEEHKac1P4oZ6p9oTj8/8ExqoSBnk9nu5Pr4nKfQ1hn2APJw== dependencies: - loader-utils "^2.0.0" - schema-utils "^2.7.0" + loader-utils "^1.0.0" + schema-utils "^0.4.0" wrap-ansi@^5.1.0: version "5.1.0" -- GitLab From 9cb2ff1e1ebcbb869134573f225f03e51e9dd5b5 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Thu, 8 Oct 2020 10:13:59 -1000 Subject: [PATCH 139/283] fixing pdf rendering --- app/javascript/components/content_files/PDFRenderer.tsx | 3 +-- app/javascript/components/content_files/SubmissionRenderer.tsx | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/javascript/components/content_files/PDFRenderer.tsx b/app/javascript/components/content_files/PDFRenderer.tsx index b9ff2c6..9f9ebe8 100644 --- a/app/javascript/components/content_files/PDFRenderer.tsx +++ b/app/javascript/components/content_files/PDFRenderer.tsx @@ -1,6 +1,5 @@ import React from 'react'; import { Document, Page, pdfjs } from 'react-pdf/dist/entry.webpack'; - pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`; type Props = { @@ -32,7 +31,7 @@ export default class PDFRenderer extends React.Component { View on Github )} -
    +
    Date: Thu, 8 Oct 2020 10:21:06 -1000 Subject: [PATCH 140/283] updating docs --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fc701f1..b7fc7d5 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Install rbenv and get the right version of ruby (the version here may change, so version. ) - `brew install rbenv` -- `rbenv install 2.6.0` +- `rbenv install 2.6.6` Install our data stores: @@ -32,7 +32,7 @@ You will need a [Github access token](https://github.com/settings/tokens). Repla The token will need **Full control of private repositories** - `git clone git@github.com:Galvanize-IT/forge.git && cd forge` -- `rbenv local 2.6.0` +- `rbenv local 2.6.6` - `gem install bundler` - `bundle config --local GITHUB__COM YOUR_GENERATED_PERSONAL_ACCESS_TOKEN:x-oauth-basic` - `bundle` -- GitLab From 160698f1dafb6cea3db6aa52adb34e95ba8a98f6 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Thu, 8 Oct 2020 10:54:21 -1000 Subject: [PATCH 141/283] fixing build error. removing old module. adding new module dependencies --- .postcssrc.yml | 6 +- package.json | 3 +- yarn.lock | 465 ++----------------------------------------------- 3 files changed, 15 insertions(+), 459 deletions(-) diff --git a/.postcssrc.yml b/.postcssrc.yml index 150dac3..6574125 100644 --- a/.postcssrc.yml +++ b/.postcssrc.yml @@ -1,3 +1,3 @@ -plugins: - postcss-import: {} - postcss-cssnext: {} +#plugins: +# postcss-import: {} +# postcss-cssnext: {} diff --git a/package.json b/package.json index 6b46e51..cc79cf0 100644 --- a/package.json +++ b/package.json @@ -74,8 +74,9 @@ "eslint-plugin-promise": "4.2.1", "eslint-plugin-react": "7.21.3", "eslint-plugin-standard": "4.0.1", - "postcss-cssnext": "^3.1.0", + "postcss-flexbugs-fixes": "^4.2.1", "postcss-import": "^12.0.1", + "postcss-preset-env": "^6.7.0", "webpack-dev-server": "^3.11.0" }, "engines": { diff --git a/yarn.lock b/yarn.lock index fc3bc6f..36061c0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1597,18 +1597,6 @@ atob@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" -autoprefixer@^7.1.1: - version "7.2.6" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-7.2.6.tgz#256672f86f7c735da849c4f07d008abb056067dc" - integrity sha512-Iq8TRIB+/9eQ8rbGhcP7ct5cYb/3qjNYAR2SnzLCEcwF6rvVOax8+9+fccgXk4bEhQGjOZd5TLhsksmAdsbGqQ== - dependencies: - browserslist "^2.11.3" - caniuse-lite "^1.0.30000805" - normalize-range "^0.1.2" - num2fraction "^1.2.2" - postcss "^6.0.17" - postcss-value-parser "^3.2.3" - autoprefixer@^9.6.1: version "9.8.6" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f" @@ -1735,7 +1723,7 @@ babel-preset-react@^6.24.1: babel-plugin-transform-react-jsx-source "^6.22.0" babel-preset-flow "^6.23.0" -babel-runtime@6.x, babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runtime@^6.26.0: +babel-runtime@6.x, babel-runtime@^6.22.0, babel-runtime@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" dependencies: @@ -1751,16 +1739,6 @@ babel-types@^6.26.0: lodash "^4.17.4" to-fast-properties "^1.0.3" -balanced-match@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.1.0.tgz#b504bd05869b39259dd0c5efc35d843176dccc4a" - integrity sha1-tQS9BYabOSWd0MXvw12EMXbczEo= - -balanced-match@^0.4.2: - version "0.4.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" - integrity sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg= - balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -2033,14 +2011,6 @@ browserify@^16.5.2: vm-browserify "^1.0.0" xtend "^4.0.0" -browserslist@^2.0.0, browserslist@^2.11.3: - version "2.11.3" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.11.3.tgz#fe36167aed1bbcde4827ebfe71347a2cc70b99b2" - integrity sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA== - dependencies: - caniuse-lite "^1.0.30000792" - electron-to-chromium "^1.3.30" - browserslist@^4.0.0: version "4.6.6" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.6.6.tgz#6e4bf467cde520bc9dbdf3747dafa03531cec453" @@ -2198,16 +2168,6 @@ camelcase@^5.0.0, camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -caniuse-api@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-2.0.0.tgz#b1ddb5a5966b16f48dc4998444d4bbc6c7d9d834" - integrity sha1-sd21pZZrFvSNxJmERNS7xsfZ2DQ= - dependencies: - browserslist "^2.0.0" - caniuse-lite "^1.0.0" - lodash.memoize "^4.1.2" - lodash.uniq "^4.5.0" - caniuse-api@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" @@ -2221,7 +2181,7 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000984: version "1.0.30000989" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000989.tgz#b9193e293ccf7e4426c5245134b8f2a56c0ac4b9" -caniuse-lite@^1.0.30000792, caniuse-lite@^1.0.30000805, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001135: +caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001135: version "1.0.30001144" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001144.tgz#bca0fffde12f97e1127a351fec3bfc1971aa3b3d" integrity sha512-4GQTEWNMnVZVOFG3BK0xvGeaDAtiPAbG2N8yuMXuXzx/c2Vd4XoMPO8+E918zeXn5IF0FRVtGShBfkfQea2wHQ== @@ -2249,7 +2209,7 @@ chalk@^1.1.1: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.0, chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" dependencies: @@ -2358,11 +2318,6 @@ clone-deep@^4.0.1: kind-of "^6.0.2" shallow-clone "^3.0.0" -clone@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= - coa@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" @@ -2382,7 +2337,7 @@ collection-visit@^1.0.0: map-visit "^1.0.0" object-visit "^1.0.0" -color-convert@^1.3.0, color-convert@^1.8.2, color-convert@^1.9.0, color-convert@^1.9.1: +color-convert@^1.9.0, color-convert@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" dependencies: @@ -2403,45 +2358,13 @@ color-name@^1.0.0, color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" -color-string@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-0.3.0.tgz#27d46fb67025c5c2fa25993bfbf579e47841b991" - integrity sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE= - dependencies: - color-name "^1.0.0" - -color-string@^1.4.0, color-string@^1.5.2: +color-string@^1.5.2: version "1.5.3" resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" dependencies: color-name "^1.0.0" simple-swizzle "^0.2.2" -color@^0.11.0: - version "0.11.4" - resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764" - integrity sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q= - dependencies: - clone "^1.0.2" - color-convert "^1.3.0" - color-string "^0.3.0" - -color@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/color/-/color-1.0.3.tgz#e48e832d85f14ef694fb468811c2d5cfe729b55d" - integrity sha1-5I6DLYXxTvaU+0aIEcLVz+cptV0= - dependencies: - color-convert "^1.8.2" - color-string "^1.4.0" - -color@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color/-/color-2.0.1.tgz#e4ed78a3c4603d0891eba5430b04b86314f4c839" - integrity sha512-ubUCVVKfT7r2w2D3qtHakj8mbmKms+tThR8gI8zEYCbUBl8/voqFGt3kgBqGwXAopgXybnkuOq+qMYCRrp4cXw== - dependencies: - color-convert "^1.9.1" - color-string "^1.5.2" - color@^3.0.0: version "3.1.2" resolved "https://registry.yarnpkg.com/color/-/color-3.1.2.tgz#68148e7f85d41ad7649c5fa8c8106f098d229e10" @@ -2776,16 +2699,6 @@ css-box-model@^1.2.0: dependencies: tiny-invariant "^1.0.6" -css-color-function@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/css-color-function/-/css-color-function-1.3.3.tgz#8ed24c2c0205073339fafa004bc8c141fccb282e" - integrity sha1-jtJMLAIFBzM5+voAS8jBQfzLKC4= - dependencies: - balanced-match "0.1.0" - color "^0.11.0" - debug "^3.1.0" - rgb "~0.1.0" - css-color-names@0.0.4, css-color-names@^0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" @@ -2997,7 +2910,7 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: dependencies: ms "2.0.0" -debug@^3.1.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6: +debug@^3.1.1, debug@^3.2.5, debug@^3.2.6: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" dependencies: @@ -3278,7 +3191,7 @@ electron-to-chromium@^1.3.191: version "1.3.241" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.241.tgz#859dc49ab7f90773ed698767372d384190f60cb1" -electron-to-chromium@^1.3.30, electron-to-chromium@^1.3.571: +electron-to-chromium@^1.3.571: version "1.3.578" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.578.tgz#e6671936f4571a874eb26e2e833aa0b2c0b776e0" integrity sha512-z4gU6dA1CbBJsAErW5swTGAaU2TBzc2mPAonJb00zqW1rOraDo2zfBMDRvaz9cVic+0JEZiYbHWPw/fTaZlG2Q== @@ -4970,11 +4883,6 @@ isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" -isnumeric@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/isnumeric/-/isnumeric-0.2.0.tgz#a2347ba360de19e33d0ffd590fddf7755cbf2e64" - integrity sha1-ojR7o2DeGeM9D/1ZD933dVy/LmQ= - isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" @@ -5322,7 +5230,7 @@ lodash.memoize@~3.0.3: version "3.0.4" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" -lodash.template@^4.2.4, lodash.template@^4.5.0: +lodash.template@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== @@ -5431,11 +5339,6 @@ marked@^1.2.0: resolved "https://registry.yarnpkg.com/marked/-/marked-1.2.0.tgz#7221ce2395fa6cf6d722e6f2871a32d3513c85ca" integrity sha512-tiRxakgbNPBr301ihe/785NntvYyhxlqcL3YaC8CaxJQh7kiaEtrN9B/eK2I2943Yjkh5gw25chYFDQhOMCwMA== -math-expression-evaluator@^1.2.14: - version "1.2.22" - resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.22.tgz#c14dcb3d8b4d150e5dcea9c68c8dad80309b0d5e" - integrity sha512-L0j0tFVZBQQLeEjmWOvDLoRciIY8gQGWahvkztXUal8jH8R5Rlqo9GCvgqvXcy9LQhEWdQCVvzqAbxgYNt4blQ== - md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -6138,11 +6041,6 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onecolor@^3.0.4: - version "3.1.0" - resolved "https://registry.yarnpkg.com/onecolor/-/onecolor-3.1.0.tgz#b72522270a49569ac20d244b3cd40fe157fda4d2" - integrity sha512-YZSypViXzu3ul5LMu/m6XjJ9ol8qAy9S2VjHl5E6UlhUH1KGKWabyEJifn0Jjpw23bYDzC2ucKMPGiH5kfwSGQ== - opn@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" @@ -6463,15 +6361,6 @@ pinkie@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" -pixrem@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pixrem/-/pixrem-4.0.1.tgz#2da4a1de6ec4423c5fc3794e930b81d4490ec686" - integrity sha1-LaSh3m7EQjxfw3lOkwuB1EkOxoY= - dependencies: - browserslist "^2.0.0" - postcss "^6.0.0" - reduce-css-calc "^1.2.7" - pkg-dir@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" @@ -6492,14 +6381,6 @@ pkg-dir@^4.1.0: dependencies: find-up "^4.0.0" -pleeease-filters@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pleeease-filters/-/pleeease-filters-4.0.0.tgz#6632b2fb05648d2758d865384fbced79e1ccaec7" - integrity sha1-ZjKy+wVkjSdY2GU4T7zteeHMrsc= - dependencies: - onecolor "^3.0.4" - postcss "^6.0.1" - pnp-webpack-plugin@^1.6.4: version "1.6.4" resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz#c9711ac4dc48a685dabafc86f8b6dd9f8df84149" @@ -6529,23 +6410,6 @@ posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" -postcss-apply@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/postcss-apply/-/postcss-apply-0.8.0.tgz#14e544bbb5cb6f1c1e048857965d79ae066b1343" - integrity sha1-FOVEu7XLbxweBIhXll15rgZrE0M= - dependencies: - babel-runtime "^6.23.0" - balanced-match "^0.4.2" - postcss "^6.0.0" - -postcss-attribute-case-insensitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-2.0.0.tgz#94dc422c8f90997f16bd33a3654bbbec084963b4" - integrity sha1-lNxCLI+QmX8WvTOjZUu77AhJY7Q= - dependencies: - postcss "^6.0.0" - postcss-selector-parser "^2.2.3" - postcss-attribute-case-insensitive@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz#d93e46b504589e94ac7277b0463226c68041a880" @@ -6554,16 +6418,6 @@ postcss-attribute-case-insensitive@^4.0.1: postcss "^7.0.2" postcss-selector-parser "^6.0.2" -postcss-calc@^6.0.0: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-6.0.2.tgz#4d9a43e27dbbf27d095fecb021ac6896e2318337" - integrity sha512-fiznXjEN5T42Qm7qqMCVJXS3roaj9r4xsSi+meaBVe7CJBl8t/QLOXu02Z2E6oWAMWIvCuF6JrvzFekmVEbOKA== - dependencies: - css-unit-converter "^1.1.1" - postcss "^7.0.2" - postcss-selector-parser "^2.2.2" - reduce-css-calc "^2.0.0" - postcss-calc@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.1.tgz#36d77bab023b0ecbb9789d84dcb23c4941145436" @@ -6573,16 +6427,6 @@ postcss-calc@^7.0.1: postcss-selector-parser "^5.0.0-rc.4" postcss-value-parser "^3.3.1" -postcss-color-function@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/postcss-color-function/-/postcss-color-function-4.1.0.tgz#b6f9355e07b12fcc5c34dab957834769b03d8f57" - integrity sha512-2/fuv6mP5Lt03XbRpVfMdGC8lRP1sykme+H1bR4ARyOmSMB8LPSjcL6EAI1iX6dqUF+jNEvKIVVXhan1w/oFDQ== - dependencies: - css-color-function "~1.3.3" - postcss "^6.0.23" - postcss-message-helpers "^2.0.0" - postcss-value-parser "^3.3.1" - postcss-color-functional-notation@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz#5efd37a88fbabeb00a2966d1e53d98ced93f74e0" @@ -6591,16 +6435,6 @@ postcss-color-functional-notation@^2.0.1: postcss "^7.0.2" postcss-values-parser "^2.0.0" -postcss-color-gray@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/postcss-color-gray/-/postcss-color-gray-4.1.0.tgz#e5581ed57eaa826fb652ca11b1e2b7b136a9f9df" - integrity sha512-L4iLKQLdqChz6ZOgGb6dRxkBNw78JFYcJmBz1orHpZoeLtuhDDGegRtX9gSyfoCIM7rWZ3VNOyiqqvk83BEN+w== - dependencies: - color "^2.0.1" - postcss "^6.0.14" - postcss-message-helpers "^2.0.0" - reduce-function-call "^1.0.2" - postcss-color-gray@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz#532a31eb909f8da898ceffe296fdc1f864be8547" @@ -6610,15 +6444,6 @@ postcss-color-gray@^5.0.0: postcss "^7.0.5" postcss-values-parser "^2.0.0" -postcss-color-hex-alpha@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-3.0.0.tgz#1e53e6c8acb237955e8fd08b7ecdb1b8b8309f95" - integrity sha1-HlPmyKyyN5Vej9CLfs2xuLgwn5U= - dependencies: - color "^1.0.3" - postcss "^6.0.1" - postcss-message-helpers "^2.0.0" - postcss-color-hex-alpha@^5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz#a8d9ca4c39d497c9661e374b9c51899ef0f87388" @@ -6627,25 +6452,6 @@ postcss-color-hex-alpha@^5.0.3: postcss "^7.0.14" postcss-values-parser "^2.0.1" -postcss-color-hsl@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-color-hsl/-/postcss-color-hsl-2.0.0.tgz#12703666fa310430e3f30a454dac1386317d5844" - integrity sha1-EnA2ZvoxBDDj8wpFTawThjF9WEQ= - dependencies: - postcss "^6.0.1" - postcss-value-parser "^3.3.0" - units-css "^0.4.0" - -postcss-color-hwb@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-color-hwb/-/postcss-color-hwb-3.0.0.tgz#3402b19ef4d8497540c1fb5072be9863ca95571e" - integrity sha1-NAKxnvTYSXVAwftQcr6YY8qVVx4= - dependencies: - color "^1.0.3" - postcss "^6.0.1" - postcss-message-helpers "^2.0.0" - reduce-function-call "^1.0.2" - postcss-color-mod-function@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz#816ba145ac11cc3cb6baa905a75a49f903e4d31d" @@ -6655,14 +6461,6 @@ postcss-color-mod-function@^3.0.3: postcss "^7.0.2" postcss-values-parser "^2.0.0" -postcss-color-rebeccapurple@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-3.1.0.tgz#ce1269ecc2d0d8bf92aab44bd884e633124c33ec" - integrity sha512-212hJUk9uSsbwO5ECqVjmh/iLsmiVL1xy9ce9TVf+X3cK/ZlUIlaMdoxje/YpsL9cmUH3I7io+/G2LyWx5rg1g== - dependencies: - postcss "^6.0.22" - postcss-values-parser "^1.5.0" - postcss-color-rebeccapurple@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz#c7a89be872bb74e45b1e3022bfe5748823e6de77" @@ -6671,23 +6469,6 @@ postcss-color-rebeccapurple@^4.0.1: postcss "^7.0.2" postcss-values-parser "^2.0.0" -postcss-color-rgb@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-color-rgb/-/postcss-color-rgb-2.0.0.tgz#14539c8a7131494b482e0dd1cc265ff6514b5263" - integrity sha1-FFOcinExSUtILg3RzCZf9lFLUmM= - dependencies: - postcss "^6.0.1" - postcss-value-parser "^3.3.0" - -postcss-color-rgba-fallback@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-color-rgba-fallback/-/postcss-color-rgba-fallback-3.0.0.tgz#37d5c9353a07a09270912a82606bb42a0d702c04" - integrity sha1-N9XJNToHoJJwkSqCYGu0Kg1wLAQ= - dependencies: - postcss "^6.0.6" - postcss-value-parser "^3.3.0" - rgb-hex "^2.1.0" - postcss-colormin@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.3.tgz#ae060bce93ed794ac71264f08132d550956bd381" @@ -6705,50 +6486,6 @@ postcss-convert-values@^4.0.1: postcss "^7.0.0" postcss-value-parser "^3.0.0" -postcss-cssnext@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/postcss-cssnext/-/postcss-cssnext-3.1.0.tgz#927dc29341a938254cde38ea60a923b9dfedead9" - integrity sha512-awPDhI4OKetcHCr560iVCoDuP6e/vn0r6EAqdWPpAavJMvkBSZ6kDpSN4b3mB3Ti57hQMunHHM8Wvx9PeuYXtA== - dependencies: - autoprefixer "^7.1.1" - caniuse-api "^2.0.0" - chalk "^2.0.1" - pixrem "^4.0.0" - pleeease-filters "^4.0.0" - postcss "^6.0.5" - postcss-apply "^0.8.0" - postcss-attribute-case-insensitive "^2.0.0" - postcss-calc "^6.0.0" - postcss-color-function "^4.0.0" - postcss-color-gray "^4.0.0" - postcss-color-hex-alpha "^3.0.0" - postcss-color-hsl "^2.0.0" - postcss-color-hwb "^3.0.0" - postcss-color-rebeccapurple "^3.0.0" - postcss-color-rgb "^2.0.0" - postcss-color-rgba-fallback "^3.0.0" - postcss-custom-media "^6.0.0" - postcss-custom-properties "^6.1.0" - postcss-custom-selectors "^4.0.1" - postcss-font-family-system-ui "^3.0.0" - postcss-font-variant "^3.0.0" - postcss-image-set-polyfill "^0.3.5" - postcss-initial "^2.0.0" - postcss-media-minmax "^3.0.0" - postcss-nesting "^4.0.1" - postcss-pseudo-class-any-link "^4.0.0" - postcss-pseudoelements "^5.0.0" - postcss-replace-overflow-wrap "^2.0.0" - postcss-selector-matches "^3.0.1" - postcss-selector-not "^3.0.1" - -postcss-custom-media@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-6.0.0.tgz#be532784110ecb295044fb5395a18006eb21a737" - integrity sha1-vlMnhBEOyylQRPtTlaGABushpzc= - dependencies: - postcss "^6.0.1" - postcss-custom-media@^7.0.8: version "7.0.8" resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz#fffd13ffeffad73621be5f387076a28b00294e0c" @@ -6756,14 +6493,6 @@ postcss-custom-media@^7.0.8: dependencies: postcss "^7.0.14" -postcss-custom-properties@^6.1.0: - version "6.3.1" - resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-6.3.1.tgz#5c52abde313d7ec9368c4abf67d27a656cba8b39" - integrity sha512-zoiwn4sCiUFbr4KcgcNZLFkR6gVQom647L+z1p/KBVHZ1OYwT87apnS42atJtx6XlX2yI7N5fjXbFixShQO2QQ== - dependencies: - balanced-match "^1.0.0" - postcss "^6.0.18" - postcss-custom-properties@^8.0.11: version "8.0.11" resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz#2d61772d6e92f22f5e0d52602df8fae46fa30d97" @@ -6772,14 +6501,6 @@ postcss-custom-properties@^8.0.11: postcss "^7.0.17" postcss-values-parser "^2.0.1" -postcss-custom-selectors@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-4.0.1.tgz#781382f94c52e727ef5ca4776ea2adf49a611382" - integrity sha1-eBOC+UxS5yfvXKR3bqKt9JphE4I= - dependencies: - postcss "^6.0.1" - postcss-selector-matches "^3.0.0" - postcss-custom-selectors@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz#64858c6eb2ecff2fb41d0b28c9dd7b3db4de7fba" @@ -6857,20 +6578,6 @@ postcss-focus-within@^3.0.0: dependencies: postcss "^7.0.2" -postcss-font-family-system-ui@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-font-family-system-ui/-/postcss-font-family-system-ui-3.0.0.tgz#675fe7a9e029669f05f8dba2e44c2225ede80623" - integrity sha512-58G/hTxMSSKlIRpcPUjlyo6hV2MEzvcVO2m4L/T7Bb2fJTG4DYYfQjQeRvuimKQh1V1sOzCIz99g+H2aFNtlQw== - dependencies: - postcss "^6.0" - -postcss-font-variant@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-3.0.0.tgz#08ccc88f6050ba82ed8ef2cc76c0c6a6b41f183e" - integrity sha1-CMzIj2BQuoLtjvLMdsDGprQfGD4= - dependencies: - postcss "^6.0.1" - postcss-font-variant@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-4.0.0.tgz#71dd3c6c10a0d846c5eda07803439617bbbabacc" @@ -6893,14 +6600,6 @@ postcss-image-set-function@^3.0.1: postcss "^7.0.2" postcss-values-parser "^2.0.0" -postcss-image-set-polyfill@^0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/postcss-image-set-polyfill/-/postcss-image-set-polyfill-0.3.5.tgz#0f193413700cf1f82bd39066ef016d65a4a18181" - integrity sha1-Dxk0E3AM8fgr05Bm7wFtZaShgYE= - dependencies: - postcss "^6.0.1" - postcss-media-query-parser "^0.2.3" - postcss-import@^12.0.1: version "12.0.1" resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-12.0.1.tgz#cf8c7ab0b5ccab5649024536e565f841928b7153" @@ -6911,14 +6610,6 @@ postcss-import@^12.0.1: read-cache "^1.0.0" resolve "^1.1.7" -postcss-initial@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-2.0.0.tgz#72715f7336e0bb79351d99ee65c4a253a8441ba4" - integrity sha1-cnFfczbgu3k1HZnuZcSiU6hEG6Q= - dependencies: - lodash.template "^4.2.4" - postcss "^6.0.1" - postcss-initial@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-3.0.2.tgz#f018563694b3c16ae8eaabe3c585ac6319637b2d" @@ -6960,13 +6651,6 @@ postcss-logical@^3.0.0: dependencies: postcss "^7.0.2" -postcss-media-minmax@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-3.0.0.tgz#675256037a43ef40bc4f0760bfd06d4dc69d48d2" - integrity sha1-Z1JWA3pD70C8Twdgv9BtTcadSNI= - dependencies: - postcss "^6.0.1" - postcss-media-minmax@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz#b75bb6cbc217c8ac49433e12f22048814a4f5ed5" @@ -6974,11 +6658,6 @@ postcss-media-minmax@^4.0.0: dependencies: postcss "^7.0.2" -postcss-media-query-parser@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz#27b39c6f4d94f81b1a73b8f76351c609e5cef244" - integrity sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ= - postcss-merge-longhand@^4.0.11: version "4.0.11" resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz#62f49a13e4a0ee04e7b98f42bb16062ca2549e24" @@ -6999,11 +6678,6 @@ postcss-merge-rules@^4.0.3: postcss-selector-parser "^3.0.0" vendors "^1.0.0" -postcss-message-helpers@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz#a4f2f4fab6e4fe002f0aed000478cdf52f9ba60e" - integrity sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4= - postcss-minify-font-values@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" @@ -7073,13 +6747,6 @@ postcss-modules-values@^3.0.0: icss-utils "^4.0.0" postcss "^7.0.6" -postcss-nesting@^4.0.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-4.2.1.tgz#0483bce338b3f0828ced90ff530b29b98b00300d" - integrity sha512-IkyWXICwagCnlaviRexi7qOdwPw3+xVVjgFfGsxmztvRVaNxAlrypOIKqDE5mxY+BVxnId1rnUKBRQoNE2VDaA== - dependencies: - postcss "^6.0.11" - postcss-nesting@^7.0.0: version "7.0.1" resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-7.0.1.tgz#b50ad7b7f0173e5b5e3880c3501344703e04c052" @@ -7232,14 +6899,6 @@ postcss-preset-env@^6.7.0: postcss-selector-matches "^4.0.0" postcss-selector-not "^4.0.0" -postcss-pseudo-class-any-link@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-4.0.0.tgz#9152a0613d3450720513e8892854bae42d0ee68e" - integrity sha1-kVKgYT00UHIFE+iJKFS65C0O5o4= - dependencies: - postcss "^6.0.1" - postcss-selector-parser "^2.2.3" - postcss-pseudo-class-any-link@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz#2ed3eed393b3702879dec4a87032b210daeb04d1" @@ -7248,13 +6907,6 @@ postcss-pseudo-class-any-link@^6.0.0: postcss "^7.0.2" postcss-selector-parser "^5.0.0-rc.3" -postcss-pseudoelements@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-pseudoelements/-/postcss-pseudoelements-5.0.0.tgz#eef194e8d524645ca520a949e95e518e812402cb" - integrity sha1-7vGU6NUkZFylIKlJ6V5RjoEkAss= - dependencies: - postcss "^6.0.0" - postcss-reduce-initial@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df" @@ -7273,13 +6925,6 @@ postcss-reduce-transforms@^4.0.2: postcss "^7.0.0" postcss-value-parser "^3.0.0" -postcss-replace-overflow-wrap@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-2.0.0.tgz#794db6faa54f8db100854392a93af45768b4e25b" - integrity sha1-eU22+qVPjbEAhUOSqTr0V2i04ls= - dependencies: - postcss "^6.0.1" - postcss-replace-overflow-wrap@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz#61b360ffdaedca84c7c918d2b0f0d0ea559ab01c" @@ -7294,14 +6939,6 @@ postcss-safe-parser@^4.0.2: dependencies: postcss "^7.0.26" -postcss-selector-matches@^3.0.0, postcss-selector-matches@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/postcss-selector-matches/-/postcss-selector-matches-3.0.1.tgz#e5634011e13950881861bbdd58c2d0111ffc96ab" - integrity sha1-5WNAEeE5UIgYYbvdWMLQER/8lqs= - dependencies: - balanced-match "^0.4.2" - postcss "^6.0.1" - postcss-selector-matches@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz#71c8248f917ba2cc93037c9637ee09c64436fcff" @@ -7310,14 +6947,6 @@ postcss-selector-matches@^4.0.0: balanced-match "^1.0.0" postcss "^7.0.2" -postcss-selector-not@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-3.0.1.tgz#2e4db2f0965336c01e7cec7db6c60dff767335d9" - integrity sha1-Lk2y8JZTNsAefOx9tsYN/3ZzNdk= - dependencies: - balanced-match "^0.4.2" - postcss "^6.0.1" - postcss-selector-not@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-4.0.0.tgz#c68ff7ba96527499e832724a2674d65603b645c0" @@ -7326,15 +6955,6 @@ postcss-selector-not@^4.0.0: balanced-match "^1.0.0" postcss "^7.0.2" -postcss-selector-parser@^2.2.2, postcss-selector-parser@^2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz#f9437788606c3c9acee16ffe8d8b16297f27bb90" - integrity sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A= - dependencies: - flatten "^1.0.2" - indexes-of "^1.0.1" - uniq "^1.0.1" - postcss-selector-parser@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865" @@ -7378,7 +6998,7 @@ postcss-unique-selectors@^4.0.1: postcss "^7.0.0" uniqs "^2.0.0" -postcss-value-parser@^3.0.0, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0, postcss-value-parser@^3.3.1: +postcss-value-parser@^3.0.0, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" @@ -7387,15 +7007,6 @@ postcss-value-parser@^4.1.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== -postcss-values-parser@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-1.5.0.tgz#5d9fa63e2bcb0179ce48f3235303765eb89f3047" - integrity sha512-3M3p+2gMp0AH3da530TlX8kiO1nxdTnc3C6vr8dMxRLIlh8UYkz0/wcwptSXjhtx2Fr0TySI7a+BHDQ8NL7LaQ== - dependencies: - flatten "^1.0.2" - indexes-of "^1.0.1" - uniq "^1.0.1" - postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz#da8b472d901da1e205b47bdc98637b9e9e550e5f" @@ -7405,15 +7016,6 @@ postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1: indexes-of "^1.0.1" uniq "^1.0.1" -postcss@^6.0, postcss@^6.0.0, postcss@^6.0.1, postcss@^6.0.11, postcss@^6.0.14, postcss@^6.0.17, postcss@^6.0.18, postcss@^6.0.22, postcss@^6.0.23, postcss@^6.0.5, postcss@^6.0.6: - version "6.0.23" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" - integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag== - dependencies: - chalk "^2.4.1" - source-map "^0.6.1" - supports-color "^5.4.0" - postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.2, postcss@^7.0.5: version "7.0.17" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.17.tgz#4da1bdff5322d4a0acaab4d87f3e782436bad31f" @@ -7958,30 +7560,6 @@ redent@^1.0.0: indent-string "^2.1.0" strip-indent "^1.0.1" -reduce-css-calc@^1.2.7: - version "1.3.0" - resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716" - integrity sha1-dHyRTgSWFKTJz7umKYca0dKSdxY= - dependencies: - balanced-match "^0.4.2" - math-expression-evaluator "^1.2.14" - reduce-function-call "^1.0.1" - -reduce-css-calc@^2.0.0: - version "2.1.7" - resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-2.1.7.tgz#1ace2e02c286d78abcd01fd92bfe8097ab0602c2" - integrity sha512-fDnlZ+AybAS3C7Q9xDq5y8A2z+lT63zLbynew/lur/IR24OQF5x98tfNwf79mzEdfywZ0a2wpM860FhFfMxZlA== - dependencies: - css-unit-converter "^1.1.1" - postcss-value-parser "^3.3.0" - -reduce-function-call@^1.0.1, reduce-function-call@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/reduce-function-call/-/reduce-function-call-1.0.3.tgz#60350f7fb252c0a67eb10fd4694d16909971300f" - integrity sha512-Hl/tuV2VDgWgCSEeWMLwxLZqX7OK59eU1guxXsRKTAyeYimivsKdtcV4fu3r710tpG5GmDKDhQ0HSZLExnNmyQ== - dependencies: - balanced-match "^1.0.0" - redux@^4.0.4: version "4.0.5" resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f" @@ -8171,20 +7749,10 @@ retry@^0.12.0: resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= -rgb-hex@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/rgb-hex/-/rgb-hex-2.1.0.tgz#c773c5fe2268a25578d92539a82a7a5ce53beda6" - integrity sha1-x3PF/iJoolV42SU5qCp6XOU77aY= - rgb-regex@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" -rgb@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/rgb/-/rgb-0.1.0.tgz#be27b291e8feffeac1bd99729721bfa40fc037b5" - integrity sha1-vieykej+/+rBvZlylyG/pA/AN7U= - rgba-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" @@ -8927,7 +8495,7 @@ supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" -supports-color@^5.3.0, supports-color@^5.4.0: +supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" dependencies: @@ -9341,14 +8909,6 @@ unique-slug@^2.0.0: dependencies: imurmurhash "^0.1.4" -units-css@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/units-css/-/units-css-0.4.0.tgz#d6228653a51983d7c16ff28f8b9dc3b1ffed3a07" - integrity sha1-1iKGU6UZg9fBb/KPi53Dsf/tOgc= - dependencies: - isnumeric "^0.2.0" - viewport-dimensions "^0.2.0" - universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" @@ -9499,11 +9059,6 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -viewport-dimensions@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/viewport-dimensions/-/viewport-dimensions-0.2.0.tgz#de740747db5387fd1725f5175e91bac76afdf36c" - integrity sha1-3nQHR9tTh/0XJfUXXpG6x2r982w= - vm-browserify@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" -- GitLab From 454e62194112bdfa7366947280cbec6e2498a19e Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Thu, 8 Oct 2020 09:28:20 -1000 Subject: [PATCH 142/283] Info for pending tests --- .../checkpoint_assessments_spec.rb | 12 ++++++------ .../features/content_files/view_feature_spec.rb | 17 +++++++++-------- .../activity_aggregator_service_spec.rb | 1 + spec/services/auth_resolver_service_spec.rb | 1 + spec/services/resync_course_service_spec.rb | 2 +- 5 files changed, 18 insertions(+), 15 deletions(-) diff --git a/spec/features/content_files/checkpoint_assessments_spec.rb b/spec/features/content_files/checkpoint_assessments_spec.rb index 0d3783c..95aefed 100644 --- a/spec/features/content_files/checkpoint_assessments_spec.rb +++ b/spec/features/content_files/checkpoint_assessments_spec.rb @@ -220,7 +220,7 @@ describe "Viewing checkpoints", js: true do end context "when hitting the back button" do - xit "shows the proper modal" do # Not sure how this will work + xit "shows the proper modal" do # TODO Not sure how this will work visit content_file_path(cohort, release.block, checkpoint.path) find(".checkpoint-landing-button").click page.evaluate_script('window.history.back()') @@ -430,7 +430,7 @@ describe "Viewing checkpoints", js: true do find(:css, ".checkpoint-landing-button").click wait_for_ajax - + within ".checkpoint-navbar-details" do expect(page).to have_selector ".checkpoint-pair-menu" find(".checkpoint-pair-menu").click @@ -477,7 +477,7 @@ describe "Viewing checkpoints", js: true do within ".modal-main" do all("input[type='checkbox']")[0].click click_button("Set Partner(s)") - end + end within ".checkpoint-landing-button" do avatars = all(".user-avatar") @@ -504,7 +504,7 @@ describe "Viewing checkpoints", js: true do within ".modal-main" do all("input[type='checkbox']")[0].click click_button("Set Partner(s)") - end + end within ".checkpoint-landing-button" do avatars = all(".user-avatar") @@ -517,7 +517,7 @@ describe "Viewing checkpoints", js: true do click_button("Start Assessment") expect(avatars.size).to eq 2 end - end + end end end @@ -629,4 +629,4 @@ describe "Viewing checkpoints", js: true do end end end -end \ No newline at end of file +end diff --git a/spec/features/content_files/view_feature_spec.rb b/spec/features/content_files/view_feature_spec.rb index ccb1fcb..87bdec6 100644 --- a/spec/features/content_files/view_feature_spec.rb +++ b/spec/features/content_files/view_feature_spec.rb @@ -64,7 +64,7 @@ describe "Viewing content files", js: true do expect(page).to have_link("Copy SSH clone link") expect(page).to have_link("Copy HTTPS clone link") end - + # download actions within(".instructor-actions") do all(".icon")[2].click @@ -284,7 +284,7 @@ describe "Viewing content files", js: true do cohort.update_attributes(mode: Cohort::MODES[:percentage]) checkpoint_submission.update_attributes(state: CheckpointSubmission::STATES[:done], cohort: cohort) visit content_file_path(cohort, release.block, checkpoint_content_file.path) - + within(".content-file-sidebar") do expect(page).to have_content("100%") end @@ -295,7 +295,7 @@ describe "Viewing content files", js: true do it "displays no checkpoint progress" do checkpoint_submission.update_attributes(state: CheckpointSubmission::STATES[:started]) visit content_file_path(cohort, release.block, checkpoint_content_file.path) - + within(".content-file-sidebar") do expect(page).to_not have_content("100%") end @@ -358,18 +358,19 @@ describe "Viewing content files", js: true do Challenge.create!(processed_text[:challenges][0].merge(content_file: content_file, points: 3)) visit content_file_path(cohort, release.block, content_file.path) - + expect(page).to_not have_content("3 PT") end end - + context "when in percentage mode" do + # Disabled since gsap package removed xit "does show point value" do checkpoint_content_file = create(:content_file, html: html, standard: standard, position: 0, content_file_type: ContentFile::TYPES[:checkpoint]) Challenge.create!(processed_text[:challenges][0].merge(content_file: checkpoint_content_file, points: 3)) cohort.update_attributes(mode: "Percentage") visit content_file_path(cohort, release.block, checkpoint_content_file.path) - + expect(page).to have_content("3 PT") end end @@ -1276,7 +1277,7 @@ describe "Viewing content files", js: true do expect(page).to have_content("1/3 = ?") find_field("answer").send_keys(:delete) - + fill_in "answer", with: ".5" find_field("answer").send_keys(:enter) # test key submission @@ -1720,7 +1721,7 @@ describe "Viewing content files", js: true do it "toggles the disabled state of the checkpoint when questions are answered" do Challenge.create!(processed_text[:challenges][2].merge(content_file: content_file)) visit content_file_path(cohort, release.block, content_file.path) - + find(:css, ".checkpoint-landing-button").click within(".checkpoint-challenges-attempted") do diff --git a/spec/services/activity_aggregator_service_spec.rb b/spec/services/activity_aggregator_service_spec.rb index 09aa834..0e3666b 100644 --- a/spec/services/activity_aggregator_service_spec.rb +++ b/spec/services/activity_aggregator_service_spec.rb @@ -251,6 +251,7 @@ describe ActivityAggregatorService do end end + # TODO Should we re-enable this performance tests? xit "does not slow to a crawl" do expect(Benchmark.measure { subject }.real.round(5)).to be < 3 end diff --git a/spec/services/auth_resolver_service_spec.rb b/spec/services/auth_resolver_service_spec.rb index ef30b18..a2a693c 100644 --- a/spec/services/auth_resolver_service_spec.rb +++ b/spec/services/auth_resolver_service_spec.rb @@ -26,6 +26,7 @@ describe AuthResolverService do ) end + # These tests are disable since we no longer are using the auth service describe ".resolve_cohort" do xit "allows a cohort with a product type of 'Course' to be created" do course_cohort = nil diff --git a/spec/services/resync_course_service_spec.rb b/spec/services/resync_course_service_spec.rb index e78f598..091b076 100644 --- a/spec/services/resync_course_service_spec.rb +++ b/spec/services/resync_course_service_spec.rb @@ -97,7 +97,7 @@ describe ResyncCourseService do let!(:standard_1) { create(:standard, release: cohort_release_1.release) } let!(:standard_2) { create(:standard, release: release_2) } - xit "creates content visibility objects for each standard when true" do + it "creates content visibility objects for each standard when true" do params.merge!(course_url: "url", default_unit_visibility: true) expect(subject).to be_a_success -- GitLab From 635d0fb76c351a8cb5faeb3119e848f3ec1c325b Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Thu, 8 Oct 2020 13:09:29 -1000 Subject: [PATCH 143/283] adding module to auto size the pdfs --- .../components/content_files/PDFRenderer.tsx | 44 +++++++++++-------- package.json | 1 + yarn.lock | 29 +++++++++++- 3 files changed, 55 insertions(+), 19 deletions(-) diff --git a/app/javascript/components/content_files/PDFRenderer.tsx b/app/javascript/components/content_files/PDFRenderer.tsx index 9f9ebe8..803de67 100644 --- a/app/javascript/components/content_files/PDFRenderer.tsx +++ b/app/javascript/components/content_files/PDFRenderer.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import { SizeMe } from 'react-sizeme' import { Document, Page, pdfjs } from 'react-pdf/dist/entry.webpack'; pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`; @@ -31,24 +32,31 @@ export default class PDFRenderer extends React.Component { View on Github )} -
    - - { - Array.from( - new Array(this.state.numPages), - (_el, index) => ( - - ), - ) - } - -
    + + {({ size }) => ( +
    + + { + Array.from( + new Array(this.state.numPages), + (_el, index) => ( + + ), + ) + } + +
    + )} +
    ) } diff --git a/package.json b/package.json index cc79cf0..099c822 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "react-paginate": "^6.5.0", "react-pdf": "^4.2.0", "react-scroll-sync": "^0.8.0", + "react-sizeme": "^2.6.12", "react-textarea-autosize": "^8.2.0", "react-tooltip": "^4.2.10", "react_ujs": "^2.6.1", diff --git a/yarn.lock b/yarn.lock index 36061c0..f8fc261 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1763,6 +1763,11 @@ base@^0.11.1: mixin-deep "^1.2.0" pascalcase "^0.1.1" +batch-processor@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/batch-processor/-/batch-processor-1.0.0.tgz#75c95c32b748e0850d10c2b168f6bdbe9891ace8" + integrity sha1-dclcMrdI4IUNEMKxaPa9vpiRrOg= + batch@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" @@ -3196,6 +3201,13 @@ electron-to-chromium@^1.3.571: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.578.tgz#e6671936f4571a874eb26e2e833aa0b2c0b776e0" integrity sha512-z4gU6dA1CbBJsAErW5swTGAaU2TBzc2mPAonJb00zqW1rOraDo2zfBMDRvaz9cVic+0JEZiYbHWPw/fTaZlG2Q== +element-resize-detector@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/element-resize-detector/-/element-resize-detector-1.2.1.tgz#b0305194447a4863155e58f13323a0aef30851d1" + integrity sha512-BdFsPepnQr9fznNPF9nF4vQ457U/ZJXQDSNF1zBe7yaga8v9AdZf3/NElYxFdUh7SitSGt040QygiTo6dtatIw== + dependencies: + batch-processor "1.0.0" + elliptic@^6.0.0: version "6.5.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.0.tgz#2b8ed4c891b7de3200e14412a5b8248c7af505ca" @@ -7403,6 +7415,16 @@ react-scroll-sync@^0.8.0: resolved "https://registry.yarnpkg.com/react-scroll-sync/-/react-scroll-sync-0.8.0.tgz#61fabed2afc47d41e6938819d620799da3610548" integrity sha512-Ms9srm41UM+lWexuqdocXjqaqqt6ZRSFxcudgB0sYhC7Or+m12WemTwY8BaQCRf7hA8zHDk55FHvMkqsH7gF+w== +react-sizeme@^2.6.12: + version "2.6.12" + resolved "https://registry.yarnpkg.com/react-sizeme/-/react-sizeme-2.6.12.tgz#ed207be5476f4a85bf364e92042520499455453e" + integrity sha512-tL4sCgfmvapYRZ1FO2VmBmjPVzzqgHA7kI8lSJ6JS6L78jXFNRdOZFpXyK6P1NBZvKPPCZxReNgzZNUajAerZw== + dependencies: + element-resize-detector "^1.2.1" + invariant "^2.2.4" + shallowequal "^1.1.0" + throttle-debounce "^2.1.0" + react-textarea-autosize@^8.2.0: version "8.2.0" resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.2.0.tgz#fae38653f5ec172a855fd5fffb39e466d56aebdb" @@ -8007,7 +8029,7 @@ shallowequal@^0.2.2: dependencies: lodash.keys "^3.1.2" -shallowequal@^1.0.1: +shallowequal@^1.0.1, shallowequal@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" @@ -8642,6 +8664,11 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= +throttle-debounce@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-2.3.0.tgz#fd31865e66502071e411817e241465b3e9c372e2" + integrity sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ== + through2@^2.0.0: version "2.0.5" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" -- GitLab From 22f000797af08a76c9f447a628eb0618d3bb0942 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Thu, 8 Oct 2020 14:44:57 -1000 Subject: [PATCH 144/283] Removed unused files --- .../webhooks/auth/cohorts_controller.rb | 34 -- .../webhooks/auth/users_controller.rb | 24 -- app/services/auth_resolver_service.rb | 85 ----- .../webhooks/auth/cohorts_controller_spec.rb | 156 -------- .../webhooks/auth/users_controller_spec.rb | 114 ------ spec/services/auth_resolver_service_spec.rb | 335 ------------------ 6 files changed, 748 deletions(-) delete mode 100644 app/controllers/webhooks/auth/cohorts_controller.rb delete mode 100644 app/controllers/webhooks/auth/users_controller.rb delete mode 100644 app/services/auth_resolver_service.rb delete mode 100644 spec/controllers/webhooks/auth/cohorts_controller_spec.rb delete mode 100644 spec/controllers/webhooks/auth/users_controller_spec.rb delete mode 100644 spec/services/auth_resolver_service_spec.rb diff --git a/app/controllers/webhooks/auth/cohorts_controller.rb b/app/controllers/webhooks/auth/cohorts_controller.rb deleted file mode 100644 index c51cc92..0000000 --- a/app/controllers/webhooks/auth/cohorts_controller.rb +++ /dev/null @@ -1,34 +0,0 @@ -module Webhooks - module Auth - class CohortsController < ActionController::Base - def update - cohort = AuthResolverService.resolve(request.env[:resolved_resource]) - - if cohort.nil? - error_message = "Provided cohort is not compatible with Learn V2" - results = { cohort: cohort_params, errors: [error_message] } - - Honeybadger.notify( - error_message, - context: { auth_resource: request.env[:resolved_resource] } - ) - - render json: { errors: results }, status: 400 - elsif cohort.errors.empty? - render json: {}, status: 200 - else - results = { cohort: cohort_params, errors: cohort.errors.full_messages } - - Honeybadger.notify("Invalid cohort payload", context: results) - render json: { errors: results }, status: 400 - end - end - - private - - def cohort_params - params.require(:data).permit! - end - end - end -end diff --git a/app/controllers/webhooks/auth/users_controller.rb b/app/controllers/webhooks/auth/users_controller.rb deleted file mode 100644 index 866f006..0000000 --- a/app/controllers/webhooks/auth/users_controller.rb +++ /dev/null @@ -1,24 +0,0 @@ -module Webhooks - module Auth - class UsersController < ActionController::Base - def update - user = AuthResolverService.resolve(request.env[:resolved_resource]) - - if user.errors.empty? - render json: {}, status: 200 - else - results = { user: user_params, errors: user.errors.full_messages } - - Honeybadger.notify("Invalid user payload", context: results) - render json: { errors: results }, status: 400 - end - end - - private - - def user_params - params.require(:data).permit! - end - end - end -end diff --git a/app/services/auth_resolver_service.rb b/app/services/auth_resolver_service.rb deleted file mode 100644 index 3601e48..0000000 --- a/app/services/auth_resolver_service.rb +++ /dev/null @@ -1,85 +0,0 @@ -class AuthResolverService - attr_accessor :auth_user - - def self.resolve(auth_resource) - # TODO: AuthApi fix - # case auth_resource - # when AuthApi::User - # new.resolve_user(auth_resource) - # when AuthApi::Product - # new.resolve_cohort(auth_resource) - # end - puts "Removed resolver" - end - - def resolve_user(auth_user) - @auth_user = auth_user - user = find_user_from(auth_user) - - update_user(user) - rescue ActiveRecord::ActiveRecordError => e - user.errors.add(:base, e.message) - user - end - - def resolve_cohort(auth_product) - return unless product_type_matches_forge?(auth_product) - - cohort = find_cohort_from(auth_product) - attrs = auth_product.attribute_intersection(cohort) - attrs[:deleted_at] = DateTime.current if auth_product.webhook_event == "product.destroy" - cohort.update(attrs) - cohort - end - - private - - def update_user(user) - attrs = auth_user.attribute_intersection(user) - - User.transaction do - user.update(attrs) - - if auth_user.attributes.dig(:is_deleted) - CohortUser.where(user: user).destroy_all - else - old_cohort_ids = CohortUser.where(user: user).pluck(:cohort_id) - - course_registrations.each do |registration| - cohort = resolve_cohort(registration.product) - next if cohort.blank? - - old_cohort_ids.delete(cohort.id) - - cohort_user = CohortUser.find_or_initialize_by(user: user, cohort: cohort) - cohort_user.update!(roles: registration.roles) - end - CohortUser.where(user: user, cohort_id: old_cohort_ids).destroy_all - end - end - - user - end - - def find_user_from(auth_user) - User.find_by(uid: auth_user.uid) || User.new - end - - def find_cohort_from(auth_product) - Cohort.find_by(uid: auth_product.uid) || Cohort.new - end - - def product_type_matches_forge?(auth_product) - auth_product.product_type.present? - end - - def course_registrations - auth_user.registrations.select { |r| product_type_matches_forge?(r.product) } - end - - def registration_unchanged?(old_registration_role, auth_product_role) - return false if old_registration_role.nil? - - old_registration_role == auth_product_role - end -end diff --git a/spec/controllers/webhooks/auth/cohorts_controller_spec.rb b/spec/controllers/webhooks/auth/cohorts_controller_spec.rb deleted file mode 100644 index ca76a70..0000000 --- a/spec/controllers/webhooks/auth/cohorts_controller_spec.rb +++ /dev/null @@ -1,156 +0,0 @@ -require "spec_helper" - -# Disabling rspec tests here since Auth is no longer used - -describe Webhooks::Auth::CohortsController, type: :request do - describe "POST #update" do - let(:action) do - post webhooks_auth_cohorts_path, params: { data: cohort_info }, headers: { "X-Auth-Token" => auth_token } - end - let(:auth_token) { "abc" } - - context "with invalid attributes" do - let(:cohort_info) do - { - "id": "10", - "type": "products", - "attributes": { - "uid": "abc123", - "slug": "17-01-wd-gt", - "name": "Galvanize Web Development Foundations with JavaScript - Seattle (7.10)", - "product_type": "", - "label": "some label", - "gcode": "g666WD", - "campus_name": "Seattle-Pioneer Square", - "slack_channel": "g666wd-seattle", - "starts_on": "2017-07-10T00:00:00.000Z", - "ends_on": "2017-08-30T00:00:00.000Z", - "created_at": "2017-10-05T14:58:46.894Z", - "mode": "Mastery" - } - } - end - - context "when the auth token is incorrect" do - before { AuthApi.configuration.webhook_token = "....bad token...." } - - xit "404s" do - expect { action }.to raise_error(ActionController::RoutingError) - end - end - - context "when the auth token is correct" do - before { AuthApi.configuration.webhook_token = auth_token } - - context "when resolving a new cohort that is not a valid Forge product type" do - let(:product_type) { "" } - - xit "notifies honeybadger" do - expect(Honeybadger).to receive(:notify) do |message, options| - expect(message).to eq("Provided cohort is not compatible with Learn V2") - expect(options[:context][:auth_resource].attributes).to eq(cohort_info[:attributes]) - end - - action - end - - xit "responds with errors" do - action - - errors = { "cohort" => cohort_info, "errors" => ["Provided cohort is not compatible with Learn V2"] }.to_json - expect(JSON.parse(response.body)["errors"]).to eq JSON.parse(errors) - expect(response.status).to eq(400) - end - end - end - end - - context "with valid attributes" do - context "when the auth token is correct" do - before { AuthApi.configuration.webhook_token = auth_token } - let(:cohort_info) do - { - "id": "10", - "type": "products", - "attributes": { - "uid": "abc123", - "slug": "17-01-wd-gt", - "name": "Galvanize Web Development Foundations with JavaScript - Seattle (7.10)", - "product_type": "Course/Foo", - "label": "17-01-WD-GT", - "gcode": "g666WD", - "campus_name": "Seattle-Pioneer Square", - "slack_channel": "g666wd-seattle", - "starts_on": "2017-07-10T00:00:00.000Z", - "ends_on": "2017-08-30T00:00:00.000Z", - "created_at": "2017-10-05T14:58:46.894Z", - "mode": "Mastery" - } - } - end - - context "when the cohort fails validation on update" do - let(:cohort_info) do - { - "id": "10", - "type": "products", - "attributes": { - "uid": "", - "slug": "17-01-wd-gt", - "name": "Galvanize Web Development Foundations with JavaScript - Seattle (7.10)", - "product_type": "Course/Foo", - "label": "17-01-WD-GT", - "gcode": "g666WD", - "campus_name": "Seattle-Pioneer Square", - "slack_channel": "g666wd-seattle", - "starts_on": "2017-07-10T00:00:00.000Z", - "ends_on": "2017-08-30T00:00:00.000Z", - "created_at": "2017-10-05T14:58:46.894Z", - "mode": "Mastery" - } - } - end - - before { create(:cohort, label: "00-00-WD-DP", uid: "abc123") } - - xit "notifies honeybadger" do - expect(Honeybadger).to receive(:notify) do |_message, options| - expect(options[:context][:errors]).to eq(["Uid can't be blank"]) - end - - action - end - - xit "responds with errors" do - action - - errors = { "cohort" => cohort_info, "errors" => ["Uid can't be blank"] }.to_json - expect(JSON.parse(response.body)["errors"]).to eq JSON.parse(errors) - end - end - - xit "creates a cohort with the valid attributes" do - expect { action }.to change { Cohort.count }.by(1) - - cohort = Cohort.last - expect(cohort.uid).to eq("abc123") - expect(cohort.name).to eq("Galvanize Web Development Foundations with JavaScript - Seattle (7.10)") - expect(cohort.product_type).to eq("Course/Foo") - expect(cohort.label).to eq("17-01-WD-GT") - expect(cohort.gcode).to eq("g666WD") - expect(cohort.campus_name).to eq("Seattle-Pioneer Square") - expect(cohort.slack_channel).to eq("g666wd-seattle") - expect(cohort.starts_on).to eq("2017-07-10T00:00:00.000Z") - expect(cohort.ends_on).to eq("2017-08-30T00:00:00.000Z") - end - - xit "updates an existing cohort with the valid attributes" do - cohort = create(:cohort, uid: "abc123", label: "foo") - - expect { action }.to_not(change { Cohort.count }) - expect(cohort.reload.label).to eq("17-01-WD-GT") - end - end - end - end -end diff --git a/spec/controllers/webhooks/auth/users_controller_spec.rb b/spec/controllers/webhooks/auth/users_controller_spec.rb deleted file mode 100644 index 03fba72..0000000 --- a/spec/controllers/webhooks/auth/users_controller_spec.rb +++ /dev/null @@ -1,114 +0,0 @@ -require "spec_helper" - -# Disabling rspec tests here since Auth is no longer used - -describe Webhooks::Auth::UsersController, type: :request do - describe "POST #update" do - let(:action) do - post webhooks_auth_users_path, params: { data: user_info }, headers: { "X-Auth-Token" => auth_token } - end - let(:auth_token) { "abc" } - - context "with invalid attributes" do - let(:user_info) do - { - id: "1", - type: "users", - attributes: { - uid: "futzybutzy", - first_name: "", - last_name: "Horse Talker", - email: "smooty@exmaple.com", - profile_image: "", - timezone: "", - roles: [""] - } - } - end - - context "when the auth token is incorrect" do - before { AuthApi.configuration.webhook_token = "baz" } - - xit "404s" do - expect { action }.to raise_error(ActionController::RoutingError) - end - end - - context "when the auth token is correct" do - before { AuthApi.configuration.webhook_token = auth_token } - - context "when the user fails validation on update" do - before { create(:user, email: "smitty@example.com", uid: "futzybutzy") } - - xit "notifies honeybadger" do - expect(Honeybadger).to receive(:notify) do |message, options| - expect(message).to eq("Invalid user payload") - expect(options[:context][:errors]).to eq(["First name can't be blank"]) - end - - action - end - - xit "responds with errors" do - action - - errors = { "user" => user_info, "errors" => ["First name can't be blank"] }.to_json - expect(JSON.parse(response.body)["errors"]).to eq JSON.parse(errors) - end - end - - context "when the user fails validation on create" do - xit "responds with errors" do - action - - errors = { "user" => user_info, "errors" => ["First name can't be blank"] }.to_json - expect(JSON.parse(response.body)["errors"]).to eq JSON.parse(errors) - end - end - end - end - - context "with valid attributes" do - context "when the auth token is correct" do - before { AuthApi.configuration.webhook_token = auth_token } - let(:user_info) do - { - id: "1", - type: "users", - attributes: { - uid: "futzybutzy", - first_name: "Smitty", - last_name: "Horse Talker", - email: "smooty@exmaple.com", - profile_image: "dsi.png", - timezone: "MDT", - roles: [""] - } - } - end - - xit "creates a user with the valid attributes" do - expect { action }.to change { User.count }.by(1) - - user = User.last - expect(user.first_name).to eq "Smitty" - expect(user.last_name).to eq "Horse Talker" - expect(user.email).to eq "smooty@exmaple.com" - end - - xit "updates an existing user with the valid attributes" do - user = create(:user, :admin, uid: "futzybutzy", first_name: "FIrst", last_name: "Name", - email: "exampleemail@something.com", profile_image: "img.img", timezone: "PST") - - expect { action }.to_not(change { User.count }) - expect(user.reload.first_name).to eq "Smitty" - expect(user.last_name).to eq "Horse Talker" - expect(user.email).to eq "smooty@exmaple.com" - expect(user.profile_image).to eq "dsi.png" - expect(user.timezone).to eq "MDT" - expect(user.admin?).to be false - end - end - end - end -end diff --git a/spec/services/auth_resolver_service_spec.rb b/spec/services/auth_resolver_service_spec.rb deleted file mode 100644 index a2a693c..0000000 --- a/spec/services/auth_resolver_service_spec.rb +++ /dev/null @@ -1,335 +0,0 @@ -require "spec_helper" - -describe AuthResolverService do - let(:auth_product) do - AuthApi::Product.new( - { attributes: { - uid: "xxxxxxx", - gcode: "g123", - starts_on: Time.zone.now, - product_type: "WDI", - label: "17-01-WD-BD", - name: "Galvanize Web Development ...", - mode: "Mastery" - } }, - event: "product.update" - ) - end - - let(:auth_product_registration) do - AuthApi::Registration.new( - attributes: { - roles: [], - data: {}, - product: auth_product - } - ) - end - - # These tests are disable since we no longer are using the auth service - describe ".resolve_cohort" do - xit "allows a cohort with a product type of 'Course' to be created" do - course_cohort = nil - - expect { course_cohort = subject.resolve_cohort(auth_product) }.to change { Cohort.count }.by(1) - - expect(course_cohort.persisted?).to be true - expect(course_cohort.uid).to eq "xxxxxxx" - expect(course_cohort.product_type).to eq "WDI" - expect(course_cohort.label).to eq "17-01-WD-BD" - end - - xit "allows a cohort with 'WDI' type to be created" do - cohort = nil - auth_product.label = nil - expect { cohort = subject.resolve_cohort(auth_product) }.to change { Cohort.count }.by(1) - - expect(cohort.persisted?).to be true - expect(cohort.uid).to eq "xxxxxxx" - expect(cohort.product_type).to eq "WDI" - expect(cohort.label).to eq nil - end - - xit "allows a cohort with 'Enterprise' type to be created" do - cohort = nil - auth_product.label = nil - auth_product.product_type = "Enterprise Data Science" - expect { cohort = subject.resolve_cohort(auth_product) }.to change { Cohort.count }.by(1) - - expect(cohort.persisted?).to be true - expect(cohort.uid).to eq "xxxxxxx" - expect(cohort.product_type).to eq "Enterprise Data Science" - expect(cohort.label).to eq nil - end - - xit "allows a cohort with 'Pre-Course' type to be created" do - cohort = nil - auth_product.label = nil - auth_product.product_type = "Pre-Course Web Development" - expect { cohort = subject.resolve_cohort(auth_product) }.to change { Cohort.count }.by(1) - - expect(cohort.persisted?).to be true - expect(cohort.uid).to eq "xxxxxxx" - expect(cohort.product_type).to eq "Pre-Course Web Development" - expect(cohort.label).to eq nil - end - - xit "allows a cohort with 'Application Prep' type to be created" do - cohort = nil - auth_product.label = nil - auth_product.product_type = "Application Prep Web Development" - expect { cohort = subject.resolve_cohort(auth_product) }.to change { Cohort.count }.by(1) - - expect(cohort.persisted?).to be true - expect(cohort.uid).to eq "xxxxxxx" - expect(cohort.product_type).to eq "Application Prep Web Development" - expect(cohort.label).to eq nil - end - - xit "allows a cohort with 'Workshop' type to be created" do - cohort = nil - auth_product.label = nil - auth_product.product_type = "Workshop Web Development" - expect { cohort = subject.resolve_cohort(auth_product) }.to change { Cohort.count }.by(1) - - expect(cohort.persisted?).to be true - expect(cohort.uid).to eq "xxxxxxx" - expect(cohort.product_type).to eq "Workshop Web Development" - expect(cohort.label).to eq nil - end - - xit "allows a cohort with a product type of 'Demo' (no slash) to be created" do - enterprise_cohort = nil - - auth_product.product_type = "Demo" - auth_product.uid = "demo" - - expect { enterprise_cohort = subject.resolve_cohort(auth_product) }.to change { Cohort.count }.by(1) - - expect(enterprise_cohort.persisted?).to be true - expect(enterprise_cohort.uid).to eq "demo" - expect(enterprise_cohort.product_type).to eq "Demo" - expect(enterprise_cohort.label).to eq "17-01-WD-BD" - end - - xit "allows a cohort with a product type of 'Other' (no slash) to be created" do - enterprise_cohort = nil - - auth_product.product_type = "Other" - auth_product.uid = "other" - - expect { enterprise_cohort = subject.resolve_cohort(auth_product) }.to change { Cohort.count }.by(1) - - expect(enterprise_cohort.persisted?).to be true - expect(enterprise_cohort.uid).to eq "other" - expect(enterprise_cohort.product_type).to eq "Other" - expect(enterprise_cohort.label).to eq "17-01-WD-BD" - end - - xit "updates an existing cohort if found by uid (name not updated)" do - cohort = nil - create(:cohort, uid: "xxxxxxx", label: "changeme") - expect { cohort = subject.resolve_cohort(auth_product) }.to_not(change { Cohort.count }) - - expect(cohort.reload.uid).to eq "xxxxxxx" - expect(cohort.label).to eq "17-01-WD-BD" - end - - context "when a product is destroyed" do - xit "updates the deleted_at column for a cohort" do - destroyed_auth_product = AuthApi::Product.new( - { attributes: { - uid: "xxxxxxx", - gcode: "g123", - starts_on: Time.zone.now, - product_type: "Course/Foo", - label: "17-01-WD-BD", - title: "Galvanize Web Development ..." - } }, - event: "product.destroy" - ) - cohort = nil - create(:cohort, uid: "xxxxxxx", label: "changeme") - expect { cohort = subject.resolve_cohort(destroyed_auth_product) }.to(change { Cohort.count }.from(1).to(0)) - - expect(cohort.deleted_at).to_not be(nil) - end - end - end - - describe ".resolve_user" do - let(:auth_user) do - AuthApi::User.new( - attributes: { - uid: "gunslinger", - first_name: "Roland", - last_name: "Deschain", - email: "tower_hunter77@example.com", - preferred_campus: "Denver", - github_username: "foobur", - roles: [] - } - ) - end - - let(:products) do - [ - AuthApi::Product.new( - attributes: { - uid: "abc123", - product_type: "Course/Foo", - gcode: "g123", - name: "dafuq", - starts_on: Time.zone.now - } - ), - AuthApi::Product.new( - attributes: { - uid: "xyz123", - product_type: "Other", - name: "dafuq-2" - } - ) - ] - end - - let(:registrations) do - [ - AuthApi::Registration.new( - attributes: { - roles: [], - data: {}, - product: products.first - } - ) - ] - end - - describe "creating a new user" do - before do - create(:cohort, uid: "abc123") - auth_user.registrations = registrations - end - - xit "allows users with the admin role, saving other roles" do - auth_user.roles = [User::ROLES[:admin], "futzy.butzy"] - - user = nil - expect { user = subject.resolve_user(auth_user) }.to change { User.count }.by(1) - expect(user.admin?).to be true - expect(user.preferred_campus.eql?("Denver")).to be true - expect(user.roles).to eq([User::ROLES[:admin], "futzy.butzy"]) - end - - context "when a user has a course product in auth" do - context "when the user does not have a role for the product" do - xit "creates the user with an enrollment cohort_user" do - user = nil - expect { user = subject.resolve_user(auth_user) }.to change { User.count }.by(1) - expect(user.cohorts.length).to eq 1 - expect(user.cohorts.first.uid).to eq "abc123" - expect(user.cohort_users.first.roles).to eq([]) - end - end - - context "when the user has an instructor role for the product in auth" do - before { auth_user.registrations.first.roles << CohortUser::ROLES[:instructor] } - - xit "creates the user with an instructor cohort_user" do - user = nil - expect { user = subject.resolve_user(auth_user) }.to change { User.count }.by(1) - expect(user.cohorts.length).to eq 1 - expect(user.cohorts.first.uid).to eq "abc123" - expect(user.cohort_users.first.roles).to eq([CohortUser::ROLES[:instructor]]) - end - end - end - - xit "lazily creates cohorts for products that it doesn't already know about" do - auth_user.registrations << auth_product_registration - - user = nil - expect { user = subject.resolve_user(auth_user) }.to change { Cohort.count }.by(1) - expect(user.cohorts.count).to eq 2 - end - end - - describe "updating existing users" do - let!(:user) do - create(:user, - uid: "gunslinger", - first_name: "changeme", - last_name: "changeme2", - email: "changeagain@example.com", - preferred_campus: "Austin", - roles: [User::ROLES[:admin]]) - end - - xit "changes the intersected attributes" do - auth_user.roles = [User::ROLES[:admin]] - - subject.resolve_user(auth_user) - expect(user.reload.first_name).to eq "Roland" - expect(user.last_name).to eq "Deschain" - expect(user.preferred_campus).to eq "Denver" - expect(user.email).to eq "tower_hunter77@example.com" - expect(user.github_username).to eq "foobur" - end - - xit "removes the admin role" do - create(:cohort, uid: "abc123") - - subject.resolve_user(auth_user) - expect(user.reload.admin?).to be false - end - - xit "adds new cohort_users" do - create(:cohort, uid: "abc123") - create(:cohort_user, :student, cohort: create(:cohort, uid: "xyz123"), user: user) - auth_user.registrations = registrations - - subject.resolve_user(auth_user) - expect(user.cohorts.length).to eq 1 - expect(user.cohorts.first.uid).to eq "abc123" - end - - xit "removes existing cohort_users that aren't active anymore" do - create(:cohort_user, :student, cohort: create(:cohort, uid: "xyz123"), user: user) - - expect { subject.resolve_user(auth_user) }.to change { user.reload.cohorts.length }.from(1).to(0) - end - - context "when the user's auth registration role has changed" do - before do - auth_user.registrations = registrations - auth_user.registrations.first.roles << CohortUser::ROLES[:instructor] - create(:cohort_user, :student, cohort: create(:cohort, uid: "abc123"), user: user) - end - - xit "updates the existing cohort_user" do - expect { subject.resolve_user(auth_user) }.to_not(change { User.count }) - expect(user.reload.cohorts.length).to eq 1 - expect(user.cohorts.first.uid).to eq "abc123" - expect(user.cohort_users.first.roles).to include(CohortUser::ROLES[:instructor]) - end - end - end - - describe "soft-deleting a user" do - let!(:user) do - create(:user, - uid: "gunslinger", - first_name: "changeme", - last_name: "changeme2", - email: "changeagain@example.com") - end - - xit "removes all cohort user records" do - auth_user.attributes[:is_deleted] = true - auth_user.registrations = registrations - create(:cohort_user, :student, cohort: create(:cohort, uid: "abc123"), user: user) - expect { subject.resolve_user(auth_user) }.to change { user.reload.cohorts.length }.from(1).to(0) - end - end - end -end -- GitLab From c3da91806ca414b19d689c68aed2250316f7815c Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Fri, 9 Oct 2020 15:41:13 -1000 Subject: [PATCH 145/283] Updated sessions and users tests --- spec/controllers/sessions_controller_spec.rb | 176 +++++-------------- spec/controllers/users_controller_spec.rb | 11 +- 2 files changed, 55 insertions(+), 132 deletions(-) diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index 299edb7..4dab6eb 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -2,16 +2,6 @@ require "spec_helper" describe SessionsController do describe "GET #new" do - # Commented out since no unauthenticated users should reach site - # context "when signing in as a user not authenticated" do - # render_views - # - # it "redirects to KeyCloak" do - # get :new - # expect(response).to redirect_to '/sign_in' - # end - # - # end context "when signing in as a user already authenticated" do @@ -26,127 +16,55 @@ describe SessionsController do expect(response).to redirect_to '/' end + it "logs out a user" do + get :destroy + expect(session[:user_uid]).to be_nil + expect(response).to redirect_to '/' + end + end - # # dbl = double(Keycloak::Internal) - # expect(Keycloak::Internal).to receive(:get_user_info).with( - # email, - # true, - # Rails.application.secrets.keycloak_client_id, - # Rails.application.secrets.keycloak_client_secret - # ).and_return(OpenStruct.new({ id: "4b58555dbbc93c9016f7325ead84667d", - # firstName: first_name, - # lastName: last_name, - # email: email - # })) - # expect { - # do_request - # }.to have_enqueued_job(CreateApiInteractionJob) - # - # new_user = User.find_by(email: email) - # expect(new_user.first_name).to eq(first_name) - # expect(new_user.last_name).to eq(last_name) - # expect(new_user.email).to eq(email) - # - # expect(status).to eq 200 - # - # expect(response_json["status"]).to eq("ok") + context "when signing a new user already authenticated" do + + before do + payload = { + exp: Time.now.to_i + 18000000, + iat: Time.now.to_i, + auth_time: Time.now.to_i, + jti: "e4600f88-1b42-4e01-ac01-8646d3cc4df6", + iss: "https://login.dsop.io/auth/realms/baby-yoda", + aud: "il4_191f836b-ec50-4819-ba10-1afaa5b99600_mission-widow", + sub: "2cba6ea8-8451-4952-80d6-c7de379d5b7e", + typ: "ID", + given_name: "Jane", + family_name: "Doe", + email: "janedoe@test.com" + } + + token = JWT.encode(payload, nil, 'none') + request.headers["Authorization"] = "Bearer #{token}" + end + + it "redirects to root" do + get :new + expect(session[:user_uid]).to eq("2cba6ea8-8451-4952-80d6-c7de379d5b7e") + expect(response).to redirect_to '/' + end + + it "logs out a user" do + get :destroy + expect(session[:user_uid]).to be_nil + expect(response).to redirect_to '/' + end + + it "works in production" do + Rails.env = 'production' + get :new + expect(session[:user_uid]).to eq("2cba6ea8-8451-4952-80d6-c7de379d5b7e") + expect(response).to redirect_to '/' + end + + end - # context "when signed in as a user with access to a cohort" do - # let(:cohort_user) { create(:cohort_user, :student) } - # - # before do - # create(:cohort_user, :student, user: cohort_user.user) - # sign_in(cohort_user.user) - # end - # - # context "when signed in with a requested path" do - # it "redirects the user to the requested path" do - # get :index, session: { requested_path: submissions_dashboard_cohort_user_path(cohort_user.cohort, cohort_user.user) } - # - # expect(response).to redirect_to(submissions_dashboard_cohort_user_path(cohort_user.cohort, cohort_user.user)) - # expect(session[:requested_path]).to eq(nil) - # end - # end - # - # it "redirects to the last created cohort" do - # last_created_cohort = create(:cohort_user, :student, user: cohort_user.user).cohort - # get :index - # - # expect(response).to redirect_to(cohort_path(last_created_cohort)) - # end - # end - # - # context "when signed in as an admin without any cohort relationships" do - # let!(:user) { create(:user, :admin) } - # - # before { sign_in(user) } - # - # it "redirects to the cohorts list" do - # get :index - # - # expect(response).to redirect_to(cohorts_path) - # end - # end - # - # context "when the user has a last viewed cohort id" do - # let(:user) { create(:user) } - # let(:cohort) { create(:cohort) } - # - # before do - # user.update(last_viewed_cohort_id: cohort.id) - # sign_in(user) - # end - # - # context "when the user is a student for the given cohort" do - # before { create(:cohort_user, :student, user: user, cohort: cohort) } - # - # it "redirects to the last viewed cohort path" do - # get :index - # - # expect(response).to redirect_to(cohort_path(cohort)) - # end - # end - # - # context "when the user is an instructor for the given cohort" do - # before { create(:cohort_user, :instructor, user: user, cohort: cohort) } - # - # it "redirects to the last viewed cohort path" do - # get :index - # - # expect(response).to redirect_to(cohort_path(cohort)) - # end - # end - # - # context "when the user is an admin" do - # before { user.update(roles: [User::ROLES[:admin]]) } - # - # it "redirects to the last viewed cohort path" do - # get :index - # - # expect(response).to redirect_to(cohort_path(cohort)) - # end - # end - # - # context "when the user doesn't have access to the cohort" do - # context "but has access to a different cohort" do - # let(:other_cohort) { create(:cohort) } - # - # before { create(:cohort_user, :student, user: user, cohort: other_cohort) } - # - # it "redirects to the other cohort path" do - # get :index - # - # expect(response).to redirect_to(cohort_path(other_cohort)) - # end - # end - # - # context "and doesn't have access to any other cohort" do - # it "renders the no Cohorts page" do - # expect(get(:index)).to render_template(:index) - # end - # end - # end - # end end end diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 308833f..b1eb3eb 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -11,12 +11,17 @@ describe UsersController do let(:user) { create(:user) } describe "GET #new" do - context "creates a new users for a given cohort" do + context "when signed in as an admin" do + let(:admin) { create(:user, :admin) } - it "creates new users for a cohort from a list of users" do - allow(controller).to receive(:render) + before do + sign_in(admin) + end + it "creates new users for a cohort from a list of users" do get :new, params: { cohort_id: cohort.id } + + expect(response).to render_template(:new) end end end -- GitLab From 01dc709eba63ed67b0303cd2997a72cc78776cc8 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Fri, 9 Oct 2020 19:41:58 -1000 Subject: [PATCH 146/283] Initial pass fixing bundle update --- Gemfile.lock | 339 ++++++------ Gemfile.lock.new | 488 ++++++++++++++++++ Gemfile.lock.old | 476 +++++++++++++++++ Gemfile.outdated | 142 +++++ .../mobile/_submissions-dashboard-table.scss | 4 +- 5 files changed, 1278 insertions(+), 171 deletions(-) create mode 100644 Gemfile.lock.new create mode 100644 Gemfile.lock.old create mode 100644 Gemfile.outdated diff --git a/Gemfile.lock b/Gemfile.lock index 34ea2ba..3d86107 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -16,14 +16,14 @@ PATH GEM remote: https://rubygems.org/ specs: - actioncable (5.2.1) - actionpack (= 5.2.1) + actioncable (5.2.4.4) + actionpack (= 5.2.4.4) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailer (5.2.1) - actionpack (= 5.2.1) - actionview (= 5.2.1) - activejob (= 5.2.1) + actionmailer (5.2.4.4) + actionpack (= 5.2.4.4) + actionview (= 5.2.4.4) + activejob (= 5.2.4.4) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) actionpack (5.2.1) @@ -33,26 +33,26 @@ GEM rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.2.1) - activesupport (= 5.2.1) + actionview (5.2.4.4) + activesupport (= 5.2.4.4) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (5.2.1) - activesupport (= 5.2.1) + activejob (5.2.4.4) + activesupport (= 5.2.4.4) globalid (>= 0.3.6) - activemodel (5.2.1) - activesupport (= 5.2.1) - activerecord (5.2.1) - activemodel (= 5.2.1) - activesupport (= 5.2.1) + activemodel (5.2.4.4) + activesupport (= 5.2.4.4) + activerecord (5.2.4.4) + activemodel (= 5.2.4.4) + activesupport (= 5.2.4.4) arel (>= 9.0) - activestorage (5.2.1) - actionpack (= 5.2.1) - activerecord (= 5.2.1) + activestorage (5.2.4.4) + actionpack (= 5.2.4.4) + activerecord (= 5.2.4.4) marcel (~> 0.3.1) - activesupport (5.2.1) + activesupport (5.2.4.4) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) @@ -63,9 +63,10 @@ GEM kramdown railties arel (9.0.0) - ast (2.4.0) - autoprefixer-rails (7.2.5) + ast (2.4.1) + autoprefixer-rails (10.0.1.0) execjs + aws-eventstream (1.1.0) aws-sdk (2.6.50) aws-sdk-resources (= 2.6.50) aws-sdk-core (2.6.50) @@ -73,29 +74,30 @@ GEM jmespath (~> 1.0) aws-sdk-resources (2.6.50) aws-sdk-core (= 2.6.50) - aws-sigv4 (1.0.2) + aws-sigv4 (1.2.2) + aws-eventstream (~> 1, >= 1.0.2) babel-source (5.8.35) babel-transpiler (0.7.0) babel-source (>= 4.0, < 6) execjs (~> 2.0) - barnes (0.0.7) + barnes (0.0.8) multi_json (~> 1) statsd-ruby (~> 1.1) - better_errors (2.5.0) + better_errors (2.8.3) coderay (>= 1.0.0) erubi (>= 1.0.0) rack (>= 0.9.0) binding_of_caller (0.8.0) debug_inspector (>= 0.0.1) - bootsnap (1.3.1) + bootsnap (1.4.8) msgpack (~> 1.0) bootstrap (4.0.0) autoprefixer-rails (>= 6.0.3) popper_js (>= 1.12.9, < 2) sass (>= 3.5.2) - browser (2.5.2) - builder (3.2.3) - byebug (9.1.0) + browser (5.1.0) + builder (3.2.4) + byebug (11.1.3) capybara (2.16.1) addressable mini_mime (>= 0.1.3) @@ -103,51 +105,51 @@ GEM rack (>= 1.0.0) rack-test (>= 0.5.4) xpath (~> 2.0) - childprocess (0.8.0) - ffi (~> 1.0, >= 1.0.11) - coderay (1.1.2) - concurrent-ruby (1.1.5) - connection_pool (2.2.1) - crack (0.4.3) - safe_yaml (~> 1.0.0) - crass (1.0.4) - database_cleaner (1.6.2) + childprocess (3.0.0) + coderay (1.1.3) + concurrent-ruby (1.1.7) + connection_pool (2.2.3) + crack (0.4.4) + crass (1.0.6) + database_cleaner (1.8.5) debug_inspector (0.0.3) deterministic (0.6.0) - diff-lcs (1.3) + diff-lcs (1.4.4) docile (1.3.2) - dotenv (2.5.0) - dotenv-rails (2.5.0) - dotenv (= 2.5.0) - railties (>= 3.2, < 6.0) - dry-configurable (0.7.0) + dotenv (2.7.6) + dotenv-rails (2.7.6) + dotenv (= 2.7.6) + railties (>= 3.2) + dry-configurable (0.11.6) concurrent-ruby (~> 1.0) - dry-container (0.6.0) + dry-core (~> 0.4, >= 0.4.7) + dry-equalizer (~> 0.2) + dry-container (0.7.2) concurrent-ruby (~> 1.0) dry-configurable (~> 0.1, >= 0.1.3) - dry-core (0.4.7) + dry-core (0.4.9) concurrent-ruby (~> 1.0) - dry-equalizer (0.2.1) - dry-inflector (0.1.2) + dry-equalizer (0.3.0) + dry-inflector (0.2.0) dry-logic (0.4.2) dry-container (~> 0.2, >= 0.2.6) dry-core (~> 0.2) dry-equalizer (~> 0.2) - dry-types (0.13.2) + dry-types (0.13.4) concurrent-ruby (~> 1.0) dry-container (~> 0.3) dry-core (~> 0.4, >= 0.4.4) dry-equalizer (~> 0.2) dry-inflector (~> 0.1, >= 0.1.2) dry-logic (~> 0.4, >= 0.4.2) - dry-validation (0.12.2) + dry-validation (0.12.3) concurrent-ruby (~> 1.0) dry-configurable (~> 0.1, >= 0.1.3) dry-core (~> 0.2, >= 0.2.1) dry-equalizer (~> 0.2) - dry-logic (~> 0.4, >= 0.4.0) + dry-logic (~> 0.4.2) dry-types (~> 0.13.1) - erubi (1.7.1) + erubi (1.9.0) execjs (2.7.0) factory_bot (4.8.2) activesupport (>= 3.0.0) @@ -156,38 +158,37 @@ GEM railties (>= 3.0.0) faraday (0.9.2) multipart-post (>= 1.2, < 3) - ffi (1.9.18) + ffi (1.13.1) flamegraph (0.9.5) - font-awesome-rails (4.7.0.4) - railties (>= 3.2, < 6.0) - foreman (0.84.0) - thor (~> 0.19.1) + font-awesome-rails (4.7.0.5) + railties (>= 3.2, < 6.1) + foreman (0.87.2) github-markdown (0.6.9) github-markup (1.6.1) github_url (0.2.1) gitlab (4.14.1) httparty (~> 0.14, >= 0.14.0) terminal-table (~> 1.5, >= 1.5.1) - globalid (0.4.1) + globalid (0.4.2) activesupport (>= 4.2.0) - haml (5.0.4) + haml (5.2.0) temple (>= 0.8.0) tilt - hashdiff (0.4.0) - honeybadger (3.2.0) + hashdiff (1.0.1) + honeybadger (3.3.1) httparty (0.15.6) multi_xml (>= 0.5.2) - i18n (1.6.0) + i18n (1.8.5) concurrent-ruby (~> 1.0) - iniparse (1.4.4) + iniparse (1.5.0) jaro_winkler (1.5.3) - jmespath (1.3.1) - jquery-rails (4.3.1) + jmespath (1.4.0) + jquery-rails (4.4.0) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) - js-routes (1.4.2) - railties (>= 3.2) + js-routes (1.4.9) + railties (>= 4) sprockets-rails json_spec (1.1.5) multi_json (~> 1.0) @@ -198,88 +199,88 @@ GEM addressable (~> 2.3) letter_opener (1.7.0) launchy (~> 2.2) - loofah (2.2.2) + loofah (2.7.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) - mail (2.7.0) + mail (2.7.1) mini_mime (>= 0.1.1) - marcel (0.3.2) + marcel (0.3.3) mimemagic (~> 0.3.2) mathjax-rails (2.6.1) railties (>= 3.0) - memory_profiler (0.9.12) - method_source (0.9.0) - mimemagic (0.3.2) - mini_mime (1.0.0) + memory_profiler (0.9.14) + method_source (1.0.0) + mimemagic (0.3.5) + mini_mime (1.0.2) mini_portile2 (2.2.0) - minitest (5.11.3) - msgpack (1.2.4) - multi_json (1.13.1) + minitest (5.14.2) + msgpack (1.3.3) + multi_json (1.15.0) multi_xml (0.6.0) - multipart-post (2.0.0) - mustache (1.1.0) - nio4r (2.3.1) + multipart-post (2.1.1) + mustache (1.1.1) + nio4r (2.5.4) nokogiri (1.8.0) mini_portile2 (~> 2.2.0) octokit (4.3.0) sawyer (~> 0.7.0, >= 0.5.3) - overcommit (0.41.0) - childprocess (~> 0.6, >= 0.6.3) + overcommit (0.57.0) + childprocess (>= 0.6.3, < 5) iniparse (~> 1.4) - pagy (3.7.1) - parallel (1.17.0) - parser (2.6.3.0) - ast (~> 2.4.0) + pagy (3.8.3) + parallel (1.19.2) + parser (2.7.2.0) + ast (~> 2.4.1) pg (0.21.0) - popper_js (1.12.9) + popper_js (1.16.0) psych (2.2.4) - puma (3.12.1) - pundit (1.1.0) + puma (3.12.6) + pundit (2.1.0) activesupport (>= 3.0.0) - rack (2.0.3) - rack-attack (6.2.1) + rack (2.2.3) + rack-attack (6.3.1) rack (>= 1.0, < 3) - rack-mini-profiler (1.0.0) + rack-mini-profiler (2.1.0) rack (>= 1.2.0) - rack-protection (2.0.0) + rack-protection (2.1.0) rack rack-proxy (0.6.5) rack - rack-test (0.8.2) + rack-test (1.1.0) rack (>= 1.0, < 3) - rails (5.2.1) - actioncable (= 5.2.1) - actionmailer (= 5.2.1) - actionpack (= 5.2.1) - actionview (= 5.2.1) - activejob (= 5.2.1) - activemodel (= 5.2.1) - activerecord (= 5.2.1) - activestorage (= 5.2.1) - activesupport (= 5.2.1) + rails (5.2.4.4) + actioncable (= 5.2.4.4) + actionmailer (= 5.2.4.4) + actionpack (= 5.2.4.4) + actionview (= 5.2.4.4) + activejob (= 5.2.4.4) + activemodel (= 5.2.4.4) + activerecord (= 5.2.4.4) + activestorage (= 5.2.4.4) + activesupport (= 5.2.4.4) bundler (>= 1.3.0) - railties (= 5.2.1) + railties (= 5.2.4.4) sprockets-rails (>= 2.0.0) - rails-controller-testing (1.0.2) - actionpack (~> 5.x, >= 5.0.1) - actionview (~> 5.x, >= 5.0.1) - activesupport (~> 5.x) + rails-controller-testing (1.0.5) + actionpack (>= 5.0.1.rc1) + actionview (>= 5.0.1.rc1) + activesupport (>= 5.0.1.rc1) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) - rails-html-sanitizer (1.0.4) - loofah (~> 2.2, >= 2.2.2) - railties (5.2.1) - actionpack (= 5.2.1) - activesupport (= 5.2.1) + rails-html-sanitizer (1.3.0) + loofah (~> 2.3) + railties (5.2.4.4) + actionpack (= 5.2.4.4) + activesupport (= 5.2.4.4) method_source rake (>= 0.8.7) thor (>= 0.19.0, < 2.0) rainbow (3.0.0) - rake (12.3.1) - rb-fsevent (0.10.2) - rb-inotify (0.9.10) - ffi (>= 0.5.0, < 2) + rake (13.0.1) + rb-fsevent (0.10.4) + rb-inotify (0.10.1) + ffi (~> 1.0) react-rails (2.4.5) babel-transpiler (>= 0.7.0) connection_pool @@ -288,32 +289,32 @@ GEM tilt redcarpet (3.3.4) redis (3.3.5) - rspec (3.7.0) - rspec-core (~> 3.7.0) - rspec-expectations (~> 3.7.0) - rspec-mocks (~> 3.7.0) - rspec-core (3.7.0) - rspec-support (~> 3.7.0) - rspec-expectations (3.7.0) + rspec (3.9.0) + rspec-core (~> 3.9.0) + rspec-expectations (~> 3.9.0) + rspec-mocks (~> 3.9.0) + rspec-core (3.9.3) + rspec-support (~> 3.9.3) + rspec-expectations (3.9.2) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.7.0) - rspec-mocks (3.7.0) + rspec-support (~> 3.9.0) + rspec-mocks (3.9.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.7.0) - rspec-rails (3.7.2) - actionpack (>= 3.0) - activesupport (>= 3.0) - railties (>= 3.0) - rspec-core (~> 3.7.0) - rspec-expectations (~> 3.7.0) - rspec-mocks (~> 3.7.0) - rspec-support (~> 3.7.0) - rspec-support (3.7.0) + rspec-support (~> 3.9.0) + rspec-rails (4.0.1) + actionpack (>= 4.2) + activesupport (>= 4.2) + railties (>= 4.2) + rspec-core (~> 3.9) + rspec-expectations (~> 3.9) + rspec-mocks (~> 3.9) + rspec-support (~> 3.9) + rspec-support (3.9.3) rspec_api_documentation (6.1.0) activesupport (>= 3.0.0) mustache (~> 1.0, >= 0.99.4) rspec (~> 3.0) - rspec_junit_formatter (0.3.0) + rspec_junit_formatter (0.4.1) rspec-core (>= 2, < 4, != 2.12.0) rubocop (0.72.0) jaro_winkler (~> 1.5.1) @@ -323,15 +324,14 @@ GEM ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 1.7) ruby-progressbar (1.10.1) - rubyzip (1.2.1) - safe_yaml (1.0.5) - sass (3.5.3) + rubyzip (2.3.0) + sass (3.7.4) sass-listen (~> 4.0.0) sass-listen (4.0.0) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) - sass-rails (5.0.7) - railties (>= 4.0.0, < 6) + sass-rails (5.1.0) + railties (>= 5.2.0) sass (~> 3.1) sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) @@ -339,50 +339,51 @@ GEM sawyer (0.7.0) addressable (>= 2.3.5, < 2.5) faraday (~> 0.8, < 0.10) - scout_apm (2.4.19) - selenium-webdriver (3.8.0) - childprocess (~> 0.5) - rubyzip (~> 1.0) + scout_apm (2.6.9) + parser + selenium-webdriver (3.142.7) + childprocess (>= 0.5, < 4.0) + rubyzip (>= 1.2.2) semantic_range (2.3.0) - shoulda-matchers (3.1.2) - activesupport (>= 4.0.0) - sidekiq (5.0.5) - concurrent-ruby (~> 1.0) - connection_pool (~> 2.2, >= 2.2.0) + shoulda-matchers (4.4.1) + activesupport (>= 4.2.0) + sidekiq (5.2.9) + connection_pool (~> 2.2, >= 2.2.2) + rack (~> 2.0) rack-protection (>= 1.5.0) - redis (>= 3.3.4, < 5) + redis (>= 3.3.5, < 4.2) simplecov (0.19.0) docile (~> 1.1) simplecov-html (~> 0.11) simplecov-html (0.12.3) solid_use_case (2.2.0) deterministic (~> 0.6.0) - sprockets (3.7.1) + sprockets (3.7.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (3.2.1) + sprockets-rails (3.2.2) actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) - stackprof (0.2.12) + stackprof (0.2.15) statsd-ruby (1.4.0) - temple (0.8.0) + temple (0.8.2) terminal-table (1.8.0) unicode-display_width (~> 1.1, >= 1.1.1) - thor (0.19.4) + thor (1.0.1) thread_safe (0.3.6) - tilt (2.0.8) + tilt (2.0.10) timecop (0.9.1) - ts_routes (1.0.1) - railties (>= 5.0) - tzinfo (1.2.5) + ts_routes (1.0.3) + railties (>= 4.0) + tzinfo (1.2.7) thread_safe (~> 0.1) - uglifier (4.0.2) + uglifier (4.2.0) execjs (>= 0.3.0, < 3) underscore-rails (1.8.3) - unicode-display_width (1.6.0) - vcr (4.0.0) - webmock (3.6.0) + unicode-display_width (1.7.0) + vcr (6.0.0) + webmock (3.9.1) addressable (>= 2.3.6) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) @@ -391,11 +392,11 @@ GEM rack-proxy (>= 0.6.1) railties (>= 5.2) semantic_range (>= 2.3.0) - websocket-driver (0.7.0) + websocket-driver (0.7.3) websocket-extensions (>= 0.1.0) - websocket-extensions (0.1.3) - xpath (2.1.0) - nokogiri (~> 1.3) + websocket-extensions (0.1.5) + xpath (3.2.0) + nokogiri (~> 1.8) zip-zip (0.3) rubyzip (>= 1.0.0) diff --git a/Gemfile.lock.new b/Gemfile.lock.new new file mode 100644 index 0000000..0a1bc01 --- /dev/null +++ b/Gemfile.lock.new @@ -0,0 +1,488 @@ +PATH + remote: gems/block-parser + specs: + block_parser (0.1.0) + activemodel (> 4.2) + github-markdown (= 0.6.9) + github-markup (= 1.6.1) + github_url (= 0.2.1) + gitlab (= 4.14.1) + nokogiri (= 1.8.0) + octokit (= 4.3.0) + psych (= 2.2.4) + redcarpet (= 3.3.4) + rspec_junit_formatter (> 0.2.3) + +GEM + remote: https://rubygems.org/ + specs: + actioncable (5.2.4.4) + actionpack (= 5.2.4.4) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailer (5.2.4.4) + actionpack (= 5.2.4.4) + actionview (= 5.2.4.4) + activejob (= 5.2.4.4) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 2.0) + actionpack (5.2.4.4) + actionview (= 5.2.4.4) + activesupport (= 5.2.4.4) + rack (~> 2.0, >= 2.0.8) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (5.2.4.4) + activesupport (= 5.2.4.4) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + activejob (5.2.4.4) + activesupport (= 5.2.4.4) + globalid (>= 0.3.6) + activemodel (5.2.4.4) + activesupport (= 5.2.4.4) + activerecord (5.2.4.4) + activemodel (= 5.2.4.4) + activesupport (= 5.2.4.4) + arel (>= 9.0) + activestorage (5.2.4.4) + actionpack (= 5.2.4.4) + activerecord (= 5.2.4.4) + marcel (~> 0.3.1) + activesupport (5.2.4.4) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + addressable (2.4.0) + analytics-ruby (2.0.13) + apitome (0.3.0) + kramdown + railties + arel (9.0.0) + ast (2.4.1) + autoprefixer-rails (10.0.1.0) + execjs + aws-eventstream (1.1.0) + aws-sdk (2.6.50) + aws-sdk-resources (= 2.6.50) + aws-sdk-core (2.6.50) + aws-sigv4 (~> 1.0) + jmespath (~> 1.0) + aws-sdk-resources (2.6.50) + aws-sdk-core (= 2.6.50) + aws-sigv4 (1.2.2) + aws-eventstream (~> 1, >= 1.0.2) + babel-source (5.8.35) + babel-transpiler (0.7.0) + babel-source (>= 4.0, < 6) + execjs (~> 2.0) + barnes (0.0.8) + multi_json (~> 1) + statsd-ruby (~> 1.1) + better_errors (2.8.3) + coderay (>= 1.0.0) + erubi (>= 1.0.0) + rack (>= 0.9.0) + binding_of_caller (0.8.0) + debug_inspector (>= 0.0.1) + bootsnap (1.4.8) + msgpack (~> 1.0) + bootstrap (4.0.0) + autoprefixer-rails (>= 6.0.3) + popper_js (>= 1.12.9, < 2) + sass (>= 3.5.2) + browser (5.1.0) + builder (3.2.4) + byebug (11.1.3) + capybara (3.33.0) + addressable + mini_mime (>= 0.1.3) + nokogiri (~> 1.8) + rack (>= 1.6.0) + rack-test (>= 0.6.3) + regexp_parser (~> 1.5) + xpath (~> 3.2) + childprocess (3.0.0) + coderay (1.1.3) + concurrent-ruby (1.1.7) + connection_pool (2.2.3) + crack (0.4.4) + crass (1.0.6) + database_cleaner (1.8.5) + debug_inspector (0.0.3) + deterministic (0.6.0) + diff-lcs (1.4.4) + docile (1.3.2) + dotenv (2.7.6) + dotenv-rails (2.7.6) + dotenv (= 2.7.6) + railties (>= 3.2) + dry-configurable (0.11.6) + concurrent-ruby (~> 1.0) + dry-core (~> 0.4, >= 0.4.7) + dry-equalizer (~> 0.2) + dry-container (0.7.2) + concurrent-ruby (~> 1.0) + dry-configurable (~> 0.1, >= 0.1.3) + dry-core (0.4.9) + concurrent-ruby (~> 1.0) + dry-equalizer (0.3.0) + dry-inflector (0.2.0) + dry-logic (0.4.2) + dry-container (~> 0.2, >= 0.2.6) + dry-core (~> 0.2) + dry-equalizer (~> 0.2) + dry-types (0.13.4) + concurrent-ruby (~> 1.0) + dry-container (~> 0.3) + dry-core (~> 0.4, >= 0.4.4) + dry-equalizer (~> 0.2) + dry-inflector (~> 0.1, >= 0.1.2) + dry-logic (~> 0.4, >= 0.4.2) + dry-validation (0.12.3) + concurrent-ruby (~> 1.0) + dry-configurable (~> 0.1, >= 0.1.3) + dry-core (~> 0.2, >= 0.2.1) + dry-equalizer (~> 0.2) + dry-logic (~> 0.4.2) + dry-types (~> 0.13.1) + erubi (1.9.0) + execjs (2.7.0) + factory_bot (6.1.0) + activesupport (>= 5.0.0) + factory_bot_rails (6.1.0) + factory_bot (~> 6.1.0) + railties (>= 5.0.0) + faraday (0.9.2) + multipart-post (>= 1.2, < 3) + ffi (1.13.1) + flamegraph (0.9.5) + font-awesome-rails (4.7.0.5) + railties (>= 3.2, < 6.1) + foreman (0.87.2) + github-markdown (0.6.9) + github-markup (1.6.1) + github_url (0.2.1) + gitlab (4.14.1) + httparty (~> 0.14, >= 0.14.0) + terminal-table (~> 1.5, >= 1.5.1) + globalid (0.4.2) + activesupport (>= 4.2.0) + haml (5.2.0) + temple (>= 0.8.0) + tilt + hashdiff (1.0.1) + honeybadger (3.3.1) + httparty (0.18.1) + mime-types (~> 3.0) + multi_xml (>= 0.5.2) + i18n (1.8.5) + concurrent-ruby (~> 1.0) + iniparse (1.5.0) + jmespath (1.4.0) + jquery-rails (4.4.0) + rails-dom-testing (>= 1, < 3) + railties (>= 4.2.0) + thor (>= 0.14, < 2.0) + js-routes (1.4.9) + railties (>= 4) + sprockets-rails + json_spec (1.1.5) + multi_json (~> 1.0) + rspec (>= 2.0, < 4.0) + jwt (2.2.2) + kramdown (2.3.0) + rexml + launchy (2.4.3) + addressable (~> 2.3) + letter_opener (1.7.0) + launchy (~> 2.2) + loofah (2.7.0) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + mail (2.7.1) + mini_mime (>= 0.1.1) + marcel (0.3.3) + mimemagic (~> 0.3.2) + mathjax-rails (2.6.1) + railties (>= 3.0) + memory_profiler (0.9.14) + method_source (1.0.0) + mime-types (3.3.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2020.0512) + mimemagic (0.3.5) + mini_mime (1.0.2) + mini_portile2 (2.2.0) + minitest (5.14.2) + msgpack (1.3.3) + multi_json (1.15.0) + multi_xml (0.6.0) + multipart-post (2.1.1) + mustache (1.1.1) + nio4r (2.5.4) + nokogiri (1.8.0) + mini_portile2 (~> 2.2.0) + octokit (4.3.0) + sawyer (~> 0.7.0, >= 0.5.3) + overcommit (0.57.0) + childprocess (>= 0.6.3, < 5) + iniparse (~> 1.4) + pagy (3.8.3) + parallel (1.19.2) + parser (2.7.2.0) + ast (~> 2.4.1) + pg (0.21.0) + popper_js (1.16.0) + psych (2.2.4) + puma (3.12.6) + pundit (2.1.0) + activesupport (>= 3.0.0) + rack (2.2.3) + rack-attack (6.3.1) + rack (>= 1.0, < 3) + rack-mini-profiler (2.1.0) + rack (>= 1.2.0) + rack-protection (2.1.0) + rack + rack-proxy (0.6.5) + rack + rack-test (1.1.0) + rack (>= 1.0, < 3) + rails (5.2.4.4) + actioncable (= 5.2.4.4) + actionmailer (= 5.2.4.4) + actionpack (= 5.2.4.4) + actionview (= 5.2.4.4) + activejob (= 5.2.4.4) + activemodel (= 5.2.4.4) + activerecord (= 5.2.4.4) + activestorage (= 5.2.4.4) + activesupport (= 5.2.4.4) + bundler (>= 1.3.0) + railties (= 5.2.4.4) + sprockets-rails (>= 2.0.0) + rails-controller-testing (1.0.5) + actionpack (>= 5.0.1.rc1) + actionview (>= 5.0.1.rc1) + activesupport (>= 5.0.1.rc1) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-html-sanitizer (1.3.0) + loofah (~> 2.3) + railties (5.2.4.4) + actionpack (= 5.2.4.4) + activesupport (= 5.2.4.4) + method_source + rake (>= 0.8.7) + thor (>= 0.19.0, < 2.0) + rainbow (3.0.0) + rake (13.0.1) + rb-fsevent (0.10.4) + rb-inotify (0.10.1) + ffi (~> 1.0) + react-rails (2.4.5) + babel-transpiler (>= 0.7.0) + connection_pool + execjs + railties (>= 3.2) + tilt + redcarpet (3.3.4) + redis (3.3.5) + regexp_parser (1.8.1) + rexml (3.2.4) + rspec (3.9.0) + rspec-core (~> 3.9.0) + rspec-expectations (~> 3.9.0) + rspec-mocks (~> 3.9.0) + rspec-core (3.9.3) + rspec-support (~> 3.9.3) + rspec-expectations (3.9.2) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.9.0) + rspec-mocks (3.9.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.9.0) + rspec-rails (4.0.1) + actionpack (>= 4.2) + activesupport (>= 4.2) + railties (>= 4.2) + rspec-core (~> 3.9) + rspec-expectations (~> 3.9) + rspec-mocks (~> 3.9) + rspec-support (~> 3.9) + rspec-support (3.9.3) + rspec_api_documentation (6.1.0) + activesupport (>= 3.0.0) + mustache (~> 1.0, >= 0.99.4) + rspec (~> 3.0) + rspec_junit_formatter (0.4.1) + rspec-core (>= 2, < 4, != 2.12.0) + rubocop (0.93.0) + parallel (~> 1.10) + parser (>= 2.7.1.5) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8) + rexml + rubocop-ast (>= 0.6.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 1.4.0, < 2.0) + rubocop-ast (0.7.1) + parser (>= 2.7.1.5) + ruby-progressbar (1.10.1) + rubyzip (2.3.0) + sass (3.7.4) + sass-listen (~> 4.0.0) + sass-listen (4.0.0) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + sass-rails (5.1.0) + railties (>= 5.2.0) + sass (~> 3.1) + sprockets (>= 2.8, < 4.0) + sprockets-rails (>= 2.0, < 4.0) + tilt (>= 1.1, < 3) + sawyer (0.7.0) + addressable (>= 2.3.5, < 2.5) + faraday (~> 0.8, < 0.10) + scout_apm (2.6.9) + parser + selenium-webdriver (3.142.7) + childprocess (>= 0.5, < 4.0) + rubyzip (>= 1.2.2) + semantic_range (2.3.0) + shoulda-matchers (4.4.1) + activesupport (>= 4.2.0) + sidekiq (5.2.9) + connection_pool (~> 2.2, >= 2.2.2) + rack (~> 2.0) + rack-protection (>= 1.5.0) + redis (>= 3.3.5, < 4.2) + simplecov (0.19.0) + docile (~> 1.1) + simplecov-html (~> 0.11) + simplecov-html (0.12.3) + solid_use_case (2.2.0) + deterministic (~> 0.6.0) + sprockets (3.7.2) + concurrent-ruby (~> 1.0) + rack (> 1, < 3) + sprockets-rails (3.2.2) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) + stackprof (0.2.15) + statsd-ruby (1.4.0) + temple (0.8.2) + terminal-table (1.8.0) + unicode-display_width (~> 1.1, >= 1.1.1) + thor (1.0.1) + thread_safe (0.3.6) + tilt (2.0.10) + timecop (0.9.1) + ts_routes (1.0.3) + railties (>= 4.0) + tzinfo (1.2.7) + thread_safe (~> 0.1) + uglifier (4.2.0) + execjs (>= 0.3.0, < 3) + underscore-rails (1.8.3) + unicode-display_width (1.7.0) + vcr (6.0.0) + webmock (3.9.1) + addressable (>= 2.3.6) + crack (>= 0.3.2) + hashdiff (>= 0.4.0, < 2.0.0) + webpacker (5.2.1) + activesupport (>= 5.2) + rack-proxy (>= 0.6.1) + railties (>= 5.2) + semantic_range (>= 2.3.0) + websocket-driver (0.7.3) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.5) + xpath (3.2.0) + nokogiri (~> 1.8) + zip-zip (0.3) + rubyzip (>= 1.0.0) + +PLATFORMS + ruby + +DEPENDENCIES + analytics-ruby (~> 2.0.0) + apitome + aws-sdk (~> 2.6.5) + barnes + better_errors + binding_of_caller + block_parser! + bootsnap (>= 1.1.0) + bootstrap (= 4.0.0) + browser + byebug + capybara + database_cleaner + dotenv-rails + dry-validation (~> 0.12.2) + factory_bot_rails + flamegraph + font-awesome-rails + foreman + github_url (= 0.2.1) + gitlab + haml + honeybadger (~> 3.1) + httparty + jquery-rails + js-routes + json_spec + jwt + letter_opener + mathjax-rails + memory_profiler + octokit + overcommit + pagy + pg (~> 0.18) + puma (~> 3.12.0) + pundit + rack-attack + rack-mini-profiler + rails (~> 5.2.1) + rails-controller-testing + react-rails (= 2.4.5) + redis (~> 3.0) + rspec-rails + rspec_api_documentation + rspec_junit_formatter + rubocop + rubyzip (>= 1.0.0) + sass-rails (~> 5.0) + scout_apm + selenium-webdriver + shoulda-matchers + sidekiq + simplecov + solid_use_case (~> 2.2.0) + stackprof + timecop + ts_routes + tzinfo-data + uglifier (>= 1.3.0) + underscore-rails (= 1.8.3) + vcr + webmock + webpacker (~> 5.2.1) + zip-zip + +RUBY VERSION + ruby 2.6.6p146 + +BUNDLED WITH + 2.1.4 diff --git a/Gemfile.lock.old b/Gemfile.lock.old new file mode 100644 index 0000000..34ea2ba --- /dev/null +++ b/Gemfile.lock.old @@ -0,0 +1,476 @@ +PATH + remote: gems/block-parser + specs: + block_parser (0.1.0) + activemodel (> 4.2) + github-markdown (= 0.6.9) + github-markup (= 1.6.1) + github_url (= 0.2.1) + gitlab (= 4.14.1) + nokogiri (= 1.8.0) + octokit (= 4.3.0) + psych (= 2.2.4) + redcarpet (= 3.3.4) + rspec_junit_formatter (> 0.2.3) + +GEM + remote: https://rubygems.org/ + specs: + actioncable (5.2.1) + actionpack (= 5.2.1) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailer (5.2.1) + actionpack (= 5.2.1) + actionview (= 5.2.1) + activejob (= 5.2.1) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 2.0) + actionpack (5.2.1) + actionview (= 5.2.1) + activesupport (= 5.2.1) + rack (~> 2.0) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (5.2.1) + activesupport (= 5.2.1) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + activejob (5.2.1) + activesupport (= 5.2.1) + globalid (>= 0.3.6) + activemodel (5.2.1) + activesupport (= 5.2.1) + activerecord (5.2.1) + activemodel (= 5.2.1) + activesupport (= 5.2.1) + arel (>= 9.0) + activestorage (5.2.1) + actionpack (= 5.2.1) + activerecord (= 5.2.1) + marcel (~> 0.3.1) + activesupport (5.2.1) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + addressable (2.4.0) + analytics-ruby (2.0.13) + apitome (0.3.0) + kramdown + railties + arel (9.0.0) + ast (2.4.0) + autoprefixer-rails (7.2.5) + execjs + aws-sdk (2.6.50) + aws-sdk-resources (= 2.6.50) + aws-sdk-core (2.6.50) + aws-sigv4 (~> 1.0) + jmespath (~> 1.0) + aws-sdk-resources (2.6.50) + aws-sdk-core (= 2.6.50) + aws-sigv4 (1.0.2) + babel-source (5.8.35) + babel-transpiler (0.7.0) + babel-source (>= 4.0, < 6) + execjs (~> 2.0) + barnes (0.0.7) + multi_json (~> 1) + statsd-ruby (~> 1.1) + better_errors (2.5.0) + coderay (>= 1.0.0) + erubi (>= 1.0.0) + rack (>= 0.9.0) + binding_of_caller (0.8.0) + debug_inspector (>= 0.0.1) + bootsnap (1.3.1) + msgpack (~> 1.0) + bootstrap (4.0.0) + autoprefixer-rails (>= 6.0.3) + popper_js (>= 1.12.9, < 2) + sass (>= 3.5.2) + browser (2.5.2) + builder (3.2.3) + byebug (9.1.0) + capybara (2.16.1) + addressable + mini_mime (>= 0.1.3) + nokogiri (>= 1.3.3) + rack (>= 1.0.0) + rack-test (>= 0.5.4) + xpath (~> 2.0) + childprocess (0.8.0) + ffi (~> 1.0, >= 1.0.11) + coderay (1.1.2) + concurrent-ruby (1.1.5) + connection_pool (2.2.1) + crack (0.4.3) + safe_yaml (~> 1.0.0) + crass (1.0.4) + database_cleaner (1.6.2) + debug_inspector (0.0.3) + deterministic (0.6.0) + diff-lcs (1.3) + docile (1.3.2) + dotenv (2.5.0) + dotenv-rails (2.5.0) + dotenv (= 2.5.0) + railties (>= 3.2, < 6.0) + dry-configurable (0.7.0) + concurrent-ruby (~> 1.0) + dry-container (0.6.0) + concurrent-ruby (~> 1.0) + dry-configurable (~> 0.1, >= 0.1.3) + dry-core (0.4.7) + concurrent-ruby (~> 1.0) + dry-equalizer (0.2.1) + dry-inflector (0.1.2) + dry-logic (0.4.2) + dry-container (~> 0.2, >= 0.2.6) + dry-core (~> 0.2) + dry-equalizer (~> 0.2) + dry-types (0.13.2) + concurrent-ruby (~> 1.0) + dry-container (~> 0.3) + dry-core (~> 0.4, >= 0.4.4) + dry-equalizer (~> 0.2) + dry-inflector (~> 0.1, >= 0.1.2) + dry-logic (~> 0.4, >= 0.4.2) + dry-validation (0.12.2) + concurrent-ruby (~> 1.0) + dry-configurable (~> 0.1, >= 0.1.3) + dry-core (~> 0.2, >= 0.2.1) + dry-equalizer (~> 0.2) + dry-logic (~> 0.4, >= 0.4.0) + dry-types (~> 0.13.1) + erubi (1.7.1) + execjs (2.7.0) + factory_bot (4.8.2) + activesupport (>= 3.0.0) + factory_bot_rails (4.8.2) + factory_bot (~> 4.8.2) + railties (>= 3.0.0) + faraday (0.9.2) + multipart-post (>= 1.2, < 3) + ffi (1.9.18) + flamegraph (0.9.5) + font-awesome-rails (4.7.0.4) + railties (>= 3.2, < 6.0) + foreman (0.84.0) + thor (~> 0.19.1) + github-markdown (0.6.9) + github-markup (1.6.1) + github_url (0.2.1) + gitlab (4.14.1) + httparty (~> 0.14, >= 0.14.0) + terminal-table (~> 1.5, >= 1.5.1) + globalid (0.4.1) + activesupport (>= 4.2.0) + haml (5.0.4) + temple (>= 0.8.0) + tilt + hashdiff (0.4.0) + honeybadger (3.2.0) + httparty (0.15.6) + multi_xml (>= 0.5.2) + i18n (1.6.0) + concurrent-ruby (~> 1.0) + iniparse (1.4.4) + jaro_winkler (1.5.3) + jmespath (1.3.1) + jquery-rails (4.3.1) + rails-dom-testing (>= 1, < 3) + railties (>= 4.2.0) + thor (>= 0.14, < 2.0) + js-routes (1.4.2) + railties (>= 3.2) + sprockets-rails + json_spec (1.1.5) + multi_json (~> 1.0) + rspec (>= 2.0, < 4.0) + jwt (2.2.2) + kramdown (2.1.0) + launchy (2.4.3) + addressable (~> 2.3) + letter_opener (1.7.0) + launchy (~> 2.2) + loofah (2.2.2) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + mail (2.7.0) + mini_mime (>= 0.1.1) + marcel (0.3.2) + mimemagic (~> 0.3.2) + mathjax-rails (2.6.1) + railties (>= 3.0) + memory_profiler (0.9.12) + method_source (0.9.0) + mimemagic (0.3.2) + mini_mime (1.0.0) + mini_portile2 (2.2.0) + minitest (5.11.3) + msgpack (1.2.4) + multi_json (1.13.1) + multi_xml (0.6.0) + multipart-post (2.0.0) + mustache (1.1.0) + nio4r (2.3.1) + nokogiri (1.8.0) + mini_portile2 (~> 2.2.0) + octokit (4.3.0) + sawyer (~> 0.7.0, >= 0.5.3) + overcommit (0.41.0) + childprocess (~> 0.6, >= 0.6.3) + iniparse (~> 1.4) + pagy (3.7.1) + parallel (1.17.0) + parser (2.6.3.0) + ast (~> 2.4.0) + pg (0.21.0) + popper_js (1.12.9) + psych (2.2.4) + puma (3.12.1) + pundit (1.1.0) + activesupport (>= 3.0.0) + rack (2.0.3) + rack-attack (6.2.1) + rack (>= 1.0, < 3) + rack-mini-profiler (1.0.0) + rack (>= 1.2.0) + rack-protection (2.0.0) + rack + rack-proxy (0.6.5) + rack + rack-test (0.8.2) + rack (>= 1.0, < 3) + rails (5.2.1) + actioncable (= 5.2.1) + actionmailer (= 5.2.1) + actionpack (= 5.2.1) + actionview (= 5.2.1) + activejob (= 5.2.1) + activemodel (= 5.2.1) + activerecord (= 5.2.1) + activestorage (= 5.2.1) + activesupport (= 5.2.1) + bundler (>= 1.3.0) + railties (= 5.2.1) + sprockets-rails (>= 2.0.0) + rails-controller-testing (1.0.2) + actionpack (~> 5.x, >= 5.0.1) + actionview (~> 5.x, >= 5.0.1) + activesupport (~> 5.x) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-html-sanitizer (1.0.4) + loofah (~> 2.2, >= 2.2.2) + railties (5.2.1) + actionpack (= 5.2.1) + activesupport (= 5.2.1) + method_source + rake (>= 0.8.7) + thor (>= 0.19.0, < 2.0) + rainbow (3.0.0) + rake (12.3.1) + rb-fsevent (0.10.2) + rb-inotify (0.9.10) + ffi (>= 0.5.0, < 2) + react-rails (2.4.5) + babel-transpiler (>= 0.7.0) + connection_pool + execjs + railties (>= 3.2) + tilt + redcarpet (3.3.4) + redis (3.3.5) + rspec (3.7.0) + rspec-core (~> 3.7.0) + rspec-expectations (~> 3.7.0) + rspec-mocks (~> 3.7.0) + rspec-core (3.7.0) + rspec-support (~> 3.7.0) + rspec-expectations (3.7.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.7.0) + rspec-mocks (3.7.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.7.0) + rspec-rails (3.7.2) + actionpack (>= 3.0) + activesupport (>= 3.0) + railties (>= 3.0) + rspec-core (~> 3.7.0) + rspec-expectations (~> 3.7.0) + rspec-mocks (~> 3.7.0) + rspec-support (~> 3.7.0) + rspec-support (3.7.0) + rspec_api_documentation (6.1.0) + activesupport (>= 3.0.0) + mustache (~> 1.0, >= 0.99.4) + rspec (~> 3.0) + rspec_junit_formatter (0.3.0) + rspec-core (>= 2, < 4, != 2.12.0) + rubocop (0.72.0) + jaro_winkler (~> 1.5.1) + parallel (~> 1.10) + parser (>= 2.6) + rainbow (>= 2.2.2, < 4.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 1.4.0, < 1.7) + ruby-progressbar (1.10.1) + rubyzip (1.2.1) + safe_yaml (1.0.5) + sass (3.5.3) + sass-listen (~> 4.0.0) + sass-listen (4.0.0) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + sass-rails (5.0.7) + railties (>= 4.0.0, < 6) + sass (~> 3.1) + sprockets (>= 2.8, < 4.0) + sprockets-rails (>= 2.0, < 4.0) + tilt (>= 1.1, < 3) + sawyer (0.7.0) + addressable (>= 2.3.5, < 2.5) + faraday (~> 0.8, < 0.10) + scout_apm (2.4.19) + selenium-webdriver (3.8.0) + childprocess (~> 0.5) + rubyzip (~> 1.0) + semantic_range (2.3.0) + shoulda-matchers (3.1.2) + activesupport (>= 4.0.0) + sidekiq (5.0.5) + concurrent-ruby (~> 1.0) + connection_pool (~> 2.2, >= 2.2.0) + rack-protection (>= 1.5.0) + redis (>= 3.3.4, < 5) + simplecov (0.19.0) + docile (~> 1.1) + simplecov-html (~> 0.11) + simplecov-html (0.12.3) + solid_use_case (2.2.0) + deterministic (~> 0.6.0) + sprockets (3.7.1) + concurrent-ruby (~> 1.0) + rack (> 1, < 3) + sprockets-rails (3.2.1) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) + stackprof (0.2.12) + statsd-ruby (1.4.0) + temple (0.8.0) + terminal-table (1.8.0) + unicode-display_width (~> 1.1, >= 1.1.1) + thor (0.19.4) + thread_safe (0.3.6) + tilt (2.0.8) + timecop (0.9.1) + ts_routes (1.0.1) + railties (>= 5.0) + tzinfo (1.2.5) + thread_safe (~> 0.1) + uglifier (4.0.2) + execjs (>= 0.3.0, < 3) + underscore-rails (1.8.3) + unicode-display_width (1.6.0) + vcr (4.0.0) + webmock (3.6.0) + addressable (>= 2.3.6) + crack (>= 0.3.2) + hashdiff (>= 0.4.0, < 2.0.0) + webpacker (5.2.1) + activesupport (>= 5.2) + rack-proxy (>= 0.6.1) + railties (>= 5.2) + semantic_range (>= 2.3.0) + websocket-driver (0.7.0) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.3) + xpath (2.1.0) + nokogiri (~> 1.3) + zip-zip (0.3) + rubyzip (>= 1.0.0) + +PLATFORMS + ruby + +DEPENDENCIES + analytics-ruby (~> 2.0.0) + apitome + aws-sdk (~> 2.6.5) + barnes + better_errors + binding_of_caller + block_parser! + bootsnap (>= 1.1.0) + bootstrap (= 4.0.0) + browser + byebug + capybara + database_cleaner + dotenv-rails + dry-validation (~> 0.12.2) + factory_bot_rails + flamegraph + font-awesome-rails + foreman + github_url (= 0.2.1) + gitlab + haml + honeybadger (~> 3.1) + httparty + jquery-rails + js-routes + json_spec + jwt + letter_opener + mathjax-rails + memory_profiler + octokit + overcommit + pagy + pg (~> 0.18) + puma (~> 3.12.0) + pundit + rack-attack + rack-mini-profiler + rails (~> 5.2.1) + rails-controller-testing + react-rails (= 2.4.5) + redis (~> 3.0) + rspec-rails + rspec_api_documentation + rspec_junit_formatter + rubocop + rubyzip (>= 1.0.0) + sass-rails (~> 5.0) + scout_apm + selenium-webdriver + shoulda-matchers + sidekiq + simplecov + solid_use_case (~> 2.2.0) + stackprof + timecop + ts_routes + tzinfo-data + uglifier (>= 1.3.0) + underscore-rails (= 1.8.3) + vcr + webmock + webpacker (~> 5.2.1) + zip-zip + +RUBY VERSION + ruby 2.6.6p146 + +BUNDLED WITH + 2.1.4 diff --git a/Gemfile.outdated b/Gemfile.outdated new file mode 100644 index 0000000..5a1c8bd --- /dev/null +++ b/Gemfile.outdated @@ -0,0 +1,142 @@ +Fetching gem metadata from https://rubygems.org/......... +Fetching gem metadata from https://rubygems.org/. +Resolving dependencies.......... + +Outdated gems included in the bundle: + * actioncable (newest 6.0.3.4, installed 5.2.1) + * actionmailer (newest 6.0.3.4, installed 5.2.1) + * actionpack (newest 6.0.3.4, installed 5.2.1) + * actionview (newest 6.0.3.4, installed 5.2.1) + * activejob (newest 6.0.3.4, installed 5.2.1) + * activemodel (newest 6.0.3.4, installed 5.2.1) + * activerecord (newest 6.0.3.4, installed 5.2.1) + * activestorage (newest 6.0.3.4, installed 5.2.1) + * activesupport (newest 6.0.3.4, installed 5.2.1) + * addressable (newest 2.7.0, installed 2.4.0) + * analytics-ruby (newest 2.2.8, installed 2.0.13, requested ~> 2.0.0) in group "default" + * ast (newest 2.4.1, installed 2.4.0) + * autoprefixer-rails (newest 10.0.1.0, installed 7.2.5) + * aws-sdk (newest 3.0.1, installed 2.6.50, requested ~> 2.6.5) in group "default" + * aws-sdk-core (newest 3.109.1, installed 2.6.50) + * aws-sdk-resources (newest 3.84.0, installed 2.6.50) + * aws-sigv4 (newest 1.2.2, installed 1.0.2) + * barnes (newest 0.0.8, installed 0.0.7) in group "default" + * better_errors (newest 2.8.3, installed 2.5.0) in group "development" + * bootsnap (newest 1.4.8, installed 1.3.1) in group "default" + * bootstrap (newest 4.5.2, installed 4.0.0, requested = 4.0.0) in group "default" + * browser (newest 5.1.0, installed 2.5.2) in group "default" + * builder (newest 3.2.4, installed 3.2.3) + * byebug (newest 11.1.3, installed 9.1.0) in groups "development, test" + * capybara (newest 3.33.0, installed 2.16.1) in group "test" + * childprocess (newest 4.0.0, installed 0.8.0) + * coderay (newest 1.1.3, installed 1.1.2) + * concurrent-ruby (newest 1.1.7, installed 1.1.5) + * connection_pool (newest 2.2.3, installed 2.2.1) + * crack (newest 0.4.4, installed 0.4.3) + * crass (newest 1.0.6, installed 1.0.4) + * database_cleaner (newest 1.8.5, installed 1.6.2) in group "test" + * deterministic (newest 0.16.0, installed 0.6.0) + * diff-lcs (newest 1.4.4, installed 1.3) + * dotenv (newest 2.7.6, installed 2.5.0) + * dotenv-rails (newest 2.7.6, installed 2.5.0) in group "default" + * dry-configurable (newest 0.11.6, installed 0.7.0) + * dry-container (newest 0.7.2, installed 0.6.0) + * dry-core (newest 0.4.9, installed 0.4.7) + * dry-equalizer (newest 0.3.0, installed 0.2.1) + * dry-inflector (newest 0.2.0, installed 0.1.2) + * dry-logic (newest 1.0.8, installed 0.4.2) + * dry-types (newest 1.4.0, installed 0.13.2) + * dry-validation (newest 1.5.6, installed 0.12.2, requested ~> 0.12.2) in group "default" + * erubi (newest 1.9.0, installed 1.7.1) + * factory_bot (newest 6.1.0, installed 4.8.2) + * factory_bot_rails (newest 6.1.0, installed 4.8.2) in groups "development, test" + * faraday (newest 1.0.1, installed 0.9.2) + * ffi (newest 1.13.1, installed 1.9.18) + * font-awesome-rails (newest 4.7.0.5, installed 4.7.0.4) in group "default" + * foreman (newest 0.87.2, installed 0.84.0) in group "development" + * github-markup (newest 3.0.4, installed 1.6.1) + * gitlab (newest 4.16.1, installed 4.14.1) in group "default" + * globalid (newest 0.4.2, installed 0.4.1) + * haml (newest 5.2.0, installed 5.0.4) in group "default" + * hashdiff (newest 1.0.1, installed 0.4.0) + * honeybadger (newest 4.7.2, installed 3.2.0, requested ~> 3.1) in group "default" + * httparty (newest 0.18.1, installed 0.15.6) in group "default" + * i18n (newest 1.8.5, installed 1.6.0) + * iniparse (newest 1.5.0, installed 1.4.4) + * jaro_winkler (newest 1.5.4, installed 1.5.3) + * jmespath (newest 1.4.0, installed 1.3.1) + * jquery-rails (newest 4.4.0, installed 4.3.1) in group "default" + * js-routes (newest 1.4.9, installed 1.4.2) in group "default" + * kramdown (newest 2.3.0, installed 2.1.0) + * launchy (newest 2.5.0, installed 2.4.3) + * loofah (newest 2.7.0, installed 2.2.2) + * mail (newest 2.7.1, installed 2.7.0) + * marcel (newest 0.3.3, installed 0.3.2) + * memory_profiler (newest 0.9.14, installed 0.9.12) in group "default" + * method_source (newest 1.0.0, installed 0.9.0) + * mimemagic (newest 0.3.5, installed 0.3.2) + * mini_mime (newest 1.0.2, installed 1.0.0) + * mini_portile2 (newest 2.5.0, installed 2.2.0) + * minitest (newest 5.14.2, installed 5.11.3) + * msgpack (newest 1.3.3, installed 1.2.4) + * multi_json (newest 1.15.0, installed 1.13.1) + * multipart-post (newest 2.1.1, installed 2.0.0) + * mustache (newest 1.1.1, installed 1.1.0) + * nio4r (newest 2.5.4, installed 2.3.1) + * nokogiri (newest 1.10.10, installed 1.8.0) + * octokit (newest 4.18.0, installed 4.3.0) in group "default" + * overcommit (newest 0.57.0, installed 0.41.0) in group "development" + * pagy (newest 3.8.3, installed 3.7.1) in group "default" + * parallel (newest 1.19.2, installed 1.17.0) + * parser (newest 2.7.2.0, installed 2.6.3.0) + * pg (newest 1.2.3, installed 0.21.0, requested ~> 0.18) in group "default" + * popper_js (newest 1.16.0, installed 1.12.9) + * psych (newest 3.2.0, installed 2.2.4) + * puma (newest 5.0.2, installed 3.12.1, requested ~> 3.12.0) in group "default" + * pundit (newest 2.1.0, installed 1.1.0) in group "default" + * rack (newest 2.2.3, installed 2.0.3) + * rack-attack (newest 6.3.1, installed 6.2.1) in group "default" + * rack-mini-profiler (newest 2.1.0, installed 1.0.0) in group "default" + * rack-protection (newest 2.1.0, installed 2.0.0) + * rack-test (newest 1.1.0, installed 0.8.2) + * rails (newest 6.0.3.4, installed 5.2.1, requested ~> 5.2.1) in group "default" + * rails-controller-testing (newest 1.0.5, installed 1.0.2) in group "test" + * rails-html-sanitizer (newest 1.3.0, installed 1.0.4) + * railties (newest 6.0.3.4, installed 5.2.1) + * rake (newest 13.0.1, installed 12.3.1) + * rb-fsevent (newest 0.10.4, installed 0.10.2) + * rb-inotify (newest 0.10.1, installed 0.9.10) + * react-rails (newest 2.6.1, installed 2.4.5, requested = 2.4.5) in group "default" + * redcarpet (newest 3.5.0, installed 3.3.4) + * redis (newest 4.2.2, installed 3.3.5, requested ~> 3.0) in group "default" + * rspec (newest 3.9.0, installed 3.7.0) + * rspec-core (newest 3.9.3, installed 3.7.0) + * rspec-expectations (newest 3.9.2, installed 3.7.0) + * rspec-mocks (newest 3.9.1, installed 3.7.0) + * rspec-rails (newest 4.0.1, installed 3.7.2) in groups "development, test" + * rspec-support (newest 3.9.3, installed 3.7.0) + * rspec_junit_formatter (newest 0.4.1, installed 0.3.0) in group "test" + * rubocop (newest 0.93.0, installed 0.72.0) in group "development" + * rubyzip (newest 2.3.0, installed 1.2.1) in group "default" + * sass (newest 3.7.4, installed 3.5.3) + * sass-rails (newest 6.0.0, installed 5.0.7, requested ~> 5.0) in group "default" + * sawyer (newest 0.8.2, installed 0.7.0) + * scout_apm (newest 2.6.9, installed 2.4.19) in group "default" + * selenium-webdriver (newest 3.142.7, installed 3.8.0) in group "test" + * shoulda-matchers (newest 4.4.1, installed 3.1.2) in group "test" + * sidekiq (newest 6.1.2, installed 5.0.5) in group "default" + * sprockets (newest 4.0.2, installed 3.7.1) + * sprockets-rails (newest 3.2.2, installed 3.2.1) + * stackprof (newest 0.2.15, installed 0.2.12) in group "default" + * temple (newest 0.8.2, installed 0.8.0) + * thor (newest 1.0.1, installed 0.19.4) + * tilt (newest 2.0.10, installed 2.0.8) + * ts_routes (newest 1.0.3, installed 1.0.1) in group "default" + * tzinfo (newest 2.0.2, installed 1.2.5) + * uglifier (newest 4.2.0, installed 4.0.2) in group "default" + * unicode-display_width (newest 1.7.0, installed 1.6.0) + * vcr (newest 6.0.0, installed 4.0.0) in group "test" + * webmock (newest 3.9.1, installed 3.6.0) in group "test" + * websocket-driver (newest 0.7.3, installed 0.7.0) + * websocket-extensions (newest 0.1.5, installed 0.1.3) + * xpath (newest 3.2.0, installed 2.1.0) diff --git a/app/assets/stylesheets/mobile/_submissions-dashboard-table.scss b/app/assets/stylesheets/mobile/_submissions-dashboard-table.scss index ac9e98f..c93e515 100644 --- a/app/assets/stylesheets/mobile/_submissions-dashboard-table.scss +++ b/app/assets/stylesheets/mobile/_submissions-dashboard-table.scss @@ -5,7 +5,7 @@ .challengeindex-table > .studentspanel > .studentcolumn > .standard > .emptyrow { height: 80px; - background: linear-gradient(top, #d4d4d4 50%,#d4d4d4 50%,#ebebeb 50%) + background: linear-gradient(to bottom, #d4d4d4 50%,#d4d4d4 50%,#ebebeb 50%) } .challengeindex-table > .curriculumpanel > .standard > .standardtitle { @@ -48,4 +48,4 @@ padding: .5rem 1rem; } } -} \ No newline at end of file +} -- GitLab From 9b83a0cfa08ed07d50fb4270c5e425a3dee25d93 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Sat, 10 Oct 2020 00:34:56 -1000 Subject: [PATCH 147/283] Changes to get to bundle update state --- Gemfile.lock | 53 +- Gemfile.lock.new | 488 ------------------ Gemfile.lock.old | 476 ----------------- Gemfile.outdated | 142 ----- app/assets/stylesheets/components/_modal.scss | 4 +- spec/factories.rb | 126 ++--- .../features/cohorts/student_progress_spec.rb | 6 +- .../checkpoint_assessments_spec.rb | 2 +- .../checkpoint_submissions_spec.rb | 8 +- .../content_files/view_feature_spec.rb | 2 +- spec/models/performance_spec.rb | 7 +- spec/models/release_spec.rb | 9 +- 12 files changed, 117 insertions(+), 1206 deletions(-) delete mode 100644 Gemfile.lock.new delete mode 100644 Gemfile.lock.old delete mode 100644 Gemfile.outdated diff --git a/Gemfile.lock b/Gemfile.lock index 3d86107..0a1bc01 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -26,10 +26,10 @@ GEM activejob (= 5.2.4.4) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.2.1) - actionview (= 5.2.1) - activesupport (= 5.2.1) - rack (~> 2.0) + actionpack (5.2.4.4) + actionview (= 5.2.4.4) + activesupport (= 5.2.4.4) + rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) @@ -98,13 +98,14 @@ GEM browser (5.1.0) builder (3.2.4) byebug (11.1.3) - capybara (2.16.1) + capybara (3.33.0) addressable mini_mime (>= 0.1.3) - nokogiri (>= 1.3.3) - rack (>= 1.0.0) - rack-test (>= 0.5.4) - xpath (~> 2.0) + nokogiri (~> 1.8) + rack (>= 1.6.0) + rack-test (>= 0.6.3) + regexp_parser (~> 1.5) + xpath (~> 3.2) childprocess (3.0.0) coderay (1.1.3) concurrent-ruby (1.1.7) @@ -151,11 +152,11 @@ GEM dry-types (~> 0.13.1) erubi (1.9.0) execjs (2.7.0) - factory_bot (4.8.2) - activesupport (>= 3.0.0) - factory_bot_rails (4.8.2) - factory_bot (~> 4.8.2) - railties (>= 3.0.0) + factory_bot (6.1.0) + activesupport (>= 5.0.0) + factory_bot_rails (6.1.0) + factory_bot (~> 6.1.0) + railties (>= 5.0.0) faraday (0.9.2) multipart-post (>= 1.2, < 3) ffi (1.13.1) @@ -176,12 +177,12 @@ GEM tilt hashdiff (1.0.1) honeybadger (3.3.1) - httparty (0.15.6) + httparty (0.18.1) + mime-types (~> 3.0) multi_xml (>= 0.5.2) i18n (1.8.5) concurrent-ruby (~> 1.0) iniparse (1.5.0) - jaro_winkler (1.5.3) jmespath (1.4.0) jquery-rails (4.4.0) rails-dom-testing (>= 1, < 3) @@ -194,7 +195,8 @@ GEM multi_json (~> 1.0) rspec (>= 2.0, < 4.0) jwt (2.2.2) - kramdown (2.1.0) + kramdown (2.3.0) + rexml launchy (2.4.3) addressable (~> 2.3) letter_opener (1.7.0) @@ -210,6 +212,9 @@ GEM railties (>= 3.0) memory_profiler (0.9.14) method_source (1.0.0) + mime-types (3.3.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2020.0512) mimemagic (0.3.5) mini_mime (1.0.2) mini_portile2 (2.2.0) @@ -289,6 +294,8 @@ GEM tilt redcarpet (3.3.4) redis (3.3.5) + regexp_parser (1.8.1) + rexml (3.2.4) rspec (3.9.0) rspec-core (~> 3.9.0) rspec-expectations (~> 3.9.0) @@ -316,13 +323,17 @@ GEM rspec (~> 3.0) rspec_junit_formatter (0.4.1) rspec-core (>= 2, < 4, != 2.12.0) - rubocop (0.72.0) - jaro_winkler (~> 1.5.1) + rubocop (0.93.0) parallel (~> 1.10) - parser (>= 2.6) + parser (>= 2.7.1.5) rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8) + rexml + rubocop-ast (>= 0.6.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 1.7) + unicode-display_width (>= 1.4.0, < 2.0) + rubocop-ast (0.7.1) + parser (>= 2.7.1.5) ruby-progressbar (1.10.1) rubyzip (2.3.0) sass (3.7.4) diff --git a/Gemfile.lock.new b/Gemfile.lock.new deleted file mode 100644 index 0a1bc01..0000000 --- a/Gemfile.lock.new +++ /dev/null @@ -1,488 +0,0 @@ -PATH - remote: gems/block-parser - specs: - block_parser (0.1.0) - activemodel (> 4.2) - github-markdown (= 0.6.9) - github-markup (= 1.6.1) - github_url (= 0.2.1) - gitlab (= 4.14.1) - nokogiri (= 1.8.0) - octokit (= 4.3.0) - psych (= 2.2.4) - redcarpet (= 3.3.4) - rspec_junit_formatter (> 0.2.3) - -GEM - remote: https://rubygems.org/ - specs: - actioncable (5.2.4.4) - actionpack (= 5.2.4.4) - nio4r (~> 2.0) - websocket-driver (>= 0.6.1) - actionmailer (5.2.4.4) - actionpack (= 5.2.4.4) - actionview (= 5.2.4.4) - activejob (= 5.2.4.4) - mail (~> 2.5, >= 2.5.4) - rails-dom-testing (~> 2.0) - actionpack (5.2.4.4) - actionview (= 5.2.4.4) - activesupport (= 5.2.4.4) - rack (~> 2.0, >= 2.0.8) - rack-test (>= 0.6.3) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.2.4.4) - activesupport (= 5.2.4.4) - builder (~> 3.1) - erubi (~> 1.4) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (5.2.4.4) - activesupport (= 5.2.4.4) - globalid (>= 0.3.6) - activemodel (5.2.4.4) - activesupport (= 5.2.4.4) - activerecord (5.2.4.4) - activemodel (= 5.2.4.4) - activesupport (= 5.2.4.4) - arel (>= 9.0) - activestorage (5.2.4.4) - actionpack (= 5.2.4.4) - activerecord (= 5.2.4.4) - marcel (~> 0.3.1) - activesupport (5.2.4.4) - concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - addressable (2.4.0) - analytics-ruby (2.0.13) - apitome (0.3.0) - kramdown - railties - arel (9.0.0) - ast (2.4.1) - autoprefixer-rails (10.0.1.0) - execjs - aws-eventstream (1.1.0) - aws-sdk (2.6.50) - aws-sdk-resources (= 2.6.50) - aws-sdk-core (2.6.50) - aws-sigv4 (~> 1.0) - jmespath (~> 1.0) - aws-sdk-resources (2.6.50) - aws-sdk-core (= 2.6.50) - aws-sigv4 (1.2.2) - aws-eventstream (~> 1, >= 1.0.2) - babel-source (5.8.35) - babel-transpiler (0.7.0) - babel-source (>= 4.0, < 6) - execjs (~> 2.0) - barnes (0.0.8) - multi_json (~> 1) - statsd-ruby (~> 1.1) - better_errors (2.8.3) - coderay (>= 1.0.0) - erubi (>= 1.0.0) - rack (>= 0.9.0) - binding_of_caller (0.8.0) - debug_inspector (>= 0.0.1) - bootsnap (1.4.8) - msgpack (~> 1.0) - bootstrap (4.0.0) - autoprefixer-rails (>= 6.0.3) - popper_js (>= 1.12.9, < 2) - sass (>= 3.5.2) - browser (5.1.0) - builder (3.2.4) - byebug (11.1.3) - capybara (3.33.0) - addressable - mini_mime (>= 0.1.3) - nokogiri (~> 1.8) - rack (>= 1.6.0) - rack-test (>= 0.6.3) - regexp_parser (~> 1.5) - xpath (~> 3.2) - childprocess (3.0.0) - coderay (1.1.3) - concurrent-ruby (1.1.7) - connection_pool (2.2.3) - crack (0.4.4) - crass (1.0.6) - database_cleaner (1.8.5) - debug_inspector (0.0.3) - deterministic (0.6.0) - diff-lcs (1.4.4) - docile (1.3.2) - dotenv (2.7.6) - dotenv-rails (2.7.6) - dotenv (= 2.7.6) - railties (>= 3.2) - dry-configurable (0.11.6) - concurrent-ruby (~> 1.0) - dry-core (~> 0.4, >= 0.4.7) - dry-equalizer (~> 0.2) - dry-container (0.7.2) - concurrent-ruby (~> 1.0) - dry-configurable (~> 0.1, >= 0.1.3) - dry-core (0.4.9) - concurrent-ruby (~> 1.0) - dry-equalizer (0.3.0) - dry-inflector (0.2.0) - dry-logic (0.4.2) - dry-container (~> 0.2, >= 0.2.6) - dry-core (~> 0.2) - dry-equalizer (~> 0.2) - dry-types (0.13.4) - concurrent-ruby (~> 1.0) - dry-container (~> 0.3) - dry-core (~> 0.4, >= 0.4.4) - dry-equalizer (~> 0.2) - dry-inflector (~> 0.1, >= 0.1.2) - dry-logic (~> 0.4, >= 0.4.2) - dry-validation (0.12.3) - concurrent-ruby (~> 1.0) - dry-configurable (~> 0.1, >= 0.1.3) - dry-core (~> 0.2, >= 0.2.1) - dry-equalizer (~> 0.2) - dry-logic (~> 0.4.2) - dry-types (~> 0.13.1) - erubi (1.9.0) - execjs (2.7.0) - factory_bot (6.1.0) - activesupport (>= 5.0.0) - factory_bot_rails (6.1.0) - factory_bot (~> 6.1.0) - railties (>= 5.0.0) - faraday (0.9.2) - multipart-post (>= 1.2, < 3) - ffi (1.13.1) - flamegraph (0.9.5) - font-awesome-rails (4.7.0.5) - railties (>= 3.2, < 6.1) - foreman (0.87.2) - github-markdown (0.6.9) - github-markup (1.6.1) - github_url (0.2.1) - gitlab (4.14.1) - httparty (~> 0.14, >= 0.14.0) - terminal-table (~> 1.5, >= 1.5.1) - globalid (0.4.2) - activesupport (>= 4.2.0) - haml (5.2.0) - temple (>= 0.8.0) - tilt - hashdiff (1.0.1) - honeybadger (3.3.1) - httparty (0.18.1) - mime-types (~> 3.0) - multi_xml (>= 0.5.2) - i18n (1.8.5) - concurrent-ruby (~> 1.0) - iniparse (1.5.0) - jmespath (1.4.0) - jquery-rails (4.4.0) - rails-dom-testing (>= 1, < 3) - railties (>= 4.2.0) - thor (>= 0.14, < 2.0) - js-routes (1.4.9) - railties (>= 4) - sprockets-rails - json_spec (1.1.5) - multi_json (~> 1.0) - rspec (>= 2.0, < 4.0) - jwt (2.2.2) - kramdown (2.3.0) - rexml - launchy (2.4.3) - addressable (~> 2.3) - letter_opener (1.7.0) - launchy (~> 2.2) - loofah (2.7.0) - crass (~> 1.0.2) - nokogiri (>= 1.5.9) - mail (2.7.1) - mini_mime (>= 0.1.1) - marcel (0.3.3) - mimemagic (~> 0.3.2) - mathjax-rails (2.6.1) - railties (>= 3.0) - memory_profiler (0.9.14) - method_source (1.0.0) - mime-types (3.3.1) - mime-types-data (~> 3.2015) - mime-types-data (3.2020.0512) - mimemagic (0.3.5) - mini_mime (1.0.2) - mini_portile2 (2.2.0) - minitest (5.14.2) - msgpack (1.3.3) - multi_json (1.15.0) - multi_xml (0.6.0) - multipart-post (2.1.1) - mustache (1.1.1) - nio4r (2.5.4) - nokogiri (1.8.0) - mini_portile2 (~> 2.2.0) - octokit (4.3.0) - sawyer (~> 0.7.0, >= 0.5.3) - overcommit (0.57.0) - childprocess (>= 0.6.3, < 5) - iniparse (~> 1.4) - pagy (3.8.3) - parallel (1.19.2) - parser (2.7.2.0) - ast (~> 2.4.1) - pg (0.21.0) - popper_js (1.16.0) - psych (2.2.4) - puma (3.12.6) - pundit (2.1.0) - activesupport (>= 3.0.0) - rack (2.2.3) - rack-attack (6.3.1) - rack (>= 1.0, < 3) - rack-mini-profiler (2.1.0) - rack (>= 1.2.0) - rack-protection (2.1.0) - rack - rack-proxy (0.6.5) - rack - rack-test (1.1.0) - rack (>= 1.0, < 3) - rails (5.2.4.4) - actioncable (= 5.2.4.4) - actionmailer (= 5.2.4.4) - actionpack (= 5.2.4.4) - actionview (= 5.2.4.4) - activejob (= 5.2.4.4) - activemodel (= 5.2.4.4) - activerecord (= 5.2.4.4) - activestorage (= 5.2.4.4) - activesupport (= 5.2.4.4) - bundler (>= 1.3.0) - railties (= 5.2.4.4) - sprockets-rails (>= 2.0.0) - rails-controller-testing (1.0.5) - actionpack (>= 5.0.1.rc1) - actionview (>= 5.0.1.rc1) - activesupport (>= 5.0.1.rc1) - rails-dom-testing (2.0.3) - activesupport (>= 4.2.0) - nokogiri (>= 1.6) - rails-html-sanitizer (1.3.0) - loofah (~> 2.3) - railties (5.2.4.4) - actionpack (= 5.2.4.4) - activesupport (= 5.2.4.4) - method_source - rake (>= 0.8.7) - thor (>= 0.19.0, < 2.0) - rainbow (3.0.0) - rake (13.0.1) - rb-fsevent (0.10.4) - rb-inotify (0.10.1) - ffi (~> 1.0) - react-rails (2.4.5) - babel-transpiler (>= 0.7.0) - connection_pool - execjs - railties (>= 3.2) - tilt - redcarpet (3.3.4) - redis (3.3.5) - regexp_parser (1.8.1) - rexml (3.2.4) - rspec (3.9.0) - rspec-core (~> 3.9.0) - rspec-expectations (~> 3.9.0) - rspec-mocks (~> 3.9.0) - rspec-core (3.9.3) - rspec-support (~> 3.9.3) - rspec-expectations (3.9.2) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.9.0) - rspec-mocks (3.9.1) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.9.0) - rspec-rails (4.0.1) - actionpack (>= 4.2) - activesupport (>= 4.2) - railties (>= 4.2) - rspec-core (~> 3.9) - rspec-expectations (~> 3.9) - rspec-mocks (~> 3.9) - rspec-support (~> 3.9) - rspec-support (3.9.3) - rspec_api_documentation (6.1.0) - activesupport (>= 3.0.0) - mustache (~> 1.0, >= 0.99.4) - rspec (~> 3.0) - rspec_junit_formatter (0.4.1) - rspec-core (>= 2, < 4, != 2.12.0) - rubocop (0.93.0) - parallel (~> 1.10) - parser (>= 2.7.1.5) - rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.8) - rexml - rubocop-ast (>= 0.6.0) - ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 2.0) - rubocop-ast (0.7.1) - parser (>= 2.7.1.5) - ruby-progressbar (1.10.1) - rubyzip (2.3.0) - sass (3.7.4) - sass-listen (~> 4.0.0) - sass-listen (4.0.0) - rb-fsevent (~> 0.9, >= 0.9.4) - rb-inotify (~> 0.9, >= 0.9.7) - sass-rails (5.1.0) - railties (>= 5.2.0) - sass (~> 3.1) - sprockets (>= 2.8, < 4.0) - sprockets-rails (>= 2.0, < 4.0) - tilt (>= 1.1, < 3) - sawyer (0.7.0) - addressable (>= 2.3.5, < 2.5) - faraday (~> 0.8, < 0.10) - scout_apm (2.6.9) - parser - selenium-webdriver (3.142.7) - childprocess (>= 0.5, < 4.0) - rubyzip (>= 1.2.2) - semantic_range (2.3.0) - shoulda-matchers (4.4.1) - activesupport (>= 4.2.0) - sidekiq (5.2.9) - connection_pool (~> 2.2, >= 2.2.2) - rack (~> 2.0) - rack-protection (>= 1.5.0) - redis (>= 3.3.5, < 4.2) - simplecov (0.19.0) - docile (~> 1.1) - simplecov-html (~> 0.11) - simplecov-html (0.12.3) - solid_use_case (2.2.0) - deterministic (~> 0.6.0) - sprockets (3.7.2) - concurrent-ruby (~> 1.0) - rack (> 1, < 3) - sprockets-rails (3.2.2) - actionpack (>= 4.0) - activesupport (>= 4.0) - sprockets (>= 3.0.0) - stackprof (0.2.15) - statsd-ruby (1.4.0) - temple (0.8.2) - terminal-table (1.8.0) - unicode-display_width (~> 1.1, >= 1.1.1) - thor (1.0.1) - thread_safe (0.3.6) - tilt (2.0.10) - timecop (0.9.1) - ts_routes (1.0.3) - railties (>= 4.0) - tzinfo (1.2.7) - thread_safe (~> 0.1) - uglifier (4.2.0) - execjs (>= 0.3.0, < 3) - underscore-rails (1.8.3) - unicode-display_width (1.7.0) - vcr (6.0.0) - webmock (3.9.1) - addressable (>= 2.3.6) - crack (>= 0.3.2) - hashdiff (>= 0.4.0, < 2.0.0) - webpacker (5.2.1) - activesupport (>= 5.2) - rack-proxy (>= 0.6.1) - railties (>= 5.2) - semantic_range (>= 2.3.0) - websocket-driver (0.7.3) - websocket-extensions (>= 0.1.0) - websocket-extensions (0.1.5) - xpath (3.2.0) - nokogiri (~> 1.8) - zip-zip (0.3) - rubyzip (>= 1.0.0) - -PLATFORMS - ruby - -DEPENDENCIES - analytics-ruby (~> 2.0.0) - apitome - aws-sdk (~> 2.6.5) - barnes - better_errors - binding_of_caller - block_parser! - bootsnap (>= 1.1.0) - bootstrap (= 4.0.0) - browser - byebug - capybara - database_cleaner - dotenv-rails - dry-validation (~> 0.12.2) - factory_bot_rails - flamegraph - font-awesome-rails - foreman - github_url (= 0.2.1) - gitlab - haml - honeybadger (~> 3.1) - httparty - jquery-rails - js-routes - json_spec - jwt - letter_opener - mathjax-rails - memory_profiler - octokit - overcommit - pagy - pg (~> 0.18) - puma (~> 3.12.0) - pundit - rack-attack - rack-mini-profiler - rails (~> 5.2.1) - rails-controller-testing - react-rails (= 2.4.5) - redis (~> 3.0) - rspec-rails - rspec_api_documentation - rspec_junit_formatter - rubocop - rubyzip (>= 1.0.0) - sass-rails (~> 5.0) - scout_apm - selenium-webdriver - shoulda-matchers - sidekiq - simplecov - solid_use_case (~> 2.2.0) - stackprof - timecop - ts_routes - tzinfo-data - uglifier (>= 1.3.0) - underscore-rails (= 1.8.3) - vcr - webmock - webpacker (~> 5.2.1) - zip-zip - -RUBY VERSION - ruby 2.6.6p146 - -BUNDLED WITH - 2.1.4 diff --git a/Gemfile.lock.old b/Gemfile.lock.old deleted file mode 100644 index 34ea2ba..0000000 --- a/Gemfile.lock.old +++ /dev/null @@ -1,476 +0,0 @@ -PATH - remote: gems/block-parser - specs: - block_parser (0.1.0) - activemodel (> 4.2) - github-markdown (= 0.6.9) - github-markup (= 1.6.1) - github_url (= 0.2.1) - gitlab (= 4.14.1) - nokogiri (= 1.8.0) - octokit (= 4.3.0) - psych (= 2.2.4) - redcarpet (= 3.3.4) - rspec_junit_formatter (> 0.2.3) - -GEM - remote: https://rubygems.org/ - specs: - actioncable (5.2.1) - actionpack (= 5.2.1) - nio4r (~> 2.0) - websocket-driver (>= 0.6.1) - actionmailer (5.2.1) - actionpack (= 5.2.1) - actionview (= 5.2.1) - activejob (= 5.2.1) - mail (~> 2.5, >= 2.5.4) - rails-dom-testing (~> 2.0) - actionpack (5.2.1) - actionview (= 5.2.1) - activesupport (= 5.2.1) - rack (~> 2.0) - rack-test (>= 0.6.3) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.2.1) - activesupport (= 5.2.1) - builder (~> 3.1) - erubi (~> 1.4) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (5.2.1) - activesupport (= 5.2.1) - globalid (>= 0.3.6) - activemodel (5.2.1) - activesupport (= 5.2.1) - activerecord (5.2.1) - activemodel (= 5.2.1) - activesupport (= 5.2.1) - arel (>= 9.0) - activestorage (5.2.1) - actionpack (= 5.2.1) - activerecord (= 5.2.1) - marcel (~> 0.3.1) - activesupport (5.2.1) - concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - addressable (2.4.0) - analytics-ruby (2.0.13) - apitome (0.3.0) - kramdown - railties - arel (9.0.0) - ast (2.4.0) - autoprefixer-rails (7.2.5) - execjs - aws-sdk (2.6.50) - aws-sdk-resources (= 2.6.50) - aws-sdk-core (2.6.50) - aws-sigv4 (~> 1.0) - jmespath (~> 1.0) - aws-sdk-resources (2.6.50) - aws-sdk-core (= 2.6.50) - aws-sigv4 (1.0.2) - babel-source (5.8.35) - babel-transpiler (0.7.0) - babel-source (>= 4.0, < 6) - execjs (~> 2.0) - barnes (0.0.7) - multi_json (~> 1) - statsd-ruby (~> 1.1) - better_errors (2.5.0) - coderay (>= 1.0.0) - erubi (>= 1.0.0) - rack (>= 0.9.0) - binding_of_caller (0.8.0) - debug_inspector (>= 0.0.1) - bootsnap (1.3.1) - msgpack (~> 1.0) - bootstrap (4.0.0) - autoprefixer-rails (>= 6.0.3) - popper_js (>= 1.12.9, < 2) - sass (>= 3.5.2) - browser (2.5.2) - builder (3.2.3) - byebug (9.1.0) - capybara (2.16.1) - addressable - mini_mime (>= 0.1.3) - nokogiri (>= 1.3.3) - rack (>= 1.0.0) - rack-test (>= 0.5.4) - xpath (~> 2.0) - childprocess (0.8.0) - ffi (~> 1.0, >= 1.0.11) - coderay (1.1.2) - concurrent-ruby (1.1.5) - connection_pool (2.2.1) - crack (0.4.3) - safe_yaml (~> 1.0.0) - crass (1.0.4) - database_cleaner (1.6.2) - debug_inspector (0.0.3) - deterministic (0.6.0) - diff-lcs (1.3) - docile (1.3.2) - dotenv (2.5.0) - dotenv-rails (2.5.0) - dotenv (= 2.5.0) - railties (>= 3.2, < 6.0) - dry-configurable (0.7.0) - concurrent-ruby (~> 1.0) - dry-container (0.6.0) - concurrent-ruby (~> 1.0) - dry-configurable (~> 0.1, >= 0.1.3) - dry-core (0.4.7) - concurrent-ruby (~> 1.0) - dry-equalizer (0.2.1) - dry-inflector (0.1.2) - dry-logic (0.4.2) - dry-container (~> 0.2, >= 0.2.6) - dry-core (~> 0.2) - dry-equalizer (~> 0.2) - dry-types (0.13.2) - concurrent-ruby (~> 1.0) - dry-container (~> 0.3) - dry-core (~> 0.4, >= 0.4.4) - dry-equalizer (~> 0.2) - dry-inflector (~> 0.1, >= 0.1.2) - dry-logic (~> 0.4, >= 0.4.2) - dry-validation (0.12.2) - concurrent-ruby (~> 1.0) - dry-configurable (~> 0.1, >= 0.1.3) - dry-core (~> 0.2, >= 0.2.1) - dry-equalizer (~> 0.2) - dry-logic (~> 0.4, >= 0.4.0) - dry-types (~> 0.13.1) - erubi (1.7.1) - execjs (2.7.0) - factory_bot (4.8.2) - activesupport (>= 3.0.0) - factory_bot_rails (4.8.2) - factory_bot (~> 4.8.2) - railties (>= 3.0.0) - faraday (0.9.2) - multipart-post (>= 1.2, < 3) - ffi (1.9.18) - flamegraph (0.9.5) - font-awesome-rails (4.7.0.4) - railties (>= 3.2, < 6.0) - foreman (0.84.0) - thor (~> 0.19.1) - github-markdown (0.6.9) - github-markup (1.6.1) - github_url (0.2.1) - gitlab (4.14.1) - httparty (~> 0.14, >= 0.14.0) - terminal-table (~> 1.5, >= 1.5.1) - globalid (0.4.1) - activesupport (>= 4.2.0) - haml (5.0.4) - temple (>= 0.8.0) - tilt - hashdiff (0.4.0) - honeybadger (3.2.0) - httparty (0.15.6) - multi_xml (>= 0.5.2) - i18n (1.6.0) - concurrent-ruby (~> 1.0) - iniparse (1.4.4) - jaro_winkler (1.5.3) - jmespath (1.3.1) - jquery-rails (4.3.1) - rails-dom-testing (>= 1, < 3) - railties (>= 4.2.0) - thor (>= 0.14, < 2.0) - js-routes (1.4.2) - railties (>= 3.2) - sprockets-rails - json_spec (1.1.5) - multi_json (~> 1.0) - rspec (>= 2.0, < 4.0) - jwt (2.2.2) - kramdown (2.1.0) - launchy (2.4.3) - addressable (~> 2.3) - letter_opener (1.7.0) - launchy (~> 2.2) - loofah (2.2.2) - crass (~> 1.0.2) - nokogiri (>= 1.5.9) - mail (2.7.0) - mini_mime (>= 0.1.1) - marcel (0.3.2) - mimemagic (~> 0.3.2) - mathjax-rails (2.6.1) - railties (>= 3.0) - memory_profiler (0.9.12) - method_source (0.9.0) - mimemagic (0.3.2) - mini_mime (1.0.0) - mini_portile2 (2.2.0) - minitest (5.11.3) - msgpack (1.2.4) - multi_json (1.13.1) - multi_xml (0.6.0) - multipart-post (2.0.0) - mustache (1.1.0) - nio4r (2.3.1) - nokogiri (1.8.0) - mini_portile2 (~> 2.2.0) - octokit (4.3.0) - sawyer (~> 0.7.0, >= 0.5.3) - overcommit (0.41.0) - childprocess (~> 0.6, >= 0.6.3) - iniparse (~> 1.4) - pagy (3.7.1) - parallel (1.17.0) - parser (2.6.3.0) - ast (~> 2.4.0) - pg (0.21.0) - popper_js (1.12.9) - psych (2.2.4) - puma (3.12.1) - pundit (1.1.0) - activesupport (>= 3.0.0) - rack (2.0.3) - rack-attack (6.2.1) - rack (>= 1.0, < 3) - rack-mini-profiler (1.0.0) - rack (>= 1.2.0) - rack-protection (2.0.0) - rack - rack-proxy (0.6.5) - rack - rack-test (0.8.2) - rack (>= 1.0, < 3) - rails (5.2.1) - actioncable (= 5.2.1) - actionmailer (= 5.2.1) - actionpack (= 5.2.1) - actionview (= 5.2.1) - activejob (= 5.2.1) - activemodel (= 5.2.1) - activerecord (= 5.2.1) - activestorage (= 5.2.1) - activesupport (= 5.2.1) - bundler (>= 1.3.0) - railties (= 5.2.1) - sprockets-rails (>= 2.0.0) - rails-controller-testing (1.0.2) - actionpack (~> 5.x, >= 5.0.1) - actionview (~> 5.x, >= 5.0.1) - activesupport (~> 5.x) - rails-dom-testing (2.0.3) - activesupport (>= 4.2.0) - nokogiri (>= 1.6) - rails-html-sanitizer (1.0.4) - loofah (~> 2.2, >= 2.2.2) - railties (5.2.1) - actionpack (= 5.2.1) - activesupport (= 5.2.1) - method_source - rake (>= 0.8.7) - thor (>= 0.19.0, < 2.0) - rainbow (3.0.0) - rake (12.3.1) - rb-fsevent (0.10.2) - rb-inotify (0.9.10) - ffi (>= 0.5.0, < 2) - react-rails (2.4.5) - babel-transpiler (>= 0.7.0) - connection_pool - execjs - railties (>= 3.2) - tilt - redcarpet (3.3.4) - redis (3.3.5) - rspec (3.7.0) - rspec-core (~> 3.7.0) - rspec-expectations (~> 3.7.0) - rspec-mocks (~> 3.7.0) - rspec-core (3.7.0) - rspec-support (~> 3.7.0) - rspec-expectations (3.7.0) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.7.0) - rspec-mocks (3.7.0) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.7.0) - rspec-rails (3.7.2) - actionpack (>= 3.0) - activesupport (>= 3.0) - railties (>= 3.0) - rspec-core (~> 3.7.0) - rspec-expectations (~> 3.7.0) - rspec-mocks (~> 3.7.0) - rspec-support (~> 3.7.0) - rspec-support (3.7.0) - rspec_api_documentation (6.1.0) - activesupport (>= 3.0.0) - mustache (~> 1.0, >= 0.99.4) - rspec (~> 3.0) - rspec_junit_formatter (0.3.0) - rspec-core (>= 2, < 4, != 2.12.0) - rubocop (0.72.0) - jaro_winkler (~> 1.5.1) - parallel (~> 1.10) - parser (>= 2.6) - rainbow (>= 2.2.2, < 4.0) - ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 1.7) - ruby-progressbar (1.10.1) - rubyzip (1.2.1) - safe_yaml (1.0.5) - sass (3.5.3) - sass-listen (~> 4.0.0) - sass-listen (4.0.0) - rb-fsevent (~> 0.9, >= 0.9.4) - rb-inotify (~> 0.9, >= 0.9.7) - sass-rails (5.0.7) - railties (>= 4.0.0, < 6) - sass (~> 3.1) - sprockets (>= 2.8, < 4.0) - sprockets-rails (>= 2.0, < 4.0) - tilt (>= 1.1, < 3) - sawyer (0.7.0) - addressable (>= 2.3.5, < 2.5) - faraday (~> 0.8, < 0.10) - scout_apm (2.4.19) - selenium-webdriver (3.8.0) - childprocess (~> 0.5) - rubyzip (~> 1.0) - semantic_range (2.3.0) - shoulda-matchers (3.1.2) - activesupport (>= 4.0.0) - sidekiq (5.0.5) - concurrent-ruby (~> 1.0) - connection_pool (~> 2.2, >= 2.2.0) - rack-protection (>= 1.5.0) - redis (>= 3.3.4, < 5) - simplecov (0.19.0) - docile (~> 1.1) - simplecov-html (~> 0.11) - simplecov-html (0.12.3) - solid_use_case (2.2.0) - deterministic (~> 0.6.0) - sprockets (3.7.1) - concurrent-ruby (~> 1.0) - rack (> 1, < 3) - sprockets-rails (3.2.1) - actionpack (>= 4.0) - activesupport (>= 4.0) - sprockets (>= 3.0.0) - stackprof (0.2.12) - statsd-ruby (1.4.0) - temple (0.8.0) - terminal-table (1.8.0) - unicode-display_width (~> 1.1, >= 1.1.1) - thor (0.19.4) - thread_safe (0.3.6) - tilt (2.0.8) - timecop (0.9.1) - ts_routes (1.0.1) - railties (>= 5.0) - tzinfo (1.2.5) - thread_safe (~> 0.1) - uglifier (4.0.2) - execjs (>= 0.3.0, < 3) - underscore-rails (1.8.3) - unicode-display_width (1.6.0) - vcr (4.0.0) - webmock (3.6.0) - addressable (>= 2.3.6) - crack (>= 0.3.2) - hashdiff (>= 0.4.0, < 2.0.0) - webpacker (5.2.1) - activesupport (>= 5.2) - rack-proxy (>= 0.6.1) - railties (>= 5.2) - semantic_range (>= 2.3.0) - websocket-driver (0.7.0) - websocket-extensions (>= 0.1.0) - websocket-extensions (0.1.3) - xpath (2.1.0) - nokogiri (~> 1.3) - zip-zip (0.3) - rubyzip (>= 1.0.0) - -PLATFORMS - ruby - -DEPENDENCIES - analytics-ruby (~> 2.0.0) - apitome - aws-sdk (~> 2.6.5) - barnes - better_errors - binding_of_caller - block_parser! - bootsnap (>= 1.1.0) - bootstrap (= 4.0.0) - browser - byebug - capybara - database_cleaner - dotenv-rails - dry-validation (~> 0.12.2) - factory_bot_rails - flamegraph - font-awesome-rails - foreman - github_url (= 0.2.1) - gitlab - haml - honeybadger (~> 3.1) - httparty - jquery-rails - js-routes - json_spec - jwt - letter_opener - mathjax-rails - memory_profiler - octokit - overcommit - pagy - pg (~> 0.18) - puma (~> 3.12.0) - pundit - rack-attack - rack-mini-profiler - rails (~> 5.2.1) - rails-controller-testing - react-rails (= 2.4.5) - redis (~> 3.0) - rspec-rails - rspec_api_documentation - rspec_junit_formatter - rubocop - rubyzip (>= 1.0.0) - sass-rails (~> 5.0) - scout_apm - selenium-webdriver - shoulda-matchers - sidekiq - simplecov - solid_use_case (~> 2.2.0) - stackprof - timecop - ts_routes - tzinfo-data - uglifier (>= 1.3.0) - underscore-rails (= 1.8.3) - vcr - webmock - webpacker (~> 5.2.1) - zip-zip - -RUBY VERSION - ruby 2.6.6p146 - -BUNDLED WITH - 2.1.4 diff --git a/Gemfile.outdated b/Gemfile.outdated deleted file mode 100644 index 5a1c8bd..0000000 --- a/Gemfile.outdated +++ /dev/null @@ -1,142 +0,0 @@ -Fetching gem metadata from https://rubygems.org/......... -Fetching gem metadata from https://rubygems.org/. -Resolving dependencies.......... - -Outdated gems included in the bundle: - * actioncable (newest 6.0.3.4, installed 5.2.1) - * actionmailer (newest 6.0.3.4, installed 5.2.1) - * actionpack (newest 6.0.3.4, installed 5.2.1) - * actionview (newest 6.0.3.4, installed 5.2.1) - * activejob (newest 6.0.3.4, installed 5.2.1) - * activemodel (newest 6.0.3.4, installed 5.2.1) - * activerecord (newest 6.0.3.4, installed 5.2.1) - * activestorage (newest 6.0.3.4, installed 5.2.1) - * activesupport (newest 6.0.3.4, installed 5.2.1) - * addressable (newest 2.7.0, installed 2.4.0) - * analytics-ruby (newest 2.2.8, installed 2.0.13, requested ~> 2.0.0) in group "default" - * ast (newest 2.4.1, installed 2.4.0) - * autoprefixer-rails (newest 10.0.1.0, installed 7.2.5) - * aws-sdk (newest 3.0.1, installed 2.6.50, requested ~> 2.6.5) in group "default" - * aws-sdk-core (newest 3.109.1, installed 2.6.50) - * aws-sdk-resources (newest 3.84.0, installed 2.6.50) - * aws-sigv4 (newest 1.2.2, installed 1.0.2) - * barnes (newest 0.0.8, installed 0.0.7) in group "default" - * better_errors (newest 2.8.3, installed 2.5.0) in group "development" - * bootsnap (newest 1.4.8, installed 1.3.1) in group "default" - * bootstrap (newest 4.5.2, installed 4.0.0, requested = 4.0.0) in group "default" - * browser (newest 5.1.0, installed 2.5.2) in group "default" - * builder (newest 3.2.4, installed 3.2.3) - * byebug (newest 11.1.3, installed 9.1.0) in groups "development, test" - * capybara (newest 3.33.0, installed 2.16.1) in group "test" - * childprocess (newest 4.0.0, installed 0.8.0) - * coderay (newest 1.1.3, installed 1.1.2) - * concurrent-ruby (newest 1.1.7, installed 1.1.5) - * connection_pool (newest 2.2.3, installed 2.2.1) - * crack (newest 0.4.4, installed 0.4.3) - * crass (newest 1.0.6, installed 1.0.4) - * database_cleaner (newest 1.8.5, installed 1.6.2) in group "test" - * deterministic (newest 0.16.0, installed 0.6.0) - * diff-lcs (newest 1.4.4, installed 1.3) - * dotenv (newest 2.7.6, installed 2.5.0) - * dotenv-rails (newest 2.7.6, installed 2.5.0) in group "default" - * dry-configurable (newest 0.11.6, installed 0.7.0) - * dry-container (newest 0.7.2, installed 0.6.0) - * dry-core (newest 0.4.9, installed 0.4.7) - * dry-equalizer (newest 0.3.0, installed 0.2.1) - * dry-inflector (newest 0.2.0, installed 0.1.2) - * dry-logic (newest 1.0.8, installed 0.4.2) - * dry-types (newest 1.4.0, installed 0.13.2) - * dry-validation (newest 1.5.6, installed 0.12.2, requested ~> 0.12.2) in group "default" - * erubi (newest 1.9.0, installed 1.7.1) - * factory_bot (newest 6.1.0, installed 4.8.2) - * factory_bot_rails (newest 6.1.0, installed 4.8.2) in groups "development, test" - * faraday (newest 1.0.1, installed 0.9.2) - * ffi (newest 1.13.1, installed 1.9.18) - * font-awesome-rails (newest 4.7.0.5, installed 4.7.0.4) in group "default" - * foreman (newest 0.87.2, installed 0.84.0) in group "development" - * github-markup (newest 3.0.4, installed 1.6.1) - * gitlab (newest 4.16.1, installed 4.14.1) in group "default" - * globalid (newest 0.4.2, installed 0.4.1) - * haml (newest 5.2.0, installed 5.0.4) in group "default" - * hashdiff (newest 1.0.1, installed 0.4.0) - * honeybadger (newest 4.7.2, installed 3.2.0, requested ~> 3.1) in group "default" - * httparty (newest 0.18.1, installed 0.15.6) in group "default" - * i18n (newest 1.8.5, installed 1.6.0) - * iniparse (newest 1.5.0, installed 1.4.4) - * jaro_winkler (newest 1.5.4, installed 1.5.3) - * jmespath (newest 1.4.0, installed 1.3.1) - * jquery-rails (newest 4.4.0, installed 4.3.1) in group "default" - * js-routes (newest 1.4.9, installed 1.4.2) in group "default" - * kramdown (newest 2.3.0, installed 2.1.0) - * launchy (newest 2.5.0, installed 2.4.3) - * loofah (newest 2.7.0, installed 2.2.2) - * mail (newest 2.7.1, installed 2.7.0) - * marcel (newest 0.3.3, installed 0.3.2) - * memory_profiler (newest 0.9.14, installed 0.9.12) in group "default" - * method_source (newest 1.0.0, installed 0.9.0) - * mimemagic (newest 0.3.5, installed 0.3.2) - * mini_mime (newest 1.0.2, installed 1.0.0) - * mini_portile2 (newest 2.5.0, installed 2.2.0) - * minitest (newest 5.14.2, installed 5.11.3) - * msgpack (newest 1.3.3, installed 1.2.4) - * multi_json (newest 1.15.0, installed 1.13.1) - * multipart-post (newest 2.1.1, installed 2.0.0) - * mustache (newest 1.1.1, installed 1.1.0) - * nio4r (newest 2.5.4, installed 2.3.1) - * nokogiri (newest 1.10.10, installed 1.8.0) - * octokit (newest 4.18.0, installed 4.3.0) in group "default" - * overcommit (newest 0.57.0, installed 0.41.0) in group "development" - * pagy (newest 3.8.3, installed 3.7.1) in group "default" - * parallel (newest 1.19.2, installed 1.17.0) - * parser (newest 2.7.2.0, installed 2.6.3.0) - * pg (newest 1.2.3, installed 0.21.0, requested ~> 0.18) in group "default" - * popper_js (newest 1.16.0, installed 1.12.9) - * psych (newest 3.2.0, installed 2.2.4) - * puma (newest 5.0.2, installed 3.12.1, requested ~> 3.12.0) in group "default" - * pundit (newest 2.1.0, installed 1.1.0) in group "default" - * rack (newest 2.2.3, installed 2.0.3) - * rack-attack (newest 6.3.1, installed 6.2.1) in group "default" - * rack-mini-profiler (newest 2.1.0, installed 1.0.0) in group "default" - * rack-protection (newest 2.1.0, installed 2.0.0) - * rack-test (newest 1.1.0, installed 0.8.2) - * rails (newest 6.0.3.4, installed 5.2.1, requested ~> 5.2.1) in group "default" - * rails-controller-testing (newest 1.0.5, installed 1.0.2) in group "test" - * rails-html-sanitizer (newest 1.3.0, installed 1.0.4) - * railties (newest 6.0.3.4, installed 5.2.1) - * rake (newest 13.0.1, installed 12.3.1) - * rb-fsevent (newest 0.10.4, installed 0.10.2) - * rb-inotify (newest 0.10.1, installed 0.9.10) - * react-rails (newest 2.6.1, installed 2.4.5, requested = 2.4.5) in group "default" - * redcarpet (newest 3.5.0, installed 3.3.4) - * redis (newest 4.2.2, installed 3.3.5, requested ~> 3.0) in group "default" - * rspec (newest 3.9.0, installed 3.7.0) - * rspec-core (newest 3.9.3, installed 3.7.0) - * rspec-expectations (newest 3.9.2, installed 3.7.0) - * rspec-mocks (newest 3.9.1, installed 3.7.0) - * rspec-rails (newest 4.0.1, installed 3.7.2) in groups "development, test" - * rspec-support (newest 3.9.3, installed 3.7.0) - * rspec_junit_formatter (newest 0.4.1, installed 0.3.0) in group "test" - * rubocop (newest 0.93.0, installed 0.72.0) in group "development" - * rubyzip (newest 2.3.0, installed 1.2.1) in group "default" - * sass (newest 3.7.4, installed 3.5.3) - * sass-rails (newest 6.0.0, installed 5.0.7, requested ~> 5.0) in group "default" - * sawyer (newest 0.8.2, installed 0.7.0) - * scout_apm (newest 2.6.9, installed 2.4.19) in group "default" - * selenium-webdriver (newest 3.142.7, installed 3.8.0) in group "test" - * shoulda-matchers (newest 4.4.1, installed 3.1.2) in group "test" - * sidekiq (newest 6.1.2, installed 5.0.5) in group "default" - * sprockets (newest 4.0.2, installed 3.7.1) - * sprockets-rails (newest 3.2.2, installed 3.2.1) - * stackprof (newest 0.2.15, installed 0.2.12) in group "default" - * temple (newest 0.8.2, installed 0.8.0) - * thor (newest 1.0.1, installed 0.19.4) - * tilt (newest 2.0.10, installed 2.0.8) - * ts_routes (newest 1.0.3, installed 1.0.1) in group "default" - * tzinfo (newest 2.0.2, installed 1.2.5) - * uglifier (newest 4.2.0, installed 4.0.2) in group "default" - * unicode-display_width (newest 1.7.0, installed 1.6.0) - * vcr (newest 6.0.0, installed 4.0.0) in group "test" - * webmock (newest 3.9.1, installed 3.6.0) in group "test" - * websocket-driver (newest 0.7.3, installed 0.7.0) - * websocket-extensions (newest 0.1.5, installed 0.1.3) - * xpath (newest 3.2.0, installed 2.1.0) diff --git a/app/assets/stylesheets/components/_modal.scss b/app/assets/stylesheets/components/_modal.scss index 56d47f4..91a7560 100644 --- a/app/assets/stylesheets/components/_modal.scss +++ b/app/assets/stylesheets/components/_modal.scss @@ -124,7 +124,7 @@ textarea { resize: none; - @extend input[type="text"]; + @extend input, [type="text"]; padding: 8px 16px; &.modal__input--large { @@ -192,4 +192,4 @@ .display-none { display: none; -} \ No newline at end of file +} diff --git a/spec/factories.rb b/spec/factories.rb index 6691672..c99384c 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -1,52 +1,52 @@ FactoryBot.define do factory :pairing do - title "PAIR" - size 2 - groups "{}" + title { "PAIR" } + size { 2 } + groups { "{}" } end factory :content_visibility do - cohort_id nil - content_type "Standard" - content_uid "MyString" - visibility_type "hidden" + cohort_id { nil } + content_type { "Standard" } + content_uid { "MyString" } + visibility_type { "hidden" } end - + factory :user do sequence(:uid) { SecureRandom.hex } sequence(:email) { |n| "#{[first_name, last_name].join(' ').gsub(/\s+/, '.').downcase}#{n}@gmail.com" } - first_name "Secret" - last_name "Spy" + first_name { "Secret" } + last_name { "Spy" } trait :admin do - roles [User::ROLES[:admin]] + roles { [User::ROLES[:admin]] } end trait :product_admin do - roles [User::ROLES[:admin], User::ROLES[:product_admin]] + roles { [User::ROLES[:admin], User::ROLES[:product_admin]] } end trait :blocks_manager do - roles [User::ROLES[:blocks_manager]] + roles { [User::ROLES[:blocks_manager]] } end end factory :block do sequence(:title) { "block-#{SecureRandom.hex}" } - sync_errors [] - org "gSchool" - origin "github.com" + sync_errors { [] } + org { "gSchool" } + origin { "github.com" } sequence(:repo_name) { "react-block-#{SecureRandom.hex}" } end factory :release do block - notes "Note: notes" - branch_name "master" + notes { "Note: notes" } + branch_name { "master" } github_sha { SecureRandom.hex } trait :pending do - state Release::STATES[:pending] + state { Release::STATES[:pending] } end end @@ -56,27 +56,27 @@ FactoryBot.define do trait :comment do association :subject, factory: :submitted_challenge_answer - name Activity::NAMES[:comment_created] - content "This is a comment on a submitted challenge answer." + name { Activity::NAMES[:comment_created] } + content { "This is a comment on a submitted challenge answer." } end trait :checkpoint_resubmitted do - name Activity::NAMES[:checkpoint_submission_resubmitted] + name { Activity::NAMES[:checkpoint_submission_resubmitted] } end trait :checkpoint_submission_comment do association :subject, factory: :checkpoint_submission - name Activity::NAMES[:comment_created] - content "This is a comment on a checkpoint submission." + name { Activity::NAMES[:comment_created] } + content { "This is a comment on a checkpoint submission." } end end factory :standard do release uid { SecureRandom.hex } - title "Some Standard" - description "This is a sample standard." - success_criteria ["Success 1", "Success 2"] + title { "Some Standard" } + description { "This is a sample standard." } + success_criteria { ["Success 1", "Success 2"] } end factory :performance do @@ -84,14 +84,14 @@ FactoryBot.define do standard user association :updator, factory: :user - score 1 + score { 1 } end factory :notification do - tagline "Notification tagline" - title "Notification title" - url "http://www.google.com" - description "Notification description" + tagline { "Notification tagline" } + title { "Notification title" } + url { "http://www.google.com" } + description { "Notification description" } user trait :read do @@ -104,20 +104,20 @@ FactoryBot.define do lesson sequence(:path) { "#{SecureRandom.hex}.md" } sequence(:position) { |n| n } - html "

    this is some html

    check out this paragraph

    " + html { "

    this is some html

    check out this paragraph

    " } title { SecureRandom.hex } uid { SecureRandom.hex } trait :checkpoint do - content_file_type ContentFile::TYPES[:checkpoint] + content_file_type { ContentFile::TYPES[:checkpoint] } end trait :lesson do - content_file_type ContentFile::TYPES[:lesson] + content_file_type { ContentFile::TYPES[:lesson] } end trait :resource do - content_file_type ContentFile::TYPES[:resource] + content_file_type { ContentFile::TYPES[:resource] } end end @@ -125,30 +125,30 @@ FactoryBot.define do content_file uid { SecureRandom.hex } challenge_type { Challenge::TYPES[:project] } - title "do some work" - explanation "

    Daddy wants you take a load of shine up to a man near Harlan!

    " - release_id nil + title { "do some work" } + explanation { "

    Daddy wants you take a load of shine up to a man near Harlan!

    " } + release_id { nil } topics {} sequence(:position) { |n| n } trait :multiple_choice do challenge_type { Challenge::TYPES[:multiple_choice] } - title "People Skills" - answer '`Peter Gr"unde`' + title { "People Skills" } + answer { '`Peter Gr"unde`' } end trait :local_snippet do challenge_type { Challenge::TYPES[:local_snippet] } - title "Local JS Test" - answer '`foo()`' + title { "Local JS Test" } + answer { '`foo()`' } end trait :sql do challenge_type { Challenge::TYPES[:code_snippet] } - language "sql" - title "Sql Test" - data_path '/test.sql' - tests "SELECT Foo FROM Bar" + language { "sql" } + title { "Sql Test" } + data_path { '/test.sql' } + tests { "SELECT Foo FROM Bar" } end end @@ -156,23 +156,23 @@ FactoryBot.define do challenge user cohort - status SubmittedChallengeAnswer::STATUSES[:correct] - answer "some answer" + status { SubmittedChallengeAnswer::STATUSES[:correct] } + answer { "some answer" } end factory :cohort do uid { SecureRandom.hex } - product_type "Some Product Type" - name "Some Really Long Unwieldy Title" + product_type { "Some Product Type" } + name { "Some Really Long Unwieldy Title" } sequence(:label) { |n| "00-#{n}-WD-DP" } - mode "Mastery" + mode { "Mastery" } trait :enterprise do - product_type "Enterprise" + product_type { "Enterprise" } end trait :deleted do - deleted_at DateTime.current + deleted_at { DateTime.current } end end @@ -180,9 +180,9 @@ FactoryBot.define do cohort user content_file_uid { SecureRandom.hex } - state CheckpointSubmission::STATES[:needs_review] - total_points 1 - correct_points 1 + state { CheckpointSubmission::STATES[:needs_review] } + total_points { 1 } + correct_points { 1 } end factory :cohort_release do @@ -196,11 +196,11 @@ FactoryBot.define do user trait :student do - roles [] + roles { [] } end trait :instructor do - roles [CohortUser::ROLES[:instructor]] + roles { [CohortUser::ROLES[:instructor]] } end end @@ -220,16 +220,16 @@ FactoryBot.define do end factory :section do - title "Test Section" + title { "Test Section" } cohort { create(:cohort) } sequence(:position) { |n| n } end factory :resync_job_result do - type "ResyncJobResult" - status "success" + type { "ResyncJobResult" } + status { "success" } edges { { cohort_id: create(:cohort).id } } - data ( { course_config_url: 'https://github.com/gSchool/test-block/config.yml' } ) + data { ( { course_config_url: 'https://github.com/gSchool/test-block/config.yml' } ) } end # Cannot for the life of me figure out why this is breaking so many things diff --git a/spec/features/cohorts/student_progress_spec.rb b/spec/features/cohorts/student_progress_spec.rb index 7f251f0..040aeb8 100644 --- a/spec/features/cohorts/student_progress_spec.rb +++ b/spec/features/cohorts/student_progress_spec.rb @@ -40,7 +40,7 @@ feature "Instructor viewing student progress" do rows = all(".progress-row") within(rows[0]) do expect(page).to have_content(student_2.full_name) - expect(page).to have_content("0% 0% 100%") + expect(page).to have_content("0%\n0%\n100%") within(".cell.mastery-progress") do expect(page).to have_content("1 Standards Scored") end @@ -48,7 +48,7 @@ feature "Instructor viewing student progress" do end within(rows[1]) do expect(page).to have_content(student_3.full_name) - expect(page).to have_content("0% 100% 0%") + expect(page).to have_content("0%\n100%\n0%") within(".cell.mastery-progress") do expect(page).to have_content("1 Standards Scored") end @@ -56,7 +56,7 @@ feature "Instructor viewing student progress" do end within(rows[2]) do expect(page).to have_content(student_1.full_name) - expect(page).to have_content("50% 50% 0%") + expect(page).to have_content("50%\n50%\n0%") within(".cell.mastery-progress") do expect(page).to have_content("2 Standards Scored") end diff --git a/spec/features/content_files/checkpoint_assessments_spec.rb b/spec/features/content_files/checkpoint_assessments_spec.rb index 95aefed..2796930 100644 --- a/spec/features/content_files/checkpoint_assessments_spec.rb +++ b/spec/features/content_files/checkpoint_assessments_spec.rb @@ -488,7 +488,7 @@ describe "Viewing checkpoints", js: true do avatars = all(".user-avatar") expect(page).to have_content ('Clear Partner') click_button("Clear Partner") - expect(avatars.size).to eq 0 + expect(avatars.size).to eq 1 end end diff --git a/spec/features/content_files/checkpoint_submissions_spec.rb b/spec/features/content_files/checkpoint_submissions_spec.rb index 7ef9620..8bb049b 100644 --- a/spec/features/content_files/checkpoint_submissions_spec.rb +++ b/spec/features/content_files/checkpoint_submissions_spec.rb @@ -23,7 +23,7 @@ describe "checkpoint submissions" do user: student, checkpoint_submission: checkpoint_submission, created_at: 1.day.ago, - answer: "human answer", + answer: "human answer", points: 1 )} @@ -150,9 +150,9 @@ describe "checkpoint submissions" do within ".standard-topics-rollups" do # displays topics and percentage rollups - expect(page).to have_content("NEAT 100%") - expect(page).to have_content("COOL 100%") - expect(page).to have_content("MATH 100%") + expect(page).to have_content("NEAT 100%") + expect(page).to have_content("COOL 100%") + expect(page).to have_content("MATH 100%") end end diff --git a/spec/features/content_files/view_feature_spec.rb b/spec/features/content_files/view_feature_spec.rb index 87bdec6..883d9bc 100644 --- a/spec/features/content_files/view_feature_spec.rb +++ b/spec/features/content_files/view_feature_spec.rb @@ -1742,7 +1742,7 @@ describe "Viewing content files", js: true do visit content_file_path(cohort, release.block, content_file.path) within(".challenge-count") do - expect(page).to have_content("1 Question") + expect(page).to have_content("1\nQuestion") end within(".checkpoint-landing-summary") do diff --git a/spec/models/performance_spec.rb b/spec/models/performance_spec.rb index 9a5b1cd..ba91d0b 100644 --- a/spec/models/performance_spec.rb +++ b/spec/models/performance_spec.rb @@ -43,7 +43,12 @@ describe Performance do four_score.save expect(four_score.errors[:score]).to include("is not included in the list") - valid_score = build(:performance, score: 2) + user = build(:user) + cohort = build(:cohort, user_id: user.id) + standard = build(:standard) + block = build(:block) + + valid_score = build(:performance, cohort: cohort, user: user, standard: standard, block: block, score: 2) expect(valid_score).to be_valid end end diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb index b0efa6f..c1a78c6 100644 --- a/spec/models/release_spec.rb +++ b/spec/models/release_spec.rb @@ -6,21 +6,22 @@ describe Release do describe "validations" do it { is_expected.to validate_presence_of(:block) } it { is_expected.to validate_presence_of(:branch_name) } + it { is_expected.to validate_presence_of(:github_sha) } context "when the branch is default master" do it { should_not validate_uniqueness_of(:branch_name) } end context "when the branch is something other than master" do - let(:release) { build(:release, branch_name: "test-branch") } + let(:release) { create(:release, branch_name: "test-branch") } context "and there is another release with the same branch name attached to the block" do it "should validate the uniqueness of the branch name in concert with the github sha" do expect(release.valid?).to be true - create(:release, block: release.block, branch_name: "test-branch", github_sha: "somethingelse") + create(:release, block: release.block, branch_name: "new-branch", github_sha: "somethingelse") expect(release.valid?).to be true - create(:release, block: release.block, branch_name: "test-branch", github_sha: release.github_sha) - expect(release.valid?).to be false + rel = build(:release, block: release.block, branch_name: "new-branch", github_sha: "somethingelse") + expect(rel.valid?).to be false end end -- GitLab From 2611ce0e2653c45cc5a093c46df42f754ccc4ef9 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Sat, 10 Oct 2020 10:55:32 -1000 Subject: [PATCH 148/283] Update gems for block parser --- Gemfile.lock | 4 +- gems/block-parser/Gemfile.lock | 57 ++++++++++--------- gems/block-parser/block_parser.gemspec | 14 ++--- .../cohorts/users/challenges_feature_spec.rb | 6 +- 4 files changed, 43 insertions(+), 38 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 0a1bc01..20cbf32 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,7 +2,7 @@ PATH remote: gems/block-parser specs: block_parser (0.1.0) - activemodel (> 4.2) + activemodel (> 5.2) github-markdown (= 0.6.9) github-markup (= 1.6.1) github_url (= 0.2.1) @@ -11,7 +11,7 @@ PATH octokit (= 4.3.0) psych (= 2.2.4) redcarpet (= 3.3.4) - rspec_junit_formatter (> 0.2.3) + rspec_junit_formatter (>= 0.4.1) GEM remote: https://rubygems.org/ diff --git a/gems/block-parser/Gemfile.lock b/gems/block-parser/Gemfile.lock index f077409..d0bc97f 100644 --- a/gems/block-parser/Gemfile.lock +++ b/gems/block-parser/Gemfile.lock @@ -2,7 +2,7 @@ PATH remote: . specs: block_parser (0.1.0) - activemodel (> 4.2) + activemodel (> 5.2) github-markdown (= 0.6.9) github-markup (= 1.6.1) github_url (= 0.2.1) @@ -11,24 +11,24 @@ PATH octokit (= 4.3.0) psych (= 2.2.4) redcarpet (= 3.3.4) - rspec_junit_formatter (> 0.2.3) + rspec_junit_formatter (>= 0.4.1) GEM remote: https://rubygems.org/ specs: - activemodel (6.0.3.1) - activesupport (= 6.0.3.1) - activesupport (6.0.3.1) + activemodel (6.0.3.4) + activesupport (= 6.0.3.4) + activesupport (6.0.3.4) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) zeitwerk (~> 2.2, >= 2.2.2) addressable (2.4.0) - ast (2.4.0) - byebug (9.1.0) - concurrent-ruby (1.1.6) - diff-lcs (1.3) + ast (2.4.1) + byebug (11.1.3) + concurrent-ruby (1.1.7) + diff-lcs (1.4.4) faraday (0.9.2) multipart-post (>= 1.2, < 3) github-markdown (0.6.9) @@ -37,35 +37,36 @@ GEM gitlab (4.14.1) httparty (~> 0.14, >= 0.14.0) terminal-table (~> 1.5, >= 1.5.1) - httparty (0.18.0) + httparty (0.18.1) mime-types (~> 3.0) multi_xml (>= 0.5.2) - i18n (1.8.2) + i18n (1.8.5) concurrent-ruby (~> 1.0) mime-types (3.3.1) mime-types-data (~> 3.2015) mime-types-data (3.2020.0512) mini_portile2 (2.2.0) - minitest (5.14.1) + minitest (5.14.2) multi_xml (0.6.0) multipart-post (2.1.1) nokogiri (1.8.0) mini_portile2 (~> 2.2.0) octokit (4.3.0) sawyer (~> 0.7.0, >= 0.5.3) - parallel (1.19.1) - parser (2.7.1.2) - ast (~> 2.4.0) + parallel (1.19.2) + parser (2.7.2.0) + ast (~> 2.4.1) psych (2.2.4) rainbow (3.0.0) - rake (10.5.0) + rake (13.0.1) redcarpet (3.3.4) + regexp_parser (1.8.1) rexml (3.2.4) rspec (3.9.0) rspec-core (~> 3.9.0) rspec-expectations (~> 3.9.0) rspec-mocks (~> 3.9.0) - rspec-core (3.9.2) + rspec-core (3.9.3) rspec-support (~> 3.9.3) rspec-expectations (3.9.2) diff-lcs (>= 1.2.0, < 2.0) @@ -76,13 +77,17 @@ GEM rspec-support (3.9.3) rspec_junit_formatter (0.4.1) rspec-core (>= 2, < 4, != 2.12.0) - rubocop (0.83.0) + rubocop (0.93.0) parallel (~> 1.10) - parser (>= 2.7.0.1) + parser (>= 2.7.1.5) rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8) rexml + rubocop-ast (>= 0.6.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 2.0) + rubocop-ast (0.7.1) + parser (>= 2.7.1.5) ruby-progressbar (1.10.1) sawyer (0.7.0) addressable (>= 2.3.5, < 2.5) @@ -93,18 +98,18 @@ GEM tzinfo (1.2.7) thread_safe (~> 0.1) unicode-display_width (1.7.0) - zeitwerk (2.3.0) + zeitwerk (2.4.0) PLATFORMS ruby DEPENDENCIES block_parser! - bundler (~> 1.15) - byebug (= 9.1.0) - rake (~> 10.0) - rspec (~> 3.0) - rubocop (> 0.72) + bundler (~> 2.0) + byebug (= 11.1.3) + rake (~> 13.0) + rspec (~> 3.8) + rubocop (>= 0.93) BUNDLED WITH - 1.17.2 + 2.1.4 diff --git a/gems/block-parser/block_parser.gemspec b/gems/block-parser/block_parser.gemspec index 5c84156..481d6f1 100644 --- a/gems/block-parser/block_parser.gemspec +++ b/gems/block-parser/block_parser.gemspec @@ -26,13 +26,13 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^bin/}) { |f| f[3..-1] } spec.require_paths = ["lib"] - spec.add_development_dependency "bundler", "~> 1.15" - spec.add_development_dependency "byebug", "9.1.0" - spec.add_development_dependency "rake", "~> 10.0" - spec.add_development_dependency "rspec", "~> 3.0" - spec.add_development_dependency "rubocop", "> 0.72" + spec.add_development_dependency "bundler", "~> 2.0" + spec.add_development_dependency "byebug", "11.1.3" + spec.add_development_dependency "rake", "~> 13.0" + spec.add_development_dependency "rspec", "~> 3.8" + spec.add_development_dependency "rubocop", ">= 0.93" - spec.add_dependency "activemodel", "> 4.2" + spec.add_dependency "activemodel", "> 5.2" spec.add_dependency "github-markdown", "0.6.9" spec.add_dependency "github-markup", "1.6.1" spec.add_dependency "github_url", "0.2.1" @@ -41,5 +41,5 @@ Gem::Specification.new do |spec| spec.add_dependency "octokit", "4.3.0" spec.add_dependency "psych", "2.2.4" spec.add_dependency "redcarpet", "3.3.4" - spec.add_dependency "rspec_junit_formatter", "> 0.2.3" + spec.add_dependency "rspec_junit_formatter", ">= 0.4.1" end diff --git a/spec/features/cohorts/users/challenges_feature_spec.rb b/spec/features/cohorts/users/challenges_feature_spec.rb index 0ca2b3a..f72a6d9 100644 --- a/spec/features/cohorts/users/challenges_feature_spec.rb +++ b/spec/features/cohorts/users/challenges_feature_spec.rb @@ -293,7 +293,7 @@ describe "Challenges" do within(".challenge-timeline") do expect(page).to have_css("li", count: 2) - expect(page).to have_content(submitted_challenge_answer_3.created_at.localtime.strftime("%B #{submitted_challenge_answer_3.created_at.localtime.day.ordinalize} %Y at %l:%M%P").to_s) + expect(page).to have_content(submitted_challenge_answer_3.created_at.localtime.strftime("%B #{submitted_challenge_answer_3.created_at.localtime.day.ordinalize} %Y at %I:%M%P").to_s) expect(page).to have_css("div.forward.disabled") expect(find("div.forward svg use").native["xlink:href"]).to eq("/assets/images/svg/svg-sprite-av-symbol.svg#ic_fast_forward_24px") @@ -305,7 +305,7 @@ describe "Challenges" do find("div.rewind").click within(".challenge-timeline") do - expect(page).to have_content(submitted_challenge_answer_1.created_at.localtime.strftime("%B #{submitted_challenge_answer_1.created_at.localtime.day.ordinalize} %Y at %l:%M%P").to_s) + expect(page).to have_content(submitted_challenge_answer_1.created_at.localtime.strftime("%B #{submitted_challenge_answer_1.created_at.localtime.day.ordinalize} %Y at %I:%M%P").to_s) expect(page).to have_css("div.rewind.disabled") expect(page).to have_css("#submission-1.highlight") end @@ -330,7 +330,7 @@ describe "Challenges" do within(".challenge-timeline") do expect(page).to have_css("li", count: 2) - expect(page).to have_content(submitted_challenge_answer_3.created_at.localtime.strftime("%B #{submitted_challenge_answer_3.created_at.localtime.day.ordinalize} %Y at %l:%M%P").to_s) + expect(page).to have_content(submitted_challenge_answer_3.created_at.localtime.strftime("%B #{submitted_challenge_answer_3.created_at.localtime.day.ordinalize} %Y at %I:%M%P").to_s) expect(page).to have_css("div.forward.disabled") expect(find("div.forward svg use").native["xlink:href"]).to eq("/assets/images/svg/svg-sprite-av-symbol.svg#ic_fast_forward_24px") -- GitLab From 9e34ce7ec6b553bf87e441ea1c0b60e7b7ed2a14 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Sat, 10 Oct 2020 21:36:57 -1000 Subject: [PATCH 149/283] Updated several gems --- Gemfile | 28 +- Gemfile.lock | 1014 ++++++++++++++++- .../cohorts/management_feature_spec.rb | 4 +- .../cohorts/users/challenges_feature_spec.rb | 23 +- .../checkpoint_submissions_spec.rb | 4 +- 5 files changed, 1014 insertions(+), 59 deletions(-) diff --git a/Gemfile b/Gemfile index d744d89..9c67f99 100644 --- a/Gemfile +++ b/Gemfile @@ -7,17 +7,17 @@ git_source(:github) do |repo_name| end # architecture -gem "aws-sdk", "~> 2.6.5" -gem "pg", "~> 0.18" -gem "redis", "~> 3.0" -gem "puma", "~> 3.12.0" +gem "aws-sdk" +gem "pg" +gem "redis" +gem "puma" gem "pundit" gem "httparty" gem "pagy" gem "rails", "~> 5.2.1" gem "sidekiq" gem "dotenv-rails" -gem "rubyzip", ">= 1.0.0" +gem "rubyzip" gem "zip-zip" gem "tzinfo-data", platforms: %i[mingw mswin x64_mingw jruby] gem "rack-attack" @@ -25,31 +25,31 @@ gem "rack-attack" # assets gem "ts_routes" gem "webpacker", "~> 5.2.1" -gem "bootstrap", "4.0.0" +gem "bootstrap" gem "font-awesome-rails" gem "sass-rails", "~> 5.0" -gem "uglifier", ">= 1.3.0" +gem "uglifier" # views gem "haml" gem "jquery-rails" gem "mathjax-rails" -gem "react-rails", "2.4.5" -gem "underscore-rails", "1.8.3" +gem "react-rails" +gem "underscore-rails" gem "js-routes" gem "browser" gem "apitome" # services gem 'jwt' -gem "honeybadger", "~> 3.1" -gem "github_url", "0.2.1" +gem "honeybadger" +gem "github_url" gem "gitlab" -gem "analytics-ruby", "~> 2.0.0", require: "segment/analytics" +gem "analytics-ruby", require: "segment/analytics" gem "octokit" gem "barnes" gem "scout_apm" -gem "solid_use_case", "~> 2.2.0" +gem "solid_use_case" gem "dry-validation", "~> 0.12.2" # file processing @@ -58,7 +58,7 @@ gem "dry-validation", "~> 0.12.2" gem "block_parser", path: "./gems/block-parser" # Reduces boot times through caching; required in config/boot.rb -gem "bootsnap", ">= 1.1.0" +gem "bootsnap" # performance gem "rack-mini-profiler" diff --git a/Gemfile.lock b/Gemfile.lock index 20cbf32..e5e1f23 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -58,7 +58,7 @@ GEM minitest (~> 5.1) tzinfo (~> 1.1) addressable (2.4.0) - analytics-ruby (2.0.13) + analytics-ruby (2.2.8) apitome (0.3.0) kramdown railties @@ -67,13 +67,949 @@ GEM autoprefixer-rails (10.0.1.0) execjs aws-eventstream (1.1.0) - aws-sdk (2.6.50) - aws-sdk-resources (= 2.6.50) - aws-sdk-core (2.6.50) - aws-sigv4 (~> 1.0) + aws-partitions (1.381.0) + aws-sdk (3.0.1) + aws-sdk-resources (~> 3) + aws-sdk-accessanalyzer (1.12.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-acm (1.38.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-acmpca (1.30.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-alexaforbusiness (1.43.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-amplify (1.26.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-apigateway (1.55.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-apigatewaymanagementapi (1.19.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-apigatewayv2 (1.29.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-appconfig (1.12.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-appflow (1.2.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-applicationautoscaling (1.48.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-applicationdiscoveryservice (1.33.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-applicationinsights (1.15.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-appmesh (1.31.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-appstream (1.48.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-appsync (1.36.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-athena (1.33.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-augmentedairuntime (1.10.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-autoscaling (1.47.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-autoscalingplans (1.28.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-backup (1.23.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-batch (1.39.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-braket (1.4.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-budgets (1.35.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-chime (1.37.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-cloud9 (1.29.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-clouddirectory (1.29.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-cloudformation (1.44.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-cloudfront (1.43.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-cloudhsm (1.27.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-cloudhsmv2 (1.30.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-cloudsearch (1.26.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-cloudsearchdomain (1.22.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-cloudtrail (1.29.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-cloudwatch (1.45.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-cloudwatchevents (1.38.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-cloudwatchlogs (1.38.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-codeartifact (1.4.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-codebuild (1.63.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-codecommit (1.40.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-codedeploy (1.37.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-codeguruprofiler (1.12.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-codegurureviewer (1.13.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-codepipeline (1.37.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-codestar (1.27.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-codestarconnections (1.11.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-codestarnotifications (1.8.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-cognitoidentity (1.27.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-cognitoidentityprovider (1.47.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-cognitosync (1.24.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-comprehend (1.41.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-comprehendmedical (1.23.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-computeoptimizer (1.9.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-configservice (1.53.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-connect (1.34.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-connectparticipant (1.8.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-core (3.109.1) + aws-eventstream (~> 1, >= 1.0.2) + aws-partitions (~> 1, >= 1.239.0) + aws-sigv4 (~> 1.1) jmespath (~> 1.0) - aws-sdk-resources (2.6.50) - aws-sdk-core (= 2.6.50) + aws-sdk-costandusagereportservice (1.28.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-costexplorer (1.51.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-databasemigrationservice (1.44.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-dataexchange (1.10.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-datapipeline (1.24.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-datasync (1.27.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-dax (1.27.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-detective (1.11.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-devicefarm (1.39.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-directconnect (1.37.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-directoryservice (1.34.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-dlm (1.35.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-docdb (1.25.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-dynamodb (1.55.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-dynamodbstreams (1.26.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-ebs (1.11.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-ec2 (1.200.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-ec2instanceconnect (1.11.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-ecr (1.39.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-ecs (1.70.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-efs (1.36.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-eks (1.45.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-elasticache (1.44.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-elasticbeanstalk (1.38.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-elasticinference (1.10.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-elasticloadbalancing (1.29.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-elasticloadbalancingv2 (1.53.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-elasticsearchservice (1.43.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-elastictranscoder (1.27.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-emr (1.39.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-eventbridge (1.16.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-firehose (1.35.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-fms (1.32.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-forecastqueryservice (1.10.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-forecastservice (1.11.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-frauddetector (1.13.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-fsx (1.31.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-gamelift (1.38.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-glacier (1.35.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-globalaccelerator (1.23.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-glue (1.74.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-greengrass (1.37.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-groundstation (1.14.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-guardduty (1.42.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-health (1.31.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-honeycode (1.3.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-iam (1.46.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-identitystore (1.3.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-imagebuilder (1.15.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-importexport (1.24.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv2 (~> 1.0) + aws-sdk-inspector (1.32.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-iot (1.58.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-iot1clickdevicesservice (1.26.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-iot1clickprojects (1.26.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-iotanalytics (1.34.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-iotdataplane (1.26.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-iotevents (1.20.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-ioteventsdata (1.13.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-iotjobsdataplane (1.25.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-iotsecuretunneling (1.8.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-iotsitewise (1.12.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-iotthingsgraph (1.12.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-ivs (1.5.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-kafka (1.29.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-kendra (1.14.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-kinesis (1.30.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-kinesisanalytics (1.29.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-kinesisanalyticsv2 (1.23.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-kinesisvideo (1.30.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-kinesisvideoarchivedmedia (1.29.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-kinesisvideomedia (1.26.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-kinesisvideosignalingchannels (1.8.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-kms (1.39.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-lakeformation (1.11.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-lambda (1.51.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-lambdapreview (1.24.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-lex (1.32.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-lexmodelbuildingservice (1.39.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-licensemanager (1.20.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-lightsail (1.39.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-machinelearning (1.25.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-macie (1.25.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-macie2 (1.12.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-managedblockchain (1.17.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-marketplacecatalog (1.9.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-marketplacecommerceanalytics (1.29.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-marketplaceentitlementservice (1.24.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-marketplacemetering (1.31.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-mediaconnect (1.28.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-mediaconvert (1.58.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-medialive (1.56.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-mediapackage (1.36.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-mediapackagevod (1.19.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-mediastore (1.30.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-mediastoredata (1.27.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-mediatailor (1.32.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-migrationhub (1.29.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-migrationhubconfig (1.9.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-mobile (1.24.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-mq (1.33.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-mturk (1.27.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-neptune (1.30.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-networkmanager (1.8.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-opsworks (1.30.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-opsworkscm (1.40.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-organizations (1.52.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-outposts (1.10.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-personalize (1.19.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-personalizeevents (1.14.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-personalizeruntime (1.18.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-pi (1.24.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-pinpoint (1.47.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-pinpointemail (1.24.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-pinpointsmsvoice (1.21.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-polly (1.37.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-pricing (1.24.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-qldb (1.11.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-qldbsession (1.9.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-quicksight (1.33.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-ram (1.22.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-rds (1.103.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-rdsdataservice (1.23.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-redshift (1.50.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-redshiftdataapiservice (1.2.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-rekognition (1.46.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-resourcegroups (1.32.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-resourcegroupstaggingapi (1.34.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-resources (3.84.0) + aws-sdk-accessanalyzer (~> 1) + aws-sdk-acm (~> 1) + aws-sdk-acmpca (~> 1) + aws-sdk-alexaforbusiness (~> 1) + aws-sdk-amplify (~> 1) + aws-sdk-apigateway (~> 1) + aws-sdk-apigatewaymanagementapi (~> 1) + aws-sdk-apigatewayv2 (~> 1) + aws-sdk-appconfig (~> 1) + aws-sdk-appflow (~> 1) + aws-sdk-applicationautoscaling (~> 1) + aws-sdk-applicationdiscoveryservice (~> 1) + aws-sdk-applicationinsights (~> 1) + aws-sdk-appmesh (~> 1) + aws-sdk-appstream (~> 1) + aws-sdk-appsync (~> 1) + aws-sdk-athena (~> 1) + aws-sdk-augmentedairuntime (~> 1) + aws-sdk-autoscaling (~> 1) + aws-sdk-autoscalingplans (~> 1) + aws-sdk-backup (~> 1) + aws-sdk-batch (~> 1) + aws-sdk-braket (~> 1) + aws-sdk-budgets (~> 1) + aws-sdk-chime (~> 1) + aws-sdk-cloud9 (~> 1) + aws-sdk-clouddirectory (~> 1) + aws-sdk-cloudformation (~> 1) + aws-sdk-cloudfront (~> 1) + aws-sdk-cloudhsm (~> 1) + aws-sdk-cloudhsmv2 (~> 1) + aws-sdk-cloudsearch (~> 1) + aws-sdk-cloudsearchdomain (~> 1) + aws-sdk-cloudtrail (~> 1) + aws-sdk-cloudwatch (~> 1) + aws-sdk-cloudwatchevents (~> 1) + aws-sdk-cloudwatchlogs (~> 1) + aws-sdk-codeartifact (~> 1) + aws-sdk-codebuild (~> 1) + aws-sdk-codecommit (~> 1) + aws-sdk-codedeploy (~> 1) + aws-sdk-codeguruprofiler (~> 1) + aws-sdk-codegurureviewer (~> 1) + aws-sdk-codepipeline (~> 1) + aws-sdk-codestar (~> 1) + aws-sdk-codestarconnections (~> 1) + aws-sdk-codestarnotifications (~> 1) + aws-sdk-cognitoidentity (~> 1) + aws-sdk-cognitoidentityprovider (~> 1) + aws-sdk-cognitosync (~> 1) + aws-sdk-comprehend (~> 1) + aws-sdk-comprehendmedical (~> 1) + aws-sdk-computeoptimizer (~> 1) + aws-sdk-configservice (~> 1) + aws-sdk-connect (~> 1) + aws-sdk-connectparticipant (~> 1) + aws-sdk-costandusagereportservice (~> 1) + aws-sdk-costexplorer (~> 1) + aws-sdk-databasemigrationservice (~> 1) + aws-sdk-dataexchange (~> 1) + aws-sdk-datapipeline (~> 1) + aws-sdk-datasync (~> 1) + aws-sdk-dax (~> 1) + aws-sdk-detective (~> 1) + aws-sdk-devicefarm (~> 1) + aws-sdk-directconnect (~> 1) + aws-sdk-directoryservice (~> 1) + aws-sdk-dlm (~> 1) + aws-sdk-docdb (~> 1) + aws-sdk-dynamodb (~> 1) + aws-sdk-dynamodbstreams (~> 1) + aws-sdk-ebs (~> 1) + aws-sdk-ec2 (~> 1) + aws-sdk-ec2instanceconnect (~> 1) + aws-sdk-ecr (~> 1) + aws-sdk-ecs (~> 1) + aws-sdk-efs (~> 1) + aws-sdk-eks (~> 1) + aws-sdk-elasticache (~> 1) + aws-sdk-elasticbeanstalk (~> 1) + aws-sdk-elasticinference (~> 1) + aws-sdk-elasticloadbalancing (~> 1) + aws-sdk-elasticloadbalancingv2 (~> 1) + aws-sdk-elasticsearchservice (~> 1) + aws-sdk-elastictranscoder (~> 1) + aws-sdk-emr (~> 1) + aws-sdk-eventbridge (~> 1) + aws-sdk-firehose (~> 1) + aws-sdk-fms (~> 1) + aws-sdk-forecastqueryservice (~> 1) + aws-sdk-forecastservice (~> 1) + aws-sdk-frauddetector (~> 1) + aws-sdk-fsx (~> 1) + aws-sdk-gamelift (~> 1) + aws-sdk-glacier (~> 1) + aws-sdk-globalaccelerator (~> 1) + aws-sdk-glue (~> 1) + aws-sdk-greengrass (~> 1) + aws-sdk-groundstation (~> 1) + aws-sdk-guardduty (~> 1) + aws-sdk-health (~> 1) + aws-sdk-honeycode (~> 1) + aws-sdk-iam (~> 1) + aws-sdk-identitystore (~> 1) + aws-sdk-imagebuilder (~> 1) + aws-sdk-importexport (~> 1) + aws-sdk-inspector (~> 1) + aws-sdk-iot (~> 1) + aws-sdk-iot1clickdevicesservice (~> 1) + aws-sdk-iot1clickprojects (~> 1) + aws-sdk-iotanalytics (~> 1) + aws-sdk-iotdataplane (~> 1) + aws-sdk-iotevents (~> 1) + aws-sdk-ioteventsdata (~> 1) + aws-sdk-iotjobsdataplane (~> 1) + aws-sdk-iotsecuretunneling (~> 1) + aws-sdk-iotsitewise (~> 1) + aws-sdk-iotthingsgraph (~> 1) + aws-sdk-ivs (~> 1) + aws-sdk-kafka (~> 1) + aws-sdk-kendra (~> 1) + aws-sdk-kinesis (~> 1) + aws-sdk-kinesisanalytics (~> 1) + aws-sdk-kinesisanalyticsv2 (~> 1) + aws-sdk-kinesisvideo (~> 1) + aws-sdk-kinesisvideoarchivedmedia (~> 1) + aws-sdk-kinesisvideomedia (~> 1) + aws-sdk-kinesisvideosignalingchannels (~> 1) + aws-sdk-kms (~> 1) + aws-sdk-lakeformation (~> 1) + aws-sdk-lambda (~> 1) + aws-sdk-lambdapreview (~> 1) + aws-sdk-lex (~> 1) + aws-sdk-lexmodelbuildingservice (~> 1) + aws-sdk-licensemanager (~> 1) + aws-sdk-lightsail (~> 1) + aws-sdk-machinelearning (~> 1) + aws-sdk-macie (~> 1) + aws-sdk-macie2 (~> 1) + aws-sdk-managedblockchain (~> 1) + aws-sdk-marketplacecatalog (~> 1) + aws-sdk-marketplacecommerceanalytics (~> 1) + aws-sdk-marketplaceentitlementservice (~> 1) + aws-sdk-marketplacemetering (~> 1) + aws-sdk-mediaconnect (~> 1) + aws-sdk-mediaconvert (~> 1) + aws-sdk-medialive (~> 1) + aws-sdk-mediapackage (~> 1) + aws-sdk-mediapackagevod (~> 1) + aws-sdk-mediastore (~> 1) + aws-sdk-mediastoredata (~> 1) + aws-sdk-mediatailor (~> 1) + aws-sdk-migrationhub (~> 1) + aws-sdk-migrationhubconfig (~> 1) + aws-sdk-mobile (~> 1) + aws-sdk-mq (~> 1) + aws-sdk-mturk (~> 1) + aws-sdk-neptune (~> 1) + aws-sdk-networkmanager (~> 1) + aws-sdk-opsworks (~> 1) + aws-sdk-opsworkscm (~> 1) + aws-sdk-organizations (~> 1) + aws-sdk-outposts (~> 1) + aws-sdk-personalize (~> 1) + aws-sdk-personalizeevents (~> 1) + aws-sdk-personalizeruntime (~> 1) + aws-sdk-pi (~> 1) + aws-sdk-pinpoint (~> 1) + aws-sdk-pinpointemail (~> 1) + aws-sdk-pinpointsmsvoice (~> 1) + aws-sdk-polly (~> 1) + aws-sdk-pricing (~> 1) + aws-sdk-qldb (~> 1) + aws-sdk-qldbsession (~> 1) + aws-sdk-quicksight (~> 1) + aws-sdk-ram (~> 1) + aws-sdk-rds (~> 1) + aws-sdk-rdsdataservice (~> 1) + aws-sdk-redshift (~> 1) + aws-sdk-redshiftdataapiservice (~> 1) + aws-sdk-rekognition (~> 1) + aws-sdk-resourcegroups (~> 1) + aws-sdk-resourcegroupstaggingapi (~> 1) + aws-sdk-robomaker (~> 1) + aws-sdk-route53 (~> 1) + aws-sdk-route53domains (~> 1) + aws-sdk-route53resolver (~> 1) + aws-sdk-s3 (~> 1) + aws-sdk-s3control (~> 1) + aws-sdk-s3outposts (~> 1) + aws-sdk-sagemaker (~> 1) + aws-sdk-sagemakerruntime (~> 1) + aws-sdk-savingsplans (~> 1) + aws-sdk-schemas (~> 1) + aws-sdk-secretsmanager (~> 1) + aws-sdk-securityhub (~> 1) + aws-sdk-serverlessapplicationrepository (~> 1) + aws-sdk-servicecatalog (~> 1) + aws-sdk-servicediscovery (~> 1) + aws-sdk-servicequotas (~> 1) + aws-sdk-ses (~> 1) + aws-sdk-sesv2 (~> 1) + aws-sdk-shield (~> 1) + aws-sdk-signer (~> 1) + aws-sdk-simpledb (~> 1) + aws-sdk-sms (~> 1) + aws-sdk-snowball (~> 1) + aws-sdk-sns (~> 1) + aws-sdk-sqs (~> 1) + aws-sdk-ssm (~> 1) + aws-sdk-ssoadmin (~> 1) + aws-sdk-ssooidc (~> 1) + aws-sdk-states (~> 1) + aws-sdk-storagegateway (~> 1) + aws-sdk-support (~> 1) + aws-sdk-swf (~> 1) + aws-sdk-synthetics (~> 1) + aws-sdk-textract (~> 1) + aws-sdk-timestreamquery (~> 1) + aws-sdk-timestreamwrite (~> 1) + aws-sdk-transcribeservice (~> 1) + aws-sdk-transcribestreamingservice (~> 1) + aws-sdk-transfer (~> 1) + aws-sdk-translate (~> 1) + aws-sdk-waf (~> 1) + aws-sdk-wafregional (~> 1) + aws-sdk-wafv2 (~> 1) + aws-sdk-workdocs (~> 1) + aws-sdk-worklink (~> 1) + aws-sdk-workmail (~> 1) + aws-sdk-workmailmessageflow (~> 1) + aws-sdk-workspaces (~> 1) + aws-sdk-xray (~> 1) + aws-sdk-robomaker (1.30.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-route53 (1.44.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-route53domains (1.28.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-route53resolver (1.21.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-s3 (1.83.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-kms (~> 1) + aws-sigv4 (~> 1.1) + aws-sdk-s3control (1.24.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-s3outposts (1.0.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-sagemaker (1.70.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-sagemakerruntime (1.27.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-savingsplans (1.12.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-schemas (1.10.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-secretsmanager (1.43.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-securityhub (1.35.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-serverlessapplicationrepository (1.32.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-servicecatalog (1.50.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-servicediscovery (1.31.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-servicequotas (1.11.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-ses (1.36.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-sesv2 (1.13.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-shield (1.32.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-signer (1.26.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-simpledb (1.24.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv2 (~> 1.0) + aws-sdk-sms (1.27.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-snowball (1.35.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-sns (1.33.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-sqs (1.34.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-ssm (1.93.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-ssoadmin (1.3.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-ssooidc (1.8.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-states (1.36.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-storagegateway (1.50.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-support (1.28.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-swf (1.25.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-synthetics (1.9.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-textract (1.21.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-timestreamquery (1.1.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-timestreamwrite (1.1.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-transcribeservice (1.50.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-transcribestreamingservice (1.22.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-transfer (1.27.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-translate (1.28.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-waf (1.36.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-wafregional (1.37.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-wafv2 (1.14.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-workdocs (1.28.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-worklink (1.21.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-workmail (1.31.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-workmailmessageflow (1.9.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-workspaces (1.47.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-xray (1.33.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sigv2 (1.0.1) aws-sigv4 (1.2.2) aws-eventstream (~> 1, >= 1.0.2) babel-source (5.8.35) @@ -91,10 +1027,10 @@ GEM debug_inspector (>= 0.0.1) bootsnap (1.4.8) msgpack (~> 1.0) - bootstrap (4.0.0) - autoprefixer-rails (>= 6.0.3) - popper_js (>= 1.12.9, < 2) - sass (>= 3.5.2) + bootstrap (4.5.2) + autoprefixer-rails (>= 9.1.0) + popper_js (>= 1.14.3, < 2) + sassc-rails (>= 2.0.0) browser (5.1.0) builder (3.2.4) byebug (11.1.3) @@ -176,7 +1112,7 @@ GEM temple (>= 0.8.0) tilt hashdiff (1.0.1) - honeybadger (3.3.1) + honeybadger (4.7.2) httparty (0.18.1) mime-types (~> 3.0) multi_xml (>= 0.5.2) @@ -236,10 +1172,11 @@ GEM parallel (1.19.2) parser (2.7.2.0) ast (~> 2.4.1) - pg (0.21.0) + pg (1.2.3) popper_js (1.16.0) psych (2.2.4) - puma (3.12.6) + puma (5.0.2) + nio4r (~> 2.0) pundit (2.1.0) activesupport (>= 3.0.0) rack (2.2.3) @@ -247,8 +1184,6 @@ GEM rack (>= 1.0, < 3) rack-mini-profiler (2.1.0) rack (>= 1.2.0) - rack-protection (2.1.0) - rack rack-proxy (0.6.5) rack rack-test (1.1.0) @@ -286,14 +1221,14 @@ GEM rb-fsevent (0.10.4) rb-inotify (0.10.1) ffi (~> 1.0) - react-rails (2.4.5) + react-rails (2.6.1) babel-transpiler (>= 0.7.0) connection_pool execjs railties (>= 3.2) tilt redcarpet (3.3.4) - redis (3.3.5) + redis (4.2.2) regexp_parser (1.8.1) rexml (3.2.4) rspec (3.9.0) @@ -347,6 +1282,14 @@ GEM sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) + sassc (2.4.0) + ffi (~> 1.9) + sassc-rails (2.1.2) + railties (>= 4.0.0) + sassc (>= 2.0) + sprockets (> 3.0) + sprockets-rails + tilt sawyer (0.7.0) addressable (>= 2.3.5, < 2.5) faraday (~> 0.8, < 0.10) @@ -358,11 +1301,10 @@ GEM semantic_range (2.3.0) shoulda-matchers (4.4.1) activesupport (>= 4.2.0) - sidekiq (5.2.9) - connection_pool (~> 2.2, >= 2.2.2) + sidekiq (6.1.2) + connection_pool (>= 2.2.2) rack (~> 2.0) - rack-protection (>= 1.5.0) - redis (>= 3.3.5, < 4.2) + redis (>= 4.2.0) simplecov (0.19.0) docile (~> 1.1) simplecov-html (~> 0.11) @@ -415,15 +1357,15 @@ PLATFORMS ruby DEPENDENCIES - analytics-ruby (~> 2.0.0) + analytics-ruby apitome - aws-sdk (~> 2.6.5) + aws-sdk barnes better_errors binding_of_caller block_parser! - bootsnap (>= 1.1.0) - bootstrap (= 4.0.0) + bootsnap + bootstrap browser byebug capybara @@ -434,10 +1376,10 @@ DEPENDENCIES flamegraph font-awesome-rails foreman - github_url (= 0.2.1) + github_url gitlab haml - honeybadger (~> 3.1) + honeybadger httparty jquery-rails js-routes @@ -449,33 +1391,33 @@ DEPENDENCIES octokit overcommit pagy - pg (~> 0.18) - puma (~> 3.12.0) + pg + puma pundit rack-attack rack-mini-profiler rails (~> 5.2.1) rails-controller-testing - react-rails (= 2.4.5) - redis (~> 3.0) + react-rails + redis rspec-rails rspec_api_documentation rspec_junit_formatter rubocop - rubyzip (>= 1.0.0) + rubyzip sass-rails (~> 5.0) scout_apm selenium-webdriver shoulda-matchers sidekiq simplecov - solid_use_case (~> 2.2.0) + solid_use_case stackprof timecop ts_routes tzinfo-data - uglifier (>= 1.3.0) - underscore-rails (= 1.8.3) + uglifier + underscore-rails vcr webmock webpacker (~> 5.2.1) diff --git a/spec/features/cohorts/management_feature_spec.rb b/spec/features/cohorts/management_feature_spec.rb index 4b12ce8..24a95c3 100644 --- a/spec/features/cohorts/management_feature_spec.rb +++ b/spec/features/cohorts/management_feature_spec.rb @@ -200,7 +200,9 @@ describe "Cohorts management", js: true do within ".cohortinfo" do expect(page).to have_content(cohort.name) - expect(page).to have_content(cohort.campus_name) + if cohort.campus_name + expect(page).to have_content(cohort.campus_name) + end expect(page).to have_content(cohort.starts_on.strftime("%b %e, %Y")) # expect(page).to have_link("Edit", href: "#{Rails.application.secrets.auth_url}/admin/products/#{cohort.uid}/edit") end diff --git a/spec/features/cohorts/users/challenges_feature_spec.rb b/spec/features/cohorts/users/challenges_feature_spec.rb index f72a6d9..07358e3 100644 --- a/spec/features/cohorts/users/challenges_feature_spec.rb +++ b/spec/features/cohorts/users/challenges_feature_spec.rb @@ -226,21 +226,27 @@ describe "Challenges" do within("#comment-#{comment_two_days.id}") do expect(page).to have_content(comment_two_days.content) expect(page).to have_content(instructor.full_name) - expect(page).to have_content(instructor.profile_image) + if instructor.profile_image + expect(page).to have_content(instructor.profile_image) + end expect(page).to have_content("#{comment_two_days.created_at.localtime.strftime('%A')} at ") end within("#comment-#{comment_one_day.id}") do expect(page).to have_content(comment_one_day.content) expect(page).to have_content(student.full_name) - expect(page).to have_content(student.profile_image) + if student.profile_image + expect(page).to have_content(student.profile_image) + end expect(page).to have_content("Yesterday at ") end within("#comment-#{comment_now.id}") do expect(page).to have_content(comment_now.content) expect(page).to have_content(instructor.full_name) - expect(page).to have_content(instructor.profile_image) + if instructor.profile_image + expect(page).to have_content(instructor.profile_image) + end expect(page).to have_content("Today at ") end end @@ -256,7 +262,9 @@ describe "Challenges" do within("#comment-#{Activity.last.id}") do expect(page).to have_content("this is a ") expect(page).to have_content(instructor.full_name) - expect(page).to have_content(instructor.profile_image) + if instructor.profile_image + expect(page).to have_content(instructor.profile_image) + end expect(page).to have_content("Today at ") within("code") do @@ -293,7 +301,8 @@ describe "Challenges" do within(".challenge-timeline") do expect(page).to have_css("li", count: 2) - expect(page).to have_content(submitted_challenge_answer_3.created_at.localtime.strftime("%B #{submitted_challenge_answer_3.created_at.localtime.day.ordinalize} %Y at %I:%M%P").to_s) + #expect(page).to have_content(submitted_challenge_answer_3.created_at.localtime.strftime("%B #{submitted_challenge_answer_3.created_at.localtime.day.ordinalize} %Y at %l:%M%P").to_s) + expect(page).to have_content(submitted_challenge_answer_3.created_at.localtime.strftime("%B #{submitted_challenge_answer_3.created_at.localtime.day.ordinalize} %Y at %-l:%M%P").to_s) expect(page).to have_css("div.forward.disabled") expect(find("div.forward svg use").native["xlink:href"]).to eq("/assets/images/svg/svg-sprite-av-symbol.svg#ic_fast_forward_24px") @@ -305,7 +314,7 @@ describe "Challenges" do find("div.rewind").click within(".challenge-timeline") do - expect(page).to have_content(submitted_challenge_answer_1.created_at.localtime.strftime("%B #{submitted_challenge_answer_1.created_at.localtime.day.ordinalize} %Y at %I:%M%P").to_s) + expect(page).to have_content(submitted_challenge_answer_1.created_at.localtime.strftime("%B #{submitted_challenge_answer_1.created_at.localtime.day.ordinalize} %Y at %-l:%M%P").to_s) expect(page).to have_css("div.rewind.disabled") expect(page).to have_css("#submission-1.highlight") end @@ -330,7 +339,7 @@ describe "Challenges" do within(".challenge-timeline") do expect(page).to have_css("li", count: 2) - expect(page).to have_content(submitted_challenge_answer_3.created_at.localtime.strftime("%B #{submitted_challenge_answer_3.created_at.localtime.day.ordinalize} %Y at %I:%M%P").to_s) + expect(page).to have_content(submitted_challenge_answer_3.created_at.localtime.strftime("%B #{submitted_challenge_answer_3.created_at.localtime.day.ordinalize} %Y at %-l:%M%P").to_s) expect(page).to have_css("div.forward.disabled") expect(find("div.forward svg use").native["xlink:href"]).to eq("/assets/images/svg/svg-sprite-av-symbol.svg#ic_fast_forward_24px") diff --git a/spec/features/content_files/checkpoint_submissions_spec.rb b/spec/features/content_files/checkpoint_submissions_spec.rb index 8bb049b..5e5c586 100644 --- a/spec/features/content_files/checkpoint_submissions_spec.rb +++ b/spec/features/content_files/checkpoint_submissions_spec.rb @@ -50,7 +50,9 @@ describe "checkpoint submissions" do within ".challenges" do within("#challenge_#{challenge_1.id}") do expect(page).to have_content(challenge_1.title) - expect(page).to have_content(challenge_1.answer) + if challenge_1.answer + expect(page).to have_content(challenge_1.answer) + end expect(page).to have_content("NEAT") expect(page).to have_content("COOL") expect(page).to have_content("MATH") -- GitLab From c8b66d7c2d4dd6d431487c0edb25a5a6918b152a Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Sun, 11 Oct 2020 11:42:30 -1000 Subject: [PATCH 150/283] Update webpacker --- Gemfile | 2 +- Gemfile.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index 9c67f99..f91c403 100644 --- a/Gemfile +++ b/Gemfile @@ -24,7 +24,7 @@ gem "rack-attack" # assets gem "ts_routes" -gem "webpacker", "~> 5.2.1" +gem "webpacker" gem "bootstrap" gem "font-awesome-rails" gem "sass-rails", "~> 5.0" diff --git a/Gemfile.lock b/Gemfile.lock index e5e1f23..4b888a2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1420,7 +1420,7 @@ DEPENDENCIES underscore-rails vcr webmock - webpacker (~> 5.2.1) + webpacker zip-zip RUBY VERSION -- GitLab From 95859ccaa29162aaa4814ec69ef9a6c492bb078d Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Mon, 12 Oct 2020 15:45:24 -1000 Subject: [PATCH 151/283] Rewrite course validator not to use dry-validation --- Gemfile | 2 +- Gemfile.lock | 33 ++++++++----- app/services/course_validator.rb | 82 +++++++++++++++++--------------- 3 files changed, 66 insertions(+), 51 deletions(-) diff --git a/Gemfile b/Gemfile index f91c403..b582b85 100644 --- a/Gemfile +++ b/Gemfile @@ -50,7 +50,7 @@ gem "octokit" gem "barnes" gem "scout_apm" gem "solid_use_case" -gem "dry-validation", "~> 0.12.2" +gem "dry-validation" # file processing ### We need to pass git credentials into the docker build command so we can clone the block-parser diff --git a/Gemfile.lock b/Gemfile.lock index 4b888a2..a29d286 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1068,24 +1068,33 @@ GEM concurrent-ruby (~> 1.0) dry-equalizer (0.3.0) dry-inflector (0.2.0) - dry-logic (0.4.2) - dry-container (~> 0.2, >= 0.2.6) + dry-initializer (3.0.4) + dry-logic (1.0.8) + concurrent-ruby (~> 1.0) dry-core (~> 0.2) dry-equalizer (~> 0.2) - dry-types (0.13.4) + dry-schema (1.5.5) + concurrent-ruby (~> 1.0) + dry-configurable (~> 0.8, >= 0.8.3) + dry-core (~> 0.4) + dry-equalizer (~> 0.2) + dry-initializer (~> 3.0) + dry-logic (~> 1.0) + dry-types (~> 1.4) + dry-types (1.4.0) concurrent-ruby (~> 1.0) dry-container (~> 0.3) dry-core (~> 0.4, >= 0.4.4) - dry-equalizer (~> 0.2) + dry-equalizer (~> 0.3) dry-inflector (~> 0.1, >= 0.1.2) - dry-logic (~> 0.4, >= 0.4.2) - dry-validation (0.12.3) + dry-logic (~> 1.0, >= 1.0.2) + dry-validation (1.5.6) concurrent-ruby (~> 1.0) - dry-configurable (~> 0.1, >= 0.1.3) - dry-core (~> 0.2, >= 0.2.1) + dry-container (~> 0.7, >= 0.7.1) + dry-core (~> 0.4) dry-equalizer (~> 0.2) - dry-logic (~> 0.4.2) - dry-types (~> 0.13.1) + dry-initializer (~> 3.0) + dry-schema (~> 1.5, >= 1.5.2) erubi (1.9.0) execjs (2.7.0) factory_bot (6.1.0) @@ -1229,7 +1238,7 @@ GEM tilt redcarpet (3.3.4) redis (4.2.2) - regexp_parser (1.8.1) + regexp_parser (1.8.2) rexml (3.2.4) rspec (3.9.0) rspec-core (~> 3.9.0) @@ -1371,7 +1380,7 @@ DEPENDENCIES capybara database_cleaner dotenv-rails - dry-validation (~> 0.12.2) + dry-validation factory_bot_rails flamegraph font-awesome-rails diff --git a/app/services/course_validator.rb b/app/services/course_validator.rb index 08a4d1a..67d2737 100644 --- a/app/services/course_validator.rb +++ b/app/services/course_validator.rb @@ -1,5 +1,3 @@ -require "dry-validation" - class CourseValidator include SolidUseCase @@ -69,7 +67,7 @@ class CourseValidator end end - errors = @@schema.call(contents).messages + errors = validate_course_format(contents) if errors.any? fail :course_validation_error, errors: massage_validation_errors(contents, errors) @@ -168,54 +166,62 @@ class CourseValidator errors end - @@schema = Dry::Validation.Schema do - configure do - def github_url?(value) - GitUrlService.new(url: value) - true - rescue StandardError - false - end - - def self.messages - super.merge(en: { - errors: { - no_duplicate_repos: "Duplicate github repos are not allowed", - github_url?: "is invalid" - } - }) - end + def validate_course_format(contents) + def github_url?(myurl) + GitUrlService.new(url: myurl) + true + rescue StandardError + false end - required("course").each do - # Sections - schema do - required("repos").each do - # Repos - schema do - required("url").filled(:str?, :github_url?) - end - end - required("section").filled(:str?) - end - end - - validate(no_duplicate_repos: "course") do |course| + def no_duplicate_repos?(course) seen = {} dupe = nil course.each do |section| break if dupe - section["repos"].each do |repo| - if seen[repo["url"]] - dupe = repo["url"] + section['repos'].each do |repo| + if seen[repo['url']] + dupe = repo['url'] break end - seen[repo["url"]] = true + seen[repo['url']] = true end end dupe.nil? end + + errors = {} + courses = contents['course'] + unless courses.kind_of?(Array) + errors['course'] = ["must be an array"] + return errors + end + + courses.each_with_index do |course, course_index| + unless course['section'] + errors['course'] = ['section is missing'] + return errors + end + repos = course['repos'] + unless repos.kind_of?(Array) + errors[:section_missing_repos] = { index: course_index, title: "No repos" } + return errors + end + repos.each_with_index do |repo, repo_index| + unless github_url?(repo['url']) + errors['course'] = { course_index => { "repos" => { + repo_index => { "url" => ['is invalid'] } + } } } + return errors + end + end + end + + errors[:no_duplicate_repos] = ['Duplicate github repos are not allowed'] unless no_duplicate_repos?(courses) + + errors end + end -- GitLab From 5fe2e91ac0025bac69969ec45a83cddccf39af32 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Mon, 12 Oct 2020 15:59:20 -1000 Subject: [PATCH 152/283] Remove dry-validation from Gemfile --- Gemfile | 1 - Gemfile.lock | 45 +++------------------------------------------ 2 files changed, 3 insertions(+), 43 deletions(-) diff --git a/Gemfile b/Gemfile index b582b85..6e94854 100644 --- a/Gemfile +++ b/Gemfile @@ -50,7 +50,6 @@ gem "octokit" gem "barnes" gem "scout_apm" gem "solid_use_case" -gem "dry-validation" # file processing ### We need to pass git credentials into the docker build command so we can clone the block-parser diff --git a/Gemfile.lock b/Gemfile.lock index a29d286..c572acf 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1057,44 +1057,6 @@ GEM dotenv-rails (2.7.6) dotenv (= 2.7.6) railties (>= 3.2) - dry-configurable (0.11.6) - concurrent-ruby (~> 1.0) - dry-core (~> 0.4, >= 0.4.7) - dry-equalizer (~> 0.2) - dry-container (0.7.2) - concurrent-ruby (~> 1.0) - dry-configurable (~> 0.1, >= 0.1.3) - dry-core (0.4.9) - concurrent-ruby (~> 1.0) - dry-equalizer (0.3.0) - dry-inflector (0.2.0) - dry-initializer (3.0.4) - dry-logic (1.0.8) - concurrent-ruby (~> 1.0) - dry-core (~> 0.2) - dry-equalizer (~> 0.2) - dry-schema (1.5.5) - concurrent-ruby (~> 1.0) - dry-configurable (~> 0.8, >= 0.8.3) - dry-core (~> 0.4) - dry-equalizer (~> 0.2) - dry-initializer (~> 3.0) - dry-logic (~> 1.0) - dry-types (~> 1.4) - dry-types (1.4.0) - concurrent-ruby (~> 1.0) - dry-container (~> 0.3) - dry-core (~> 0.4, >= 0.4.4) - dry-equalizer (~> 0.3) - dry-inflector (~> 0.1, >= 0.1.2) - dry-logic (~> 1.0, >= 1.0.2) - dry-validation (1.5.6) - concurrent-ruby (~> 1.0) - dry-container (~> 0.7, >= 0.7.1) - dry-core (~> 0.4) - dry-equalizer (~> 0.2) - dry-initializer (~> 3.0) - dry-schema (~> 1.5, >= 1.5.2) erubi (1.9.0) execjs (2.7.0) factory_bot (6.1.0) @@ -1267,7 +1229,7 @@ GEM rspec (~> 3.0) rspec_junit_formatter (0.4.1) rspec-core (>= 2, < 4, != 2.12.0) - rubocop (0.93.0) + rubocop (0.93.1) parallel (~> 1.10) parser (>= 2.7.1.5) rainbow (>= 2.2.2, < 4.0) @@ -1276,7 +1238,7 @@ GEM rubocop-ast (>= 0.6.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 2.0) - rubocop-ast (0.7.1) + rubocop-ast (0.8.0) parser (>= 2.7.1.5) ruby-progressbar (1.10.1) rubyzip (2.3.0) @@ -1345,7 +1307,7 @@ GEM underscore-rails (1.8.3) unicode-display_width (1.7.0) vcr (6.0.0) - webmock (3.9.1) + webmock (3.9.2) addressable (>= 2.3.6) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) @@ -1380,7 +1342,6 @@ DEPENDENCIES capybara database_cleaner dotenv-rails - dry-validation factory_bot_rails flamegraph font-awesome-rails -- GitLab From 247f8ef65ca958d376d651c7865a11a28e3656a9 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Mon, 12 Oct 2020 17:37:28 -1000 Subject: [PATCH 153/283] Refactor course_validator --- app/services/course_validator.rb | 61 ++++---------------------------- gems/block-parser/Gemfile.lock | 6 ++-- 2 files changed, 10 insertions(+), 57 deletions(-) diff --git a/app/services/course_validator.rb b/app/services/course_validator.rb index 67d2737..981dcaf 100644 --- a/app/services/course_validator.rb +++ b/app/services/course_validator.rb @@ -70,7 +70,7 @@ class CourseValidator errors = validate_course_format(contents) if errors.any? - fail :course_validation_error, errors: massage_validation_errors(contents, errors) + fail :course_validation_error, errors: errors else default_unit_visibility = contents["defaultunitvisibility"].nil? ? false : contents["defaultunitvisibility"] continue(params.merge(course: { @@ -152,20 +152,6 @@ class CourseValidator "User-Agent" => "Galvanize Forge").read end - def massage_validation_errors(contents, errors) - course = errors["course"] - if course == ["must be an array"] - return { empty_course: true } - elsif course&.is_a?(Hash) && course.keys.count == 1 - index = course.keys.first - if course[index]["repos"] == ["is missing"] - return { section_missing_repos: { title: contents["course"][index]["section"], index: index } } - end - end - - errors - end - def validate_course_format(contents) def github_url?(myurl) GitUrlService.new(url: myurl) @@ -174,53 +160,20 @@ class CourseValidator false end - def no_duplicate_repos?(course) - seen = {} - dupe = nil - course.each do |section| - break if dupe - - section['repos'].each do |repo| - if seen[repo['url']] - dupe = repo['url'] - break - end - seen[repo['url']] = true - end - end - - dupe.nil? - end - errors = {} + seen = {} courses = contents['course'] - unless courses.kind_of?(Array) - errors['course'] = ["must be an array"] - return errors - end - + errors = { empty_course: true } and return errors unless courses.kind_of?(Array) courses.each_with_index do |course, course_index| - unless course['section'] - errors['course'] = ['section is missing'] - return errors - end repos = course['repos'] - unless repos.kind_of?(Array) - errors[:section_missing_repos] = { index: course_index, title: "No repos" } - return errors - end + errors[:section_missing_repos] = { index: course_index, title: "No repos" } and return errors unless repos.kind_of?(Array) repos.each_with_index do |repo, repo_index| - unless github_url?(repo['url']) - errors['course'] = { course_index => { "repos" => { - repo_index => { "url" => ['is invalid'] } - } } } - return errors - end + errors[:no_duplicate_repos] = ['Duplicate github repos are not allowed'] and return errors if seen[repo['url']] + seen[repo['url']] = true + errors['course'] = { course_index => { "repos" => { repo_index => { "url" => ['is invalid'] } } } } and return errors unless github_url?(repo['url']) end end - errors[:no_duplicate_repos] = ['Duplicate github repos are not allowed'] unless no_duplicate_repos?(courses) - errors end diff --git a/gems/block-parser/Gemfile.lock b/gems/block-parser/Gemfile.lock index d0bc97f..29aa5e3 100644 --- a/gems/block-parser/Gemfile.lock +++ b/gems/block-parser/Gemfile.lock @@ -60,7 +60,7 @@ GEM rainbow (3.0.0) rake (13.0.1) redcarpet (3.3.4) - regexp_parser (1.8.1) + regexp_parser (1.8.2) rexml (3.2.4) rspec (3.9.0) rspec-core (~> 3.9.0) @@ -77,7 +77,7 @@ GEM rspec-support (3.9.3) rspec_junit_formatter (0.4.1) rspec-core (>= 2, < 4, != 2.12.0) - rubocop (0.93.0) + rubocop (0.93.1) parallel (~> 1.10) parser (>= 2.7.1.5) rainbow (>= 2.2.2, < 4.0) @@ -86,7 +86,7 @@ GEM rubocop-ast (>= 0.6.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 2.0) - rubocop-ast (0.7.1) + rubocop-ast (0.8.0) parser (>= 2.7.1.5) ruby-progressbar (1.10.1) sawyer (0.7.0) -- GitLab From 290fdad98c5aaa4dccc6c1687dbea7a71585cd39 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 12 Oct 2020 20:36:36 -1000 Subject: [PATCH 154/283] got ruby image working. moving package installs to centos image builder layer --- Dockerfile | 124 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 97 insertions(+), 27 deletions(-) diff --git a/Dockerfile b/Dockerfile index d35d8b7..88f5677 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,32 +1,97 @@ -FROM bitnami/ruby:2.6.6 - -# Install what we can through OS package management -RUN apt-get -y update -RUN apt-get -y install --no-install-recommends \ - redis-tools \ - curl \ - software-properties-common \ - postgresql-client\ - libpq-dev \ - libxml2-dev \ - libxslt1-dev \ - qt5-default \ - libqt5webkit5-dev \ - xvfb - -# Clear off space. -RUN apt-get -q clean - -# Install Node.js. +# Stage 1: Install libararies +FROM centos:8 as builder +USER 0 + +# Install the redis-cli tools +RUN dnf update -y && \ + dnf install -y \ + redis \ + make \ + patch \ + git +# libxml2-devel \ +# libxslt-devel \ +# libpq-devel \ +# gcc \ +# zlib-devel + +# Stage 2: Setup the Image. +FROM registry.il2.dsop.io/platform-one/devops/pipeline-templates/ironbank/ruby26:2.6.6.212 +USER 0 + +RUN dnf update -y && \ + dnf install -y gcc \ + zlib-devel \ + libpq-devel \ + libxml2-devel \ + libxslt-devel + +# Copy over the libraries. +COPY --from=builder /usr/bin/redis-cli /usr/bin/redis-cli +COPY --from=builder /usr/bin/patch /usr/bin/patch +COPY --from=builder /usr/bin/make /usr/bin/make +COPY --from=builder /usr/bin/git* /usr/bin/ +#COPY --from=builder /usr/lib64/libxml* /usr/lib64/ +#COPY --from=builder /usr/lib64/libxslt* /usr/lib64/ +#COPY --from=builder /usr/lib64/libpq* /usr/lib64/ +#COPY --from=builder /usr/bin/gcc* /usr/bin/ +#COPY --from=builder /usr/lib/gcc /usr/lib/gcc +#COPY --from=builder /usr/bin/as /usr/bin/as +#COPY --from=builder /usr/bin/ld /usr/bin/ld +#COPY --from=builder /usr/bin/pkgconf /usr/bin/pkgconf +#COPY --from=builder /usr/libexec/gcc /usr/libexec/gcc +#COPY --from=builder /usr/lib64/libmpc* /usr/lib64/ +#COPY --from=builder /usr/lib64/libopcodes* /usr/lib64/ +#COPY --from=builder /usr/lib64/libbfd* /usr/lib64/ +#COPY --from=builder /usr/lib64/libc.so* /usr/lib64/ +#COPY --from=builder /usr/lib64/libc_nonshared* /usr/lib64/ +#COPY --from=builder /usr/lib64/libcrypt* /usr/lib64/ +#COPY --from=builder /usr/lib64/libgomp* /usr/lib64/ +#COPY --from=builder /usr/lib64/libgpg* /usr/lib64/ +#COPY --from=builder /usr/lib64/libgcrypt* /usr/lib64/ +#COPY --from=builder /usr/lib64/libgcc* /usr/lib64/ +#COPY --from=builder /usr/lib64/libpkgconf* /usr/lib64/ +#COPY --from=builder /usr/lib64/crt* /usr/lib64/ +#COPY --from=builder /usr/lib64/libm-2* /usr/lib64/ +#COPY --from=builder /usr/lib64/libm.so* /usr/lib64/ +#COPY --from=builder /usr/lib64/libmcheck* /usr/lib64/ +#COPY --from=builder /usr/lib64/Mcrt1* /usr/lib64/ +#COPY --from=builder /usr/lib64/Scrt1* /usr/lib64/ +#COPY --from=builder /usr/lib64/gcrt* /usr/lib64/ +#COPY --from=builder /usr/lib64/libanl* /usr/lib64/ +#COPY --from=builder /usr/lib64/libdl* /usr/lib64/ +#COPY --from=builder /usr/lib64/libexslt* /usr/lib64/ +#COPY --from=builder /usr/lib64/libg* /usr/lib64/ +#COPY --from=builder /usr/lib64/libisl* /usr/lib64/ +#COPY --from=builder /usr/lib64/liblzma* /usr/lib64/ +#COPY --from=builder /usr/lib64/libmvec* /usr/lib64/ +#COPY --from=builder /usr/lib64/libpthread* /usr/lib64/ +#COPY --from=builder /usr/lib64/libresolv* /usr/lib64/ +#COPY --from=builder /usr/lib64/librt* /usr/lib64/ +#COPY --from=builder /usr/lib64/libthread_db* /usr/lib64/ +#COPY --from=builder /usr/lib64/libutil* /usr/lib64/ +#COPY --from=builder /usr/lib64/libz* /usr/lib64/ +#COPY --from=builder /usr/lib64/rcrt* /usr/lib64/ +#COPY --from=builder /usr/lib64/xml2Conf.sh /usr/lib64/xml2Conf.sh +#COPY --from=builder /usr/lib64/xsltConf.sh /usr/lib64/xsltConf.sh +#COPY --from=builder /usr/include /usr/include + +# Install Node ADD .nvmrc . RUN curl -L https://raw.githubusercontent.com/tj/n/master/bin/n -o n RUN bash n auto -RUN npm install -g yarn # Setup our environment WORKDIR /usr/src/app ADD . . +# Add write permissions. +RUN chown -R 1001 . +RUN chmod -R u+w . + +# Become the ruby user +USER 1001 + # Set the Rails environment variable. ENV RAILS_ENV production @@ -36,18 +101,23 @@ RUN gem install rake:13.0.1 --source 'https://rubygems.org/' # Run the bundle install RUN bundle install +#RUN cat /usr/local/bundle/extensions/x86_64-linux/2.6.0/nokogiri-1.8.0/mkmf.log -# Precompile assets -RUN bundle exec rake assets:precompile +# Install Yarn. +RUN npm install yarn +RUN rm package-lock.json + +# Add the node_modules to the path. +ENV PATH /usr/src/app/node_modules/.bin:$PATH # Run Yarn Install RUN yarn install +# Precompile assets +RUN bundle exec rake assets:precompile + # Asset Clean RUN bundle exec rake assets:clean -# Add the node_modules to the path. -ENV PATH /usr/src/app/node_modules/.bin:$PATH - # Set the entry point. -CMD ["./entrypoint-server.sh"] +ENTRYPOINT ["./entrypoint-server.sh"] \ No newline at end of file -- GitLab From fcfd94c80bc033e571e4877f331a80f63fb3c0ef Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 12 Oct 2020 21:27:56 -1000 Subject: [PATCH 155/283] moving libz install --- Dockerfile | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/Dockerfile b/Dockerfile index 88f5677..e05ff3a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,12 +8,12 @@ RUN dnf update -y && \ redis \ make \ patch \ - git + git \ + zlib-devel # libxml2-devel \ # libxslt-devel \ # libpq-devel \ # gcc \ -# zlib-devel # Stage 2: Setup the Image. FROM registry.il2.dsop.io/platform-one/devops/pipeline-templates/ironbank/ruby26:2.6.6.212 @@ -31,6 +31,7 @@ COPY --from=builder /usr/bin/redis-cli /usr/bin/redis-cli COPY --from=builder /usr/bin/patch /usr/bin/patch COPY --from=builder /usr/bin/make /usr/bin/make COPY --from=builder /usr/bin/git* /usr/bin/ +COPY --from=builder /usr/lib64/libz* /usr/lib64/ #COPY --from=builder /usr/lib64/libxml* /usr/lib64/ #COPY --from=builder /usr/lib64/libxslt* /usr/lib64/ #COPY --from=builder /usr/lib64/libpq* /usr/lib64/ @@ -97,27 +98,27 @@ ENV RAILS_ENV production # Install Rails Dependecies. RUN gem install bundler:2.1.4 -RUN gem install rake:13.0.1 --source 'https://rubygems.org/' +#RUN gem install rake:13.0.1 --source 'https://rubygems.org/' # Run the bundle install RUN bundle install #RUN cat /usr/local/bundle/extensions/x86_64-linux/2.6.0/nokogiri-1.8.0/mkmf.log -# Install Yarn. -RUN npm install yarn -RUN rm package-lock.json - -# Add the node_modules to the path. -ENV PATH /usr/src/app/node_modules/.bin:$PATH - -# Run Yarn Install -RUN yarn install - -# Precompile assets -RUN bundle exec rake assets:precompile - -# Asset Clean -RUN bundle exec rake assets:clean - -# Set the entry point. -ENTRYPOINT ["./entrypoint-server.sh"] \ No newline at end of file +## Install Yarn. +#RUN npm install yarn +#RUN rm package-lock.json +# +## Add the node_modules to the path. +#ENV PATH /usr/src/app/node_modules/.bin:$PATH +# +## Run Yarn Install +#RUN yarn install +# +## Precompile assets +#RUN bundle exec rake assets:precompile +# +## Asset Clean +#RUN bundle exec rake assets:clean +# +## Set the entry point. +#ENTRYPOINT ["./entrypoint-server.sh"] \ No newline at end of file -- GitLab From b92058628a6851f303e0b1314893a604ba17830f Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 12 Oct 2020 21:38:22 -1000 Subject: [PATCH 156/283] moving libz install --- Dockerfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index e05ff3a..97e6a9a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,6 @@ USER 0 RUN dnf update -y && \ dnf install -y gcc \ - zlib-devel \ libpq-devel \ libxml2-devel \ libxslt-devel -- GitLab From a18245d9bc1b344fbbc196225154b765f652bf70 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 12 Oct 2020 23:07:11 -1000 Subject: [PATCH 157/283] moving postgres install --- Dockerfile | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 97e6a9a..968e8bd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,10 +9,10 @@ RUN dnf update -y && \ make \ patch \ git \ - zlib-devel + zlib-devel \ + libpq-devel # libxml2-devel \ # libxslt-devel \ -# libpq-devel \ # gcc \ # Stage 2: Setup the Image. @@ -21,19 +21,37 @@ USER 0 RUN dnf update -y && \ dnf install -y gcc \ - libpq-devel \ libxml2-devel \ libxslt-devel -# Copy over the libraries. +# Redis CLI Binary. COPY --from=builder /usr/bin/redis-cli /usr/bin/redis-cli + +# Patch Binary. COPY --from=builder /usr/bin/patch /usr/bin/patch + +# Make Binary. COPY --from=builder /usr/bin/make /usr/bin/make + +# Git Binaries. COPY --from=builder /usr/bin/git* /usr/bin/ + +# libz Dependencies. COPY --from=builder /usr/lib64/libz* /usr/lib64/ + +# Postgres Dependencies +COPY --from=builder /usr/bin/pkgconf /usr/bin/pkgconf +COPY --from=builder /usr/bin/pg_config /usr/bin/pg_config +COPY --from=builder /usr/lib64/libpq* /usr/lib64/ +COPY --from=builder /usr/lib64/libpkgconf* /usr/lib64/ +COPY --from=builder /usr/include/libpq /usr/include/libpq +COPY --from=builder /usr/include/libpq* /usr/include/ +COPY --from=builder /usr/include/pg* /usr/include/ +COPY --from=builder /usr/include/pgsql /usr/include/pgsql +COPY --from=builder /usr/include/postgres* /usr/include/ + #COPY --from=builder /usr/lib64/libxml* /usr/lib64/ #COPY --from=builder /usr/lib64/libxslt* /usr/lib64/ -#COPY --from=builder /usr/lib64/libpq* /usr/lib64/ #COPY --from=builder /usr/bin/gcc* /usr/bin/ #COPY --from=builder /usr/lib/gcc /usr/lib/gcc #COPY --from=builder /usr/bin/as /usr/bin/as -- GitLab From 299c039d48e3b0880f80b467b232d0941d20aed1 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 13 Oct 2020 00:19:08 -1000 Subject: [PATCH 158/283] moving libxml and libxslt --- Dockerfile | 68 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 28 deletions(-) diff --git a/Dockerfile b/Dockerfile index 968e8bd..7dd4d98 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,19 +10,17 @@ RUN dnf update -y && \ patch \ git \ zlib-devel \ - libpq-devel -# libxml2-devel \ -# libxslt-devel \ -# gcc \ + libpq-devel \ + libxml2-devel \ + libxslt-devel \ + gcc # Stage 2: Setup the Image. FROM registry.il2.dsop.io/platform-one/devops/pipeline-templates/ironbank/ruby26:2.6.6.212 USER 0 RUN dnf update -y && \ - dnf install -y gcc \ - libxml2-devel \ - libxslt-devel + dnf install -y gcc # Redis CLI Binary. COPY --from=builder /usr/bin/redis-cli /usr/bin/redis-cli @@ -50,13 +48,28 @@ COPY --from=builder /usr/include/pg* /usr/include/ COPY --from=builder /usr/include/pgsql /usr/include/pgsql COPY --from=builder /usr/include/postgres* /usr/include/ -#COPY --from=builder /usr/lib64/libxml* /usr/lib64/ -#COPY --from=builder /usr/lib64/libxslt* /usr/lib64/ +# libxml2 Dependencies. +COPY --from=builder /usr/lib64/libxml* /usr/lib64/ +COPY --from=builder /usr/lib64/liblz* /usr/lib64/ +COPY --from=builder /usr/lib64/libm-2* /usr/lib64/ +COPY --from=builder /usr/lib64/libm.so* /usr/lib64/ +COPY --from=builder /usr/include/lzma /usr/include/lzma +COPY --from=builder /usr/include/zlib* /usr/include/ +COPY --from=builder /usr/include/zconf* /usr/include/ +COPY --from=builder /usr/include/libxml2 /usr/include/libxml2 + +# libxslt Dependencies. +COPY --from=builder /usr/lib64/libxslt* /usr/lib64/ +COPY --from=builder /usr/lib64/libexslt* /usr/lib64/ +COPY --from=builder /usr/include/libxslt /usr/include/libxslt +COPY --from=builder /usr/include/libexslt /usr/include/libexslt +COPY --from=builder /usr/include/gcrypt* /usr/include/ +COPY --from=builder /usr/include/gpg* /usr/include/ + #COPY --from=builder /usr/bin/gcc* /usr/bin/ #COPY --from=builder /usr/lib/gcc /usr/lib/gcc #COPY --from=builder /usr/bin/as /usr/bin/as #COPY --from=builder /usr/bin/ld /usr/bin/ld -#COPY --from=builder /usr/bin/pkgconf /usr/bin/pkgconf #COPY --from=builder /usr/libexec/gcc /usr/libexec/gcc #COPY --from=builder /usr/lib64/libmpc* /usr/lib64/ #COPY --from=builder /usr/lib64/libopcodes* /usr/lib64/ @@ -68,7 +81,6 @@ COPY --from=builder /usr/include/postgres* /usr/include/ #COPY --from=builder /usr/lib64/libgpg* /usr/lib64/ #COPY --from=builder /usr/lib64/libgcrypt* /usr/lib64/ #COPY --from=builder /usr/lib64/libgcc* /usr/lib64/ -#COPY --from=builder /usr/lib64/libpkgconf* /usr/lib64/ #COPY --from=builder /usr/lib64/crt* /usr/lib64/ #COPY --from=builder /usr/lib64/libm-2* /usr/lib64/ #COPY --from=builder /usr/lib64/libm.so* /usr/lib64/ @@ -121,21 +133,21 @@ RUN gem install bundler:2.1.4 RUN bundle install #RUN cat /usr/local/bundle/extensions/x86_64-linux/2.6.0/nokogiri-1.8.0/mkmf.log -## Install Yarn. -#RUN npm install yarn -#RUN rm package-lock.json -# -## Add the node_modules to the path. -#ENV PATH /usr/src/app/node_modules/.bin:$PATH -# +# Install Yarn. +RUN npm install yarn +RUN rm package-lock.json + +# Add the node_modules to the path. +ENV PATH /usr/src/app/node_modules/.bin:$PATH + ## Run Yarn Install -#RUN yarn install -# -## Precompile assets -#RUN bundle exec rake assets:precompile -# -## Asset Clean -#RUN bundle exec rake assets:clean -# -## Set the entry point. -#ENTRYPOINT ["./entrypoint-server.sh"] \ No newline at end of file +RUN yarn install + +# Precompile assets +RUN bundle exec rake assets:precompile + +# Asset Clean +RUN bundle exec rake assets:clean + +# Set the entry point. +ENTRYPOINT ["./entrypoint-server.sh"] \ No newline at end of file -- GitLab From a7280dad2308ed1c5be60090a98dd6c0e6426485 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 13 Oct 2020 01:01:30 -1000 Subject: [PATCH 159/283] moving yarn install to the builder --- Dockerfile | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7dd4d98..ed4f881 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,13 +2,18 @@ FROM centos:8 as builder USER 0 -# Install the redis-cli tools +# Setup the yarn repo. +RUN curl --silent --location https://dl.yarnpkg.com/rpm/yarn.repo | tee /etc/yum.repos.d/yarn.repo +RUN rpm --import https://dl.yarnpkg.com/rpm/pubkey.gpg + +# Install the required packages. RUN dnf update -y && \ dnf install -y \ redis \ make \ patch \ git \ + yarn \ zlib-devel \ libpq-devel \ libxml2-devel \ @@ -34,6 +39,11 @@ COPY --from=builder /usr/bin/make /usr/bin/make # Git Binaries. COPY --from=builder /usr/bin/git* /usr/bin/ +# Yarn Binaries. +COPY --from=builder /usr/share/yarn /usr/share/yarn +RUN ln -s /usr/share/yarn/bin/yarn /usr/bin/yarn +RUN ln -s /usr/share/yarn/bin/yarn /usr/bin/yarnpkg + # libz Dependencies. COPY --from=builder /usr/lib64/libz* /usr/lib64/ @@ -90,7 +100,6 @@ COPY --from=builder /usr/include/gpg* /usr/include/ #COPY --from=builder /usr/lib64/gcrt* /usr/lib64/ #COPY --from=builder /usr/lib64/libanl* /usr/lib64/ #COPY --from=builder /usr/lib64/libdl* /usr/lib64/ -#COPY --from=builder /usr/lib64/libexslt* /usr/lib64/ #COPY --from=builder /usr/lib64/libg* /usr/lib64/ #COPY --from=builder /usr/lib64/libisl* /usr/lib64/ #COPY --from=builder /usr/lib64/liblzma* /usr/lib64/ @@ -111,6 +120,8 @@ ADD .nvmrc . RUN curl -L https://raw.githubusercontent.com/tj/n/master/bin/n -o n RUN bash n auto +RUN yarn -v + # Setup our environment WORKDIR /usr/src/app ADD . . @@ -127,18 +138,9 @@ ENV RAILS_ENV production # Install Rails Dependecies. RUN gem install bundler:2.1.4 -#RUN gem install rake:13.0.1 --source 'https://rubygems.org/' # Run the bundle install RUN bundle install -#RUN cat /usr/local/bundle/extensions/x86_64-linux/2.6.0/nokogiri-1.8.0/mkmf.log - -# Install Yarn. -RUN npm install yarn -RUN rm package-lock.json - -# Add the node_modules to the path. -ENV PATH /usr/src/app/node_modules/.bin:$PATH ## Run Yarn Install RUN yarn install @@ -149,5 +151,8 @@ RUN bundle exec rake assets:precompile # Asset Clean RUN bundle exec rake assets:clean +# Add the node_modules to the path. +ENV PATH /usr/src/app/node_modules/.bin:$PATH + # Set the entry point. ENTRYPOINT ["./entrypoint-server.sh"] \ No newline at end of file -- GitLab From 8d58ca9c053c5466c1c7c9364910f96d5936e437 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 13 Oct 2020 01:02:35 -1000 Subject: [PATCH 160/283] moving yarn install to the builder --- Dockerfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index ed4f881..dd60aaa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -120,8 +120,6 @@ ADD .nvmrc . RUN curl -L https://raw.githubusercontent.com/tj/n/master/bin/n -o n RUN bash n auto -RUN yarn -v - # Setup our environment WORKDIR /usr/src/app ADD . . -- GitLab From 73ddd3c9fcf1f0d3d603bc1e90687f2d5a1cc074 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 13 Oct 2020 10:17:36 -1000 Subject: [PATCH 161/283] switching to install in the ruby container --- Dockerfile | 129 +++++++++++++++++++++++++++++------------------------ 1 file changed, 71 insertions(+), 58 deletions(-) diff --git a/Dockerfile b/Dockerfile index dd60aaa..cc7161c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,14 +2,33 @@ FROM centos:8 as builder USER 0 -# Setup the yarn repo. +## Setup the yarn repo. +#RUN curl --silent --location https://dl.yarnpkg.com/rpm/yarn.repo | tee /etc/yum.repos.d/yarn.repo +#RUN rpm --import https://dl.yarnpkg.com/rpm/pubkey.gpg + +## Install the required packages. +RUN dnf update -y && \ + dnf install -y \ + redis +# make \ +# patch \ +# git \ +# yarn \ +# zlib-devel \ +# libpq-devel \ +# libxml2-devel \ +# libxslt-devel \ +# gcc + +# Stage 2: Setup the Image. +FROM registry.il2.dsop.io/platform-one/devops/pipeline-templates/ironbank/ruby26:2.6.6.212 +USER 0 + RUN curl --silent --location https://dl.yarnpkg.com/rpm/yarn.repo | tee /etc/yum.repos.d/yarn.repo RUN rpm --import https://dl.yarnpkg.com/rpm/pubkey.gpg -# Install the required packages. RUN dnf update -y && \ dnf install -y \ - redis \ make \ patch \ git \ @@ -20,62 +39,58 @@ RUN dnf update -y && \ libxslt-devel \ gcc -# Stage 2: Setup the Image. -FROM registry.il2.dsop.io/platform-one/devops/pipeline-templates/ironbank/ruby26:2.6.6.212 -USER 0 - -RUN dnf update -y && \ - dnf install -y gcc - # Redis CLI Binary. COPY --from=builder /usr/bin/redis-cli /usr/bin/redis-cli -# Patch Binary. -COPY --from=builder /usr/bin/patch /usr/bin/patch - -# Make Binary. -COPY --from=builder /usr/bin/make /usr/bin/make - -# Git Binaries. -COPY --from=builder /usr/bin/git* /usr/bin/ - -# Yarn Binaries. -COPY --from=builder /usr/share/yarn /usr/share/yarn -RUN ln -s /usr/share/yarn/bin/yarn /usr/bin/yarn -RUN ln -s /usr/share/yarn/bin/yarn /usr/bin/yarnpkg - -# libz Dependencies. -COPY --from=builder /usr/lib64/libz* /usr/lib64/ - -# Postgres Dependencies -COPY --from=builder /usr/bin/pkgconf /usr/bin/pkgconf -COPY --from=builder /usr/bin/pg_config /usr/bin/pg_config -COPY --from=builder /usr/lib64/libpq* /usr/lib64/ -COPY --from=builder /usr/lib64/libpkgconf* /usr/lib64/ -COPY --from=builder /usr/include/libpq /usr/include/libpq -COPY --from=builder /usr/include/libpq* /usr/include/ -COPY --from=builder /usr/include/pg* /usr/include/ -COPY --from=builder /usr/include/pgsql /usr/include/pgsql -COPY --from=builder /usr/include/postgres* /usr/include/ - -# libxml2 Dependencies. -COPY --from=builder /usr/lib64/libxml* /usr/lib64/ -COPY --from=builder /usr/lib64/liblz* /usr/lib64/ -COPY --from=builder /usr/lib64/libm-2* /usr/lib64/ -COPY --from=builder /usr/lib64/libm.so* /usr/lib64/ -COPY --from=builder /usr/include/lzma /usr/include/lzma -COPY --from=builder /usr/include/zlib* /usr/include/ -COPY --from=builder /usr/include/zconf* /usr/include/ -COPY --from=builder /usr/include/libxml2 /usr/include/libxml2 - -# libxslt Dependencies. -COPY --from=builder /usr/lib64/libxslt* /usr/lib64/ -COPY --from=builder /usr/lib64/libexslt* /usr/lib64/ -COPY --from=builder /usr/include/libxslt /usr/include/libxslt -COPY --from=builder /usr/include/libexslt /usr/include/libexslt -COPY --from=builder /usr/include/gcrypt* /usr/include/ -COPY --from=builder /usr/include/gpg* /usr/include/ +## Patch Binary. +#COPY --from=builder /usr/bin/patch /usr/bin/patch +# +## Make Binary. +#COPY --from=builder /usr/bin/make /usr/bin/make +# +## Git Binaries. +#COPY --from=builder /usr/bin/git* /usr/bin/ +# +## Yarn Binaries. +#COPY --from=builder /usr/share/yarn /usr/share/yarn +#RUN ln -s /usr/share/yarn/bin/yarn /usr/bin/yarn +#RUN ln -s /usr/share/yarn/bin/yarn /usr/bin/yarnpkg +# +## libz Dependencies. +#COPY --from=builder /usr/lib64/libz* /usr/lib64/ +# +## Postgres Dependencies +#COPY --from=builder /usr/bin/pkgconf /usr/bin/pkgconf +#COPY --from=builder /usr/bin/pg_config /usr/bin/pg_config +#COPY --from=builder /usr/lib64/libpq* /usr/lib64/ +#COPY --from=builder /usr/lib64/libpkgconf* /usr/lib64/ +#COPY --from=builder /usr/include/libpq /usr/include/libpq +#COPY --from=builder /usr/include/libpq* /usr/include/ +#COPY --from=builder /usr/include/pg* /usr/include/ +#COPY --from=builder /usr/include/pgsql /usr/include/pgsql +#COPY --from=builder /usr/include/postgres* /usr/include/ +# +## libxml2 Dependencies. +#COPY --from=builder /usr/lib64/libxml* /usr/lib64/ +#COPY --from=builder /usr/lib64/liblz* /usr/lib64/ +#COPY --from=builder /usr/lib64/libm-2* /usr/lib64/ +#COPY --from=builder /usr/lib64/libm.so* /usr/lib64/ +#COPY --from=builder /usr/include/lzma /usr/include/lzma +#COPY --from=builder /usr/include/zlib* /usr/include/ +#COPY --from=builder /usr/include/zconf* /usr/include/ +#COPY --from=builder /usr/include/libxml2 /usr/include/libxml2 +#COPY --from=builder /usr/lib64/xml2Conf.sh /usr/lib64/xml2Conf.sh +# +## libxslt Dependencies. +#COPY --from=builder /usr/lib64/libxslt* /usr/lib64/ +#COPY --from=builder /usr/lib64/libexslt* /usr/lib64/ +#COPY --from=builder /usr/include/libxslt /usr/include/libxslt +#COPY --from=builder /usr/include/libexslt /usr/include/libexslt +#COPY --from=builder /usr/include/gcrypt* /usr/include/ +#COPY --from=builder /usr/include/gpg* /usr/include/ +#COPY --from=builder /usr/lib64/xsltConf.sh /usr/lib64/xsltConf.sh +## GCC Dependencies. #COPY --from=builder /usr/bin/gcc* /usr/bin/ #COPY --from=builder /usr/lib/gcc /usr/lib/gcc #COPY --from=builder /usr/bin/as /usr/bin/as @@ -111,8 +126,6 @@ COPY --from=builder /usr/include/gpg* /usr/include/ #COPY --from=builder /usr/lib64/libutil* /usr/lib64/ #COPY --from=builder /usr/lib64/libz* /usr/lib64/ #COPY --from=builder /usr/lib64/rcrt* /usr/lib64/ -#COPY --from=builder /usr/lib64/xml2Conf.sh /usr/lib64/xml2Conf.sh -#COPY --from=builder /usr/lib64/xsltConf.sh /usr/lib64/xsltConf.sh #COPY --from=builder /usr/include /usr/include # Install Node @@ -126,7 +139,7 @@ ADD . . # Add write permissions. RUN chown -R 1001 . -RUN chmod -R u+w . +#RUN chmod -R u+w . # Become the ruby user USER 1001 -- GitLab From bef0654abaaf8d8d7275c461233099ff723b9219 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 13 Oct 2020 11:27:19 -1000 Subject: [PATCH 162/283] adding c++ compiler --- Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index cc7161c..d747128 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,7 +37,8 @@ RUN dnf update -y && \ libpq-devel \ libxml2-devel \ libxslt-devel \ - gcc + gcc \ + gcc-c++ # Redis CLI Binary. COPY --from=builder /usr/bin/redis-cli /usr/bin/redis-cli -- GitLab From c660b475d08af5e043cf1ffd129c493e7567a882 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 13 Oct 2020 12:23:42 -1000 Subject: [PATCH 163/283] updating initializer for aws sdk. --- config/initializers/aws.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/initializers/aws.rb b/config/initializers/aws.rb index bf80004..4002801 100644 --- a/config/initializers/aws.rb +++ b/config/initializers/aws.rb @@ -46,5 +46,6 @@ else options[:force_path_style] = true end - Rails.application.config.aws = Aws::S3::Resource.new(options).bucket(Rails.application.secrets.glearn_bucket_name) + client = Aws::S3::Client.new(options) + Rails.application.config.aws = Aws::S3::Resource.new(client: client).bucket(Rails.application.secrets.glearn_bucket_name) end \ No newline at end of file -- GitLab From 0ca27dd2a21b507e7d4c99828a856e96593cadec Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 13 Oct 2020 12:39:27 -1000 Subject: [PATCH 164/283] defaulting s3 bucket names to temp name for build --- config/initializers/aws.rb | 3 +-- config/secrets.yml | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/config/initializers/aws.rb b/config/initializers/aws.rb index 4002801..bf80004 100644 --- a/config/initializers/aws.rb +++ b/config/initializers/aws.rb @@ -46,6 +46,5 @@ else options[:force_path_style] = true end - client = Aws::S3::Client.new(options) - Rails.application.config.aws = Aws::S3::Resource.new(client: client).bucket(Rails.application.secrets.glearn_bucket_name) + Rails.application.config.aws = Aws::S3::Resource.new(options).bucket(Rails.application.secrets.glearn_bucket_name) end \ No newline at end of file diff --git a/config/secrets.yml b/config/secrets.yml index f66ca92..bd0e92d 100644 --- a/config/secrets.yml +++ b/config/secrets.yml @@ -11,7 +11,7 @@ shared: github_token: <%= ENV["GITHUB_COM_TOKEN"] %> mixpanel_project_token: <%= ENV["MIXPANEL_PROJECT_TOKEN"] %> protocol: <%= ENV['PROTOCOL'] || "http://" %> - s3_bucket_name: <%= ENV["APP_S3_BUCKET"] %> + s3_bucket_name: <%= ENV["APP_S3_BUCKET"] || "temp" %> secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> sendgrid_password: <%= ENV['SENDGRID_PASSWORD'] %> sendgrid_username: <%= ENV['SENDGRID_USERNAME'] %> @@ -24,7 +24,7 @@ shared: glearn_access_key_id: <%= ENV['accesskey'] %> glearn_secret_access_key: <%= ENV['secretkey'] %> glearn_key_prefix: <%= ENV['GLEARN_KEY_PREFIX'] || "forge" %> - glearn_bucket_name: <%= ENV["APP_S3_BUCKET"] %> + glearn_bucket_name: <%= ENV["APP_S3_BUCKET"] || "temp" %> s3_region: <%= ENV["S3_REGION"] || "us-gov-west-1" %> dev_notify_slack_url: <%= ENV['DEV_NOTIFY_SLACK_URL'] %> minio_endpoint_url: <%= ENV["MINIO_ENDPOINT_URL"] %> -- GitLab From dd7c3b218f26f6f980da63111ff994a635c3a1a5 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Tue, 13 Oct 2020 16:36:27 -1000 Subject: [PATCH 165/283] fix for sass_rails gem --- Gemfile | 2 +- Gemfile.lock | 20 ++++--------------- .../settings/CohortBlockReleaseRow.tsx | 2 +- 3 files changed, 6 insertions(+), 18 deletions(-) diff --git a/Gemfile b/Gemfile index 6e94854..d9fca00 100644 --- a/Gemfile +++ b/Gemfile @@ -27,7 +27,7 @@ gem "ts_routes" gem "webpacker" gem "bootstrap" gem "font-awesome-rails" -gem "sass-rails", "~> 5.0" +gem "sass-rails" gem "uglifier" # views diff --git a/Gemfile.lock b/Gemfile.lock index c572acf..fafb5ed 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1189,9 +1189,6 @@ GEM thor (>= 0.19.0, < 2.0) rainbow (3.0.0) rake (13.0.1) - rb-fsevent (0.10.4) - rb-inotify (0.10.1) - ffi (~> 1.0) react-rails (2.6.1) babel-transpiler (>= 0.7.0) connection_pool @@ -1242,17 +1239,8 @@ GEM parser (>= 2.7.1.5) ruby-progressbar (1.10.1) rubyzip (2.3.0) - sass (3.7.4) - sass-listen (~> 4.0.0) - sass-listen (4.0.0) - rb-fsevent (~> 0.9, >= 0.9.4) - rb-inotify (~> 0.9, >= 0.9.7) - sass-rails (5.1.0) - railties (>= 5.2.0) - sass (~> 3.1) - sprockets (>= 2.8, < 4.0) - sprockets-rails (>= 2.0, < 4.0) - tilt (>= 1.1, < 3) + sass-rails (6.0.0) + sassc-rails (~> 2.1, >= 2.1.1) sassc (2.4.0) ffi (~> 1.9) sassc-rails (2.1.2) @@ -1282,7 +1270,7 @@ GEM simplecov-html (0.12.3) solid_use_case (2.2.0) deterministic (~> 0.6.0) - sprockets (3.7.2) + sprockets (4.0.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) sprockets-rails (3.2.2) @@ -1375,7 +1363,7 @@ DEPENDENCIES rspec_junit_formatter rubocop rubyzip - sass-rails (~> 5.0) + sass-rails scout_apm selenium-webdriver shoulda-matchers diff --git a/app/javascript/components/cohorts/settings/CohortBlockReleaseRow.tsx b/app/javascript/components/cohorts/settings/CohortBlockReleaseRow.tsx index 943214f..fe0693d 100644 --- a/app/javascript/components/cohorts/settings/CohortBlockReleaseRow.tsx +++ b/app/javascript/components/cohorts/settings/CohortBlockReleaseRow.tsx @@ -64,7 +64,7 @@ export default class CohortBlockReleaseRow extends React.Component }; // so dom element exists before init - setTimeout(() => { window.hopscotch.startTour(tour); }, 50); + setTimeout(() => { window.hopscotch.startTour(tour); }, 500); } } -- GitLab From 9ef640f200208f769af9e7fc645c2bb75d1aa57e Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 13 Oct 2020 16:53:17 -1000 Subject: [PATCH 166/283] removing line --- Dockerfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index d747128..613216e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -140,7 +140,6 @@ ADD . . # Add write permissions. RUN chown -R 1001 . -#RUN chmod -R u+w . # Become the ruby user USER 1001 -- GitLab From b31a619b9c9f99b5eb2702a420dd9e6a9f3a569e Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 13 Oct 2020 18:53:24 -1000 Subject: [PATCH 167/283] adding variable imports to scss files --- app/assets/stylesheets/base.scss | 2 ++ app/assets/stylesheets/cohorts.scss | 2 ++ app/assets/stylesheets/hopscotch-overrides.scss | 2 ++ app/assets/stylesheets/mixins.scss | 1 + 4 files changed, 7 insertions(+) diff --git a/app/assets/stylesheets/base.scss b/app/assets/stylesheets/base.scss index 1e9d53d..e6d4540 100644 --- a/app/assets/stylesheets/base.scss +++ b/app/assets/stylesheets/base.scss @@ -1,3 +1,5 @@ +@import "variables"; + html, body { overflow-x: hidden; diff --git a/app/assets/stylesheets/cohorts.scss b/app/assets/stylesheets/cohorts.scss index 18fbca1..a65763f 100644 --- a/app/assets/stylesheets/cohorts.scss +++ b/app/assets/stylesheets/cohorts.scss @@ -1,3 +1,5 @@ +@import "variables"; + .center { text-align: center; } diff --git a/app/assets/stylesheets/hopscotch-overrides.scss b/app/assets/stylesheets/hopscotch-overrides.scss index d9bc5c3..0a3f058 100644 --- a/app/assets/stylesheets/hopscotch-overrides.scss +++ b/app/assets/stylesheets/hopscotch-overrides.scss @@ -1,3 +1,5 @@ +@import "variables"; + .hopscotch-bubble-number { content: ""; background-image: url(/assets/svg/mobile-logo-d01e8af51b97d9f642d52a826ffe07193b8290e4d1767f6f2b2475bac759e9bc.svg)!important; diff --git a/app/assets/stylesheets/mixins.scss b/app/assets/stylesheets/mixins.scss index d06598c..a7a5914 100644 --- a/app/assets/stylesheets/mixins.scss +++ b/app/assets/stylesheets/mixins.scss @@ -1,5 +1,6 @@ // Fonts // ===== +@import "variables"; @mixin font-base () { color: $color-tundora; -- GitLab From 6dbfb9f6f85f39797169dcd1a238b389e72a91b7 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Tue, 13 Oct 2020 18:46:40 -1000 Subject: [PATCH 168/283] Change to manifest.js --- app/assets/config/manifest.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js index b16e53d..1983ee4 100644 --- a/app/assets/config/manifest.js +++ b/app/assets/config/manifest.js @@ -1,3 +1,3 @@ //= link_tree ../images -//= link_directory ../javascripts .js -//= link_directory ../stylesheets .css +//= link application.css +//= link application.js -- GitLab From 31eca6b4a712d4e0ee3085a62d16721ae0e239ca Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 13 Oct 2020 19:23:27 -1000 Subject: [PATCH 169/283] removing imports --- app/assets/stylesheets/base.scss | 2 -- app/assets/stylesheets/cohorts.scss | 2 -- app/assets/stylesheets/hopscotch-overrides.scss | 2 -- app/assets/stylesheets/mixins.scss | 1 - 4 files changed, 7 deletions(-) diff --git a/app/assets/stylesheets/base.scss b/app/assets/stylesheets/base.scss index e6d4540..1e9d53d 100644 --- a/app/assets/stylesheets/base.scss +++ b/app/assets/stylesheets/base.scss @@ -1,5 +1,3 @@ -@import "variables"; - html, body { overflow-x: hidden; diff --git a/app/assets/stylesheets/cohorts.scss b/app/assets/stylesheets/cohorts.scss index a65763f..18fbca1 100644 --- a/app/assets/stylesheets/cohorts.scss +++ b/app/assets/stylesheets/cohorts.scss @@ -1,5 +1,3 @@ -@import "variables"; - .center { text-align: center; } diff --git a/app/assets/stylesheets/hopscotch-overrides.scss b/app/assets/stylesheets/hopscotch-overrides.scss index 0a3f058..d9bc5c3 100644 --- a/app/assets/stylesheets/hopscotch-overrides.scss +++ b/app/assets/stylesheets/hopscotch-overrides.scss @@ -1,5 +1,3 @@ -@import "variables"; - .hopscotch-bubble-number { content: ""; background-image: url(/assets/svg/mobile-logo-d01e8af51b97d9f642d52a826ffe07193b8290e4d1767f6f2b2475bac759e9bc.svg)!important; diff --git a/app/assets/stylesheets/mixins.scss b/app/assets/stylesheets/mixins.scss index a7a5914..d06598c 100644 --- a/app/assets/stylesheets/mixins.scss +++ b/app/assets/stylesheets/mixins.scss @@ -1,6 +1,5 @@ // Fonts // ===== -@import "variables"; @mixin font-base () { color: $color-tundora; -- GitLab From 67d87e1d8ecaac70b6e5c626aa189bf7a0d964c9 Mon Sep 17 00:00:00 2001 From: Derrin Chong Date: Wed, 14 Oct 2020 08:36:59 -1000 Subject: [PATCH 170/283] Disable sidekiq --- entrypoint-server.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/entrypoint-server.sh b/entrypoint-server.sh index 95515d9..3df1bbc 100755 --- a/entrypoint-server.sh +++ b/entrypoint-server.sh @@ -2,5 +2,4 @@ rm -f tmp/pids/server.pid bundle exec rails db:migrate -bundle exec sidekiq -e production -L sidekiq.log & -RAILS_ENV=production rails server -b 0.0.0.0 -p 3000 \ No newline at end of file +RAILS_ENV=production rails server -b 0.0.0.0 -p 3000 -- GitLab From f859febb6d531395f520105efecc0cc16c20746c Mon Sep 17 00:00:00 2001 From: jeason Date: Wed, 14 Oct 2020 13:01:57 -0600 Subject: [PATCH 171/283] Project template: file templates --- .gitlab/CODEOWNERS | 6 +++ .gitlab/issue_templates/Access Request.md | 16 ++++++++ .../issue_templates/Application - Archive.md | 21 +++++++++++ .../issue_templates/Application - Initial.md | 32 ++++++++++++++++ .../issue_templates/Application - Update.md | 35 ++++++++++++++++++ .gitlab/issue_templates/Bug.md | 37 +++++++++++++++++++ .gitlab/issue_templates/Feature Request.md | 32 ++++++++++++++++ .../issue_templates/Leadership Question.md | 7 ++++ .gitlab/issue_templates/New Findings.md | 20 ++++++++++ .../issue_templates/Onboarding Question.md | 7 ++++ .gitlab/issue_templates/Pipeline Failure.md | 31 ++++++++++++++++ 11 files changed, 244 insertions(+) create mode 100644 .gitlab/CODEOWNERS create mode 100644 .gitlab/issue_templates/Access Request.md create mode 100644 .gitlab/issue_templates/Application - Archive.md create mode 100644 .gitlab/issue_templates/Application - Initial.md create mode 100644 .gitlab/issue_templates/Application - Update.md create mode 100644 .gitlab/issue_templates/Bug.md create mode 100644 .gitlab/issue_templates/Feature Request.md create mode 100644 .gitlab/issue_templates/Leadership Question.md create mode 100644 .gitlab/issue_templates/New Findings.md create mode 100644 .gitlab/issue_templates/Onboarding Question.md create mode 100644 .gitlab/issue_templates/Pipeline Failure.md diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS new file mode 100644 index 0000000..64a2c68 --- /dev/null +++ b/.gitlab/CODEOWNERS @@ -0,0 +1,6 @@ +[Pipelines] +.gitlab-ci.yml @ironbank-notifications/cht +.gitlab-ci.yaml @ironbank-notifications/cht + +[Gitlab Configuration Files] +.gitlab/* @ironbank-notifications/cht diff --git a/.gitlab/issue_templates/Access Request.md b/.gitlab/issue_templates/Access Request.md new file mode 100644 index 0000000..1a7b224 --- /dev/null +++ b/.gitlab/issue_templates/Access Request.md @@ -0,0 +1,16 @@ +## Summary + +The following individuals are requesting access to this project (one per line): +(List or tag all individuals here) + + +The access level should be: +- [ ] Developer access +- [ ] Remove access + + +## Definition of Done +- [ ] All accounts have been provided the necessary accesses + + +/label ~"Access" ~"To Do" \ No newline at end of file diff --git a/.gitlab/issue_templates/Application - Archive.md b/.gitlab/issue_templates/Application - Archive.md new file mode 100644 index 0000000..9f3b5fe --- /dev/null +++ b/.gitlab/issue_templates/Application - Archive.md @@ -0,0 +1,21 @@ +## Summary + +Requesting this application be archived due to one of the following reasons: +- [ ] Version is no longer supported by vendor +- [ ] Application is End-Of-Life +- [ ] License violation. +- [ ] Other. See below. + +## Detailed Description + +(Please provide a detailed description of why this application should be archived) + + +## Definition of Done +- [ ] Application has been reviewed for archival +- [ ] Project is officially marked as stale +- [ ] Iron Bank frontend no longer lists application as available or approved + + +/label ~"Container::Archive" +/cc @ironbank-notifications/archive \ No newline at end of file diff --git a/.gitlab/issue_templates/Application - Initial.md b/.gitlab/issue_templates/Application - Initial.md new file mode 100644 index 0000000..6594a05 --- /dev/null +++ b/.gitlab/issue_templates/Application - Initial.md @@ -0,0 +1,32 @@ +## Summary + +Requesting application to be hardened. This is only for initial hardening of a container. + + +## Version Information + +Current version: (State the current version of the application as you see it) + +Under support: (Is the updated version within the same major version of the application or is this a new major version?) + + +## Definition of Done +Hardening: +- [ ] Container builds successfully +- [ ] Greylist file has been created (requires a member from container hardening) +- [ ] Branch has been merged into `development` + +Justifications: +- [ ] All findings have been justified per the above documentation +- [ ] Justifications have been provided to the container hardening team + +Approval Process (container hardening team processes): +- [ ] Peer review from Container Hardening Team +- [ ] Findings Approver has reviewed and approved all justifications +- [ ] Approval request has been sent to Authorizing Official +- [ ] Approval request has been processed by Authorizing Official + + + +/label ~"Container::Initial" +/cc @ironbank-notifications/cht \ No newline at end of file diff --git a/.gitlab/issue_templates/Application - Update.md b/.gitlab/issue_templates/Application - Update.md new file mode 100644 index 0000000..caebb3e --- /dev/null +++ b/.gitlab/issue_templates/Application - Update.md @@ -0,0 +1,35 @@ +## Summary + +Requesting application be updated to a newer version. + + + +## Version Information + +Current version: (State the current version of the application as you see it) + +Updated version: (State the version you would like the application updated to) + +Under support: (Is the updated version within the same major version of the application or is this a new major version?) + + +## Definition of Done +Hardening: +- [ ] Container builds successfully +- [ ] Container version has been updated in greylist file +- [ ] Branch has been merged into `development` + +Justifications: +- [ ] All findings have been justified per the above documentation +- [ ] Justifications have been provided to the container hardening team + +Approval Process: +- [ ] Peer review from Container Hardening Team +- [ ] Findings Approver has reviewed and approved all justifications +- [ ] Approval request has been sent to Authorizing Official +- [ ] Approval request has been processed by Authorizing Official + + + +/label ~"Container::Update" +/cc @ironbank-notifications/updates \ No newline at end of file diff --git a/.gitlab/issue_templates/Bug.md b/.gitlab/issue_templates/Bug.md new file mode 100644 index 0000000..1427a0c --- /dev/null +++ b/.gitlab/issue_templates/Bug.md @@ -0,0 +1,37 @@ +## Summary + +(Summarize the bug encountered concisely) + + +## Steps to reproduce + +(How one can reproduce the issue - this is very important) + + +## What is the current bug behavior? + +(What actually happens) + + +## What is the expected correct behavior? + +(What you should see instead) + + +## Relevant logs and/or screenshots + +(Paste any relevant logs - please use code blocks (```) to format console output, +logs, and code as it's very hard to read otherwise.) + + +## Possible fixes + +(If you can, link to the line of code that might be responsible for the problem) + + +## Defintion of Done +- [ ] Bug has been identified and corrected within the container + + +/label ~Bug +/cc @ironbank-notifications/bug \ No newline at end of file diff --git a/.gitlab/issue_templates/Feature Request.md b/.gitlab/issue_templates/Feature Request.md new file mode 100644 index 0000000..a0e2f19 --- /dev/null +++ b/.gitlab/issue_templates/Feature Request.md @@ -0,0 +1,32 @@ +## Feature description + +(Detailed description of the feature being requested) + + +## Use cases + + +(Detailed description of the use case for this feature) + + +## Benefits + +(How does this benefit others) + + +## Requirements + +(Any requirements for this feature to be enabled?) + + +## Links / references + +(List of links or references that support this feature) + + +## Definition of Done +- [ ] Feature has been implemented + + +/label ~Feature +/cc @ironbank-notifications/feature \ No newline at end of file diff --git a/.gitlab/issue_templates/Leadership Question.md b/.gitlab/issue_templates/Leadership Question.md new file mode 100644 index 0000000..4674f82 --- /dev/null +++ b/.gitlab/issue_templates/Leadership Question.md @@ -0,0 +1,7 @@ +## Leadership question + +(Detailed description of the question you'd like to ask the leadership team) + + +/label ~"Question::Leadership" ~"To Do" +/cc @ironbank-notifications/leadership \ No newline at end of file diff --git a/.gitlab/issue_templates/New Findings.md b/.gitlab/issue_templates/New Findings.md new file mode 100644 index 0000000..068d029 --- /dev/null +++ b/.gitlab/issue_templates/New Findings.md @@ -0,0 +1,20 @@ +## Summary + +Container has new findings discovered during continuous monitoring. + + + +## Definition of Done +Justifications: +- [ ] All findings have been justified +- [ ] Justifications have been provided to the container hardening team + +Approval Process: +- [ ] Findings Approver has reviewed and approved all justifications +- [ ] Approval request has been sent to Authorizing Official +- [ ] Approval request has been processed by Authorizing Official + + + +/label ~"Container::New Findings" +/cc @ironbank-notifications/security \ No newline at end of file diff --git a/.gitlab/issue_templates/Onboarding Question.md b/.gitlab/issue_templates/Onboarding Question.md new file mode 100644 index 0000000..77dea11 --- /dev/null +++ b/.gitlab/issue_templates/Onboarding Question.md @@ -0,0 +1,7 @@ +## Onboarding question + +(Detailed description of the question you'd like to ask the onboarding team) + + +/label ~"Question::Onboarding" ~"To Do" +/cc @ironbank-notifications/onboarding \ No newline at end of file diff --git a/.gitlab/issue_templates/Pipeline Failure.md b/.gitlab/issue_templates/Pipeline Failure.md new file mode 100644 index 0000000..28b82a9 --- /dev/null +++ b/.gitlab/issue_templates/Pipeline Failure.md @@ -0,0 +1,31 @@ +## Summary + +(Summarize the pipeline issue encountered concisely) + + +## Link to failed pipeline + +(Link to the failed pipeline) + + +## What is the current bug behavior? + +(What actually happens) + + +## What is the expected correct behavior? + +(What you should see instead) + + +## Possible fixes + +(If you can, link to the line of code that might be responsible for the problem) + + +## Definition of Done +- [ ] Pipeline failure has been resolved + + +/label ~Pipeline +/cc @ironbank-notifications/pipelines \ No newline at end of file -- GitLab From ebc0a7b5f6aa470d2bf9d38ec6b90b59cb80f40c Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Wed, 14 Oct 2020 10:38:21 -1000 Subject: [PATCH 172/283] Update gemfile for rails --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index d9fca00..8cc46b1 100644 --- a/Gemfile +++ b/Gemfile @@ -14,7 +14,7 @@ gem "puma" gem "pundit" gem "httparty" gem "pagy" -gem "rails", "~> 5.2.1" +gem "rails", "~> 5.2.4" gem "sidekiq" gem "dotenv-rails" gem "rubyzip" diff --git a/Gemfile.lock b/Gemfile.lock index fafb5ed..d456bf8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1285,7 +1285,7 @@ GEM thor (1.0.1) thread_safe (0.3.6) tilt (2.0.10) - timecop (0.9.1) + timecop (0.9.2) ts_routes (1.0.3) railties (>= 4.0) tzinfo (1.2.7) @@ -1354,7 +1354,7 @@ DEPENDENCIES pundit rack-attack rack-mini-profiler - rails (~> 5.2.1) + rails (~> 5.2.4) rails-controller-testing react-rails redis -- GitLab From 76df5aa7e449a64d8f6448ac8b967a727e419391 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Wed, 14 Oct 2020 17:56:02 -1000 Subject: [PATCH 173/283] replace github-markdown with commonmarker --- Gemfile.lock | 7 +++++-- gems/block-parser/Gemfile.lock | 7 +++++-- gems/block-parser/block_parser.gemspec | 2 +- gems/block-parser/spec/build_html_from_md_json_spec.rb | 5 ++--- gems/block-parser/spec/parse_directory_spec.rb | 2 +- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index d456bf8..433980f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -3,7 +3,7 @@ PATH specs: block_parser (0.1.0) activemodel (> 5.2) - github-markdown (= 0.6.9) + commonmarker (= 0.21.0) github-markup (= 1.6.1) github_url (= 0.2.1) gitlab (= 4.14.1) @@ -1044,6 +1044,8 @@ GEM xpath (~> 3.2) childprocess (3.0.0) coderay (1.1.3) + commonmarker (0.21.0) + ruby-enum (~> 0.5) concurrent-ruby (1.1.7) connection_pool (2.2.3) crack (0.4.4) @@ -1071,7 +1073,6 @@ GEM font-awesome-rails (4.7.0.5) railties (>= 3.2, < 6.1) foreman (0.87.2) - github-markdown (0.6.9) github-markup (1.6.1) github_url (0.2.1) gitlab (4.14.1) @@ -1237,6 +1238,8 @@ GEM unicode-display_width (>= 1.4.0, < 2.0) rubocop-ast (0.8.0) parser (>= 2.7.1.5) + ruby-enum (0.8.0) + i18n ruby-progressbar (1.10.1) rubyzip (2.3.0) sass-rails (6.0.0) diff --git a/gems/block-parser/Gemfile.lock b/gems/block-parser/Gemfile.lock index 29aa5e3..24076a7 100644 --- a/gems/block-parser/Gemfile.lock +++ b/gems/block-parser/Gemfile.lock @@ -3,7 +3,7 @@ PATH specs: block_parser (0.1.0) activemodel (> 5.2) - github-markdown (= 0.6.9) + commonmarker (= 0.21.0) github-markup (= 1.6.1) github_url (= 0.2.1) gitlab (= 4.14.1) @@ -27,11 +27,12 @@ GEM addressable (2.4.0) ast (2.4.1) byebug (11.1.3) + commonmarker (0.21.0) + ruby-enum (~> 0.5) concurrent-ruby (1.1.7) diff-lcs (1.4.4) faraday (0.9.2) multipart-post (>= 1.2, < 3) - github-markdown (0.6.9) github-markup (1.6.1) github_url (0.2.1) gitlab (4.14.1) @@ -88,6 +89,8 @@ GEM unicode-display_width (>= 1.4.0, < 2.0) rubocop-ast (0.8.0) parser (>= 2.7.1.5) + ruby-enum (0.8.0) + i18n ruby-progressbar (1.10.1) sawyer (0.7.0) addressable (>= 2.3.5, < 2.5) diff --git a/gems/block-parser/block_parser.gemspec b/gems/block-parser/block_parser.gemspec index 481d6f1..88f0fe1 100644 --- a/gems/block-parser/block_parser.gemspec +++ b/gems/block-parser/block_parser.gemspec @@ -33,7 +33,7 @@ Gem::Specification.new do |spec| spec.add_development_dependency "rubocop", ">= 0.93" spec.add_dependency "activemodel", "> 5.2" - spec.add_dependency "github-markdown", "0.6.9" + spec.add_dependency "commonmarker", "0.21.0" spec.add_dependency "github-markup", "1.6.1" spec.add_dependency "github_url", "0.2.1" spec.add_dependency "gitlab", "4.14.1" diff --git a/gems/block-parser/spec/build_html_from_md_json_spec.rb b/gems/block-parser/spec/build_html_from_md_json_spec.rb index 3f4216c..f73e244 100644 --- a/gems/block-parser/spec/build_html_from_md_json_spec.rb +++ b/gems/block-parser/spec/build_html_from_md_json_spec.rb @@ -82,8 +82,7 @@ describe BlockParser::BuildHtmlFromMdJson do end it "returns the html wrapped in a callout container div" do - expected_html = "

    test

    \n\n

    test

    \n
    " - + expected_html = "

    Danger

    #test\ntest

    \n
    " expect(described_class.process_json( json_hash: json_hash, asset_uploader: Freeloader.new, @@ -191,7 +190,7 @@ describe BlockParser::BuildHtmlFromMdJson do ] } - expected_html = "
    \n" + expected_html = "\n" expect(described_class.process_json( json_hash: json_hash, diff --git a/gems/block-parser/spec/parse_directory_spec.rb b/gems/block-parser/spec/parse_directory_spec.rb index 9a32ded..b123eb1 100644 --- a/gems/block-parser/spec/parse_directory_spec.rb +++ b/gems/block-parser/spec/parse_directory_spec.rb @@ -171,7 +171,7 @@ describe BlockParser::ParseDirectory do content_file_attribute_hashes: [ { title: "Ipynb Test.Ipynb", - html: "

    Introduction

    \n\n

    To open this notebook so you can run this code, navigate to this file's directory at the comandline and then type jupyter notebook

    \n\n

    This notebook here is meant to get you oriented with one of the tools that we will be using for our pre-class material. The notes and exercises will be built into IPython notebooks (like this one). Before coming to each class, you should work through the materials in the pre-class folder and play around/follow along with the code in those notebooks. You should run the code provided, and additionally modify it to learn what happens when you change certain/different pieces.

    \n\n

    Effectively learning to program means having your hands-on the keyboard often. It means playing with code, breaking code, reading errors, and reading google. It means banging your head against the keyboard, but getting to revel in that time spent banging your head when you're program finally works. To that end, this notebook here will hopefully give you a taste of that.

    \n\n

    You might not know exactly what all the lines of code in this notebook do. But, don't worry, because you will know all about these ideas in a week. For now, it's going to be good to get used to your environment and reading and writing some simple Python code. Besides, there's a good chance you'll know what's going on in most of these exercises.

    \n\n

    You'll start off by type some working code, and playing around with it. Then, we'll walk you through an example of working with some broken code (don't worry, it won't be too bad). Finally, you'll finish up by learning how to move the working code into a script, and you'll run you're very first Python program!

    \n\n

    For all of the exercises below, we've included the exact number of cells for you to complete the assignment in. However, if you want more to experiment with, at any time you can click the + button in the upper-left hand corner of the notebook, and a new cell will be created below the one that is currently selected. If you would like to delete a cell you've created for experimentation, simply select the cell and click the edit tab at the top of the notebook. Then, select "Delete Cells".

    \n\n

    Part 1 - Working with Working Code

    \n\n

    For the first part, type in the following code. Type it one line at a time into a cell, and then run that cell (click the button at the top to do this, or try Shift + Enter). Don't copy and paste it, but instead type it - fingers on the keyboard style. Building up your programming chops will come through muscle memory, and tonight will get you started with that. You will be writing your own programs soon enough!

    \n\n

    Type this code out and run it one line at at time:

    \n\n
    my_first_var = 'Wohoo!'\nprint(my_first_var)\n\nmy_second_var = "I'm typing code."\nprint(my_second_var)\n\nmy_third_var = "Even though this doesn't feel like code, I've been told it is code."\nprint(my_third_var) \n\nmy_combined_var = my_first_var + ' ' + my_second_var + ' ' + my_third_var \nprint(my_combined_var)\n
    \n\n

    We've included a cell below for each one of the lines above.

    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n

    Above, we just worked with text. Let's try working with some numbers now.

    \n\n

    Type this code out line by line:

    \n\n
    my_first_num = 3\nprint(my_first_num)\n\nmy_second_num = 13\nprint(my_second_num)\n\nquotient = my_second_num // my_first_num\nremainder = my_second_num % my_first_num\n\nprint(quotient, remainder)\n
    \n\n

    We've included a cell below for each one of the lines above.

    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n

    Part 2 - Working with Error Messages

    \n\n

    Now, let's work with some code that will break (sorry). This can and will happen all the time when writing code. Half the battle of being a good programmer is learning how to read through error messages and fix your code. Google will be your best friend through this. If you ask any software engineer or programmer you may know, she/he will be likely to tell you the same.

    \n\n

    Type out the code below, again line by line. When you encounter the error, we'll walk you through it.

    \n\n
    my_str_var = 'Hello. My favorite number is '\nprint(my_str_var)\n\nmy_fav_num = 3\nprint(my_fav_num)\n\nfull_str = my_str_var + my_fav_num \nprint(full_str)\n
    \n\n

    There is a cell below for each one of the lines above.

    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n

    By now, you'll have encountered the following error:

    \n\n
    TypeError: cannot concatenate 'str' and 'int' objects\n
    \n\n

    We've said Google will be your best friend. Let's put that to the test. Take that error (the entire thing) and paste it into Google. The first link should be this page, a stackoverflow post explaining what this error means and how to fix it. Reading through the first five posts there, we see that we can fix it if we simply throw a str around the variable my_fav_num above. This means the line

    \n\n

    full_str = my_str_var + my_fav_num

    \n\n

    will become:

    \n\n

    full_str = my_str_var + str(my_fav_num).

    \n\n

    Make this change above, and then re-run all your code.

    \n\n
    \n
    \n\n

    Notice, too, that you could put that line in the cell below and it would still work. This is because the notebook's state is the same no matter what cell you're in. This is true throughout the life of a notebook session. So you could actually insert a cell at the top of the notebook and run the same line! However, this is a very dangerous thing to do! If you inserted that line in a cell at the top of the notebook, and then came back to it later after it was shutdown, it would not run. This is because the variables my_str_var and my_fav_num wouldn't have been defined yet. You can try this if you want. Insert the that line at the top of the notebook, then click the Kernel tab at the top of the notebook and select "Restart". This put's the notebook in a state as though you just opened it. Try running that top line now. It won't work. But, if you run the cells that define my_str_var and my_fav_num it will!

    \n\n

    Part 3 - Moving to a Script

    \n\n

    Now that you have some functioning code here in a notebook, it's time for you to turn it into a Python script!

    \n\n

    Aside: Python is known as a scripting language, which means that you technically write scripts, not programs. This distinction is normally not important, and as a result you will frequently hear people say they wrote a Python program (and that's accepted language).

    \n\n

    Python scripts live in .py files. So, what you're going to need to do is re-write all of the code from the exercise above in a file. This will be done in your text editor (Atom if you followed the advice from the introduction).

    \n\n

    Start a new file and name it my_first_program.py. Inside of the file, re-type all of the lines of code from the working version of the example from above. Once you're done, save it in today's folder.

    \n\n

    Now you have a python script you can run! This can be done in one of two ways. The first is by navigating to the directory that contains my_first_program.py and then typing python my_first_program.py at the command line. You should see the statements that were printed above appear in the console.

    \n\n

    The other way to run a python script is from IPython. To do this from the directory that contains my_first_program.py, type ipython. This will start the IPython console, which allows you to interact with Python code in much the same way as we have done in this notebook. Now, to run your script. Simply type run my_first_program.py into IPython and watch the same output appear on the screen!

    \n\n
    \n
    \n", + html: "

    Introduction

    \n

    To open this notebook so you can run this code, navigate to this file's directory at the comandline and then type jupyter notebook

    \n

    This notebook here is meant to get you oriented with one of the tools that we will be using for our pre-class material. The notes and exercises will be built into IPython notebooks (like this one). Before coming to each class, you should work through the materials in the pre-class folder and play around/follow along with the code in those notebooks. You should run the code provided, and additionally modify it to learn what happens when you change certain/different pieces.

    \n

    Effectively learning to program means having your hands-on the keyboard often. It means playing with code, breaking code, reading errors, and reading google. It means banging your head against the keyboard, but getting to revel in that time spent banging your head when you're program finally works. To that end, this notebook here will hopefully give you a taste of that.

    \n

    You might not know exactly what all the lines of code in this notebook do. But, don't worry, because you will know all about these ideas in a week. For now, it's going to be good to get used to your environment and reading and writing some simple Python code. Besides, there's a good chance you'll know what's going on in most of these exercises.

    \n

    You'll start off by type some working code, and playing around with it. Then, we'll walk you through an example of working with some broken code (don't worry, it won't be too bad). Finally, you'll finish up by learning how to move the working code into a script, and you'll run you're very first Python program!

    \n

    For all of the exercises below, we've included the exact number of cells for you to complete the assignment in. However, if you want more to experiment with, at any time you can click the + button in the upper-left hand corner of the notebook, and a new cell will be created below the one that is currently selected. If you would like to delete a cell you've created for experimentation, simply select the cell and click the edit tab at the top of the notebook. Then, select "Delete Cells".

    \n

    Part 1 - Working with Working Code

    \n

    For the first part, type in the following code. Type it one line at a time into a cell, and then run that cell (click the button at the top to do this, or try Shift + Enter). Don't copy and paste it, but instead type it - fingers on the keyboard style. Building up your programming chops will come through muscle memory, and tonight will get you started with that. You will be writing your own programs soon enough!

    \n

    Type this code out and run it one line at at time:

    \n
    my_first_var = 'Wohoo!'\nprint(my_first_var)\n\nmy_second_var = "I'm typing code."\nprint(my_second_var)\n\nmy_third_var = "Even though this doesn't feel like code, I've been told it is code."\nprint(my_third_var) \n\nmy_combined_var = my_first_var + ' ' + my_second_var + ' ' + my_third_var \nprint(my_combined_var)\n
    \n

    We've included a cell below for each one of the lines above.

    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n

    Above, we just worked with text. Let's try working with some numbers now.

    \n

    Type this code out line by line:

    \n
    my_first_num = 3\nprint(my_first_num)\n\nmy_second_num = 13\nprint(my_second_num)\n\nquotient = my_second_num // my_first_num\nremainder = my_second_num % my_first_num\n\nprint(quotient, remainder)\n
    \n

    We've included a cell below for each one of the lines above.

    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n

    Part 2 - Working with Error Messages

    \n

    Now, let's work with some code that will break (sorry). This can and will happen all the time when writing code. Half the battle of being a good programmer is learning how to read through error messages and fix your code. Google will be your best friend through this. If you ask any software engineer or programmer you may know, she/he will be likely to tell you the same.

    \n

    Type out the code below, again line by line. When you encounter the error, we'll walk you through it.

    \n
    my_str_var = 'Hello. My favorite number is '\nprint(my_str_var)\n\nmy_fav_num = 3\nprint(my_fav_num)\n\nfull_str = my_str_var + my_fav_num \nprint(full_str)\n
    \n

    There is a cell below for each one of the lines above.

    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n

    By now, you'll have encountered the following error:

    \n
    TypeError: cannot concatenate 'str' and 'int' objects\n
    \n

    We've said Google will be your best friend. Let's put that to the test. Take that error (the entire thing) and paste it into Google. The first link should be this page, a stackoverflow post explaining what this error means and how to fix it. Reading through the first five posts there, we see that we can fix it if we simply throw a str around the variable my_fav_num above. This means the line

    \n

    full_str = my_str_var + my_fav_num

    \n

    will become:

    \n

    full_str = my_str_var + str(my_fav_num).

    \n

    Make this change above, and then re-run all your code.

    \n
    \n
    \n

    Notice, too, that you could put that line in the cell below and it would still work. This is because the notebook's state is the same no matter what cell you're in. This is true throughout the life of a notebook session. So you could actually insert a cell at the top of the notebook and run the same line! However, this is a very dangerous thing to do! If you inserted that line in a cell at the top of the notebook, and then came back to it later after it was shutdown, it would not run. This is because the variables my_str_var and my_fav_num wouldn't have been defined yet. You can try this if you want. Insert the that line at the top of the notebook, then click the Kernel tab at the top of the notebook and select "Restart". This put's the notebook in a state as though you just opened it. Try running that top line now. It won't work. But, if you run the cells that define my_str_var and my_fav_num it will!

    \n

    Part 3 - Moving to a Script

    \n

    Now that you have some functioning code here in a notebook, it's time for you to turn it into a Python script!

    \n

    Aside: Python is known as a scripting language, which means that you technically write scripts, not programs. This distinction is normally not important, and as a result you will frequently hear people say they wrote a Python program (and that's accepted language).

    \n

    Python scripts live in .py files. So, what you're going to need to do is re-write all of the code from the exercise above in a file. This will be done in your text editor (Atom if you followed the advice from the introduction).

    \n

    Start a new file and name it my_first_program.py. Inside of the file, re-type all of the lines of code from the working version of the example from above. Once you're done, save it in today's folder.

    \n

    Now you have a python script you can run! This can be done in one of two ways. The first is by navigating to the directory that contains my_first_program.py and then typing python my_first_program.py at the command line. You should see the statements that were printed above appear in the console.

    \n

    The other way to run a python script is from IPython. To do this from the directory that contains my_first_program.py, type ipython. This will start the IPython console, which allows you to interact with Python code in much the same way as we have done in this notebook. Now, to run your script. Simply type run my_first_program.py into IPython and watch the same output appear on the screen!

    \n
    \n
    \n", challenges: [], path: "/ipynb-test.ipynb", content_file_type: BlockParser::ParseStandards::CONTENT_FILE_TYPES[:lesson], -- GitLab From 140fa8fcdccdf943c09467efa43b2a08ad314169 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Thu, 15 Oct 2020 11:06:56 -1000 Subject: [PATCH 174/283] Upgrade to Rails 6 --- Gemfile | 3 +- Gemfile.lock | 194 ++++++++++-------- bin/bundle | 2 +- bin/setup | 4 +- bin/update | 6 +- bin/yarn | 6 +- config/application.rb | 2 + config/boot.rb | 5 +- config/environment.rb | 2 +- config/environments/development.rb | 20 +- config/environments/production.rb | 38 +--- config/environments/test.rb | 8 +- config/initializers/assets.rb | 6 +- .../initializers/content_security_policy.rb | 25 +++ .../new_framework_defaults_5_2.rb | 38 ++++ config/puma.rb | 30 +-- config/storage.yml | 34 +++ gems/block-parser/Gemfile.lock | 61 +++--- gems/block-parser/block_parser.gemspec | 30 +-- 19 files changed, 307 insertions(+), 207 deletions(-) create mode 100644 config/initializers/content_security_policy.rb create mode 100644 config/initializers/new_framework_defaults_5_2.rb create mode 100644 config/storage.yml diff --git a/Gemfile b/Gemfile index 8cc46b1..d937d75 100644 --- a/Gemfile +++ b/Gemfile @@ -14,7 +14,7 @@ gem "puma" gem "pundit" gem "httparty" gem "pagy" -gem "rails", "~> 5.2.4" +gem "rails" gem "sidekiq" gem "dotenv-rails" gem "rubyzip" @@ -79,6 +79,7 @@ group :development do gem "better_errors" gem "binding_of_caller" gem "letter_opener" + gem "listen" end group :test do diff --git a/Gemfile.lock b/Gemfile.lock index 433980f..12b55c6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,75 +2,89 @@ PATH remote: gems/block-parser specs: block_parser (0.1.0) - activemodel (> 5.2) - commonmarker (= 0.21.0) - github-markup (= 1.6.1) - github_url (= 0.2.1) - gitlab (= 4.14.1) - nokogiri (= 1.8.0) - octokit (= 4.3.0) - psych (= 2.2.4) - redcarpet (= 3.3.4) - rspec_junit_formatter (>= 0.4.1) + activemodel + commonmarker + github-markup + github_url + gitlab + nokogiri + octokit + psych + redcarpet + rspec_junit_formatter GEM remote: https://rubygems.org/ specs: - actioncable (5.2.4.4) - actionpack (= 5.2.4.4) + actioncable (6.0.3.4) + actionpack (= 6.0.3.4) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailer (5.2.4.4) - actionpack (= 5.2.4.4) - actionview (= 5.2.4.4) - activejob (= 5.2.4.4) + actionmailbox (6.0.3.4) + actionpack (= 6.0.3.4) + activejob (= 6.0.3.4) + activerecord (= 6.0.3.4) + activestorage (= 6.0.3.4) + activesupport (= 6.0.3.4) + mail (>= 2.7.1) + actionmailer (6.0.3.4) + actionpack (= 6.0.3.4) + actionview (= 6.0.3.4) + activejob (= 6.0.3.4) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.2.4.4) - actionview (= 5.2.4.4) - activesupport (= 5.2.4.4) + actionpack (6.0.3.4) + actionview (= 6.0.3.4) + activesupport (= 6.0.3.4) rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.2.4.4) - activesupport (= 5.2.4.4) + rails-html-sanitizer (~> 1.0, >= 1.2.0) + actiontext (6.0.3.4) + actionpack (= 6.0.3.4) + activerecord (= 6.0.3.4) + activestorage (= 6.0.3.4) + activesupport (= 6.0.3.4) + nokogiri (>= 1.8.5) + actionview (6.0.3.4) + activesupport (= 6.0.3.4) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (5.2.4.4) - activesupport (= 5.2.4.4) + rails-html-sanitizer (~> 1.1, >= 1.2.0) + activejob (6.0.3.4) + activesupport (= 6.0.3.4) globalid (>= 0.3.6) - activemodel (5.2.4.4) - activesupport (= 5.2.4.4) - activerecord (5.2.4.4) - activemodel (= 5.2.4.4) - activesupport (= 5.2.4.4) - arel (>= 9.0) - activestorage (5.2.4.4) - actionpack (= 5.2.4.4) - activerecord (= 5.2.4.4) + activemodel (6.0.3.4) + activesupport (= 6.0.3.4) + activerecord (6.0.3.4) + activemodel (= 6.0.3.4) + activesupport (= 6.0.3.4) + activestorage (6.0.3.4) + actionpack (= 6.0.3.4) + activejob (= 6.0.3.4) + activerecord (= 6.0.3.4) marcel (~> 0.3.1) - activesupport (5.2.4.4) + activesupport (6.0.3.4) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) - addressable (2.4.0) + zeitwerk (~> 2.2, >= 2.2.2) + addressable (2.7.0) + public_suffix (>= 2.0.2, < 5.0) analytics-ruby (2.2.8) apitome (0.3.0) kramdown railties - arel (9.0.0) ast (2.4.1) autoprefixer-rails (10.0.1.0) execjs aws-eventstream (1.1.0) - aws-partitions (1.381.0) + aws-partitions (1.382.0) aws-sdk (3.0.1) aws-sdk-resources (~> 3) - aws-sdk-accessanalyzer (1.12.0) + aws-sdk-accessanalyzer (1.13.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-acm (1.38.0) @@ -139,7 +153,7 @@ GEM aws-sdk-braket (1.4.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-budgets (1.35.0) + aws-sdk-budgets (1.36.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-chime (1.37.0) @@ -246,10 +260,10 @@ GEM aws-sdk-costandusagereportservice (1.28.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-costexplorer (1.51.0) + aws-sdk-costexplorer (1.52.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-databasemigrationservice (1.44.0) + aws-sdk-databasemigrationservice (1.45.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-dataexchange (1.10.0) @@ -363,13 +377,13 @@ GEM aws-sdk-globalaccelerator (1.23.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-glue (1.74.0) + aws-sdk-glue (1.75.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-greengrass (1.37.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-groundstation (1.14.0) + aws-sdk-groundstation (1.15.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-guardduty (1.42.0) @@ -396,7 +410,7 @@ GEM aws-sdk-inspector (1.32.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-iot (1.58.0) + aws-sdk-iot (1.59.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-iot1clickdevicesservice (1.26.0) @@ -489,7 +503,7 @@ GEM aws-sdk-macie (1.25.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-macie2 (1.12.0) + aws-sdk-macie2 (1.13.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-managedblockchain (1.17.0) @@ -603,7 +617,7 @@ GEM aws-sdk-ram (1.22.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-rds (1.103.0) + aws-sdk-rds (1.104.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-rdsdataservice (1.23.0) @@ -615,7 +629,7 @@ GEM aws-sdk-redshiftdataapiservice (1.2.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-rekognition (1.46.0) + aws-sdk-rekognition (1.47.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-resourcegroups (1.32.0) @@ -937,7 +951,7 @@ GEM aws-sdk-sqs (1.34.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-ssm (1.93.0) + aws-sdk-ssm (1.94.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-ssoadmin (1.3.0) @@ -976,7 +990,7 @@ GEM aws-sdk-transcribestreamingservice (1.22.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-transfer (1.27.0) + aws-sdk-transfer (1.28.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-translate (1.28.0) @@ -997,16 +1011,16 @@ GEM aws-sdk-worklink (1.21.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-workmail (1.31.0) + aws-sdk-workmail (1.32.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-workmailmessageflow (1.9.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-workspaces (1.47.0) + aws-sdk-workspaces (1.48.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-xray (1.33.0) + aws-sdk-xray (1.34.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sigv2 (1.0.1) @@ -1066,16 +1080,16 @@ GEM factory_bot_rails (6.1.0) factory_bot (~> 6.1.0) railties (>= 5.0.0) - faraday (0.9.2) + faraday (1.0.1) multipart-post (>= 1.2, < 3) ffi (1.13.1) flamegraph (0.9.5) font-awesome-rails (4.7.0.5) railties (>= 3.2, < 6.1) foreman (0.87.2) - github-markup (1.6.1) + github-markup (3.0.4) github_url (0.2.1) - gitlab (4.14.1) + gitlab (4.16.1) httparty (~> 0.14, >= 0.14.0) terminal-table (~> 1.5, >= 1.5.1) globalid (0.4.2) @@ -1105,10 +1119,13 @@ GEM jwt (2.2.2) kramdown (2.3.0) rexml - launchy (2.4.3) - addressable (~> 2.3) + launchy (2.5.0) + addressable (~> 2.7) letter_opener (1.7.0) launchy (~> 2.2) + listen (3.2.1) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) loofah (2.7.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) @@ -1125,7 +1142,7 @@ GEM mime-types-data (3.2020.0512) mimemagic (0.3.5) mini_mime (1.0.2) - mini_portile2 (2.2.0) + mini_portile2 (2.4.0) minitest (5.14.2) msgpack (1.3.3) multi_json (1.15.0) @@ -1133,10 +1150,11 @@ GEM multipart-post (2.1.1) mustache (1.1.1) nio4r (2.5.4) - nokogiri (1.8.0) - mini_portile2 (~> 2.2.0) - octokit (4.3.0) - sawyer (~> 0.7.0, >= 0.5.3) + nokogiri (1.10.10) + mini_portile2 (~> 2.4.0) + octokit (4.18.0) + faraday (>= 0.9) + sawyer (~> 0.8.0, >= 0.5.3) overcommit (0.57.0) childprocess (>= 0.6.3, < 5) iniparse (~> 1.4) @@ -1146,7 +1164,8 @@ GEM ast (~> 2.4.1) pg (1.2.3) popper_js (1.16.0) - psych (2.2.4) + psych (3.2.0) + public_suffix (4.0.6) puma (5.0.2) nio4r (~> 2.0) pundit (2.1.0) @@ -1160,18 +1179,20 @@ GEM rack rack-test (1.1.0) rack (>= 1.0, < 3) - rails (5.2.4.4) - actioncable (= 5.2.4.4) - actionmailer (= 5.2.4.4) - actionpack (= 5.2.4.4) - actionview (= 5.2.4.4) - activejob (= 5.2.4.4) - activemodel (= 5.2.4.4) - activerecord (= 5.2.4.4) - activestorage (= 5.2.4.4) - activesupport (= 5.2.4.4) + rails (6.0.3.4) + actioncable (= 6.0.3.4) + actionmailbox (= 6.0.3.4) + actionmailer (= 6.0.3.4) + actionpack (= 6.0.3.4) + actiontext (= 6.0.3.4) + actionview (= 6.0.3.4) + activejob (= 6.0.3.4) + activemodel (= 6.0.3.4) + activerecord (= 6.0.3.4) + activestorage (= 6.0.3.4) + activesupport (= 6.0.3.4) bundler (>= 1.3.0) - railties (= 5.2.4.4) + railties (= 6.0.3.4) sprockets-rails (>= 2.0.0) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) @@ -1182,21 +1203,24 @@ GEM nokogiri (>= 1.6) rails-html-sanitizer (1.3.0) loofah (~> 2.3) - railties (5.2.4.4) - actionpack (= 5.2.4.4) - activesupport (= 5.2.4.4) + railties (6.0.3.4) + actionpack (= 6.0.3.4) + activesupport (= 6.0.3.4) method_source rake (>= 0.8.7) - thor (>= 0.19.0, < 2.0) + thor (>= 0.20.3, < 2.0) rainbow (3.0.0) rake (13.0.1) + rb-fsevent (0.10.4) + rb-inotify (0.10.1) + ffi (~> 1.0) react-rails (2.6.1) babel-transpiler (>= 0.7.0) connection_pool execjs railties (>= 3.2) tilt - redcarpet (3.3.4) + redcarpet (3.5.0) redis (4.2.2) regexp_parser (1.8.2) rexml (3.2.4) @@ -1252,9 +1276,9 @@ GEM sprockets (> 3.0) sprockets-rails tilt - sawyer (0.7.0) - addressable (>= 2.3.5, < 2.5) - faraday (~> 0.8, < 0.10) + sawyer (0.8.2) + addressable (>= 2.3.5) + faraday (> 0.8, < 2.0) scout_apm (2.6.9) parser selenium-webdriver (3.142.7) @@ -1312,6 +1336,7 @@ GEM websocket-extensions (0.1.5) xpath (3.2.0) nokogiri (~> 1.8) + zeitwerk (2.4.0) zip-zip (0.3) rubyzip (>= 1.0.0) @@ -1347,6 +1372,7 @@ DEPENDENCIES json_spec jwt letter_opener + listen mathjax-rails memory_profiler octokit @@ -1357,7 +1383,7 @@ DEPENDENCIES pundit rack-attack rack-mini-profiler - rails (~> 5.2.4) + rails rails-controller-testing react-rails redis diff --git a/bin/bundle b/bin/bundle index 66e9889..f19acf5 100755 --- a/bin/bundle +++ b/bin/bundle @@ -1,3 +1,3 @@ #!/usr/bin/env ruby -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) load Gem.bin_path('bundler', 'bundle') diff --git a/bin/setup b/bin/setup index 78c4e86..94fd4d7 100755 --- a/bin/setup +++ b/bin/setup @@ -1,10 +1,9 @@ #!/usr/bin/env ruby -require 'pathname' require 'fileutils' include FileUtils # path to your application root. -APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) +APP_ROOT = File.expand_path('..', __dir__) def system!(*args) system(*args) || abort("\n== Command #{args} failed ==") @@ -21,7 +20,6 @@ chdir APP_ROOT do # Install JavaScript dependencies if using Yarn # system('bin/yarn') - # puts "\n== Copying sample files ==" # unless File.exist?('config/database.yml') # cp 'config/database.yml.sample', 'config/database.yml' diff --git a/bin/update b/bin/update index a8e4462..58bfaed 100755 --- a/bin/update +++ b/bin/update @@ -1,10 +1,9 @@ #!/usr/bin/env ruby -require 'pathname' require 'fileutils' include FileUtils # path to your application root. -APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) +APP_ROOT = File.expand_path('..', __dir__) def system!(*args) system(*args) || abort("\n== Command #{args} failed ==") @@ -18,6 +17,9 @@ chdir APP_ROOT do system! 'gem install bundler --conservative' system('bundle check') || system!('bundle install') + # Install JavaScript dependencies if using Yarn + # system('bin/yarn') + puts "\n== Updating database ==" system! 'bin/rails db:migrate' diff --git a/bin/yarn b/bin/yarn index c2bacef..460dd56 100755 --- a/bin/yarn +++ b/bin/yarn @@ -1,8 +1,8 @@ #!/usr/bin/env ruby -VENDOR_PATH = File.expand_path('..', __dir__) -Dir.chdir(VENDOR_PATH) do +APP_ROOT = File.expand_path('..', __dir__) +Dir.chdir(APP_ROOT) do begin - exec "yarnpkg #{ARGV.join(" ")}" + exec "yarnpkg", *ARGV rescue Errno::ENOENT $stderr.puts "Yarn executable was not detected in the system." $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" diff --git a/config/application.rb b/config/application.rb index 4aa0ed1..ef9d3f5 100644 --- a/config/application.rb +++ b/config/application.rb @@ -5,9 +5,11 @@ require "rails" require "active_model/railtie" require "active_job/railtie" require "active_record/railtie" +require "active_storage/engine" require "action_controller/railtie" require "action_mailer/railtie" require "action_view/railtie" +# require "action_cable/engine" require "sprockets/railtie" # require "rails/test_unit/railtie" require "sidekiq/web" diff --git a/config/boot.rb b/config/boot.rb index 2820116..ec779bb 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,3 +1,4 @@ -ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) -require "bundler/setup" # Set up gems listed in the Gemfile. +require 'bundler/setup' # Set up gems listed in the Gemfile. +#require 'bootsnap/setup' # Speed up boot time by caching expensive operations. diff --git a/config/environment.rb b/config/environment.rb index cac5315..426333b 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -1,5 +1,5 @@ # Load the Rails application. -require_relative "application" +require_relative 'application' # Initialize the Rails application. Rails.application.initialize! diff --git a/config/environments/development.rb b/config/environments/development.rb index 42e6d03..790abda 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -1,7 +1,4 @@ Rails.application.configure do - # Verifies that versions and hashed value of the package contents in the project's package.json - - config.webpacker.check_yarn_integrity = true # Settings specified here will take precedence over those in config/application.rb. # In the development environment your application's code is reloaded on @@ -16,12 +13,13 @@ Rails.application.configure do config.consider_all_requests_local = true # Enable/disable caching. By default caching is disabled. - if Rails.root.join("tmp/caching-dev.txt").exist? + # Run rails dev:cache to toggle caching. + if Rails.root.join('tmp', 'caching-dev.txt').exist? config.action_controller.perform_caching = true config.cache_store = :memory_store config.public_file_server.headers = { - "Cache-Control" => "public, max-age=#{2.days.seconds.to_i}" + 'Cache-Control' => "public, max-age=#{2.days.to_i}" } else config.action_controller.perform_caching = false @@ -29,10 +27,11 @@ Rails.application.configure do config.cache_store = :null_store end + # Store uploaded files on the local file system (see config/storage.yml for options) + config.active_storage.service = :local + # Don't care if the mailer can't send. - config.action_mailer.delivery_method = :letter_opener - config.action_mailer.raise_delivery_errors = true - config.action_mailer.perform_caching = false + config.action_mailer.raise_delivery_errors = false config.action_mailer.perform_caching = false @@ -42,6 +41,9 @@ Rails.application.configure do # Raise an error on page load if there are pending migrations. config.active_record.migration_error = :page_load + # Highlight code that triggered database queries in logs. + config.active_record.verbose_query_logs = true + # Debug mode disables concatenation and preprocessing of assets. # This option may cause significant delays in view rendering with a large # number of complex assets. @@ -55,7 +57,7 @@ Rails.application.configure do # Use an evented file watcher to asynchronously detect changes in source code, # routes, locales, etc. This feature depends on the listen gem. - # config.file_watcher = ActiveSupport::EventedFileUpdateChecker + config.file_watcher = ActiveSupport::EventedFileUpdateChecker # Set default host for url_helpers Rails.application.routes.default_url_options[:host] = "http://localhost:3003" diff --git a/config/environments/production.rb b/config/environments/production.rb index 9e68ea7..cc9244a 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,6 +1,4 @@ Rails.application.configure do - # Verifies that versions and hashed value of the package contents in the project's package.json - config.webpacker.check_yarn_integrity = false # Settings specified here will take precedence over those in config/application.rb. # Code is not reloaded between requests. @@ -16,25 +14,21 @@ Rails.application.configure do config.consider_all_requests_local = false config.action_controller.perform_caching = true - # Attempt to read encrypted secrets from `config/secrets.yml.enc`. - # Requires an encryption key in `ENV["RAILS_MASTER_KEY"]` or - # `config/secrets.yml.key`. - config.read_encrypted_secrets = true + # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] + # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). + # config.require_master_key = true # Disable serving static files from the `/public` folder by default since # Apache or NGINX already handles this. - config.public_file_server.enabled = true + config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? # Compress JavaScripts and CSS. config.assets.js_compressor = :uglifier - config.assets.css_compressor = :sass + # config.assets.css_compressor = :sass # Do not fallback to assets pipeline if a precompiled asset is missed. config.assets.compile = false - # Generate digests for assets URLs. - config.assets.digest = true - # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb # Enable serving of images, stylesheets, and JavaScripts from an asset server. @@ -44,8 +38,11 @@ Rails.application.configure do # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX + # Store uploaded files on the local file system (see config/storage.yml for options) + config.active_storage.service = :local + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. - config.force_ssl = false + # config.force_ssl = true # Enable stdout logger. config.logger = Logger.new(STDOUT) @@ -55,7 +52,7 @@ Rails.application.configure do config.log_level = :debug # Prepend all log lines with the following tags. - config.log_tags = [:request_id] + config.log_tags = [ :request_id ] # Use a different cache store in production. # config.cache_store = :mem_cache_store @@ -63,6 +60,7 @@ Rails.application.configure do # Use a real queuing backend for Active Job (and separate queues per environment) # config.active_job.queue_adapter = :resque # config.active_job.queue_name_prefix = "forge_#{Rails.env}" + config.action_mailer.perform_caching = false # Ignore bad email addresses and do not raise email delivery errors. @@ -91,18 +89,4 @@ Rails.application.configure do # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false - - if ENV["ACTIONMAILER_HOST"].present? - Rails.application.routes.default_url_options[:host] = ENV["ACTIONMAILER_HOST"] - end end - -ActionMailer::Base.smtp_settings = { - user_name: Rails.application.secrets.sendgrid_username, - password: Rails.application.secrets.sendgrid_password, - domain: Rails.application.secrets.actionmailer_host, - address: "smtp.sendgrid.net", - port: 587, - authentication: :plain, - enable_starttls_auto: true -} diff --git a/config/environments/test.rb b/config/environments/test.rb index 7d1d7f6..b1fea1e 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -15,7 +15,7 @@ Rails.application.configure do # Configure public file server for tests with Cache-Control for performance. config.public_file_server.enabled = true config.public_file_server.headers = { - "Cache-Control" => "public, max-age=#{1.hour.seconds.to_i}" + 'Cache-Control' => "public, max-age=#{1.hour.to_i}" } # Show full error reports and disable caching. @@ -27,6 +27,10 @@ Rails.application.configure do # Disable request forgery protection in test environment. config.action_controller.allow_forgery_protection = false + + # Store uploaded files on the local file system in a temporary directory + config.active_storage.service = :test + config.action_mailer.perform_caching = false # Tell Action Mailer not to deliver emails to the real world. @@ -39,7 +43,7 @@ Rails.application.configure do # Raises error for missing translations # config.action_view.raise_on_missing_translations = true - # + config.active_job.queue_adapter = :test # Set default host for url_helpers diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index d633520..4b828e8 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -1,14 +1,14 @@ # Be sure to restart your server when you modify this file. # Version of your assets, change this if you want to expire all your assets. -Rails.application.config.assets.version = "1.0" +Rails.application.config.assets.version = '1.0' # Add additional assets to the asset load path. # Rails.application.config.assets.paths << Emoji.images_path # Add Yarn node_modules folder to the asset load path. -Rails.application.config.assets.paths << Rails.root.join("node_modules") +Rails.application.config.assets.paths << Rails.root.join('node_modules') # Precompile additional assets. # application.js, application.css, and all non-JS/CSS in the app/assets # folder are already added. -Rails.application.config.assets.precompile += %w[mobile.css mobile.js] +# Rails.application.config.assets.precompile += %w( admin.js admin.css ) diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb new file mode 100644 index 0000000..d3bcaa5 --- /dev/null +++ b/config/initializers/content_security_policy.rb @@ -0,0 +1,25 @@ +# Be sure to restart your server when you modify this file. + +# Define an application-wide content security policy +# For further information see the following documentation +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy + +# Rails.application.config.content_security_policy do |policy| +# policy.default_src :self, :https +# policy.font_src :self, :https, :data +# policy.img_src :self, :https, :data +# policy.object_src :none +# policy.script_src :self, :https +# policy.style_src :self, :https + +# # Specify URI for violation reports +# # policy.report_uri "/csp-violation-report-endpoint" +# end + +# If you are using UJS then enable automatic nonce generation +# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } + +# Report CSP violations to a specified URI +# For further information see the following documentation: +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only +# Rails.application.config.content_security_policy_report_only = true diff --git a/config/initializers/new_framework_defaults_5_2.rb b/config/initializers/new_framework_defaults_5_2.rb new file mode 100644 index 0000000..c383d07 --- /dev/null +++ b/config/initializers/new_framework_defaults_5_2.rb @@ -0,0 +1,38 @@ +# Be sure to restart your server when you modify this file. +# +# This file contains migration options to ease your Rails 5.2 upgrade. +# +# Once upgraded flip defaults one by one to migrate to the new default. +# +# Read the Guide for Upgrading Ruby on Rails for more info on each option. + +# Make Active Record use stable #cache_key alongside new #cache_version method. +# This is needed for recyclable cache keys. +# Rails.application.config.active_record.cache_versioning = true + +# Use AES-256-GCM authenticated encryption for encrypted cookies. +# Also, embed cookie expiry in signed or encrypted cookies for increased security. +# +# This option is not backwards compatible with earlier Rails versions. +# It's best enabled when your entire app is migrated and stable on 5.2. +# +# Existing cookies will be converted on read then written with the new scheme. +# Rails.application.config.action_dispatch.use_authenticated_cookie_encryption = true + +# Use AES-256-GCM authenticated encryption as default cipher for encrypting messages +# instead of AES-256-CBC, when use_authenticated_message_encryption is set to true. +# Rails.application.config.active_support.use_authenticated_message_encryption = true + +# Add default protection from forgery to ActionController::Base instead of in +# ApplicationController. +# Rails.application.config.action_controller.default_protect_from_forgery = true + +# Store boolean values are in sqlite3 databases as 1 and 0 instead of 't' and +# 'f' after migrating old data. +# Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true + +# Use SHA-1 instead of MD5 to generate non-sensitive digests, such as the ETag header. +# Rails.application.config.active_support.use_sha1_digests = true + +# Make `form_with` generate id attributes for any generated HTML tags. +# Rails.application.config.action_view.form_with_generates_ids = true diff --git a/config/puma.rb b/config/puma.rb index ba9b984..b210207 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -15,43 +15,23 @@ port ENV.fetch("PORT") { 3000 } # environment ENV.fetch("RAILS_ENV") { "development" } +# Specifies the `pidfile` that Puma will use. +pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" } + # Specifies the number of `workers` to boot in clustered mode. # Workers are forked webserver processes. If using threads and workers together # the concurrency of the application would be max `threads` * `workers`. # Workers do not work on JRuby or Windows (both of which do not support # processes). # -workers ENV.fetch("WEB_CONCURRENCY") { 2 } +# workers ENV.fetch("WEB_CONCURRENCY") { 2 } # Use the `preload_app!` method when specifying a `workers` number. # This directive tells Puma to first boot the application and load code # before forking the application. This takes advantage of Copy On Write -# process behavior so workers use less memory. If you use this option -# you need to make sure to reconnect any threads in the `on_worker_boot` -# block. +# process behavior so workers use less memory. # # preload_app! -# If you are preloading your application and using Active Record, it's -# recommended that you close any connections to the database before workers -# are forked to prevent connection leakage. -# -# before_fork do -# ActiveRecord::Base.connection_pool.disconnect! if defined?(ActiveRecord) -# end - -# The code in the `on_worker_boot` will be called if you are using -# clustered mode by specifying a number of `workers`. After each worker -# process is booted, this block will be run. If you are using the `preload_app!` -# option, you will want to use this block to reconnect to any threads -# or connections that may have been created at application boot, as Ruby -# cannot share connections between processes. -# -before_fork do - # Used for heroku metrics for ruby - Barnes.start - # ActiveRecord::Base.establish_connection if defined?(ActiveRecord) -end - # Allow puma to be restarted by `rails restart` command. plugin :tmp_restart diff --git a/config/storage.yml b/config/storage.yml new file mode 100644 index 0000000..d32f76e --- /dev/null +++ b/config/storage.yml @@ -0,0 +1,34 @@ +test: + service: Disk + root: <%= Rails.root.join("tmp/storage") %> + +local: + service: Disk + root: <%= Rails.root.join("storage") %> + +# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) +# amazon: +# service: S3 +# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> +# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> +# region: us-east-1 +# bucket: your_own_bucket + +# Remember not to checkin your GCS keyfile to a repository +# google: +# service: GCS +# project: your_project +# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> +# bucket: your_own_bucket + +# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) +# microsoft: +# service: AzureStorage +# storage_account_name: your_account_name +# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> +# container: your_container_name + +# mirror: +# service: Mirror +# primary: local +# mirrors: [ amazon, google, microsoft ] diff --git a/gems/block-parser/Gemfile.lock b/gems/block-parser/Gemfile.lock index 24076a7..3d84f82 100644 --- a/gems/block-parser/Gemfile.lock +++ b/gems/block-parser/Gemfile.lock @@ -2,16 +2,16 @@ PATH remote: . specs: block_parser (0.1.0) - activemodel (> 5.2) - commonmarker (= 0.21.0) - github-markup (= 1.6.1) - github_url (= 0.2.1) - gitlab (= 4.14.1) - nokogiri (= 1.8.0) - octokit (= 4.3.0) - psych (= 2.2.4) - redcarpet (= 3.3.4) - rspec_junit_formatter (>= 0.4.1) + activemodel + commonmarker + github-markup + github_url + gitlab + nokogiri + octokit + psych + redcarpet + rspec_junit_formatter GEM remote: https://rubygems.org/ @@ -24,18 +24,19 @@ GEM minitest (~> 5.1) tzinfo (~> 1.1) zeitwerk (~> 2.2, >= 2.2.2) - addressable (2.4.0) + addressable (2.7.0) + public_suffix (>= 2.0.2, < 5.0) ast (2.4.1) byebug (11.1.3) commonmarker (0.21.0) ruby-enum (~> 0.5) concurrent-ruby (1.1.7) diff-lcs (1.4.4) - faraday (0.9.2) + faraday (1.0.1) multipart-post (>= 1.2, < 3) - github-markup (1.6.1) + github-markup (3.0.4) github_url (0.2.1) - gitlab (4.14.1) + gitlab (4.16.1) httparty (~> 0.14, >= 0.14.0) terminal-table (~> 1.5, >= 1.5.1) httparty (0.18.1) @@ -46,21 +47,23 @@ GEM mime-types (3.3.1) mime-types-data (~> 3.2015) mime-types-data (3.2020.0512) - mini_portile2 (2.2.0) + mini_portile2 (2.4.0) minitest (5.14.2) multi_xml (0.6.0) multipart-post (2.1.1) - nokogiri (1.8.0) - mini_portile2 (~> 2.2.0) - octokit (4.3.0) - sawyer (~> 0.7.0, >= 0.5.3) + nokogiri (1.10.10) + mini_portile2 (~> 2.4.0) + octokit (4.18.0) + faraday (>= 0.9) + sawyer (~> 0.8.0, >= 0.5.3) parallel (1.19.2) parser (2.7.2.0) ast (~> 2.4.1) - psych (2.2.4) + psych (3.2.0) + public_suffix (4.0.6) rainbow (3.0.0) rake (13.0.1) - redcarpet (3.3.4) + redcarpet (3.5.0) regexp_parser (1.8.2) rexml (3.2.4) rspec (3.9.0) @@ -92,9 +95,9 @@ GEM ruby-enum (0.8.0) i18n ruby-progressbar (1.10.1) - sawyer (0.7.0) - addressable (>= 2.3.5, < 2.5) - faraday (~> 0.8, < 0.10) + sawyer (0.8.2) + addressable (>= 2.3.5) + faraday (> 0.8, < 2.0) terminal-table (1.8.0) unicode-display_width (~> 1.1, >= 1.1.1) thread_safe (0.3.6) @@ -108,11 +111,11 @@ PLATFORMS DEPENDENCIES block_parser! - bundler (~> 2.0) - byebug (= 11.1.3) - rake (~> 13.0) - rspec (~> 3.8) - rubocop (>= 0.93) + bundler + byebug + rake + rspec + rubocop BUNDLED WITH 2.1.4 diff --git a/gems/block-parser/block_parser.gemspec b/gems/block-parser/block_parser.gemspec index 88f0fe1..5d1cbe3 100644 --- a/gems/block-parser/block_parser.gemspec +++ b/gems/block-parser/block_parser.gemspec @@ -26,20 +26,20 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^bin/}) { |f| f[3..-1] } spec.require_paths = ["lib"] - spec.add_development_dependency "bundler", "~> 2.0" - spec.add_development_dependency "byebug", "11.1.3" - spec.add_development_dependency "rake", "~> 13.0" - spec.add_development_dependency "rspec", "~> 3.8" - spec.add_development_dependency "rubocop", ">= 0.93" + spec.add_development_dependency "bundler" + spec.add_development_dependency "byebug" + spec.add_development_dependency "rake" + spec.add_development_dependency "rspec" + spec.add_development_dependency "rubocop" - spec.add_dependency "activemodel", "> 5.2" - spec.add_dependency "commonmarker", "0.21.0" - spec.add_dependency "github-markup", "1.6.1" - spec.add_dependency "github_url", "0.2.1" - spec.add_dependency "gitlab", "4.14.1" - spec.add_dependency "nokogiri", "1.8.0" - spec.add_dependency "octokit", "4.3.0" - spec.add_dependency "psych", "2.2.4" - spec.add_dependency "redcarpet", "3.3.4" - spec.add_dependency "rspec_junit_formatter", ">= 0.4.1" + spec.add_dependency "activemodel" + spec.add_dependency "commonmarker" + spec.add_dependency "github-markup" + spec.add_dependency "github_url" + spec.add_dependency "gitlab" + spec.add_dependency "nokogiri" + spec.add_dependency "octokit" + spec.add_dependency "psych" + spec.add_dependency "redcarpet" + spec.add_dependency "rspec_junit_formatter" end -- GitLab From 202427548679c5bd586cc1af05b8cd02c67548d9 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Thu, 15 Oct 2020 11:24:46 -1000 Subject: [PATCH 175/283] Fix conversion of datetime to string --- app/presenters/checkpoint_submission_presenter/for_index.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/presenters/checkpoint_submission_presenter/for_index.rb b/app/presenters/checkpoint_submission_presenter/for_index.rb index 5be1a2d..48fc9d8 100644 --- a/app/presenters/checkpoint_submission_presenter/for_index.rb +++ b/app/presenters/checkpoint_submission_presenter/for_index.rb @@ -95,7 +95,7 @@ class CheckpointSubmissionPresenter::ForIndex state: submission["state"], correct_points: submission["correct_points"], total_points: submission["total_points"], - updated_at: DateTime.parse(submission["updated_at"]).in_time_zone(Rails.application.config.time_zone), + updated_at: DateTime.parse(submission["updated_at"].to_s).in_time_zone(Rails.application.config.time_zone), url: url_for_checkpoint_submission(submission["id"]), grader_name: submission["first_name"].blank? ? "" : "#{submission['first_name']} #{submission['last_name']}" } -- GitLab From a64d2cc48850c6805e93e5fe51a0d808f6b32901 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Thu, 15 Oct 2020 13:05:54 -1000 Subject: [PATCH 176/283] Fix update_attributes deprecation warning --- .../cohorts/cohort_releases_controller.rb | 2 +- .../submitted_challenge_answers_controller.rb | 2 +- .../submitted_challenge_answers_controller.rb | 2 +- app/jobs/content_file_visit_job.rb | 2 +- app/models/user.rb | 2 +- app/services/assessment_service.rb | 14 ++++++------ ...eate_submitted_challenge_answer_service.rb | 12 +++++----- ...0412223312_populate_used_by_application.rb | 4 ++-- .../20180813214453_populate_mode_cohorts.rb | 2 +- lib/tasks/content_visibility_update.rake | 2 +- .../activities_controller_spec.rb | 4 ++-- .../checkpoint_submissions_controller_spec.rb | 8 +++---- .../activities_controller_spec.rb | 4 ++-- ...itted_challenge_answers_controller_spec.rb | 4 ++-- .../cohorts/management_feature_spec.rb | 8 +++---- .../features/cohorts/student_progress_spec.rb | 2 +- spec/features/cohorts/submissions_spec.rb | 22 +++++++++---------- .../cohorts/users/challenges_feature_spec.rb | 2 +- .../checkpoint_submissions_spec.rb | 4 ++-- .../content_files/view_feature_spec.rb | 22 +++++++++---------- spec/features_helper.rb | 2 +- spec/jobs/switch_to_branch_job_spec.rb | 2 +- spec/models/checkpoint_submission_spec.rb | 12 +++++----- spec/models/user_spec.rb | 2 +- .../content_file_presenter/for_show_spec.rb | 2 +- .../student_progress_presenter_spec.rb | 10 ++++----- .../activity_aggregator_service_spec.rb | 18 +++++++-------- .../cohort_standard_progress_service_spec.rb | 4 ++-- spec/services/notification_service_spec.rb | 2 +- 29 files changed, 89 insertions(+), 89 deletions(-) diff --git a/app/controllers/cohorts/cohort_releases_controller.rb b/app/controllers/cohorts/cohort_releases_controller.rb index 99a2210..76bf5c8 100644 --- a/app/controllers/cohorts/cohort_releases_controller.rb +++ b/app/controllers/cohorts/cohort_releases_controller.rb @@ -104,7 +104,7 @@ module Cohorts current_cohort_release.update(release_id: release_at_sha.id, pending_release_id: nil, use_latest_release: false) flash_info = { type: "success", msg: msg } elsif release_at_sha.present? && !release_at_sha.successfully_synced? - release_at_sha.update_attributes( + release_at_sha.update( state: Release::STATES[:pending], sync_errors: [] ) diff --git a/app/controllers/cohorts/content_files/submitted_challenge_answers_controller.rb b/app/controllers/cohorts/content_files/submitted_challenge_answers_controller.rb index 968e4d8..5dec944 100644 --- a/app/controllers/cohorts/content_files/submitted_challenge_answers_controller.rb +++ b/app/controllers/cohorts/content_files/submitted_challenge_answers_controller.rb @@ -215,7 +215,7 @@ module Cohorts authorize(current_submitted_challenge_answer) if current_submitted_challenge_answer.processing? - current_submitted_challenge_answer.update_attributes( + current_submitted_challenge_answer.update( status: SubmittedChallengeAnswer::STATUSES[:canceled], test_results: "Tests canceled by student." ) diff --git a/app/controllers/webhooks/assessments_service/submitted_challenge_answers_controller.rb b/app/controllers/webhooks/assessments_service/submitted_challenge_answers_controller.rb index 8eedbb0..751a64b 100644 --- a/app/controllers/webhooks/assessments_service/submitted_challenge_answers_controller.rb +++ b/app/controllers/webhooks/assessments_service/submitted_challenge_answers_controller.rb @@ -21,7 +21,7 @@ module Webhooks status = params[:status] correct = status == SubmittedChallengeAnswer::STATUSES[:correct] points = correct ? submitted_challenge_answer.challenge.points : 0 - submitted_challenge_answer.update_attributes( + submitted_challenge_answer.update( status: status, test_results: results, points: points, diff --git a/app/jobs/content_file_visit_job.rb b/app/jobs/content_file_visit_job.rb index c6ee45b..4931a20 100644 --- a/app/jobs/content_file_visit_job.rb +++ b/app/jobs/content_file_visit_job.rb @@ -19,7 +19,7 @@ class ContentFileVisitJob < ApplicationJob standard_uid: standard_uid ) - visit.update_attributes( + visit.update( visit_count: visit.visit_count + 1, challenge_count: content_file.challenges.count, content_file_path: content_file.path diff --git a/app/models/user.rb b/app/models/user.rb index 6f3563c..0145dc5 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -110,7 +110,7 @@ class User < ApplicationRecord def sandbox sb = Cohort.find_by(user_id: id) if sb - sb.update_attributes(name: "Preview") if sb.name != "Preview" + sb.update(name: "Preview") if sb.name != "Preview" else sb = Cohort.create(uid: "#{id}-#{uid}", name: "Preview", diff --git a/app/services/assessment_service.rb b/app/services/assessment_service.rb index 49f228d..589c245 100644 --- a/app/services/assessment_service.rb +++ b/app/services/assessment_service.rb @@ -36,9 +36,9 @@ class AssessmentService # end # rescue Faraday::ConnectionFailed => e # Honeybadger.notify(e) - # submitted_challenge_answer.update_attributes(status: "failed", test_results: "Connection failed") and return + # submitted_challenge_answer.update(status: "failed", test_results: "Connection failed") and return # end - # submitted_challenge_answer.update_attributes(status: "failed", test_results: "Connection failed") if response.status != 200 + # submitted_challenge_answer.update(status: "failed", test_results: "Connection failed") if response.status != 200 # # response end @@ -60,13 +60,13 @@ class AssessmentService }.to_json end - submitted_challenge_answer.update_attributes(status: "failed", test_results: "Connection failed") if response.status != 200 + submitted_challenge_answer.update(status: "failed", test_results: "Connection failed") if response.status != 200 response rescue Faraday::ConnectionFailed => e Honeybadger.notify(e) - submitted_challenge_answer.update_attributes(status: "failed", test_results: "Connection failed") + submitted_challenge_answer.update(status: "failed", test_results: "Connection failed") rescue GithubUrl::Invalid - submitted_challenge_answer.update_attributes( + submitted_challenge_answer.update( status: SubmittedChallengeAnswer::STATUSES[:invalid_fork], test_results: "Unexpected URL. Please verify that you submitted a full URL." ) @@ -92,9 +92,9 @@ class AssessmentService end rescue Faraday::ConnectionFailed => e Honeybadger.notify(e) - submitted_challenge_answer.update_attributes(status: "failed", test_results: "Connection failed") and return + submitted_challenge_answer.update(status: "failed", test_results: "Connection failed") and return end - submitted_challenge_answer.update_attributes(status: "failed", test_results: "Connection failed") if response.status != 200 + submitted_challenge_answer.update(status: "failed", test_results: "Connection failed") if response.status != 200 response end diff --git a/app/services/create_submitted_challenge_answer_service.rb b/app/services/create_submitted_challenge_answer_service.rb index 5c03958..5840c8b 100644 --- a/app/services/create_submitted_challenge_answer_service.rb +++ b/app/services/create_submitted_challenge_answer_service.rb @@ -115,7 +115,7 @@ module CreateSubmittedChallengeAnswerService def create_project_evaluation_job(challenge, cohort_id, submitted_challenge_answer) if submitted_challenge_answer.answer.empty? - submitted_challenge_answer.update_attributes( + submitted_challenge_answer.update( status: SubmittedChallengeAnswer::STATUSES[:incorrect], test_results: "Please verify that you submitted a full URL.", points: 0 @@ -126,7 +126,7 @@ module CreateSubmittedChallengeAnswerService def create_code_snippet_job(challenge, cohort_id, submitted_challenge_answer) if submitted_challenge_answer.answer.empty? - submitted_challenge_answer.update_attributes( + submitted_challenge_answer.update( status: SubmittedChallengeAnswer::STATUSES[:incorrect], test_results: "Please submit code", points: 0 @@ -137,7 +137,7 @@ module CreateSubmittedChallengeAnswerService def create_custom_snippet_job(challenge, cohort_id, submitted_challenge_answer) if submitted_challenge_answer.answer.empty? - submitted_challenge_answer.update_attributes( + submitted_challenge_answer.update( status: SubmittedChallengeAnswer::STATUSES[:incorrect], test_results: "Please submit code", points: 0 @@ -150,17 +150,17 @@ module CreateSubmittedChallengeAnswerService validate_fork(submitted_challenge_answer, challenge_upstream_path) if validate_fork EvaluateProjectJob.perform_later(submitted_challenge_answer.id, cohort_id) rescue Octokit::InvalidRepository - submitted_challenge_answer.update_attributes( + submitted_challenge_answer.update( status: "invalid_fork", test_results: "Unexpected URL. Be sure you have both user and repo." ) rescue Octokit::NotFound - submitted_challenge_answer.update_attributes( + submitted_challenge_answer.update( status: "invalid_fork", test_results: "Unexpected URL. A repository was not found for that submission url." ) rescue GithubUrl::Invalid, InvalidBranchError, InvalidForkError, ParentMatchError, FolderMatchError => e - submitted_challenge_answer.update_attributes( + submitted_challenge_answer.update( status: "invalid_fork", test_results: "Unexpected URL. #{e.message}" ) diff --git a/db/migrate/20180412223312_populate_used_by_application.rb b/db/migrate/20180412223312_populate_used_by_application.rb index 3824dfe..e75dac7 100644 --- a/db/migrate/20180412223312_populate_used_by_application.rb +++ b/db/migrate/20180412223312_populate_used_by_application.rb @@ -6,9 +6,9 @@ class PopulateUsedByApplication < ActiveRecord::Migration[5.1] def change CohortMigration.all.each do |p| if p.learn_v2 - p.update_attributes(used_by_application: "Learn V2") + p.update(used_by_application: "Learn V2") else - p.update_attributes(used_by_application: "Learn") + p.update(used_by_application: "Learn") end end end diff --git a/db/migrate/20180813214453_populate_mode_cohorts.rb b/db/migrate/20180813214453_populate_mode_cohorts.rb index cb7a56f..586d669 100644 --- a/db/migrate/20180813214453_populate_mode_cohorts.rb +++ b/db/migrate/20180813214453_populate_mode_cohorts.rb @@ -5,7 +5,7 @@ class PopulateModeCohorts < ActiveRecord::Migration[5.1] def change CohortMigration.all.each do |p| - p.update_attributes(mode: Cohort::MODES[:mastery]) + p.update(mode: Cohort::MODES[:mastery]) end end end diff --git a/lib/tasks/content_visibility_update.rake b/lib/tasks/content_visibility_update.rake index 5b851ec..c744d90 100644 --- a/lib/tasks/content_visibility_update.rake +++ b/lib/tasks/content_visibility_update.rake @@ -2,7 +2,7 @@ namespace :content_visibility do desc "Updates the content visibility to default, only run 1 time" task default_all_to_hidden: :environment do ContentVisibility.all.each do |cv| - cv.update_attributes(visibility_type: ContentVisibility::VISIBILITY_TYPES[:hidden]) + cv.update(visibility_type: ContentVisibility::VISIBILITY_TYPES[:hidden]) end end end diff --git a/spec/controllers/cohorts/checkpoint_submissions/activities_controller_spec.rb b/spec/controllers/cohorts/checkpoint_submissions/activities_controller_spec.rb index 9d23073..8592907 100644 --- a/spec/controllers/cohorts/checkpoint_submissions/activities_controller_spec.rb +++ b/spec/controllers/cohorts/checkpoint_submissions/activities_controller_spec.rb @@ -30,7 +30,7 @@ describe Cohorts::CheckpointSubmissions::ActivitiesController do end it "sends a Slack message to the instructor to notify them that a comment has been given for the students submission" do - instructor.update_attributes(slack_username: "@duffus", slack_username_verified_at: Time.now) + instructor.update(slack_username: "@duffus", slack_username_verified_at: Time.now) expect(SlackStudentJob).to receive(:perform_later) do |message, username| expect(username).to eq(instructor.slack_username) @@ -75,7 +75,7 @@ describe Cohorts::CheckpointSubmissions::ActivitiesController do end it "sends a Slack message to the student to notify them that a comment has been given for their submission" do - student.update_attributes(slack_username: "@duffus", slack_username_verified_at: Time.now) + student.update(slack_username: "@duffus", slack_username_verified_at: Time.now) expect(SlackStudentJob).to receive(:perform_later) do |message, username| expect(username).to eq(student.slack_username) diff --git a/spec/controllers/cohorts/content_files/checkpoint_submissions_controller_spec.rb b/spec/controllers/cohorts/content_files/checkpoint_submissions_controller_spec.rb index f6cb00f..665abc3 100644 --- a/spec/controllers/cohorts/content_files/checkpoint_submissions_controller_spec.rb +++ b/spec/controllers/cohorts/content_files/checkpoint_submissions_controller_spec.rb @@ -34,7 +34,7 @@ describe Cohorts::ContentFiles::CheckpointSubmissionsController do end context "viewing a checkpoint that is in started state" do - before do + before do create(:cohort_user, :instructor, user: user, cohort: cohort) checkpoint_submission.update(state: CheckpointSubmission::STATES[:started]) end @@ -408,7 +408,7 @@ describe Cohorts::ContentFiles::CheckpointSubmissionsController do context "with valid params" do context "when cohort is in percentage mode" do it "creates bad data in the sense that we need a performance" do - cohort.update_attributes(mode: Cohort::MODES[:percentage]) + cohort.update(mode: Cohort::MODES[:percentage]) action expect(checkpoint_submission.reload.state).to eq(CheckpointSubmission::STATES[:rejected]) perf = Performance.last @@ -437,7 +437,7 @@ describe Cohorts::ContentFiles::CheckpointSubmissionsController do end it "sends a slack message to the student when rejecting a checkpoint submission" do - student_user.update_attributes(slack_username: "@test", slack_username_verified_at: Time.now) + student_user.update(slack_username: "@test", slack_username_verified_at: Time.now) expect(SlackStudentJob).to receive(:perform_later) do |message, username| expect(username).to eq(student_user.slack_username) expect(message).to include(instructor.full_name) @@ -454,7 +454,7 @@ describe Cohorts::ContentFiles::CheckpointSubmissionsController do let(:checkpoint_submission_params) { { state: CheckpointSubmission::STATES[:done] } } it "sends a slack message to the student" do - student_user.update_attributes(slack_username: "@test", slack_username_verified_at: Time.now) + student_user.update(slack_username: "@test", slack_username_verified_at: Time.now) expect(SlackStudentJob).to receive(:perform_later) do |message, username| expect(username).to eq(student_user.slack_username) expect(message).to include(instructor.full_name) diff --git a/spec/controllers/cohorts/submitted_challenge_answers/activities_controller_spec.rb b/spec/controllers/cohorts/submitted_challenge_answers/activities_controller_spec.rb index 2867c10..ace349b 100644 --- a/spec/controllers/cohorts/submitted_challenge_answers/activities_controller_spec.rb +++ b/spec/controllers/cohorts/submitted_challenge_answers/activities_controller_spec.rb @@ -30,7 +30,7 @@ describe Cohorts::SubmittedChallengeAnswers::ActivitiesController do end it "sends a Slack message to the instructor to notify them that a comment has been given for the students submission" do - instructor.update_attributes(slack_username: "@duffus", slack_username_verified_at: Time.now) + instructor.update(slack_username: "@duffus", slack_username_verified_at: Time.now) expect(SlackStudentJob).to receive(:perform_later) do |message, username| expect(username).to eq(instructor.slack_username) @@ -84,7 +84,7 @@ describe Cohorts::SubmittedChallengeAnswers::ActivitiesController do end it "sends a Slack message to the student to notify them that a comment has been given for their submission" do - student.update_attributes(slack_username: "@duffus", slack_username_verified_at: Time.now) + student.update(slack_username: "@duffus", slack_username_verified_at: Time.now) expect(SlackStudentJob).to receive(:perform_later) do |message, username| expect(username).to eq(student.slack_username) diff --git a/spec/controllers/webhooks/assessments_service/submitted_challenge_answers_controller_spec.rb b/spec/controllers/webhooks/assessments_service/submitted_challenge_answers_controller_spec.rb index ee48462..78aa7e7 100644 --- a/spec/controllers/webhooks/assessments_service/submitted_challenge_answers_controller_spec.rb +++ b/spec/controllers/webhooks/assessments_service/submitted_challenge_answers_controller_spec.rb @@ -77,7 +77,7 @@ describe Webhooks::AssessmentsService::SubmittedChallengeAnswersController do let(:test_results) { "✓ 3 passing (112ms)" } before do - submitted_challenge_answer.update_attributes(status: SubmittedChallengeAnswer::STATUSES[:canceled], test_results: "Tests canceled by student.") + submitted_challenge_answer.update(status: SubmittedChallengeAnswer::STATUSES[:canceled], test_results: "Tests canceled by student.") end it "does not update the submitted challenge answer" do @@ -102,7 +102,7 @@ describe Webhooks::AssessmentsService::SubmittedChallengeAnswersController do context "when challenge isn't a code snippet or project type" do let(:test_results) { "✓ 3 passing (112ms)" } before do - submitted_challenge_answer.update_attributes(status: SubmittedChallengeAnswer::STATUSES[:ungraded], challenge: create(:challenge, challenge_type: Challenge::TYPES[:multiple_choice])) + submitted_challenge_answer.update(status: SubmittedChallengeAnswer::STATUSES[:ungraded], challenge: create(:challenge, challenge_type: Challenge::TYPES[:multiple_choice])) end it "does not update the submitted challenge answer" do diff --git a/spec/features/cohorts/management_feature_spec.rb b/spec/features/cohorts/management_feature_spec.rb index 24a95c3..6629248 100644 --- a/spec/features/cohorts/management_feature_spec.rb +++ b/spec/features/cohorts/management_feature_spec.rb @@ -634,11 +634,11 @@ describe "Cohorts management", js: true do expect(page).to have_content(cohort.name) expect(page).to_not have_link("Manage Users in Auth") - admin.update_attributes(roles: [User::ROLES[:product_admin], User::ROLES[:admin]]) + admin.update(roles: [User::ROLES[:product_admin], User::ROLES[:admin]]) visit(users_cohort_path(cohort)) expect(page).to have_link("Manage Users in Auth") - admin.update_attributes(roles: [User::ROLES[:admin]]) + admin.update(roles: [User::ROLES[:admin]]) create(:cohort_user, :instructor, user: admin, cohort: cohort, roles: [CohortUser::ROLES[:product_admin]]) visit(users_cohort_path(cohort)) expect(page).to have_link("Manage Users in Auth") @@ -649,11 +649,11 @@ describe "Cohorts management", js: true do expect(page).to have_content(cohort.name) expect(page).to_not have_link("Manage Users in Auth") - admin.update_attributes(roles: [User::ROLES[:product_admin], User::ROLES[:admin]]) + admin.update(roles: [User::ROLES[:product_admin], User::ROLES[:admin]]) visit(setup_cohort_path(cohort)) expect(page).to have_link("Edit") - admin.update_attributes(roles: [User::ROLES[:admin]]) + admin.update(roles: [User::ROLES[:admin]]) create(:cohort_user, :instructor, user: admin, cohort: cohort, roles: [CohortUser::ROLES[:product_admin]]) visit(setup_cohort_path(cohort)) expect(page).to have_link("Edit") diff --git a/spec/features/cohorts/student_progress_spec.rb b/spec/features/cohorts/student_progress_spec.rb index 040aeb8..cdbc12f 100644 --- a/spec/features/cohorts/student_progress_spec.rb +++ b/spec/features/cohorts/student_progress_spec.rb @@ -208,7 +208,7 @@ feature "Instructor viewing student progress" do end before(:each) do - cohort.update_attributes(mode: Cohort::MODES[:percentage]) + cohort.update(mode: Cohort::MODES[:percentage]) visit course_stats_cohort_path(cohort) end diff --git a/spec/features/cohorts/submissions_spec.rb b/spec/features/cohorts/submissions_spec.rb index 0279ddf..36b317f 100644 --- a/spec/features/cohorts/submissions_spec.rb +++ b/spec/features/cohorts/submissions_spec.rb @@ -176,7 +176,7 @@ describe "Submissions", js: true do end it "allows navigation to rejected checkpoint submissoins which have a grade" do - current_checkpoint_submission.update_attributes(state: CheckpointSubmission::STATES[:rejected], grader_id: create(:user).id) + current_checkpoint_submission.update(state: CheckpointSubmission::STATES[:rejected], grader_id: create(:user).id) create(:performance, cohort: cohort, user: student_1, @@ -194,7 +194,7 @@ describe "Submissions", js: true do end it "does not display 'started' state checkpoints" do - current_checkpoint_submission.update_attributes(state: CheckpointSubmission::STATES[:started], grader_id: create(:user).id) + current_checkpoint_submission.update(state: CheckpointSubmission::STATES[:started], grader_id: create(:user).id) SubmittedChallengeAnswer.destroy_all visit path within all(".studentcolumn")[1] do @@ -212,7 +212,7 @@ describe "Submissions", js: true do context "checkpoint visibility changes" do it "does not include checkpoint submission details when the checkpoint is hidden" do - current_checkpoint_submission.update_attributes(state: CheckpointSubmission::STATES[:done], total_points: 10, correct_points: 7) + current_checkpoint_submission.update(state: CheckpointSubmission::STATES[:done], total_points: 10, correct_points: 7) create(:performance, score: 3, cohort: cohort, user: student_1, checkpoint_submission: current_checkpoint_submission, standard: standard_1, standard_uid: standard_1.uid) visit path within all(".studentcolumn")[1] do @@ -242,10 +242,10 @@ describe "Submissions", js: true do end it "shows the percentage of a completed checkpoints" do - older_checkpoint_submission.update_attributes(state: CheckpointSubmission::STATES[:done]) - current_checkpoint_submission.update_attributes(state: CheckpointSubmission::STATES[:done]) + older_checkpoint_submission.update(state: CheckpointSubmission::STATES[:done]) + current_checkpoint_submission.update(state: CheckpointSubmission::STATES[:done]) create(:performance, score: 3, cohort: cohort, user: student_1, checkpoint_submission: current_checkpoint_submission, standard: standard_1, standard_uid: standard_1.uid) - current_challenge_submission.update_attributes(status: SubmittedChallengeAnswer::STATUSES[:correct]) + current_challenge_submission.update(status: SubmittedChallengeAnswer::STATUSES[:correct]) visit path within all(".studentcolumn")[1] do @@ -256,10 +256,10 @@ describe "Submissions", js: true do end it "shows the percentage of completed checkpoints in the checkpoint content file row" do - older_checkpoint_submission.update_attributes(state: CheckpointSubmission::STATES[:done]) - current_checkpoint_submission.update_attributes(state: CheckpointSubmission::STATES[:done]) + older_checkpoint_submission.update(state: CheckpointSubmission::STATES[:done]) + current_checkpoint_submission.update(state: CheckpointSubmission::STATES[:done]) create(:performance, score: 3, cohort: cohort, user: student_1, checkpoint_submission: current_checkpoint_submission, standard: standard_1, standard_uid: standard_1.uid) - current_challenge_submission.update_attributes(status: SubmittedChallengeAnswer::STATUSES[:correct]) + current_challenge_submission.update(status: SubmittedChallengeAnswer::STATUSES[:correct]) visit path within all(".standardtitle")[0] do @@ -273,8 +273,8 @@ describe "Submissions", js: true do end it "shows an emdash when there is an ungraded submission" do - older_checkpoint_submission.update_attributes(state: CheckpointSubmission::STATES[:needs_review]) - current_checkpoint_submission.update_attributes(state: CheckpointSubmission::STATES[:needs_review]) + older_checkpoint_submission.update(state: CheckpointSubmission::STATES[:needs_review]) + current_checkpoint_submission.update(state: CheckpointSubmission::STATES[:needs_review]) visit path within all(".standardtitle")[0] do diff --git a/spec/features/cohorts/users/challenges_feature_spec.rb b/spec/features/cohorts/users/challenges_feature_spec.rb index 07358e3..8db44db 100644 --- a/spec/features/cohorts/users/challenges_feature_spec.rb +++ b/spec/features/cohorts/users/challenges_feature_spec.rb @@ -194,7 +194,7 @@ describe "Challenges" do expect(page).to have_content("Running Tests") end - submitted_challenge_answer_1.update_attributes!(status: SubmittedChallengeAnswer::STATUSES[:correct]) + submitted_challenge_answer_1.update!(status: SubmittedChallengeAnswer::STATUSES[:correct]) within ".challenge-grading-buttons" do expect(page).to have_css(".correct-check") diff --git a/spec/features/content_files/checkpoint_submissions_spec.rb b/spec/features/content_files/checkpoint_submissions_spec.rb index 5e5c586..9c695c7 100644 --- a/spec/features/content_files/checkpoint_submissions_spec.rb +++ b/spec/features/content_files/checkpoint_submissions_spec.rb @@ -139,7 +139,7 @@ describe "checkpoint submissions" do describe "percentage mode" do before do - cohort.update_attributes(mode: Cohort::MODES[:percentage]) + cohort.update(mode: Cohort::MODES[:percentage]) end it "displays the amount of points the user got correct over the available" do @@ -289,7 +289,7 @@ describe "checkpoint submissions" do let!(:another_pair_sca) { create(:submitted_challenge_answer, cohort: cohort, challenge: challenge_2, user: paired_student, checkpoint_submission: paired_checkpoint_submission, status: "ungraded", points: 2) } before do - cohort.update_attributes(mode: Cohort::MODES[:percentage]) + cohort.update(mode: Cohort::MODES[:percentage]) checkpoint_submission.update(pair_submission_ids: [paired_checkpoint_submission.id]) visit cohort_checkpoint_submission_path(cohort, checkpoint_submission) end diff --git a/spec/features/content_files/view_feature_spec.rb b/spec/features/content_files/view_feature_spec.rb index 883d9bc..b28178e 100644 --- a/spec/features/content_files/view_feature_spec.rb +++ b/spec/features/content_files/view_feature_spec.rb @@ -30,8 +30,8 @@ describe "Viewing content files", js: true do context "in a sandbox preview cohort" do it "shows content file warnings at the top of the page" do content_file = create(:content_file, html: "some content here!", warnings: ["This content file is too cold"], standard: create(:standard, release: release, position: 1)) - cohort.update_attributes(sandbox: true) - release.update_attributes(sync_warnings: ["This content file is too cold"]) + cohort.update(sandbox: true) + release.update(sync_warnings: ["This content file is too cold"]) visit content_file_path(cohort, release.block, content_file.path) expect(page).to have_content "1 error on this lesson" find(".alert-danger").click @@ -281,8 +281,8 @@ describe "Viewing content files", js: true do context "percentage mode" do it "displays the perctage correct for a checkpoint" do - cohort.update_attributes(mode: Cohort::MODES[:percentage]) - checkpoint_submission.update_attributes(state: CheckpointSubmission::STATES[:done], cohort: cohort) + cohort.update(mode: Cohort::MODES[:percentage]) + checkpoint_submission.update(state: CheckpointSubmission::STATES[:done], cohort: cohort) visit content_file_path(cohort, release.block, checkpoint_content_file.path) within(".content-file-sidebar") do @@ -293,7 +293,7 @@ describe "Viewing content files", js: true do context "checkpoint is in started state" do it "displays no checkpoint progress" do - checkpoint_submission.update_attributes(state: CheckpointSubmission::STATES[:started]) + checkpoint_submission.update(state: CheckpointSubmission::STATES[:started]) visit content_file_path(cohort, release.block, checkpoint_content_file.path) within(".content-file-sidebar") do @@ -368,7 +368,7 @@ describe "Viewing content files", js: true do xit "does show point value" do checkpoint_content_file = create(:content_file, html: html, standard: standard, position: 0, content_file_type: ContentFile::TYPES[:checkpoint]) Challenge.create!(processed_text[:challenges][0].merge(content_file: checkpoint_content_file, points: 3)) - cohort.update_attributes(mode: "Percentage") + cohort.update(mode: "Percentage") visit content_file_path(cohort, release.block, checkpoint_content_file.path) expect(page).to have_content("3 PT") @@ -386,7 +386,7 @@ describe "Viewing content files", js: true do click_button "RUN TESTS" expect(page).to have_content "CANCEL" - SubmittedChallengeAnswer.last.update_attributes(status: "failed", test_results: "Connection failed") + SubmittedChallengeAnswer.last.update(status: "failed", test_results: "Connection failed") wait_for_ajax within(".feedback") do @@ -425,7 +425,7 @@ describe "Viewing content files", js: true do click_button "RUN TESTS" expect(page).to have_content "CANCEL" - SubmittedChallengeAnswer.last.update_attributes(status: "correct", test_results: "1) You got the test right hooray") + SubmittedChallengeAnswer.last.update(status: "correct", test_results: "1) You got the test right hooray") wait_for_ajax expect(page).to have_content("Correct") @@ -437,7 +437,7 @@ describe "Viewing content files", js: true do click_button "RUN TESTS" expect(page).to have_content "CANCEL" - SubmittedChallengeAnswer.last.update_attributes(status: "incorrect", test_results: "1) Y'all goofed the pooch") + SubmittedChallengeAnswer.last.update(status: "incorrect", test_results: "1) Y'all goofed the pooch") expect(page).to have_content("Err, try again…") expect(page).to have_content("1) Y'all goofed the pooch") @@ -480,7 +480,7 @@ describe "Viewing content files", js: true do click_button "RUN TESTS" end expect(page).to have_content "CANCEL" - SubmittedChallengeAnswer.last.update_attributes(status: "correct", test_results: "1) You got the test right hooray") + SubmittedChallengeAnswer.last.update(status: "correct", test_results: "1) You got the test right hooray") wait_for_ajax expect(page).to have_content("Correct") @@ -1601,7 +1601,7 @@ describe "Viewing content files", js: true do click_button "RUN TESTS" end expect(page).to have_content "CANCEL" - SubmittedChallengeAnswer.last.update_attributes(status: "correct", test_results: "1) You got the test right hooray") + SubmittedChallengeAnswer.last.update(status: "correct", test_results: "1) You got the test right hooray") wait_for_ajax expect(page).to have_content("Correct") diff --git a/spec/features_helper.rb b/spec/features_helper.rb index 5016fe5..90add4f 100644 --- a/spec/features_helper.rb +++ b/spec/features_helper.rb @@ -61,7 +61,7 @@ def find_ace_editor_field end def mock_assessment_callback(submitted_challenge_answer, result, test_results) - submitted_challenge_answer.update_attributes(status: result, test_results: test_results) + submitted_challenge_answer.update(status: result, test_results: test_results) end def set_ace_editor_text(text, wrapper_selector = nil) diff --git a/spec/jobs/switch_to_branch_job_spec.rb b/spec/jobs/switch_to_branch_job_spec.rb index e6e76df..e0ab2d5 100644 --- a/spec/jobs/switch_to_branch_job_spec.rb +++ b/spec/jobs/switch_to_branch_job_spec.rb @@ -95,7 +95,7 @@ describe SwitchToBranchJob do context "when the block has existing sync_errors" do it "resets the sync_errors" do - pending_release.update_attributes(sync_errors: ["foo"]) + pending_release.update(sync_errors: ["foo"]) expect { subject }.to change { pending_release.reload.sync_errors }.from(["foo"]).to([]) end end diff --git a/spec/models/checkpoint_submission_spec.rb b/spec/models/checkpoint_submission_spec.rb index f0b224a..e2c76f9 100644 --- a/spec/models/checkpoint_submission_spec.rb +++ b/spec/models/checkpoint_submission_spec.rb @@ -22,11 +22,11 @@ describe CheckpointSubmission do let(:standard) { create(:standard, release: release) } let(:content_file) { create(:content_file, :checkpoint, standard: standard) } let(:challenge) { create(:challenge, content_file: content_file) } - let(:checkpoint_submission) { + let(:checkpoint_submission) { create(:checkpoint_submission, content_file_block_id: release.block_id, content_file_uid: content_file.uid, user: user) } let!(:sca) { - create(:submitted_challenge_answer, challenge: challenge, checkpoint_submission: checkpoint_submission, status: "correct", user: user) + create(:submitted_challenge_answer, challenge: challenge, checkpoint_submission: checkpoint_submission, status: "correct", user: user) } it "yields the standard of the checkpoint" do expect(checkpoint_submission.standard).to eq(standard) @@ -68,14 +68,14 @@ describe CheckpointSubmission do let(:content_file) { create(:content_file, :checkpoint, standard: standard) } let(:challenge_1) { create(:challenge, content_file: content_file) } let(:challenge_2) { create(:challenge, content_file: content_file) } - let(:checkpoint_submission) { + let(:checkpoint_submission) { create(:checkpoint_submission, content_file_block_id: release.block_id, content_file_uid: content_file.uid, user: user) } let!(:sca_1) { - create(:submitted_challenge_answer, challenge: challenge_1, checkpoint_submission: checkpoint_submission, status: "correct", user: user) + create(:submitted_challenge_answer, challenge: challenge_1, checkpoint_submission: checkpoint_submission, status: "correct", user: user) } let!(:sca_2) { - create(:submitted_challenge_answer, challenge: challenge_1, checkpoint_submission: checkpoint_submission, status: "correct", user: user) + create(:submitted_challenge_answer, challenge: challenge_1, checkpoint_submission: checkpoint_submission, status: "correct", user: user) } it "returns true when all submitted challenge answers are correct" do @@ -83,7 +83,7 @@ describe CheckpointSubmission do end it "returns false if any submitted challenge answers aren't correct" do - sca_2.update_attributes(status: "incorrect") + sca_2.update(status: "incorrect") expect(checkpoint_submission.all_correct?).to eq false end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 42e22cb..191e9e6 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -253,7 +253,7 @@ describe User do describe "#role?" do before do - subject.update_attributes(roles: [User::ROLES[:product_admin], "futzy.butzy"]) + subject.update(roles: [User::ROLES[:product_admin], "futzy.butzy"]) end it "returns true if the user has at least one of the roles given" do diff --git a/spec/presenters/content_file_presenter/for_show_spec.rb b/spec/presenters/content_file_presenter/for_show_spec.rb index 051c09a..4eda358 100644 --- a/spec/presenters/content_file_presenter/for_show_spec.rb +++ b/spec/presenters/content_file_presenter/for_show_spec.rb @@ -39,7 +39,7 @@ describe ContentFilePresenter::ForShow do context "submission has a checkpoint submission association" do it "returns false" do - sca.update_attributes(checkpoint_submission_id: create_checkpoint_submission(student, challenge, cohort: cohort).id) + sca.update(checkpoint_submission_id: create_checkpoint_submission(student, challenge, cohort: cohort).id) presenter = described_class.new(content_file, cohort, student) expect(presenter.is_checkpoint_draft).to eq(false) diff --git a/spec/presenters/student_progress_presenter_spec.rb b/spec/presenters/student_progress_presenter_spec.rb index 69bd953..7d551f9 100644 --- a/spec/presenters/student_progress_presenter_spec.rb +++ b/spec/presenters/student_progress_presenter_spec.rb @@ -25,7 +25,7 @@ describe StudentProgressPresenter do performances: [performance_1, performance_2, performance_3, performance_4], total_standards: 4, progress_data: nil, - lesson_visits: nil, + lesson_visits: nil, include_totals: true ) end @@ -105,7 +105,7 @@ describe StudentProgressPresenter do performances: [], total_standards: nil, progress_data: progress_data, - lesson_visits: nil, + lesson_visits: nil, include_totals: include_totals ) end @@ -153,7 +153,7 @@ describe StudentProgressPresenter do context "include totals set to true" do let(:include_totals) {true} it "returns the cohorts progress for all the students with totals" do - cohort.update_attributes(mode: Cohort::MODES[:percentage]) + cohort.update(mode: Cohort::MODES[:percentage]) expect(presenter.progress_percentages).to eq(percent_completed: 50, totals: {total_earned: 4, total_possible: 5, percent: 80}, @@ -166,7 +166,7 @@ describe StudentProgressPresenter do context "include totals set to false" do let(:include_totals) {false} it "returns the cohorts progress for all the students without totals" do - cohort.update_attributes(mode: Cohort::MODES[:percentage]) + cohort.update(mode: Cohort::MODES[:percentage]) expect(presenter.progress_percentages).to eq(percent_completed: 50, percent_completed_dasharray: "138.230075 138.230075", @@ -174,7 +174,7 @@ describe StudentProgressPresenter do checkpoint_average: 80, topic_averages: {}) end - end + end end end diff --git a/spec/services/activity_aggregator_service_spec.rb b/spec/services/activity_aggregator_service_spec.rb index 0e3666b..6009552 100644 --- a/spec/services/activity_aggregator_service_spec.rb +++ b/spec/services/activity_aggregator_service_spec.rb @@ -16,7 +16,7 @@ describe ActivityAggregatorService do context "when there are no activities" do context "when the cohort has no start date" do let(:month_ago) { date - 1.month } - before { cohort.update_attributes(starts_on: nil) } + before { cohort.update(starts_on: nil) } it "it is one month ago" do expect(subject[:dates][0]).to include( month_name: month_ago.strftime("%B"), @@ -29,7 +29,7 @@ describe ActivityAggregatorService do context "when the cohort has a start date" do let(:starts_on) { date - 2.months } - before { cohort.update_attributes(starts_on: starts_on) } + before { cohort.update(starts_on: starts_on) } it "is the cohort start date" do expect(subject[:dates][0]).to include( month_name: starts_on.strftime("%B"), @@ -45,7 +45,7 @@ describe ActivityAggregatorService do context "when the cohort start date is before the earliest activity" do let(:student) { create(:cohort_user, :student, cohort: cohort).user } let!(:activity) { create(:activity, :comment, cohort: cohort, creator: student, created_at: Date.new(2017, 11, 15)) } - before { cohort.update_attributes(starts_on: Date.new(2017, 11, 14)) } + before { cohort.update(starts_on: Date.new(2017, 11, 14)) } it "is the date of the earliest activity" do expect(subject[:dates][0]).to include( month_name: cohort.starts_on.strftime("%B"), @@ -59,7 +59,7 @@ describe ActivityAggregatorService do context "when the cohort start date is after the earliest activity" do let(:student) { create(:cohort_user, :student, cohort: cohort).user } let!(:activity) { create(:activity, :comment, cohort: cohort, creator: student, created_at: Date.new(2017, 11, 15)) } - before { cohort.update_attributes(starts_on: Date.new(2017, 11, 16)) } + before { cohort.update(starts_on: Date.new(2017, 11, 16)) } it "is the cohort start date" do expect(subject[:dates][0]).to include( month_name: cohort.starts_on.strftime("%B"), @@ -74,7 +74,7 @@ describe ActivityAggregatorService do describe "last date" do context "when the cohort has no end date" do - before { cohort.update_attributes(ends_on: nil) } + before { cohort.update(ends_on: nil) } it "is today" do expect(subject[:dates].last).to include( month_name: one_week_from_now.strftime("%B"), @@ -87,7 +87,7 @@ describe ActivityAggregatorService do context "when the cohort has a end date" do context "when the end date is after today" do - before { cohort.update_attributes(ends_on: Date.new(2018, 1, 15)) } + before { cohort.update(ends_on: Date.new(2018, 1, 15)) } it "is today" do expect(subject[:dates].last).to include( month_name: one_week_from_now.strftime("%B"), @@ -99,7 +99,7 @@ describe ActivityAggregatorService do end context "when there is an activity after the end date" do - before { cohort.update_attributes(ends_on: Date.new(2018, 1, 15)) } + before { cohort.update(ends_on: Date.new(2018, 1, 15)) } let(:student) { create(:cohort_user, :student, cohort: cohort).user } let!(:activity) { create(:activity, :comment, cohort: cohort, creator: student, created_at: Date.new(2019, 11, 15)) } it "is activity created at date" do @@ -113,7 +113,7 @@ describe ActivityAggregatorService do end context "when the end date is before today" do - before { cohort.update_attributes(ends_on: Date.new(2017, 12, 14)) } + before { cohort.update(ends_on: Date.new(2017, 12, 14)) } it "is the cohort end date" do expect(subject[:dates].last).to include( month_name: cohort.ends_on.strftime("%B"), @@ -136,7 +136,7 @@ describe ActivityAggregatorService do end describe ":grouped_dates" do - before { cohort.update_attributes(starts_on: Date.new(2017, 11, 14), ends_on: Date.new(2017, 12, 14)) } + before { cohort.update(starts_on: Date.new(2017, 11, 14), ends_on: Date.new(2017, 12, 14)) } it "groups dates by month" do expect(subject[:grouped_dates].first.first).to eq("November") expect(subject[:grouped_dates].last.first).to eq("December") diff --git a/spec/services/cohort_standard_progress_service_spec.rb b/spec/services/cohort_standard_progress_service_spec.rb index 944117b..c17db53 100644 --- a/spec/services/cohort_standard_progress_service_spec.rb +++ b/spec/services/cohort_standard_progress_service_spec.rb @@ -115,7 +115,7 @@ describe CohortStandardProgressService do let!(:earlier_student_sca) { create(:submitted_challenge_answer, user: student, challenge: challenge_3, status: SubmittedChallengeAnswer::GRADED_STATUSES[:incorrect], checkpoint_submission_id: earlier_checkpoint_submission.id) } let!(:checkpoint_submissions) { [checkpoint_submission, earlier_checkpoint_submission] } let!(:checkpoints_for_submission_service) { CheckpointSubmission.where(id: [checkpoint_submission.id, earlier_checkpoint_submission.id]) } - + before do checkpoint_submission.update(state: "started") end @@ -166,7 +166,7 @@ describe CohortStandardProgressService do let!(:student_sca_3) { create(:submitted_challenge_answer, user: student, challenge: challenge_3, status: SubmittedChallengeAnswer::GRADED_STATUSES[:correct], checkpoint_submission_id: checkpoint_submission.id) } it "returns a hash with progress data" do - checkpoint_submission.update_attributes(total_points: 2, correct_points: 2) + checkpoint_submission.update(total_points: 2, correct_points: 2) expect(subject).to eq( percent_done: 100.00, remaining: 0, diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index 7067455..fa279a3 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -22,7 +22,7 @@ describe NotificationService do let!(:checkpoint_submission) { create(:checkpoint_submission, user_id: student.id, content_file_uid: content_file.uid, content_file_block_id: content_file.standard.release.block_id , cohort: cohort, state: CheckpointSubmission::STATES[:done], correct_points: 3, total_points: 5) } it "calculates percentage when challenge_completion is not set on the performance" do - cohort.update_attributes(mode: Cohort::MODES[:percentage]) + cohort.update(mode: Cohort::MODES[:percentage]) create(:performance, user: student, checkpoint_submission: checkpoint_submission, score: 2, challenge_completion: nil) expect_any_instance_of(User).to receive(:notify).with( tagline: "Checkpoint Scored", -- GitLab From 17bd2ad48904e792463d875ee7520bbe44362ba9 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Thu, 15 Oct 2020 13:25:46 -1000 Subject: [PATCH 177/283] Fix NOT deprecation warnings --- .../cohorts/content_files/checkpoint_submissions_controller.rb | 2 +- app/models/block.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/cohorts/content_files/checkpoint_submissions_controller.rb b/app/controllers/cohorts/content_files/checkpoint_submissions_controller.rb index 491b2be..131ec5a 100644 --- a/app/controllers/cohorts/content_files/checkpoint_submissions_controller.rb +++ b/app/controllers/cohorts/content_files/checkpoint_submissions_controller.rb @@ -189,7 +189,7 @@ module Cohorts content_file_block_id: current_content_file.standard.release.block_id, user_id: user_ids, cohort_id: checkpoint_submission.cohort_id). - where.not(id: not_in_ids + previous_submission_ids_by_users, state: CheckpointSubmission::STATES[:started]). + where.not(id: not_in_ids + previous_submission_ids_by_users).where.not(state: CheckpointSubmission::STATES[:started]). select("DISTINCT ON (checkpoint_submissions.user_id) checkpoint_submissions.id, checkpoint_submissions.state"). order("checkpoint_submissions.user_id, created_at DESC").to_a.select {|cs| cs.state == "needs_review"}.last if oldest_ungraded_submission diff --git a/app/models/block.rb b/app/models/block.rb index 778a93f..6a95462 100644 --- a/app/models/block.rb +++ b/app/models/block.rb @@ -6,7 +6,7 @@ class Block < ApplicationRecord has_many :releases - scope(:without_preview, -> { where.not(title: "preview", repo_name: "preview") }) + scope(:without_preview, -> { where.not(title: "preview").where.not(repo_name: "preview") }) scope(:active, -> { where(archived_at: nil) }) def cohorts -- GitLab From ca1b1435c79700e24b422ad03fdfef0a04069506 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Thu, 15 Oct 2020 13:30:46 -1000 Subject: [PATCH 178/283] updating db/schema files --- db/schema.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index f205c10..9afa02c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -2,11 +2,11 @@ # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. # -# Note that this schema.rb definition is the authoritative source for your -# database schema. If you need to create the application database on another -# system, you should be using db:schema:load, not running all the migrations -# from scratch. The latter is a flawed and unsustainable approach (the more migrations -# you'll amass, the slower it'll run and the greater likelihood for issues). +# This file is the source Rails uses to define your schema when running `rails +# db:schema:load`. When creating a new database, `rails db:schema:load` tends to +# be faster and is potentially less error prone than running all of your +# migrations from scratch. Old migrations may fail to apply correctly if those +# migrations use external dependencies or application code. # # It's strongly recommended that you check this file into your version control system. -- GitLab From 1790c89f109ad2ff054c7a8204feb24b04dad03f Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Thu, 15 Oct 2020 16:06:57 -1000 Subject: [PATCH 179/283] changing public file serve setting --- config/environments/production.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/environments/production.rb b/config/environments/production.rb index cc9244a..bfe198d 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -20,7 +20,7 @@ Rails.application.configure do # Disable serving static files from the `/public` folder by default since # Apache or NGINX already handles this. - config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? + config.public_file_server.enabled = true # Compress JavaScripts and CSS. config.assets.js_compressor = :uglifier -- GitLab From 14e8cbfcb28f4aece3760b3a0b8b8f9c5e5b3ab1 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Fri, 16 Oct 2020 19:52:50 -1000 Subject: [PATCH 180/283] Update user_controller tests --- spec/controllers/users_controller_spec.rb | 108 +++++++++++++++++++--- 1 file changed, 93 insertions(+), 15 deletions(-) diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index b1eb3eb..42adb57 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -2,13 +2,85 @@ require "spec_helper" describe UsersController do - # let(:user) { create(:user, :admin, api_token: "token") } - # let(:student_to_enroll) { create(:user) } - # let!(:cohort) { create(:cohort) } - # let!(:enrolled_student) { create(:user, first_name: "Eric", last_name: "Ericson", email: "eric@example.com") } - # let!(:cohort_user) { create(:cohort_user, created_at: 3.days.ago, cohort: cohort, user: enrolled_student) } + let(:student_to_enroll) { create(:user) } let(:cohort) { create(:cohort) } - let(:user) { create(:user) } + let(:enrolled_student) { create(:user, first_name: "Eric", last_name: "Ericson", email: "eric@example.com") } + let(:cohort_user) { create(:cohort_user, created_at: 3.days.ago, cohort: cohort, user: enrolled_student) } + # let(:user) { create(:user, :admin, api_token: "token") } + + describe "GET #index" do + context "when signed in as an admin" do + # let(:new_student) { create(:user, first_name: "Inigo", last_name: "Montoya", email: "inigo@example.com") } + let(:admin) { create(:user, :admin) } + + before do + sign_in(admin) + end + + it "populates an array of users" do + get :index + + expect(assigns(:users)).to eq([enrolled_student, admin]) + + expect(response).to be_successful + expect(response).to render_template(:index) + end + end + end + + describe "GET #edit_user" do + context "edits a user" do + let(:admin) { create(:user, :admin) } + + before do + sign_in(admin) + end + + it "edits user" do + get :edit_user, params: { id: admin.id } + + expect(response).to be_successful + expect(response).to render_template(:edit_user) + end + end + end + + describe "PATCH #update_user" do + let(:admin) { create(:user, :admin) } + + before do + sign_in(admin) + end + + context "when the update succeeds" do + it "updates the user and redirects to user path" do + allow(User).to receive(:find_by).and_return(enrolled_student) + allow(enrolled_student).to receive(:update).and_return(true) + + patch :update_user, params: { + id: enrolled_student.id + } + + expect(enrolled_student).to have_received(:update) + expect(response).to redirect_to(users_path) + end + end + + context "when the update fails" do + before do + allow(User).to receive(:find_by).and_return(enrolled_student) + allow(enrolled_student).to receive(:update).and_return(false) + end + + it "renders the edit page again" do + patch :update_user, params: { + id: enrolled_student.id + } + expect(enrolled_student).to have_received(:update) + expect(response).to render_template(:edit) + end + end + end describe "GET #new" do context "when signed in as an admin" do @@ -28,17 +100,23 @@ describe UsersController do describe "GET #edit" do context "edits a user for a given cohort" do + let(:admin) { create(:user, :admin) } + + before do + sign_in(admin) + end it "edits users for a cohort" do - allow(controller).to receive(:render) + get :edit, params: { cohort_id: cohort.id, id: admin.id } - get :edit, params: { cohort_id: cohort.id, id: user.id } + expect(response).to be_successful + expect(response).to render_template(:edit) end end end describe "PATCH #update" do - let(:cohort_user) { create(:cohort_user, cohort: cohort, user: user) } + let(:cohort_user) { create(:cohort_user, cohort: cohort, user: enrolled_student) } before do sign_in(create(:user, :admin, :product_admin)) @@ -49,7 +127,7 @@ describe UsersController do it "updates the cohort user" do patch :update, params: { cohort_id: cohort.id, - id: user.id + id: enrolled_student.id } expect(cohort_user).to have_received(:update) end @@ -58,7 +136,7 @@ describe UsersController do it "redirects to the user cohorts page" do patch :update, params: { cohort_id: cohort.id, - id: user.id + id: enrolled_student.id } expect(response).to redirect_to(users_cohort_path(cohort)) end @@ -72,7 +150,7 @@ describe UsersController do it "renders the edit page again" do patch :update, params: { cohort_id: cohort.id, - id: user.id + id: enrolled_student.id } expect(response).to render_template(:edit) end @@ -80,7 +158,7 @@ describe UsersController do end describe "DELETE #destroy" do - let(:cohort_user) { create(:cohort_user, cohort: cohort, user: user) } + let(:cohort_user) { create(:cohort_user, cohort: cohort, user: enrolled_student) } before do sign_in(create(:user, :admin, :product_admin)) @@ -91,7 +169,7 @@ describe UsersController do it "deletes the cohort user" do delete :destroy, params: { cohort_id: cohort.id, - id: user.id + id: enrolled_student.id } expect(cohort_user).to have_received(:destroy) end @@ -100,7 +178,7 @@ describe UsersController do it "redirects to the user cohorts page" do delete :destroy, params: { cohort_id: cohort.id, - id: user.id + id: enrolled_student.id } expect(response).to redirect_to(users_cohort_path(cohort)) end -- GitLab From 1783bac75323aaa949f76abf9c6500f0b75a74e9 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Mon, 19 Oct 2020 17:18:19 -1000 Subject: [PATCH 181/283] Removed cohorts_users update and delete paths --- .../api/v1/cohorts/users_controller.rb | 101 ------------------ .../api/v1/cohorts/users_controller_spec.rb | 6 -- 2 files changed, 107 deletions(-) diff --git a/app/controllers/api/v1/cohorts/users_controller.rb b/app/controllers/api/v1/cohorts/users_controller.rb index ad3efca..9dc65df 100644 --- a/app/controllers/api/v1/cohorts/users_controller.rb +++ b/app/controllers/api/v1/cohorts/users_controller.rb @@ -30,34 +30,6 @@ class Api::V1::Cohorts::UsersController < Api::ApplicationController json_response({ error: e.message }, 400) and return end - def update - render_method_not_allowed_response and return unless request.patch? - authorize(current_cohort, :enroll?) - - if target_user&.student_or_instructor_of?(current_cohort.id) - enroll_existing_user(target_user) - json_response({ status: "ok" }, :ok) - else - json_response({ status: "404" }, 404) - end - rescue StandardError => e - json_response({ error: e.message }, 400) and return - end - - def destroy - render_method_not_allowed_response and return unless request.delete? - authorize(current_cohort, :enroll?) - - if target_user&.student_or_instructor_of?(current_cohort.id) - unenroll_existing_user - json_response({ status: "ok" }, :ok) - else - json_response({ status: "404" }, 404) - end - rescue StandardError => e - json_response({ error: e.message }, 400) and return - end - private def current_cohort @@ -92,82 +64,9 @@ class Api::V1::Cohorts::UsersController < Api::ApplicationController end end - def invite_user - # TODO: AuthApi fix - # client = AuthApi::Client.new("user.invite user.write user.product_roles") - # options = { - # user: { - # first_name: params[:first_name], - # last_name: params[:last_name], - # email: params[:email], - # registrations: [{ - # product_uid: current_cohort.uid, - # roles: enroll_roles - # }] - # } - # } - # - # resp = client.invite_user(options) - # AuthResolverService.resolve(resp) if resp&.uid - # resp&.uid - 'todo' - end - - def enroll_roles - [ - params[:instructor] == true ? "instructor" : nil, - params[:onboard] == true ? "auth.product_admin" : nil - ].compact - end - - def enroll_existing_user(user) - # TODO: AuthApi fix - - # client = AuthApi::Client.new("user.write user.product_roles") - # options = { - # id: user.uid, - # user: { - # registrations: [{ - # product_uid: current_cohort.uid, - # roles: enroll_roles - # }] - # } - # } - # - # resp = client.update_user(options) - # AuthResolverService.resolve(resp) if resp&.uid - # resp&.uid - 'todo' - end - - def unenroll_existing_user - # TODO: AuthApi fix - - # client = AuthApi::Client.new("user.write user.unregister") - # options = { - # id: target_user.uid, - # user: { - # registrations: [{ - # product_uid: current_cohort.uid, - # _destroy: true - # }] - # } - # } - # - # resp = client.update_user(options) - # AuthResolverService.resolve(resp) if resp&.uid - 'todo' - end - def param_errors validation_response = [] - # if params[:first_name].blank? - # validation_response.push "first_name can't be blank" - # end - # if params[:last_name].blank? - # validation_response.push "last_name can't be blank" - # end if params[:email].blank? validation_response.push "email can't be blank" end diff --git a/spec/controllers/api/v1/cohorts/users_controller_spec.rb b/spec/controllers/api/v1/cohorts/users_controller_spec.rb index e345933..ac2970a 100644 --- a/spec/controllers/api/v1/cohorts/users_controller_spec.rb +++ b/spec/controllers/api/v1/cohorts/users_controller_spec.rb @@ -61,18 +61,12 @@ resource "Enrollments" do describe "Creating an enrollment" do parameter ":cohort_id", "[Path Parameter]\nThe ID of the cohort. Matches the ID from the URL when viewing any cohort in Learn", required: true, example: "1500" - parameter :first_name, "[Body Parameter]\nThe first name of the user to enroll.", required: true, example: "Jamie" - parameter :last_name, "[Body Parameter]\nThe last name of the user to enroll.", required: true, example: "Wittman" parameter :email, "[Body Parameter]\nThe email of the user to enroll. This field is used to find existing users.", required: true, example: "jamie@example.com" - parameter :instructor, "[Body Parameter]\nThe boolean that sets the forge.instructor role for enrollment. Default = false.", required: false, example: "true = has instructor role\nfalse = has student role" - parameter :onboard, "[Body Parameter]\nThe boolean that sets the auth.product_admin role for enrollment. Default = false.", required: false, example: "true = user can enroll others in the cohort\nfalse = no onboarding ability" let(:cohort_id) { cohort.id } let(:first_name) { "Jamie" } let(:last_name) { "Wittman" } let(:email) { "jamie@example.com" } - let(:instructor) { true } - let(:onboard) { true } post "/api/v1/cohorts/:cohort_id/users" do example "Creating a user and their enrollment" do -- GitLab From 7b99f5f10eb359a1220b0c94ba0e06f3f683acb5 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Thu, 22 Oct 2020 15:47:23 -1000 Subject: [PATCH 182/283] removed numpy from python evaluator tests --- spec/fixtures/test-block-repo/challenges-smoketest.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/fixtures/test-block-repo/challenges-smoketest.md b/spec/fixtures/test-block-repo/challenges-smoketest.md index 350905f..5d88305 100644 --- a/spec/fixtures/test-block-repo/challenges-smoketest.md +++ b/spec/fixtures/test-block-repo/challenges-smoketest.md @@ -493,7 +493,7 @@ def filter_by_class(X, y, label): ```python import unittest import main as p -import numpy as np +#import numpy as np ``` ##### !end-setup -- GitLab From 55d186a96cc54a6510aa70f5d8a4284852d90832 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 27 Oct 2020 10:46:24 -1000 Subject: [PATCH 183/283] adding temp values for aws secret and access key. --- config/secrets.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/secrets.yml b/config/secrets.yml index bd0e92d..a3a095e 100644 --- a/config/secrets.yml +++ b/config/secrets.yml @@ -21,8 +21,8 @@ shared: aws_sqlsnippets_password: <%= ENV["AWS_SQLSNIPPETS_PASSWORD"] %> aws_sqlsnippets_user: <%= ENV["AWS_SQLSNIPPETS_USER"] %> aws_sqlsnippets_host: <%= ENV["AWS_SQLSNIPPETS_HOST"] %> - glearn_access_key_id: <%= ENV['accesskey'] %> - glearn_secret_access_key: <%= ENV['secretkey'] %> + glearn_access_key_id: <%= ENV['accesskey'] || "temp" %> + glearn_secret_access_key: <%= ENV['secretkey'] || "temp" %> glearn_key_prefix: <%= ENV['GLEARN_KEY_PREFIX'] || "forge" %> glearn_bucket_name: <%= ENV["APP_S3_BUCKET"] || "temp" %> s3_region: <%= ENV["S3_REGION"] || "us-gov-west-1" %> -- GitLab From 26bd3bc382c0176f73345ff73c9066e15746b0aa Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Thu, 22 Oct 2020 15:45:50 -1000 Subject: [PATCH 184/283] more testing changes --- app/controllers/api/v1/users_controller.rb | 2 +- .../api/v1/users_controller_spec.rb | 69 ++++++++++++++ ...platform_one_auth_resolver_service_spec.rb | 89 +++++++++++++++++++ 3 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 spec/services/platform_one_auth_resolver_service_spec.rb diff --git a/app/controllers/api/v1/users_controller.rb b/app/controllers/api/v1/users_controller.rb index 245729e..1712099 100644 --- a/app/controllers/api/v1/users_controller.rb +++ b/app/controllers/api/v1/users_controller.rb @@ -32,7 +32,7 @@ class Api::V1::UsersController < Api::ApplicationController render_method_not_allowed_response and return unless request.post? authorize(current_user, :learn_cli_metadata?) - + byebug @api_interaction_metadata = { cli_benchmark: user_params.as_json } diff --git a/spec/controllers/api/v1/users_controller_spec.rb b/spec/controllers/api/v1/users_controller_spec.rb index 4bc6be9..9a5c4a7 100644 --- a/spec/controllers/api/v1/users_controller_spec.rb +++ b/spec/controllers/api/v1/users_controller_spec.rb @@ -53,6 +53,75 @@ resource "Users" do end end end + + describe "learn_cli_metadata" do + describe "with correct HTTP method" do + + let(:user) { create(:user, :admin, api_token: "token") } + # let(:params) { + # { cli_benchmark: { + # time_to_compress: "0", + # time_to_build_on_learn: "0", + # time_to_upload_to_s3: "0", + # master_release_and_build: "0", + # total_cmd_time: "0", + # command_name: "p1learn" + # } + # } + # } + + header "Content-Type", "application/json" + header "Accept", "application/json" + + # Can't seem to pass params to this post operation correctly + post "/api/v1/users/learn_cli_metadata", format: :json do + parameter ":time_to_compress", "[Path Parameter]\nThe time taken to compress the files", required: true, scope: :cli_benchmark + parameter ":time_to_build_on_learn", "[Path Parameter]\nThe time taken to build the files on learn", required: true, scope: :cli_benchmark + parameter ":time_to_upload_to_s3", "[Path Parameter]\nThe time taken to upload to AWS S3", required: true, scope: :cli_benchmark + parameter ":master_release_and_build", "[Path Parameter]\nThe master build and release version number", required: true, scope: :cli_benchmark + parameter ":total_cmd_time", "[Path Parameter]\nThe total time taken for the command", required: true, scope: :cli_benchmark + parameter ":command_name", "[Path Parameter]\nThe command executed", required: true, scope: :cli_benchmark + + let(:time_to_compress) { 0 } + let(:time_to_build_on_learn) { 0 } + let(:time_to_upload_to_s3) { 0 } + let(:master_release_and_build) { 0 } + let(:total_cmd_time) { 0 } + let(:command_name) { "p1learn" } + + # example "Creating an order" do + # byebug + # expect(params).to eq({ cli_benchmark: { + # time_to_compress: 0 + # }}) + # end + + + # example "Access CLI metadata", document:false do + # header "X-LEARN-API-TOKEN", "Bearer #{user.api_token}" + # do_request + # + # expect(status).to eq 200 + # end + end + end + + describe "with incorrect HTTP method" do + let(:user) { create(:user, :admin, api_token: "token") } + + header "Content-Type", "application/json" + header "Accept", "application/json" + + get "/api/v1/users/learn_cli_metadata" do + example "CLI metadata with incorrect method", document:false do + header "X-LEARN-API-TOKEN", "Bearer #{user.api_token}" + do_request + + expect(status).to eq 405 + end + end + end + end end context "with wrong or no credentials" do diff --git a/spec/services/platform_one_auth_resolver_service_spec.rb b/spec/services/platform_one_auth_resolver_service_spec.rb new file mode 100644 index 0000000..8d6354f --- /dev/null +++ b/spec/services/platform_one_auth_resolver_service_spec.rb @@ -0,0 +1,89 @@ +require "spec_helper" + +describe PlatformOneAuthResolverService do + describe "resolves a user" do + + payload = { + exp: Time.now.to_i + 18000000, + iat: Time.now.to_i, + auth_time: Time.now.to_i, + jti: "e4600f88-1b42-4e01-ac01-8646d3cc4df6", + iss: "https://login.dsop.io/auth/realms/baby-yoda", + aud: "il4_191f836b-ec50-4819-ba10-1afaa5b99600_mission-widow", + sub: "2cba6ea8-8451-4952-80d6-c7de379d5b7e", + typ: "ID", + given_name: "Steve", + family_name: "Wozniak", + email: "the_woz@test.com" + } + + token = JWT.encode(payload, nil, 'none') + + subject { PlatformOneAuthResolverService.new(token) } + + context "the user does not exist" do + it "creates a new user" do + subject.find_or_create_user + + new_user = User.find_by(email: "the_woz@test.com"); + expect(new_user.first_name).to eq("Steve") + expect(new_user.last_name).to eq("Wozniak") + expect(new_user.email).to eq("the_woz@test.com") + expect(new_user.roles).to eq([]) + end + end + + context "the user exists" do + it "finds the user and sets its values" do + create(:user, email: "the_woz@test.com") + + subject.find_or_create_user + + found_user = User.find_by(email: "the_woz@test.com"); + expect(found_user.first_name).to eq("Steve") + expect(found_user.last_name).to eq("Wozniak") + expect(found_user.email).to eq("the_woz@test.com") + expect(found_user.roles).to eq([]) + end + end + + end + + describe "for a token with a missing email" do + payload = { + exp: Time.now.to_i + 18000000, + iat: Time.now.to_i, + auth_time: Time.now.to_i, + jti: "e4600f88-1b42-4e01-ac01-8646d3cc4df6", + iss: "https://login.dsop.io/auth/realms/baby-yoda", + aud: "il4_191f836b-ec50-4819-ba10-1afaa5b99600_mission-widow", + sub: "2cba6ea8-8451-4952-80d6-c7de379d5b7e", + typ: "ID", + given_name: "Steve", + family_name: "Wozniak", + email: "" + } + + token = JWT.encode(payload, nil, 'none') + + subject { PlatformOneAuthResolverService.new(token) } + + it "generates an error" do + expect { subject.find_or_create_user }.to raise_error(PlatformOneAuthResolverService::CreateUserError) + end + end + + describe "for an empty token" do + payload = {} + + token = JWT.encode(payload, nil, 'none') + + subject { PlatformOneAuthResolverService.new(token) } + + it "generates an error" do + # expect(subject.errors.full_messages).to include("Email can't be blank") + expect { subject.find_or_create_user }.to raise_error(PlatformOneAuthResolverService::CreateUserError) + end + end + +end -- GitLab From 9bc3d3d22bd002c6eeabdddb095ad1d2f6b3156b Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Tue, 27 Oct 2020 11:23:24 -1000 Subject: [PATCH 185/283] Some small testing changes --- .../platform_one_auth_resolver_service.rb | 3 +- .../api/v1/users_controller_spec.rb | 98 +++++++++---------- ...platform_one_auth_resolver_service_spec.rb | 1 - 3 files changed, 50 insertions(+), 52 deletions(-) diff --git a/app/services/platform_one_auth_resolver_service.rb b/app/services/platform_one_auth_resolver_service.rb index 7ad8286..f6bde0d 100644 --- a/app/services/platform_one_auth_resolver_service.rb +++ b/app/services/platform_one_auth_resolver_service.rb @@ -32,8 +32,7 @@ class PlatformOneAuthResolverService ) unless user.valid? - puts user.errors.full_messages - raise CreateUserError + raise CreateUserError.new(user.errors.full_messages.join(', ')) end user diff --git a/spec/controllers/api/v1/users_controller_spec.rb b/spec/controllers/api/v1/users_controller_spec.rb index 9a5c4a7..b706241 100644 --- a/spec/controllers/api/v1/users_controller_spec.rb +++ b/spec/controllers/api/v1/users_controller_spec.rb @@ -55,56 +55,56 @@ resource "Users" do end describe "learn_cli_metadata" do - describe "with correct HTTP method" do - - let(:user) { create(:user, :admin, api_token: "token") } - # let(:params) { - # { cli_benchmark: { - # time_to_compress: "0", - # time_to_build_on_learn: "0", - # time_to_upload_to_s3: "0", - # master_release_and_build: "0", - # total_cmd_time: "0", - # command_name: "p1learn" - # } - # } - # } - - header "Content-Type", "application/json" - header "Accept", "application/json" - # Can't seem to pass params to this post operation correctly - post "/api/v1/users/learn_cli_metadata", format: :json do - parameter ":time_to_compress", "[Path Parameter]\nThe time taken to compress the files", required: true, scope: :cli_benchmark - parameter ":time_to_build_on_learn", "[Path Parameter]\nThe time taken to build the files on learn", required: true, scope: :cli_benchmark - parameter ":time_to_upload_to_s3", "[Path Parameter]\nThe time taken to upload to AWS S3", required: true, scope: :cli_benchmark - parameter ":master_release_and_build", "[Path Parameter]\nThe master build and release version number", required: true, scope: :cli_benchmark - parameter ":total_cmd_time", "[Path Parameter]\nThe total time taken for the command", required: true, scope: :cli_benchmark - parameter ":command_name", "[Path Parameter]\nThe command executed", required: true, scope: :cli_benchmark - - let(:time_to_compress) { 0 } - let(:time_to_build_on_learn) { 0 } - let(:time_to_upload_to_s3) { 0 } - let(:master_release_and_build) { 0 } - let(:total_cmd_time) { 0 } - let(:command_name) { "p1learn" } - - # example "Creating an order" do - # byebug - # expect(params).to eq({ cli_benchmark: { - # time_to_compress: 0 - # }}) - # end - - - # example "Access CLI metadata", document:false do - # header "X-LEARN-API-TOKEN", "Bearer #{user.api_token}" - # do_request - # - # expect(status).to eq 200 - # end - end - end + # # Commenting this section out since the learn cli metadata is an undocumented interface + # describe "with correct HTTP method" do + # + # let(:user) { create(:user, :admin, api_token: "token") } + # + # header "Content-Type", "application/json" + # header "Accept", "application/json" + # + # # Can't seem to pass params to this post operation correctly + # post "/api/v1/users/learn_cli_metadata", format: :json do + # parameter ":time_to_compress", "[Path Parameter]\nThe time taken to compress the files", required: true, scope: :cli_benchmark + # parameter ":time_to_build_on_learn", "[Path Parameter]\nThe time taken to build the files on learn", required: true, scope: :cli_benchmark + # parameter ":time_to_upload_to_s3", "[Path Parameter]\nThe time taken to upload to AWS S3", required: true, scope: :cli_benchmark + # parameter ":master_release_and_build", "[Path Parameter]\nThe master build and release version number", required: true, scope: :cli_benchmark + # parameter ":total_cmd_time", "[Path Parameter]\nThe total time taken for the command", required: true, scope: :cli_benchmark + # parameter ":command_name", "[Path Parameter]\nThe command executed", required: true, scope: :cli_benchmark + # + # let(:time_to_compress) { 0 } + # let(:time_to_build_on_learn) { 0 } + # let(:time_to_upload_to_s3) { 0 } + # let(:master_release_and_build) { 0 } + # let(:total_cmd_time) { 0 } + # let(:command_name) { "p1learn" } + # + # let(:cli_benchmark) { + # time_to_compress: "0", + # time_to_build_on_learn: "0", + # time_to_upload_to_s3: "0", + # master_release_and_build: "0", + # total_cmd_time: "0", + # command_name: "p1learn" + # } + # } + # + # # example "Creating an order" do + # # byebug + # # expect(params).to eq({ cli_benchmark: { + # # time_to_compress: 0 + # # }}) + # # end + # + # # example "Access CLI metadata", document:false do + # # header "X-LEARN-API-TOKEN", "Bearer #{user.api_token}" + # # do_request + # # + # # expect(status).to eq 200 + # # end + # end + # end describe "with incorrect HTTP method" do let(:user) { create(:user, :admin, api_token: "token") } diff --git a/spec/services/platform_one_auth_resolver_service_spec.rb b/spec/services/platform_one_auth_resolver_service_spec.rb index 8d6354f..cf0f3f2 100644 --- a/spec/services/platform_one_auth_resolver_service_spec.rb +++ b/spec/services/platform_one_auth_resolver_service_spec.rb @@ -81,7 +81,6 @@ describe PlatformOneAuthResolverService do subject { PlatformOneAuthResolverService.new(token) } it "generates an error" do - # expect(subject.errors.full_messages).to include("Email can't be blank") expect { subject.find_or_create_user }.to raise_error(PlatformOneAuthResolverService::CreateUserError) end end -- GitLab From e68c29234e9c5753b73ae44e0f16843a03df6257 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Thu, 5 Nov 2020 09:41:11 -1000 Subject: [PATCH 186/283] Change to add python 3.8 --- .../components/challenges/challenge_block/ChallengeBlock.tsx | 2 +- .../challenge_validators/code_snippet_challenge_validator.rb | 4 ++-- .../code_snippet_challenge_validator_spec.rb | 4 ++-- spec/features/cohorts/management_feature_spec.rb | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/javascript/components/challenges/challenge_block/ChallengeBlock.tsx b/app/javascript/components/challenges/challenge_block/ChallengeBlock.tsx index 0bfcf1e..8bc8131 100644 --- a/app/javascript/components/challenges/challenge_block/ChallengeBlock.tsx +++ b/app/javascript/components/challenges/challenge_block/ChallengeBlock.tsx @@ -538,7 +538,7 @@ export default class ChallengeBlock extends React.Component { editorMode() { const { language } = this.props.challenge; - return language === 'python2.7' || language === 'python3.6' ? 'python' : language; + return language === 'python2.7' || language === 'python3.6' || language === 'python3.8' ? 'python' : language; } toggleFakeProcessing() { diff --git a/gems/block-parser/lib/block_parser/challenge_validators/code_snippet_challenge_validator.rb b/gems/block-parser/lib/block_parser/challenge_validators/code_snippet_challenge_validator.rb index 28ed635..f137bba 100644 --- a/gems/block-parser/lib/block_parser/challenge_validators/code_snippet_challenge_validator.rb +++ b/gems/block-parser/lib/block_parser/challenge_validators/code_snippet_challenge_validator.rb @@ -7,8 +7,8 @@ module BlockParser :language, presence: true, inclusion: { - in: ["java", "javascript", "python2.7", "python3.6", "sql"], - message: "language must be java, javascript, python2.7, or python3.6, or sql" + in: ["java", "javascript", "python2.7", "python3.6", "python3.8", "sql"], + message: "language must be java, javascript, python3.6, or python3.8" } ) validates :tests, presence: true diff --git a/gems/block-parser/spec/challenge_validators/code_snippet_challenge_validator_spec.rb b/gems/block-parser/spec/challenge_validators/code_snippet_challenge_validator_spec.rb index 15a5342..cb6fa75 100644 --- a/gems/block-parser/spec/challenge_validators/code_snippet_challenge_validator_spec.rb +++ b/gems/block-parser/spec/challenge_validators/code_snippet_challenge_validator_spec.rb @@ -54,13 +54,13 @@ describe BlockParser::ChallengeValidators::CodeSnippetChallengeValidator do challenge_validator = described_class.new(code_snippet_json) expect(challenge_validator.valid?).to eq(false) - expect(challenge_validator.errors[:language]).to eq(["can't be blank", "language must be java, javascript, python2.7, or python3.6, or sql"]) + expect(challenge_validator.errors[:language]).to eq(["can't be blank", "language must be java, javascript, python3.6, or python3.8"]) code_snippet_json[:language] = "Lua" challenge_validator = described_class.new(code_snippet_json) expect(challenge_validator.valid?).to eq(false) - expect(challenge_validator.errors[:language]).to eq(["language must be java, javascript, python2.7, or python3.6, or sql"]) + expect(challenge_validator.errors[:language]).to eq(["language must be java, javascript, python3.6, or python3.8"]) end it "requires tests" do diff --git a/spec/features/cohorts/management_feature_spec.rb b/spec/features/cohorts/management_feature_spec.rb index 6629248..d5279ed 100644 --- a/spec/features/cohorts/management_feature_spec.rb +++ b/spec/features/cohorts/management_feature_spec.rb @@ -203,7 +203,7 @@ describe "Cohorts management", js: true do if cohort.campus_name expect(page).to have_content(cohort.campus_name) end - expect(page).to have_content(cohort.starts_on.strftime("%b %e, %Y")) + expect(page).to have_content(cohort.starts_on.strftime("%b %-d, %Y")) # expect(page).to have_link("Edit", href: "#{Rails.application.secrets.auth_url}/admin/products/#{cohort.uid}/edit") end end -- GitLab From 00dc84c3a9a028bc52290f72cd8a250294937b6b Mon Sep 17 00:00:00 2001 From: Derrin Chong Date: Thu, 5 Nov 2020 16:02:42 -1000 Subject: [PATCH 187/283] Convert to IB directory format --- .Dockerfile.swp | Bin 0 -> 20480 bytes .circleci/config.yml | 97 ---------- Dockerfile | 81 ++++++--- Dockerfile.base | 47 ----- Dockerfile.old | 169 ++++++++++++++++++ Jenkinsfile | 14 ++ download.json | 13 ++ .browserslistrc => scripts/.browserslistrc | 0 .env.example => scripts/.env.example | 0 .eslintrc.json => scripts/.eslintrc.json | 0 .haml-lint.yml => scripts/.haml-lint.yml | 0 .nvmrc => scripts/.nvmrc | 0 .overcommit.yml => scripts/.overcommit.yml | 0 .postcssrc.yml => scripts/.postcssrc.yml | 0 .rubocop.yml => scripts/.rubocop.yml | 0 .ruby-version => scripts/.ruby-version | 0 .stylelintrc => scripts/.stylelintrc | 0 Gemfile => scripts/Gemfile | 0 Gemfile.lock => scripts/Gemfile.lock | 0 Procfile => scripts/Procfile | 0 Procfile.local => scripts/Procfile.local | 0 README.md => scripts/README.md | 0 Rakefile => scripts/Rakefile | 0 app.json => scripts/app.json | 0 .../app}/assets/config/manifest.js | 0 .../app}/assets/images/favicon.ico | Bin .../app}/assets/images/loader-black.svg | 0 .../app}/assets/images/loader-cyan.svg | 0 .../app}/assets/images/loader-white.svg | 0 {app => scripts/app}/assets/images/lost.jpg | Bin .../app}/assets/images/spinner.gif | Bin .../assets/images/svg/baseline-notes-24px.svg | 0 .../app}/assets/images/svg/g-learn-lockup.svg | 0 .../app}/assets/images/svg/galvanize-logo.svg | 0 .../app}/assets/images/svg/github-icon.svg | 0 .../app}/assets/images/svg/mobile-logo.svg | 0 .../assets/images/svg/octicon-git-branch.svg | 0 .../images/svg/svg-sprite-action-symbol.svg | 0 .../images/svg/svg-sprite-av-symbol.svg | 0 .../images/svg/svg-sprite-device-symbol.svg | 0 .../images/svg/svg-sprite-image-symbol.svg | 0 .../svg/svg-sprite-navigation-symbol.svg | 0 .../app}/assets/javascripts/application.js | 0 .../app}/assets/javascripts/mobile.js | 0 .../app}/assets/stylesheets/application.scss | 0 .../app}/assets/stylesheets/base.scss | 0 .../assets/stylesheets/bootstrap-custom.scss | 0 .../app}/assets/stylesheets/cohorts.scss | 0 .../components/_404-container.scss | 0 .../stylesheets/components/_action-menu.scss | 0 .../components/_activity-dashboard.scss | 0 .../components/_activity-feed.scss | 0 .../components/_api-interactions.scss | 0 .../stylesheets/components/_api_token.scss | 0 .../components/_auth-style-search.scss | 0 .../stylesheets/components/_blocks-index.scss | 0 .../stylesheets/components/_blocks-stats.scss | 0 .../stylesheets/components/_button.scss | 0 .../stylesheets/components/_callouts.scss | 0 .../components/_challenge-block.scss | 0 .../components/_challenge_status.scss | 0 .../components/_checkbox-input.scss | 0 .../components/_checkpoint-landing.scss | 0 .../components/_checkpoint-submission.scss | 0 ...heckpoint-submissions-columns-student.scss | 0 .../_checkpoint-submissions-columns.scss | 0 .../_checkpoint-submissions-index.scss | 0 .../_checkpoint_student_scores.scss | 0 .../_checkpoint_submisstion_state.scss | 0 .../components/_checkpoint_toolbar.scss | 0 .../stylesheets/components/_code-block.scss | 0 .../components/_cohort-submissions-table.scss | 0 .../components/_cohort_releases.scss | 0 .../stylesheets/components/_cohorts.scss | 0 .../components/_content-file-show.scss | 0 .../components/_content-file-sidebar.scss | 0 .../_curriculum-checkpoint-summary.scss | 0 .../components/_curriculum-progress.scss | 0 .../stylesheets/components/_curriculum.scss | 0 .../components/_dropdown-component.scss | 0 .../components/_external-link.scss | 0 .../components/_flash-message.scss | 0 .../stylesheets/components/_footer.scss | 0 .../components/_grade-buttons.scss | 0 .../components/_integer_picker.scss | 0 .../components/_lp-style-button.scss | 0 .../components/_mastery-table.scss | 0 .../assets/stylesheets/components/_modal.scss | 0 .../components/_navigation-dropdown.scss | 0 .../components/_notifications.scss | 0 .../stylesheets/components/_pagination.scss | 0 .../assets/stylesheets/components/_pill.scss | 0 .../components/_point_grade_buttons.scss | 0 .../components/_primary-header.scss | 0 .../components/_primary-navigation.scss | 0 .../stylesheets/components/_progress.scss | 0 .../components/_progress_thresholds_key.scss | 0 .../_progress_thresholds_modal.scss | 0 .../_progress_thresholds_slider.scss | 0 .../stylesheets/components/_search-bar.scss | 0 .../components/_secondary-navigation.scss | 0 .../stylesheets/components/_slideshow.scss | 0 .../components/_sort-dropdown-component.scss | 0 .../components/_standard-card.scss | 0 .../components/_standard-cards.scss | 0 .../components/_standards-mastery-beans.scss | 0 .../components/_status_picker.scss | 0 .../components/_student-mastery-table.scss | 0 .../components/_student-name-bar.scss | 0 .../_submissions-dashboard-table.scss | 0 .../stylesheets/components/_svg-icon.scss | 0 .../stylesheets/components/_thresholds.scss | 0 .../components/_universal-list.scss | 0 .../components/_universal-row.scss | 0 .../components/_universal-table.scss | 0 .../stylesheets/components/_user-avatar.scss | 0 .../stylesheets/components/_video-player.scss | 0 .../assets/stylesheets/components/badge.scss | 0 .../components/challenge-detail-comments.scss | 0 .../components/challenge-detail-view.scss | 0 .../components/challenge-timeline.scss | 0 .../components/new-comment-form.scss | 0 .../stylesheets/components/partnerup.scss | 0 .../components/progress-table.scss | 0 .../stylesheets/hopscotch-overrides.scss | 0 .../app}/assets/stylesheets/mixins.scss | 0 .../app}/assets/stylesheets/mobile.scss | 0 .../mobile/_submissions-dashboard-table.scss | 0 .../app}/assets/stylesheets/typography.scss | 0 .../app}/assets/stylesheets/variables.scss | 0 .../activity_feed_item_component_props.rb | 0 .../notifications_component_props.rb | 0 .../standard_card_component_props.rb | 0 .../controllers/api/application_controller.rb | 0 .../api/v1/blocks/releases_controller.rb | 0 .../controllers/api/v1/blocks_controller.rb | 0 .../blocks/content_files_controller.rb | 0 .../api/v1/cohorts/blocks/units_controller.rb | 0 .../api/v1/cohorts/cohorts_controller.rb | 0 .../api/v1/cohorts/users_controller.rb | 0 .../api/v1/content_files_controller.rb | 0 .../api/v1/pineapple_controller.rb | 0 .../controllers/api/v1/releases_controller.rb | 0 .../controllers/api/v1/users_controller.rb | 0 .../controllers/application_controller.rb | 0 .../controllers/blocks/releases_controller.rb | 0 .../app}/controllers/blocks_controller.rb | 0 .../blocks/content_files_controller.rb | 0 .../activities_controller.rb | 0 .../cohorts/cohort_releases_controller.rb | 0 .../checkpoint_submissions_controller.rb | 0 .../submitted_challenge_answers_controller.rb | 0 .../cohorts/content_files_controller.rb | 0 .../cohorts/pairings_controller.rb | 0 .../cohorts/standards_controller.rb | 0 .../activities_controller.rb | 0 .../cohorts/users/challenges_controller.rb | 0 .../cohorts/users/performances_controller.rb | 0 .../controllers/cohorts/users_controller.rb | 0 .../app}/controllers/cohorts_controller.rb | 0 .../concerns/api/content_visibility_crud.rb | 0 .../concerns/api/exception_handler.rb | 0 .../app}/controllers/concerns/api/response.rb | 0 .../app}/controllers/home_controller.rb | 0 .../controllers/notifications_controller.rb | 0 .../app}/controllers/permalinks_controller.rb | 0 .../app}/controllers/sessions_controller.rb | 0 .../app}/controllers/users_controller.rb | 0 .../submitted_challenge_answers_controller.rb | 0 .../app}/exporters/performance_exporter.rb | 0 .../app}/exporters/progress_exporter.rb | 0 {app => scripts/app}/finders/block_finder.rb | 0 .../finders/checkpoint_submission_finder.rb | 0 .../app}/finders/cohort_user_finder.rb | 0 .../app}/finders/content_file_finder.rb | 0 .../app}/finders/performance_finder.rb | 0 .../app}/finders/release_finder.rb | 0 .../app}/finders/standard_finder.rb | 0 .../submitted_challenge_answer_finder.rb | 0 {app => scripts/app}/finders/user_finder.rb | 0 .../app}/helpers/application_helper.rb | 0 {app => scripts/app}/helpers/json_helper.rb | 0 .../helpers/secondary_navigation_helper.rb | 0 .../helpers/standard_navigation_helper.rb | 0 {app => scripts/app}/javascript/api.d.ts | 0 .../app}/javascript/components/AceEditor.tsx | 0 .../app}/javascript/components/Badge.tsx | 0 .../app}/javascript/components/Button.tsx | 0 .../app}/javascript/components/ButtonTo.tsx | 0 .../app}/javascript/components/Dropdown.tsx | 0 .../app}/javascript/components/Icon.tsx | 0 .../app}/javascript/components/Loading.tsx | 0 .../app}/javascript/components/Marked.tsx | 0 .../app}/javascript/components/Menu.tsx | 0 .../javascript/components/Notifications.tsx | 0 .../javascript/components/ProcessingIcon.tsx | 0 .../app}/javascript/components/RowKebab.tsx | 0 .../javascript/components/ScoreCircle.tsx | 0 .../javascript/components/SidebarProgress.tsx | 0 .../javascript/components/SortDropdown.tsx | 0 .../javascript/components/StandardBean.tsx | 0 .../javascript/components/SvgRenderer.tsx | 0 .../app}/javascript/components/Timestamp.tsx | 0 .../app}/javascript/components/UserAvatar.tsx | 0 .../components/activities/NewActivityForm.tsx | 0 .../components/api/ApiInteractions.tsx | 0 .../javascript/components/api/ApiToken.tsx | 0 .../components/blocks/BlockPage-v2.tsx | 0 .../components/blocks/BlocksIndex-v2.tsx | 0 .../components/blocks/BlocksNewModal.tsx | 0 .../components/blocks/BlocksNewRelease.tsx | 0 .../components/blocks/BlocksRow.tsx | 0 .../components/blocks/BlocksShow.tsx | 0 .../components/blocks/BlocksStats.tsx | 0 .../components/blocks/CohortsTooltip.tsx | 0 .../components/challenges/AvatarBar.tsx | 0 .../challenges/ChallengeDetailView.tsx | 0 .../components/challenges/ChallengeShow.tsx | 0 .../challenge_block/ChallengeActionBlock.tsx | 0 .../challenge_block/ChallengeBlock.tsx | 0 .../ChallengeDetailActivities.tsx | 0 .../ChallengeExplanationBlock.tsx | 0 .../ChallengeFeedbackBlock.tsx | 0 .../challenge_block/ChallengeHintsBlock.tsx | 0 .../challenge_block/ChallengeInputs.tsx | 0 .../ChallengeLocalTestResults.tsx | 0 .../challenge_block/ChallengeRubricBlock.tsx | 0 .../challenge_block/ChallengeStatus.tsx | 0 .../challenge_block/ChallengeStatusBar.tsx | 0 .../challenge_block/ChallengeTestResults.tsx | 0 .../challenge_block/ChallengeTests.tsx | 0 .../challenge_block/ChallengeTimeLine.tsx | 0 .../challenge_block/GradeIndicator.tsx | 0 .../challenge_block/GradedTimestamp.tsx | 0 .../challenge_block/StatusPicker.tsx | 0 .../challenges/local/run-local-challenge.ts | 0 .../components/challenges/local/sandbox.ts | 0 .../challenges/local/stack-traces.ts | 0 .../CheckpointAfterSubmitButton.tsx | 0 .../CheckpointAfterSubmitModal.tsx | 0 .../CheckpointAfterSubmitModalError.tsx | 0 .../CheckpointSubmissionChallenges.tsx | 0 .../checkpoints/CheckpointSubmissionShow.tsx | 0 .../checkpoints/CheckpointSubmissionState.tsx | 0 .../CheckpointSubmissionStudentNameBar.tsx | 0 .../components/cohorts/CohortsIndex.tsx | 0 .../components/cohorts/UsersNew.tsx | 0 .../activity_dashboard/ActivityDashboard.tsx | 0 .../cohorts/activity_feed/ActivityFeed.tsx | 0 .../cohort_releases/ReleaseVersionsTable.tsx | 0 .../cohort_submissions/CohortSubmissions.tsx | 0 .../CohortSubmissionsChallengeItem.tsx | 0 .../CohortSubmissionsLessonRow.tsx | 0 .../CohortSubmissionsPerformanceModal.tsx | 0 .../CohortSubmissionsStandardRow.tsx | 0 .../CohortSubmissionsStudentColumn.tsx | 0 .../CohortSubmissionsStudentNameBar.tsx | 0 .../CohortSubmissionsStudentStandard.tsx | 0 .../CohortSubmissionsTable.tsx | 0 .../CohortSubmissionsUnitPercent.tsx | 0 .../cohorts/mastery/MasteryTable.tsx | 0 .../components/cohorts/mastery/MetricRow.tsx | 0 .../cohorts/mastery/MetricsBody.tsx | 0 .../cohorts/mastery/PerformanceCell.tsx | 0 .../cohorts/mastery/PerformanceRow.tsx | 0 .../cohorts/mastery/ReleaseBody.tsx | 0 .../cohorts/mastery/StandardRow.tsx | 0 .../cohorts/mastery/StudentHeader.tsx | 0 .../cohorts/mastery/StudentMasteryTable.tsx | 0 .../cohorts/mastery/StudentReleaseRow.tsx | 0 .../components/cohorts/pairing/GroupPairs.tsx | 0 .../cohorts/pairing/InnerStudentList.tsx | 0 .../components/cohorts/pairing/NewPairing.tsx | 0 .../cohorts/pairing/PairingBoard.tsx | 0 .../cohorts/pairing/StudentItem.tsx | 0 .../cohorts/pairing/StudentList.tsx | 0 .../progress/MasteryProgressionBar.tsx | 0 .../progress/ProgressThresholdCellHeaders.tsx | 0 .../cohorts/progress/StudentProgress.tsx | 0 .../cohorts/progress/StudentProgressBar.tsx | 0 .../cohorts/progress/StudentProgressCells.tsx | 0 .../cohorts/progress/StudentProgressRow.tsx | 0 .../progress/StudentProgressSortArrow.tsx | 0 .../cohorts/settings/BranchReleaseModal.tsx | 0 .../settings/CohortBlockReleaseRow.tsx | 0 .../cohorts/settings/CohortContentTab.tsx | 0 .../cohorts/settings/CohortInfo.tsx | 0 .../cohorts/settings/CohortSettingsResync.tsx | 0 .../cohorts/settings/CohortSettingsTabs.tsx | 0 .../settings/CohortVisibilitySection.tsx | 0 .../settings/CurriculumSettingsTab.tsx | 0 .../cohorts/settings/ReleaseVersionModal.tsx | 0 .../cohorts/settings/ReleaseVersionRow.tsx | 0 .../cohorts/settings/UserCohortKebab.tsx | 0 .../cohorts/settings/UserImport.tsx | 0 .../components/cohorts/settings/UserKebab.tsx | 0 .../AnswerStatusRollup.tsx | 0 .../HeaderStandardContainer.tsx | 0 .../StandardContainer.tsx | 0 .../SubmissionsDashboard.tsx | 0 .../SubmissionsDashboardChallengeItem.tsx | 0 .../SubmissionsDashboardContentFileRow.tsx | 0 .../SubmissionsDashboardStudentColumn.tsx | 0 .../SubmissionsDashboardStudentNameBar.tsx | 0 .../SubmissionsDashboardTable.tsx | 0 .../components/content_files/ActionMenus.tsx | 0 .../components/content_files/Lesson.tsx | 0 .../content_files/MarkdownRenderer.tsx | 0 .../components/content_files/PDFRenderer.tsx | 0 .../components/content_files/SideBar.tsx | 0 .../content_files/SubmissionRenderer.tsx | 0 .../content_files/checkpoints/Checkpoint.tsx | 0 .../checkpoints/CheckpointActionBar.tsx | 0 .../checkpoints/CheckpointDetails.tsx | 0 .../checkpoints/CheckpointLanding.tsx | 0 .../CheckpointLandingAttribute.tsx | 0 .../checkpoints/CheckpointPairs.tsx | 0 .../content_files/checkpoints/PairAvatars.tsx | 0 .../student_scores/CheckpointStudentRow.tsx | 0 .../CheckpointStudentScores.tsx | 0 .../curriculum/CheckpointSummary.tsx | 0 .../curriculum/CohortCurriculum.tsx | 0 .../curriculum/CurriculumStandardCard.tsx | 0 .../curriculum/ProgressIndicators.tsx | 0 .../components/curriculum/StandardBeans.tsx | 0 .../curriculum/StandardsRenderer.tsx | 0 .../StudentOverallProgressDoughnut.tsx | 0 .../app}/javascript/components/lib/ace.ts | 0 .../notifications/NotificationsIcon.tsx | 0 .../shared/ActionMenu/ActionMenu.tsx | 0 .../components/shared/Button/Button.tsx | 0 .../ChallengePoints/ChallengePoints.tsx | 0 .../ChallengePoints/PartialCreditBaton.tsx | 0 .../shared/ChallengePoints/SpinText.tsx | 0 .../IntegerPicker/IntegerPicker.tsx | 0 .../components/shared/DonutRing/DonutRing.tsx | 0 .../components/ColorDonut/ColorDonut.tsx | 0 .../CompleteDonut/CompleteDonut.tsx | 0 .../UngradedDonut/UngradedDonut.tsx | 0 .../UngradedDonut/UngradedDonut.tsx | 0 .../ErrorMessagesTable/ErrorMessagesTable.tsx | 0 .../shared/FlashAlert/FlashAlert.tsx | 0 .../shared/FormatNumber/FormatNumber.tsx | 0 .../components/shared/Icons/AlertSign.tsx | 0 .../components/shared/Icons/Clear.tsx | 0 .../components/shared/Icons/CloseButton.tsx | 0 .../components/shared/Icons/Done.tsx | 0 .../shared/Icons/KeyboardArrowDown.tsx | 0 .../shared/Icons/KeyboardArrowUp.tsx | 0 .../components/shared/Icons/SettingsCog.tsx | 0 .../components/shared/Icons/StatusCircle.tsx | 0 .../MasteryProgressBar/MasteryProgressBar.tsx | 0 .../components/shared/Modal/Modal.tsx | 0 .../shared/Pagination/Pagination.tsx | 0 .../PercentageProgressBar.tsx | 0 .../components/shared/Pill/Pill.tsx | 0 .../PointGradeButtons/PointGradeButtons.tsx | 0 .../shared/PointGradeButtons/SpinText.tsx | 0 .../shared/ProgressBar/ProgressBar.tsx | 0 .../ProgressThresholdsKey.tsx | 0 .../ProgressThresholdsModal.tsx | 0 .../ProgressThresholdsSlider.tsx | 0 .../components/shared/SearchBar/SearchBar.tsx | 0 .../components/shared/Slideshow/Slideshow.tsx | 0 .../shared/UngradedDonut/UngradedDonut.tsx | 0 .../shared/UniversalList/UniversalList.tsx | 0 .../shared/UniversalRow/UniversalRow.tsx | 0 .../shared/UniversalTable/UniversalTable.tsx | 0 .../standards/CompletionScoringBlock.tsx | 0 .../standards/MasteryScoringBlock.tsx | 0 .../components/standards/StandardCard.tsx | 0 .../standards/StandardScoreButton.tsx | 0 .../standards/StandardScoringBlock.tsx | 0 .../standards/StandardTopicsRollups.tsx | 0 .../components/users/UsersIndex.tsx | 0 .../components/vendor/ReactTooltip.js | 0 .../app}/javascript/generated/routes.ts | 0 {app => scripts/app}/javascript/globals.ts | 0 {app => scripts/app}/javascript/lib/http.ts | 0 {app => scripts/app}/javascript/lib/utils.ts | 0 .../app}/javascript/packs/application.js | 0 .../app}/javascript/packs/server_rendering.js | 0 {app => scripts/app}/jobs/application_job.rb | 0 .../app}/jobs/branch_release_notifier_job.rb | 0 .../jobs/checkpoint_paired_submission_job.rb | 0 .../content_file_default_visibility_job.rb | 0 .../app}/jobs/content_file_visit_job.rb | 0 .../app}/jobs/create_api_interaction_job.rb | 0 .../app}/jobs/create_release_job.rb | 0 .../app}/jobs/evaluate_code_snippet_job.rb | 0 .../app}/jobs/evaluate_custom_snippet_job.rb | 0 .../app}/jobs/evaluate_project_job.rb | 0 .../app}/jobs/grade_timed_checkpoint_job.rb | 0 .../app}/jobs/import_student_work_job.rb | 0 .../app}/jobs/java_code_evaluation_job.rb | 0 .../jobs/javascript_code_evaluation_job.rb | 0 {app => scripts/app}/jobs/progress_csv_job.rb | 0 .../app}/jobs/python_code_evaluation_job.rb | 0 .../app}/jobs/release_notifier_job.rb | 0 .../app}/jobs/resync_course_job.rb | 0 .../app}/jobs/set_block_caches_job.rb | 0 .../jobs/slack_challenge_performance_job.rb | 0 .../app}/jobs/slack_dev_notify_job.rb | 0 .../app}/jobs/slack_ds_prep_job.rb | 0 {app => scripts/app}/jobs/slack_job.rb | 0 .../app}/jobs/slack_se_prep_job.rb | 0 .../app}/jobs/slack_student_job.rb | 0 .../app}/jobs/student_progress_auth_job.rb | 0 .../app}/jobs/switch_to_branch_job.rb | 0 .../app}/mailers/application_mailer.rb | 0 {app => scripts/app}/mailers/user_mailer.rb | 0 {app => scripts/app}/models/activity.rb | 0 .../app}/models/api_interaction.rb | 0 .../app}/models/application_record.rb | 0 {app => scripts/app}/models/block.rb | 0 {app => scripts/app}/models/challenge.rb | 0 .../app}/models/checkpoint_submission.rb | 0 {app => scripts/app}/models/cohort.rb | 0 {app => scripts/app}/models/cohort_release.rb | 0 {app => scripts/app}/models/cohort_user.rb | 0 .../app}/models/concerns/findable_by_uid.rb | 0 .../app}/models/concerns/read_only_model.rb | 0 {app => scripts/app}/models/content_file.rb | 0 .../app}/models/content_visibility.rb | 0 {app => scripts/app}/models/job_result.rb | 0 {app => scripts/app}/models/lesson_visit.rb | 0 {app => scripts/app}/models/notification.rb | 0 {app => scripts/app}/models/pairing.rb | 0 {app => scripts/app}/models/performance.rb | 0 {app => scripts/app}/models/release.rb | 0 .../app}/models/resync_job_result.rb | 0 {app => scripts/app}/models/section.rb | 0 {app => scripts/app}/models/standard.rb | 0 .../app}/models/submitted_challenge_answer.rb | 0 {app => scripts/app}/models/unit.rb | 0 {app => scripts/app}/models/user.rb | 0 .../models/user_last_viewed_standard_path.rb | 0 .../app}/policies/activity_policy.rb | 0 .../app}/policies/application_policy.rb | 0 {app => scripts/app}/policies/block_policy.rb | 0 .../policies/checkpoint_submission_policy.rb | 0 .../app}/policies/cohort_policy.rb | 0 .../app}/policies/cohort_release_policy.rb | 0 .../app}/policies/cohort_user_policy.rb | 0 .../app}/policies/content_file_policy.rb | 0 .../app}/policies/notification_policy.rb | 0 .../app}/policies/performance_policy.rb | 0 .../app}/policies/release_policy.rb | 0 .../submitted_challenge_answer_policy.rb | 0 {app => scripts/app}/policies/user_policy.rb | 0 .../app}/presenters/activity_presenter.rb | 0 .../presenters/block_presenter/for_block.rb | 0 .../block_presenter/for_cohort_releases.rb | 0 .../for_cohort_releases_new.rb | 0 .../block_presenter/for_releases.rb | 0 ...h_submitted_challenge_answers_presenter.rb | 0 .../checkpoint_submission_presenter.rb | 0 .../for_index.rb | 0 .../for_student_row.rb | 0 .../for_cohort_setup.rb | 0 .../presenters/cohort_setup/visibility.rb | 0 .../for_curriculum_last_viewed.rb | 0 .../content_file_presenter/for_footer.rb | 0 .../content_file_presenter/for_show.rb | 0 .../content_file_presenter/for_sidebar.rb | 0 .../app}/presenters/performance_presenter.rb | 0 .../standard_card_component_props.rb | 0 .../for_challenge_detail_view.rb | 0 .../for_checkpoint_submission.rb | 0 .../standard_presenter/for_standard_card.rb | 0 .../for_submissions_dashboard.rb | 0 .../presenters/stat_progress_presenter.rb | 0 .../presenters/student_progress_presenter.rb | 0 .../submissions_dashboard_presenter.rb | 0 .../submitted_challenge_answer_presenter.rb | 0 .../presenters/user_presenter/for_avatar.rb | 0 .../services/activity_aggregator_service.rb | 0 .../app}/services/assessment_service.rb | 0 .../services/auto_assign_release_service.rb | 0 .../services/checkpoint_submission_service.rb | 0 .../cohort_standard_progress_service.rb | 0 .../cohort_student_progress_service.rb | 0 .../completion_mode_percent_service.rb | 0 .../app}/services/course_validator.rb | 0 ...eate_submitted_challenge_answer_service.rb | 0 .../services/curriculum_progress_service.rb | 0 .../download_github_repository_service.rb | 0 .../download_gitlab_repository_service.rb | 0 .../services/download_repository_service.rb | 0 .../download_s3_repository_service.rb | 0 .../services/encoded_image_link_service.rb | 0 .../app}/services/git_url_service.rb | 0 .../app}/services/mastery_average_service.rb | 0 .../services/mastery_mode_percent_service.rb | 0 .../app}/services/mock_mixpanel.rb | 0 .../app}/services/notification_service.rb | 0 .../platform_one_auth_resolver_service.rb | 0 .../services/preview_content_file_service.rb | 0 .../services/release_destroyer_service.rb | 0 .../app}/services/release_helper_service.rb | 0 .../app}/services/resync_course_service.rb | 0 .../services/s3_asset_uploader_service.rb | 0 .../app}/services/segment_track_service.rb | 0 .../app}/services/sql_challenge_db_service.rb | 0 .../services/standard_submissions_service.rb | 0 .../app}/views/api_interactions.html.haml | 0 .../app}/views/api_token.html.haml | 0 .../app}/views/apitome/docs/_headers.html.erb | 0 .../app}/views/apitome/docs/_params.html.erb | 0 .../app}/views/blocks/blockpagev2.html.haml | 0 .../app}/views/blocks/index.html.haml | 0 .../app}/views/blocks/new.html.haml | 0 .../app}/views/blocks/releases/new.html.haml | 0 .../app}/views/blocks/show.html.haml | 0 .../views/cohorts/_cohort_edit_form.html.haml | 0 .../app}/views/cohorts/_cohort_info.html.haml | 0 .../_completion_progress_donut.html.haml | 0 .../app}/views/cohorts/_user_table.html.haml | 0 .../cohorts/activity_dashboard.html.haml | 0 .../blocks/content_files/_footer.html.haml | 0 .../blocks/content_files/show.html.haml | 0 .../cohorts/cohort_releases/index.html.haml | 0 .../app}/views/cohorts/content.html.haml | 0 .../checkpoint_submissions/show.html.haml | 0 .../app}/views/cohorts/course_stats.html.haml | 0 .../app}/views/cohorts/edit.html.haml | 0 .../app}/views/cohorts/error.html.haml | 0 .../app}/views/cohorts/feed.html.haml | 0 .../app}/views/cohorts/index.html.haml | 0 .../app}/views/cohorts/new.html.haml | 0 .../app}/views/cohorts/partnerup.html.haml | 0 .../app}/views/cohorts/setup.html.haml | 0 .../app}/views/cohorts/show.html.haml | 0 .../checkpoint_submissions/index.html.haml | 0 .../views/cohorts/unit_progress.html.haml | 0 .../app}/views/cohorts/users.html.haml | 0 .../cohorts/users/challenges/show.html.haml | 0 .../cohorts/users/mastery/index.html.haml | 0 .../users/submissions_dashboard.html.haml | 0 .../app}/views/error_404.html.haml | 0 .../app}/views/error_500.html.haml | 0 .../app}/views/home/index.html.haml | 0 .../layouts/_primary_navigation.html.haml | 0 .../layouts/_secondary_navigation.html.haml | 0 .../app}/views/layouts/application.html.haml | 0 .../app}/views/layouts/mailer.html.erb | 0 .../app}/views/layouts/mailer.text.erb | 0 .../app}/views/permalinks/permalink.html.haml | 0 .../views/shared/_content_file_js.html.haml | 0 .../shared/_hopscotch_callbacks_js.html.haml | 0 .../app}/views/shared/_intercom_js.html.haml | 0 .../app}/views/shared/_segment_js.html.haml | 0 .../app}/views/user_mailer/send_file.html | 0 .../user_mailer/user_import_work.html.haml | 0 .../app}/views/users/edit.html.haml | 0 .../app}/views/users/edit_user.html.haml | 0 .../app}/views/users/index.html.haml | 0 .../app}/views/users/new.html.haml | 0 babel.config.js => scripts/babel.config.js | 0 {bin => scripts/bin}/bundle | 0 {bin => scripts/bin}/rails | 0 {bin => scripts/bin}/rake | 0 {bin => scripts/bin}/setup | 0 {bin => scripts/bin}/update | 0 {bin => scripts/bin}/webpack | 0 {bin => scripts/bin}/webpack-dev-server | 0 {bin => scripts/bin}/yarn | 0 config.ru => scripts/config.ru | 0 {config => scripts/config}/application.rb | 0 {config => scripts/config}/boot.rb | 0 {config => scripts/config}/database.yml | 0 {config => scripts/config}/environment.rb | 0 .../config}/environments/development.rb | 0 .../config}/environments/production.rb | 0 .../config}/environments/test.rb | 0 .../config}/get-routes-audit.md | 0 {config => scripts/config}/honeybadger.yml | 0 .../config}/initializers/apitome.rb | 0 .../application_controller_renderer.rb | 0 .../config}/initializers/assets.rb | 0 .../config}/initializers/auth_api.rb | 0 .../config}/initializers/aws.rb | 0 .../initializers/backtrace_silencers.rb | 0 .../initializers/content_security_policy.rb | 0 .../initializers/cookies_serializer.rb | 0 .../initializers/filter_parameter_logging.rb | 0 .../config}/initializers/inflections.rb | 0 .../config}/initializers/mime_types.rb | 0 .../new_framework_defaults_5_1.rb | 0 .../new_framework_defaults_5_2.rb | 0 .../config}/initializers/octokit.rb | 0 .../config}/initializers/pagy.rb | 0 .../config}/initializers/pundit.rb | 0 .../config}/initializers/rack_attack.rb | 0 .../config}/initializers/segment.rb | 0 .../config}/initializers/sidekiq.rb | 0 .../config}/initializers/wrap_parameters.rb | 0 {config => scripts/config}/locales/en.yml | 0 {config => scripts/config}/puma.rb | 0 {config => scripts/config}/routes.rb | 0 {config => scripts/config}/secrets.yml | 0 {config => scripts/config}/sidekiq.yml | 0 {config => scripts/config}/spring.rb | 0 {config => scripts/config}/storage.yml | 0 .../config}/webpack/development.js | 0 .../config}/webpack/environment.js | 0 .../config}/webpack/loaders/typescript.js | 0 .../config}/webpack/production.js | 0 {config => scripts/config}/webpack/test.js | 0 {config => scripts/config}/webpacker.yml | 0 .../db}/drawio_schema_with_explanations.xml | 0 .../migrate/20171003191909_create_users.rb | 0 .../20171005135550_add_admin_to_users.rb | 0 ...05140042_rename_users_profile_image_url.rb | 0 .../migrate/20171006195948_create_blocks.rb | 0 .../migrate/20171009194124_create_releases.rb | 0 ...20171011232501_add_sync_errors_to_block.rb | 0 .../20171012200106_create_standards.rb | 0 .../migrate/20171016192627_create_cohorts.rb | 0 .../20171017205306_create_cohort_users.rb | 0 ...s_from_label_and_pretty_name_on_cohorts.rb | 0 .../20171019165527_create_content_files.rb | 0 .../20171019192005_create_cohort_releases.rb | 0 .../20171023211301_create_challenges.rb | 0 ...024202210_create_checkpoint_submissions.rb | 0 ...3630_create_submitted_challenge_answers.rb | 0 .../20171025211916_create_performances.rb | 0 ...25223250_add_autoscore_to_content_files.rb | 0 ...171026193413_add_title_to_content_files.rb | 0 ...71102144822_cohort_release_unique_index.rb | 0 ...14_add_unique_constraint_to_block_title.rb | 0 ...2171128_add_position_to_cohort_releases.rb | 0 .../20171127223701_create_activities.rb | 0 ...3_create_user_last_viewed_standard_path.rb | 0 ...20171130185636_add_uid_to_content_files.rb | 0 .../20171205211624_add_slack_data_to_user.rb | 0 ...213519_add_standard_uid_to_performances.rb | 0 ..._relative_display_name_to_content_files.rb | 0 .../20180110223429_add_auth_roles_to_user.rb | 0 ...denormalize_submitted_challenge_answers.rb | 0 ...20180110233303_add_roles_to_cohort_user.rb | 0 ...4504_add_last_viewed_cohort_id_to_users.rb | 0 ...0116174519_add_github_user_name_to_user.rb | 0 ...16181937_add_taught_in_learn_to_cohorts.rb | 0 ...80116213927_remove_forge_admin_and_role.rb | 0 ...cohort_id_to_submitted_challenge_answer.rb | 0 ...1642_denormalize_checkpoint_submissions.rb | 0 .../20180125212203_rename_taught_in_learn.rb | 0 .../20180125222044_change_learn_v2_default.rb | 0 .../20180131220605_create_notifications.rb | 0 ...180202225951_add_github_sha_to_releases.rb | 0 ...d_use_latest_release_to_cohort_releases.rb | 0 ...add_docker_directory_path_to_challenges.rb | 0 ...80316222140_rename_cohort_title_to_name.rb | 0 ...0180320162849_add_deleted_at_to_cohorts.rb | 0 ...02212114_remove_pretty_name_from_cohort.rb | 0 ...4504_add_used_by_application_to_cohorts.rb | 0 ...0412223312_populate_used_by_application.rb | 0 ..._add_feature_branch_columns_to_releases.rb | 0 ...d_pending_release_id_to_cohort_releases.rb | 0 ...180813205413_add_readme_text_to_release.rb | 0 .../20180813213358_add_mode_to_cohort.rb | 0 .../20180813214453_populate_mode_cohorts.rb | 0 ...rt_id_to_user_last_viewed_standard_path.rb | 0 .../20180824200753_create_lesson_visits.rb | 0 ...112215710_add_preferred_campus_to_users.rb | 0 .../20181114190340_create_job_results.rb | 0 .../migrate/20181120221622_create_sections.rb | 0 ...02104_add_section_id_to_cohort_releases.rb | 0 ...add_challenge_completion_to_performance.rb | 0 ...1213180900_add_show_tests_to_challenges.rb | 0 ...81214175640_create_content_visibilities.rb | 0 ...add_default_visibility_to_content_files.rb | 0 .../migrate/20190410171829_create_pairings.rb | 0 ...190423171448_add_data_path_to_challenge.rb | 0 ...10_add_last_setup_visit_to_cohort_users.rb | 0 ...23958_add_max_attempts_to_content_files.rb | 0 ...70059_add_allowed_attempts_to_challenge.rb | 0 ...000_remove_max_attempts_from_challenges.rb | 0 ...ints_and_success_criteria_to_challenges.rb | 0 ...1_drop_learn_version_columns_on_cohorts.rb | 0 .../20190829203949_add_settings_to_cohorts.rb | 0 ...dd_points_to_submitted_challenge_answer.rb | 0 ...03_add_points_to_checkpoint_submissions.rb | 0 ...uccess_criteria_to_rubric_on_challenges.rb | 0 ...20191001214559_add_topics_to_challenges.rb | 0 ...1001221324_add_perf_data_to_submissions.rb | 0 ...1008211403_add_release_id_to_challenges.rb | 0 .../20191009214248_add_user_id_to_release.rb | 0 ...visibility_type_to_content_visibilities.rb | 0 .../20191031212058_add_api_token_to_user.rb | 0 .../20191108211234_add_preview_to_releases.rb | 0 .../20191114211938_create_api_interactions.rb | 0 ...19225902_add_sandbox_boolean_to_cohorts.rb | 0 .../20191206230913_add_sync_warnings.rb | 0 ...165026_add_metadata_to_api_interactions.rb | 0 ...add_assign_partial_credig_to_challenges.rb | 0 ..._add_end_time_to_checkpoint_submissions.rb | 0 ...201253_change_cohort_default_percentage.rb | 0 ...13201649_add_time_limit_to_content_file.rb | 0 ..._submitted_at_to_checkpoint_submissions.rb | 0 ..._add_allow_paired_submissions_to_cohort.rb | 0 ...ubmission_ids_to_checkpoint_submissinos.rb | 0 ...0200430165251_add_external_to_challenge.rb | 0 .../20200702155846_add_cache_to_blocks.rb | 0 ...0200707164932_add_archived_at_to_blocks.rb | 0 ...20_add_block_location_details_to_blocks.rb | 0 ...00724195251_add_whitelabeled_to_cohorts.rb | 0 ...4247_remove_block_uniqueness_pg_columns.rb | 0 ...13_add_student_import_status_to_cohorts.rb | 0 ...addd_docker_directory_zip_to_challenges.rb | 0 ...0828165130_default_block_org_tog_school.rb | 0 ...0149_remove_null_constraints_from_users.rb | 0 ...0929004708_remove_null_email_from_users.rb | 0 {db => scripts/db}/schema.rb | 0 {db => scripts/db}/seeds.rb | 0 scripts/delete-blocks | 11 ++ {doc => scripts/doc}/api.md | 0 .../api/cohorts/creating_a_new_cohort.json | 0 .../cohorts/viewing_curriculum_details.json | 0 .../content/update_content_visibility.json | 0 .../creating_a_user_and_their_enrollment.json | 0 .../unenrolling_a_user_from_a_cohort.json | 0 .../updating_a_user's_enrollment_roles.json | 0 .../viewing_cohort_enrollments.json | 0 {doc => scripts/doc}/api/index.json | 0 .../api/units/update_unit_visibility.json | 0 .../doc}/api/users/regenerate_user_token.json | 0 .../entrypoint-server.sh | 0 .../gems}/block-parser/Dockerfile | 0 {gems => scripts/gems}/block-parser/Gemfile | 0 .../gems}/block-parser/Gemfile.lock | 0 {gems => scripts/gems}/block-parser/README.md | 0 {gems => scripts/gems}/block-parser/Rakefile | 0 .../gems}/block-parser/bin/console | 0 .../gems}/block-parser/bin/parse_block | 0 {gems => scripts/gems}/block-parser/bin/setup | 0 .../gems}/block-parser/block_parser-0.1.0.gem | Bin .../gems}/block-parser/block_parser.gemspec | 0 {gems => scripts/gems}/block-parser/build | 0 .../gems}/block-parser/lib/block_parser.rb | 0 .../lib/block_parser/build_challenge.rb | 0 .../lib/block_parser/build_html.rb | 0 .../block_parser/build_html_from_md_json.rb | 0 .../lib/block_parser/build_image_link.rb | 0 .../lib/block_parser/build_link.rb | 0 .../build_title_from_filename_and_html.rb | 0 .../challenge_validators/challenge.rb | 0 .../challenge_validator.rb | 0 .../checkbox_challenge_validator.rb | 0 .../code_snippet_challenge_validator.rb | 0 .../custom_snippet_challenge_validator.rb | 0 .../local_snippet_challenge_validator.rb | 0 .../multiple_choice_challenge_validator.rb | 0 .../number_challenge_validator.rb | 0 .../paragraph_challenge_validator.rb | 0 .../poll_challenge_validator.rb | 0 .../project_challenge_validator.rb | 0 .../short_answer_challenge_validator.rb | 0 .../testable_project_challenge_validator.rb | 0 .../lib/block_parser/convert_md_to_json.rb | 0 .../lib/block_parser/parse_directory.rb | 0 .../lib/block_parser/parse_markdown_file.rb | 0 .../lib/block_parser/parse_standards.rb | 0 .../block-parser/lib/block_parser/version.rb | 0 .../block-parser/pkg/block_parser-0.1.0.gem | Bin .../block-parser/spec/build_challenge_spec.rb | 0 .../spec/build_html_from_md_json_spec.rb | 0 .../block-parser/spec/build_html_spec.rb | 0 .../spec/build_image_link_spec.rb | 0 .../block-parser/spec/build_link_spec.rb | 0 ...build_title_from_filename_and_html_spec.rb | 0 .../challenge_validators/challenge_spec.rb | 0 .../challenge_validator_spec.rb | 0 .../checkbox_challenge_validator_spec.rb | 0 .../code_snippet_challenge_validator_spec.rb | 0 ...custom_snippet_challenge_validator_spec.rb | 0 ...ultiple_choice_challenge_validator_spec.rb | 0 .../number_challenge_validator_spec.rb | 0 .../project_challenge_validator_spec.rb | 0 .../short_answer_challenge_validator_spec.rb | 0 ...stable_project_challenge_validator_spec.rb | 0 .../spec/convert_md_to_json_spec.rb | 0 .../bad-challenges.md | 0 .../config.yaml | 0 .../config.yaml | 0 .../no-challenges.md | 0 .../config.yaml | 0 .../no-lessons-nor-checkpoints/config.yaml | 0 .../no-lessons-nor-checkpoints/resources.md | 0 .../config.yaml | 0 .../spec/fixtures/sample-iframe.md | 0 .../fixtures/test-block-repo-yml/config.yml | 0 .../fixtures/test-block-repo-yml/dummy.pdf | Bin .../test-block-repo-yml/folder/sibling.md | 0 .../test-block-repo-yml/folder/target.md | 0 .../images/galvanize-logo.png | Bin .../images/register_klass.gif | Bin .../fixtures/test-block-repo-yml/lessoN.md | 0 .../test-block-repo-yml/markdown-smoketest.md | 0 .../fixtures/test-block-repo-yml/target.md | 0 .../spec/fixtures/test-block-repo/README.md | 0 .../spec/fixtures/test-block-repo/config.yaml | 0 .../test-block-repo/folder/sibling.md | 0 .../fixtures/test-block-repo/folder/target.md | 0 .../test-block-repo/images/galvanize-logo.png | Bin .../test-block-repo/images/register_klass.gif | Bin .../fixtures/test-block-repo/ipynb-test.ipynb | 0 .../fixtures/test-block-repo/ipynb-test.md | 0 .../spec/fixtures/test-block-repo/lessoN.md | 0 .../test-block-repo/markdown-smoketest.md | 0 .../spec/fixtures/test-block-repo/target.md | 0 .../test-block-two-configs/config.yaml | 0 .../test-block-two-configs/config.yml | 0 .../Dockerfile | 0 .../test.sh | 0 .../config.yaml | 0 .../block-parser/spec/parse_directory_spec.rb | 0 .../spec/parse_markdown_file_spec.rb | 0 .../block-parser/spec/parse_standards_spec.rb | 0 .../gems}/block-parser/spec/spec_helper.rb | 0 .../block-parser/spec/support/freeloader.rb | 0 .../block-parser/spec/support/mocktokit.rb | 0 .../gems}/block-parser/spec/tmp/.keep | 0 .../gems}/block-parser/validate-block | 0 .../lib}/tasks/challenge_release_ids.rake | 0 .../lib}/tasks/checkpoint_resubmission.rake | 0 .../tasks/checkpoint_submission_points.rake | 0 .../lib}/tasks/content_visibility_update.rake | 0 .../lib}/tasks/course_progress.rake | 0 .../lib}/tasks/course_yaml_backfill.rake | 0 .../lib}/tasks/grade_checkpoints.rake | 0 .../lib}/tasks/object_space_count.rake | 0 {lib => scripts/lib}/tasks/prep_notifier.rake | 0 .../lib}/tasks/set_block_caches.rake | 0 {lib => scripts/lib}/tasks/spec.rake | 0 {lib => scripts/lib}/tasks/ts_routes.rake | 0 lintspec.sh => scripts/lintspec.sh | 0 package.json => scripts/package.json | 0 .../postcss.config.js | 0 {public => scripts/public}/404.html | 0 {public => scripts/public}/422.html | 0 {public => scripts/public}/500.html | 0 .../public}/apple-touch-icon-152x152.png | 0 .../apple-touch-icon-precomposed-152x152.png | 0 .../public}/apple-touch-icon-precomposed.png | 0 .../public}/apple-touch-icon.png | 0 .../assets/images/hopscotch-sprite-green.png | Bin .../assets/images/hopscotch-sprite-orange.png | Bin .../public}/assets/images/jupyter-logo.png | Bin .../images/svg/checkpoint-is-rejected.svg | 0 .../images/svg/checkpoint-is-scored.svg | 0 .../images/svg/checkpoint-is-submitted.svg | 0 .../public}/assets/images/svg/github-icon.svg | 0 .../assets/images/svg/gitlab-icon-rgb.svg | 0 .../assets/images/svg/octicon-git-branch.svg | 0 .../images/svg/redpriority_high-24px.svg | 0 .../assets/images/svg/svg-link_off-24px.svg | 0 .../images/svg/svg-sprite-action-symbol.svg | 0 .../images/svg/svg-sprite-alert-symbol.svg | 0 .../images/svg/svg-sprite-av-symbol.svg | 0 .../images/svg/svg-sprite-content-symbol.svg | 0 .../images/svg/svg-sprite-custom-symbol.svg | 0 .../svg/svg-sprite-custom_material-symbol.svg | 0 .../images/svg/svg-sprite-device-symbol.svg | 0 .../images/svg/svg-sprite-file-symbol.svg | 0 .../images/svg/svg-sprite-hardware-symbol.svg | 0 .../svg/svg-sprite-navigation-symbol.svg | 0 .../svg/svg-sprite-notification-symbol.svg | 0 .../images/svg/svg-sprite-social-symbol.svg | 0 {public => scripts/public}/favicon.ico | 0 .../javascripts/apitome/application.js | 0 {public => scripts/public}/robots.txt | 0 {public => scripts/public}/sandbox/chai.js | 0 .../public}/sandbox/challenge-worker.js | 0 .../public}/sandbox/jasmine/boot.js | 0 .../public}/sandbox/jasmine/jasmine.js | 0 .../public}/sandbox/mocha/boot.js | 0 .../public}/sandbox/mocha/mocha.js | 0 .../public}/sandbox/mocha/test.html | 0 .../public}/sandbox/sandbox.html | 0 .../public}/sandbox/stacktrace.js | 0 {public => scripts/public}/sandbox/worker.js | 0 .../stylesheets/apitome/application.css | 0 requirements.txt => scripts/requirements.txt | 0 scripts/{ => scripts}/sh/cohort_curriculum.sh | 0 .../sh/content_file_mark_hidden.sh | 0 .../sh/content_file_mark_visible.sh | 0 scripts/{ => scripts}/sh/unit_mark_hidden.sh | 0 scripts/{ => scripts}/sh/unit_mark_visible.sh | 0 .../{ => scripts}/sql/checkpoint_answers.sql | 0 .../sql/cohort_challenges_with_answers.sql | 0 .../sql/cohort_prune_for_testing.sql | 0 scripts/{ => scripts}/sql/percent_metrics.sql | 0 .../{ => scripts}/sql/scrub_cohort_data.sql | 0 scripts/serviceentry.yaml | 15 ++ ...activity_feed_item_component_props_spec.rb | 0 .../notifications_component_props_spec.rb | 0 .../standard_card_component_props_spec.rb | 0 .../api/v1/blocks/releases_controller_spec.rb | 0 .../api/v1/blocks_controller_spec.rb | 0 .../blocks/content_files_controller_spec.rb | 0 .../cohorts/blocks/units_controller_spec.rb | 0 .../api/v1/cohorts/cohorts_controller_spec.rb | 0 .../api/v1/cohorts/users_controller_spec.rb | 0 .../api/v1/content_files_controller_spec.rb | 0 .../api/v1/users_controller_spec.rb | 0 .../application_controller_spec.rb | 0 .../blocks/releases_controller_spec.rb | 0 .../controllers/blocks_controller_spec.rb | 0 .../blocks/content_files_controller_spec.rb | 0 .../activities_controller_spec.rb | 0 .../cohort_releases_controller_spec.rb | 0 .../checkpoint_submissions_controller_spec.rb | 0 ...itted_challenge_answers_controller_spec.rb | 0 .../cohorts/content_files_controller_spec.rb | 0 .../cohorts/pairings_controller_spec.rb | 0 .../cohorts/standards_controller_spec.rb | 0 .../activities_controller_spec.rb | 0 .../users/challenges_controller_spec.rb | 0 .../users/performances_controller_spec.rb | 0 .../cohorts/users_controller_spec.rb | 0 .../controllers/cohorts_controller_spec.rb | 0 .../spec}/controllers/home_controller_spec.rb | 0 .../notifications_controller_spec.rb | 0 .../controllers/permalinks_controller_spec.rb | 0 .../controllers/sessions_controller_spec.rb | 0 .../controllers/users_controller_spec.rb | 0 ...itted_challenge_answers_controller_spec.rb | 0 .../exporters/performance_exporter_spec.rb | 0 {spec => scripts/spec}/factories.rb | 0 .../blocks/management_feature_spec.rb | 0 .../cohorts/activity_dashboard_spec.rb | 0 .../cohorts/checkpoint_submissions_spec.rb | 0 .../cohorts/curriculum_feature_spec.rb | 0 .../features/cohorts/feed_feature_spec.rb | 0 .../cohorts/management_feature_spec.rb | 0 .../spec}/features/cohorts/sandboxes_spec.rb | 0 .../features/cohorts/student_progress_spec.rb | 0 .../features/cohorts/submissions_spec.rb | 0 .../cohorts/users/challenges_feature_spec.rb | 0 .../submissions_dashboard_feature_spec.rb | 0 .../checkpoint_assessments_spec.rb | 0 .../checkpoint_submissions_spec.rb | 0 .../content_files/navigation_feature_spec.rb | 0 .../features/content_files/permalinks_spec.rb | 0 .../content_files/view_feature_spec.rb | 0 .../features/home/header_feature_spec.rb | 0 {spec => scripts/spec}/features_helper.rb | 0 .../spec}/finders/block_finder_spec.rb | 0 .../checkpoint_submission_finder_spec.rb | 0 .../spec}/finders/cohort_user_finder_spec.rb | 0 .../spec}/finders/content_file_finder_spec.rb | 0 .../spec}/finders/performance_finder_spec.rb | 0 .../spec}/finders/release_finder_spec.rb | 0 .../spec}/finders/standard_finder_spec.rb | 0 .../submitted_challenge_answer_finder_spec.rb | 0 .../spec}/finders/user_finder_spec.rb | 0 .../fixtures/preview-content-file/preview.md | 0 ..._docker_directories_test-docker-folder.zip | Bin .../spec}/fixtures/test-block-repo/README.md | 0 .../test-block-repo/challenges-smoketest.md | 0 .../fixtures/test-block-repo/config.yaml | 0 .../test-docker-folder/Dockerfile | 0 .../test-docker-folder/test.sh | 0 .../test-block-repo/folder/sibling.md | 0 .../fixtures/test-block-repo/folder/target.md | 0 .../test-block-repo/images/galvanize-logo.png | Bin .../test-block-repo/images/register_klass.gif | Bin .../test-block-repo/markdown-smoketesT.md | 0 .../spec}/fixtures/test-block-repo/target.md | 0 .../spec}/fixtures/test-block-repo/test.sql | 0 .../vcr_cassettes/github-branch-success.yml | 0 .../github-course-yaml-not-found.yml | 0 .../github-course-yaml-success-2.yml | 0 .../github-course-yaml-success.yml | 0 .../vcr_cassettes/github-not-found.yml | 0 .../vcr_cassettes/github-repo-success.yml | 0 .../gitlab-course-yaml-branch-failure.yml | 0 .../gitlab-course-yaml-success.yml | 0 .../vcr_cassettes/gitlab-not-found.yml | 0 .../fixtures/vcr_cassettes/gitlab-success.yml | 0 .../resync-course-job-success.yml | 0 .../spec}/helpers/json_helper_spec.rb | 0 .../mastery_mode_percent_helper_spec.rb | 0 .../standard_navigation_helper_spec.rb | 0 {spec => scripts/spec}/integration_helper.rb | 0 .../jobs/branch_release_notifier_job_spec.rb | 0 .../checkpoint_paired_submission_job_spec.rb | 0 ...ontent_file_default_visibility_job_spec.rb | 0 .../spec}/jobs/content_file_visit_job_spec.rb | 0 .../jobs/create_api_interaction_job_spec.rb | 0 .../spec}/jobs/create_release_job_spec.rb | 0 .../jobs/evaluate_code_snippet_job_spec.rb | 0 .../jobs/evaluate_custom_snippet_job_spec.rb | 0 .../spec}/jobs/evaluate_project_job_spec.rb | 0 .../jobs/grade_timed_checkpoint_job_spec.rb | 0 .../jobs/import_student_work_job_spec.rb | 0 .../spec}/jobs/release_notifier_job_spec.rb | 0 .../spec}/jobs/resync_course_job_spec.rb | 0 .../spec}/jobs/set_block_caches_job_spec.rb | 0 .../spec}/jobs/slack_ds_prep_job_spec.rb | 0 .../spec}/jobs/slack_se_prep_job_spec.rb | 0 .../spec}/jobs/slack_student_job_spec.rb | 0 .../spec}/jobs/switch_to_branch_job_spec.rb | 0 .../spec}/models/activity_spec.rb | 0 .../spec}/models/api_interaction_spec.rb | 0 {spec => scripts/spec}/models/block_spec.rb | 0 .../spec}/models/challenge_spec.rb | 0 .../models/checkpoint_submission_spec.rb | 0 .../spec}/models/cohort_release_spec.rb | 0 {spec => scripts/spec}/models/cohort_spec.rb | 0 .../spec}/models/cohort_user_spec.rb | 0 .../spec}/models/content_file_spec.rb | 0 .../spec}/models/content_visibility_spec.rb | 0 .../spec}/models/lesson_visit_spec.rb | 0 .../spec}/models/notification_spec.rb | 0 {spec => scripts/spec}/models/pairing_spec.rb | 0 .../spec}/models/performance_spec.rb | 0 {spec => scripts/spec}/models/release_spec.rb | 0 .../spec}/models/resync_job_result_spec.rb | 0 {spec => scripts/spec}/models/section_spec.rb | 0 .../spec}/models/standard_spec.rb | 0 .../models/submitted_challenge_answer_spec.rb | 0 .../user_last_viewed_standard_path_spec.rb | 0 {spec => scripts/spec}/models/user_spec.rb | 0 .../spec}/policies/cohort_policy_spec.rb | 0 .../policies/content_file_policy_spec.rb | 0 .../spec}/policies/user_policy_spec.rb | 0 .../for_cohort_releases_new_spec.rb | 0 .../for_cohort_releases_spec.rb | 0 .../block_presenter/for_releases_spec.rb | 0 ...mitted_challenge_answers_presenter_spec.rb | 0 .../for_index_spec.rb | 0 .../checkpoint_submission_presenter_spec.rb | 0 .../for_curriculum_last_viewed_spec.rb | 0 .../content_file_presenter/for_show_spec.rb | 0 .../for_sidebar_spec.rb | 0 .../for_checkpoint_submission_spec.rb | 0 .../for_standard_card_spec.rb | 0 .../student_progress_presenter_spec.rb | 0 .../submissions_dashboard_presenter_spec.rb | 0 ...bmitted_challenge_answer_presenter_spec.rb | 0 .../activity_aggregator_service_spec.rb | 0 .../spec}/services/assessment_service_spec.rb | 0 .../auto_assign_release_service_spec.rb | 0 .../checkpoint_submission_service_spec.rb | 0 .../cohort_standard_progress_service_spec.rb | 0 .../spec}/services/course_validator_spec.rb | 0 .../curriculum_progress_service_spec.rb | 0 .../download_repository_service_spec.rb | 0 .../spec}/services/git_url_service_spec.rb | 0 .../services/mastery_average_service_spec.rb | 0 .../services/notification_service_spec.rb | 0 ...platform_one_auth_resolver_service_spec.rb | 0 .../preview_content_file_service_spec.rb | 0 .../release_destroyer_service_spec.rb | 0 .../services/resync_course_service_spec.rb | 0 .../s3_asset_uploader_service_spec.rb | 0 .../standard_submissions_service_spec.rb | 0 {spec => scripts/spec}/spec_helper.rb | 0 .../spec}/support/json_spec_matchers.rb | 0 {spec => scripts/spec}/support/mocktokit.rb | 0 .../spec}/support/object_creation_methods.rb | 0 tsconfig.json => scripts/tsconfig.json | 0 .../javascripts/bootstrap-datepicker.js | 0 .../vendor}/assets/javascripts/hopscotch.js | 0 .../assets/javascripts/react-tooltip.js | 0 .../stylesheets/bootstrap-datepicker.css | 0 .../vendor}/assets/stylesheets/hopscotch.css | 0 yarn.lock => scripts/yarn.lock | 0 1071 files changed, 274 insertions(+), 173 deletions(-) create mode 100644 .Dockerfile.swp delete mode 100644 .circleci/config.yml delete mode 100644 Dockerfile.base create mode 100644 Dockerfile.old create mode 100644 Jenkinsfile create mode 100644 download.json rename .browserslistrc => scripts/.browserslistrc (100%) rename .env.example => scripts/.env.example (100%) rename .eslintrc.json => scripts/.eslintrc.json (100%) rename .haml-lint.yml => scripts/.haml-lint.yml (100%) rename .nvmrc => scripts/.nvmrc (100%) rename .overcommit.yml => scripts/.overcommit.yml (100%) rename .postcssrc.yml => scripts/.postcssrc.yml (100%) rename .rubocop.yml => scripts/.rubocop.yml (100%) rename .ruby-version => scripts/.ruby-version (100%) rename .stylelintrc => scripts/.stylelintrc (100%) rename Gemfile => scripts/Gemfile (100%) rename Gemfile.lock => scripts/Gemfile.lock (100%) rename Procfile => scripts/Procfile (100%) rename Procfile.local => scripts/Procfile.local (100%) rename README.md => scripts/README.md (100%) rename Rakefile => scripts/Rakefile (100%) rename app.json => scripts/app.json (100%) rename {app => scripts/app}/assets/config/manifest.js (100%) rename {app => scripts/app}/assets/images/favicon.ico (100%) rename {app => scripts/app}/assets/images/loader-black.svg (100%) rename {app => scripts/app}/assets/images/loader-cyan.svg (100%) rename {app => scripts/app}/assets/images/loader-white.svg (100%) rename {app => scripts/app}/assets/images/lost.jpg (100%) rename {app => scripts/app}/assets/images/spinner.gif (100%) rename {app => scripts/app}/assets/images/svg/baseline-notes-24px.svg (100%) rename {app => scripts/app}/assets/images/svg/g-learn-lockup.svg (100%) rename {app => scripts/app}/assets/images/svg/galvanize-logo.svg (100%) rename {app => scripts/app}/assets/images/svg/github-icon.svg (100%) rename {app => scripts/app}/assets/images/svg/mobile-logo.svg (100%) rename {app => scripts/app}/assets/images/svg/octicon-git-branch.svg (100%) rename {app => scripts/app}/assets/images/svg/svg-sprite-action-symbol.svg (100%) rename {app => scripts/app}/assets/images/svg/svg-sprite-av-symbol.svg (100%) rename {app => scripts/app}/assets/images/svg/svg-sprite-device-symbol.svg (100%) rename {app => scripts/app}/assets/images/svg/svg-sprite-image-symbol.svg (100%) rename {app => scripts/app}/assets/images/svg/svg-sprite-navigation-symbol.svg (100%) rename {app => scripts/app}/assets/javascripts/application.js (100%) rename {app => scripts/app}/assets/javascripts/mobile.js (100%) rename {app => scripts/app}/assets/stylesheets/application.scss (100%) rename {app => scripts/app}/assets/stylesheets/base.scss (100%) rename {app => scripts/app}/assets/stylesheets/bootstrap-custom.scss (100%) rename {app => scripts/app}/assets/stylesheets/cohorts.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_404-container.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_action-menu.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_activity-dashboard.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_activity-feed.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_api-interactions.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_api_token.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_auth-style-search.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_blocks-index.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_blocks-stats.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_button.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_callouts.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_challenge-block.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_challenge_status.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_checkbox-input.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_checkpoint-landing.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_checkpoint-submission.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_checkpoint-submissions-columns-student.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_checkpoint-submissions-columns.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_checkpoint-submissions-index.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_checkpoint_student_scores.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_checkpoint_submisstion_state.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_checkpoint_toolbar.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_code-block.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_cohort-submissions-table.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_cohort_releases.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_cohorts.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_content-file-show.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_content-file-sidebar.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_curriculum-checkpoint-summary.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_curriculum-progress.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_curriculum.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_dropdown-component.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_external-link.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_flash-message.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_footer.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_grade-buttons.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_integer_picker.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_lp-style-button.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_mastery-table.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_modal.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_navigation-dropdown.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_notifications.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_pagination.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_pill.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_point_grade_buttons.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_primary-header.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_primary-navigation.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_progress.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_progress_thresholds_key.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_progress_thresholds_modal.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_progress_thresholds_slider.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_search-bar.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_secondary-navigation.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_slideshow.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_sort-dropdown-component.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_standard-card.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_standard-cards.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_standards-mastery-beans.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_status_picker.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_student-mastery-table.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_student-name-bar.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_submissions-dashboard-table.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_svg-icon.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_thresholds.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_universal-list.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_universal-row.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_universal-table.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_user-avatar.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/_video-player.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/badge.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/challenge-detail-comments.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/challenge-detail-view.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/challenge-timeline.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/new-comment-form.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/partnerup.scss (100%) rename {app => scripts/app}/assets/stylesheets/components/progress-table.scss (100%) rename {app => scripts/app}/assets/stylesheets/hopscotch-overrides.scss (100%) rename {app => scripts/app}/assets/stylesheets/mixins.scss (100%) rename {app => scripts/app}/assets/stylesheets/mobile.scss (100%) rename {app => scripts/app}/assets/stylesheets/mobile/_submissions-dashboard-table.scss (100%) rename {app => scripts/app}/assets/stylesheets/typography.scss (100%) rename {app => scripts/app}/assets/stylesheets/variables.scss (100%) rename {app => scripts/app}/component_props/activity_feed_item_component_props.rb (100%) rename {app => scripts/app}/component_props/notifications_component_props.rb (100%) rename {app => scripts/app}/component_props/standard_card_component_props.rb (100%) rename {app => scripts/app}/controllers/api/application_controller.rb (100%) rename {app => scripts/app}/controllers/api/v1/blocks/releases_controller.rb (100%) rename {app => scripts/app}/controllers/api/v1/blocks_controller.rb (100%) rename {app => scripts/app}/controllers/api/v1/cohorts/blocks/content_files_controller.rb (100%) rename {app => scripts/app}/controllers/api/v1/cohorts/blocks/units_controller.rb (100%) rename {app => scripts/app}/controllers/api/v1/cohorts/cohorts_controller.rb (100%) rename {app => scripts/app}/controllers/api/v1/cohorts/users_controller.rb (100%) rename {app => scripts/app}/controllers/api/v1/content_files_controller.rb (100%) rename {app => scripts/app}/controllers/api/v1/pineapple_controller.rb (100%) rename {app => scripts/app}/controllers/api/v1/releases_controller.rb (100%) rename {app => scripts/app}/controllers/api/v1/users_controller.rb (100%) rename {app => scripts/app}/controllers/application_controller.rb (100%) rename {app => scripts/app}/controllers/blocks/releases_controller.rb (100%) rename {app => scripts/app}/controllers/blocks_controller.rb (100%) rename {app => scripts/app}/controllers/cohorts/blocks/content_files_controller.rb (100%) rename {app => scripts/app}/controllers/cohorts/checkpoint_submissions/activities_controller.rb (100%) rename {app => scripts/app}/controllers/cohorts/cohort_releases_controller.rb (100%) rename {app => scripts/app}/controllers/cohorts/content_files/checkpoint_submissions_controller.rb (100%) rename {app => scripts/app}/controllers/cohorts/content_files/submitted_challenge_answers_controller.rb (100%) rename {app => scripts/app}/controllers/cohorts/content_files_controller.rb (100%) rename {app => scripts/app}/controllers/cohorts/pairings_controller.rb (100%) rename {app => scripts/app}/controllers/cohorts/standards_controller.rb (100%) rename {app => scripts/app}/controllers/cohorts/submitted_challenge_answers/activities_controller.rb (100%) rename {app => scripts/app}/controllers/cohorts/users/challenges_controller.rb (100%) rename {app => scripts/app}/controllers/cohorts/users/performances_controller.rb (100%) rename {app => scripts/app}/controllers/cohorts/users_controller.rb (100%) rename {app => scripts/app}/controllers/cohorts_controller.rb (100%) rename {app => scripts/app}/controllers/concerns/api/content_visibility_crud.rb (100%) rename {app => scripts/app}/controllers/concerns/api/exception_handler.rb (100%) rename {app => scripts/app}/controllers/concerns/api/response.rb (100%) rename {app => scripts/app}/controllers/home_controller.rb (100%) rename {app => scripts/app}/controllers/notifications_controller.rb (100%) rename {app => scripts/app}/controllers/permalinks_controller.rb (100%) rename {app => scripts/app}/controllers/sessions_controller.rb (100%) rename {app => scripts/app}/controllers/users_controller.rb (100%) rename {app => scripts/app}/controllers/webhooks/assessments_service/submitted_challenge_answers_controller.rb (100%) rename {app => scripts/app}/exporters/performance_exporter.rb (100%) rename {app => scripts/app}/exporters/progress_exporter.rb (100%) rename {app => scripts/app}/finders/block_finder.rb (100%) rename {app => scripts/app}/finders/checkpoint_submission_finder.rb (100%) rename {app => scripts/app}/finders/cohort_user_finder.rb (100%) rename {app => scripts/app}/finders/content_file_finder.rb (100%) rename {app => scripts/app}/finders/performance_finder.rb (100%) rename {app => scripts/app}/finders/release_finder.rb (100%) rename {app => scripts/app}/finders/standard_finder.rb (100%) rename {app => scripts/app}/finders/submitted_challenge_answer_finder.rb (100%) rename {app => scripts/app}/finders/user_finder.rb (100%) rename {app => scripts/app}/helpers/application_helper.rb (100%) rename {app => scripts/app}/helpers/json_helper.rb (100%) rename {app => scripts/app}/helpers/secondary_navigation_helper.rb (100%) rename {app => scripts/app}/helpers/standard_navigation_helper.rb (100%) rename {app => scripts/app}/javascript/api.d.ts (100%) rename {app => scripts/app}/javascript/components/AceEditor.tsx (100%) rename {app => scripts/app}/javascript/components/Badge.tsx (100%) rename {app => scripts/app}/javascript/components/Button.tsx (100%) rename {app => scripts/app}/javascript/components/ButtonTo.tsx (100%) rename {app => scripts/app}/javascript/components/Dropdown.tsx (100%) rename {app => scripts/app}/javascript/components/Icon.tsx (100%) rename {app => scripts/app}/javascript/components/Loading.tsx (100%) rename {app => scripts/app}/javascript/components/Marked.tsx (100%) rename {app => scripts/app}/javascript/components/Menu.tsx (100%) rename {app => scripts/app}/javascript/components/Notifications.tsx (100%) rename {app => scripts/app}/javascript/components/ProcessingIcon.tsx (100%) rename {app => scripts/app}/javascript/components/RowKebab.tsx (100%) rename {app => scripts/app}/javascript/components/ScoreCircle.tsx (100%) rename {app => scripts/app}/javascript/components/SidebarProgress.tsx (100%) rename {app => scripts/app}/javascript/components/SortDropdown.tsx (100%) rename {app => scripts/app}/javascript/components/StandardBean.tsx (100%) rename {app => scripts/app}/javascript/components/SvgRenderer.tsx (100%) rename {app => scripts/app}/javascript/components/Timestamp.tsx (100%) rename {app => scripts/app}/javascript/components/UserAvatar.tsx (100%) rename {app => scripts/app}/javascript/components/activities/NewActivityForm.tsx (100%) rename {app => scripts/app}/javascript/components/api/ApiInteractions.tsx (100%) rename {app => scripts/app}/javascript/components/api/ApiToken.tsx (100%) rename {app => scripts/app}/javascript/components/blocks/BlockPage-v2.tsx (100%) rename {app => scripts/app}/javascript/components/blocks/BlocksIndex-v2.tsx (100%) rename {app => scripts/app}/javascript/components/blocks/BlocksNewModal.tsx (100%) rename {app => scripts/app}/javascript/components/blocks/BlocksNewRelease.tsx (100%) rename {app => scripts/app}/javascript/components/blocks/BlocksRow.tsx (100%) rename {app => scripts/app}/javascript/components/blocks/BlocksShow.tsx (100%) rename {app => scripts/app}/javascript/components/blocks/BlocksStats.tsx (100%) rename {app => scripts/app}/javascript/components/blocks/CohortsTooltip.tsx (100%) rename {app => scripts/app}/javascript/components/challenges/AvatarBar.tsx (100%) rename {app => scripts/app}/javascript/components/challenges/ChallengeDetailView.tsx (100%) rename {app => scripts/app}/javascript/components/challenges/ChallengeShow.tsx (100%) rename {app => scripts/app}/javascript/components/challenges/challenge_block/ChallengeActionBlock.tsx (100%) rename {app => scripts/app}/javascript/components/challenges/challenge_block/ChallengeBlock.tsx (100%) rename {app => scripts/app}/javascript/components/challenges/challenge_block/ChallengeDetailActivities.tsx (100%) rename {app => scripts/app}/javascript/components/challenges/challenge_block/ChallengeExplanationBlock.tsx (100%) rename {app => scripts/app}/javascript/components/challenges/challenge_block/ChallengeFeedbackBlock.tsx (100%) rename {app => scripts/app}/javascript/components/challenges/challenge_block/ChallengeHintsBlock.tsx (100%) rename {app => scripts/app}/javascript/components/challenges/challenge_block/ChallengeInputs.tsx (100%) rename {app => scripts/app}/javascript/components/challenges/challenge_block/ChallengeLocalTestResults.tsx (100%) rename {app => scripts/app}/javascript/components/challenges/challenge_block/ChallengeRubricBlock.tsx (100%) rename {app => scripts/app}/javascript/components/challenges/challenge_block/ChallengeStatus.tsx (100%) rename {app => scripts/app}/javascript/components/challenges/challenge_block/ChallengeStatusBar.tsx (100%) rename {app => scripts/app}/javascript/components/challenges/challenge_block/ChallengeTestResults.tsx (100%) rename {app => scripts/app}/javascript/components/challenges/challenge_block/ChallengeTests.tsx (100%) rename {app => scripts/app}/javascript/components/challenges/challenge_block/ChallengeTimeLine.tsx (100%) rename {app => scripts/app}/javascript/components/challenges/challenge_block/GradeIndicator.tsx (100%) rename {app => scripts/app}/javascript/components/challenges/challenge_block/GradedTimestamp.tsx (100%) rename {app => scripts/app}/javascript/components/challenges/challenge_block/StatusPicker.tsx (100%) rename {app => scripts/app}/javascript/components/challenges/local/run-local-challenge.ts (100%) rename {app => scripts/app}/javascript/components/challenges/local/sandbox.ts (100%) rename {app => scripts/app}/javascript/components/challenges/local/stack-traces.ts (100%) rename {app => scripts/app}/javascript/components/checkpoints/CheckpointAfterSubmitButton.tsx (100%) rename {app => scripts/app}/javascript/components/checkpoints/CheckpointAfterSubmitModal.tsx (100%) rename {app => scripts/app}/javascript/components/checkpoints/CheckpointAfterSubmitModalError.tsx (100%) rename {app => scripts/app}/javascript/components/checkpoints/CheckpointSubmissionChallenges.tsx (100%) rename {app => scripts/app}/javascript/components/checkpoints/CheckpointSubmissionShow.tsx (100%) rename {app => scripts/app}/javascript/components/checkpoints/CheckpointSubmissionState.tsx (100%) rename {app => scripts/app}/javascript/components/checkpoints/CheckpointSubmissionStudentNameBar.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/CohortsIndex.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/UsersNew.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/activity_dashboard/ActivityDashboard.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/activity_feed/ActivityFeed.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/cohort_releases/ReleaseVersionsTable.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/cohort_submissions/CohortSubmissions.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/cohort_submissions/CohortSubmissionsChallengeItem.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/cohort_submissions/CohortSubmissionsLessonRow.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/cohort_submissions/CohortSubmissionsPerformanceModal.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/cohort_submissions/CohortSubmissionsStandardRow.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/cohort_submissions/CohortSubmissionsStudentColumn.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/cohort_submissions/CohortSubmissionsStudentNameBar.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/cohort_submissions/CohortSubmissionsStudentStandard.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/cohort_submissions/CohortSubmissionsTable.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/cohort_submissions/CohortSubmissionsUnitPercent.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/mastery/MasteryTable.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/mastery/MetricRow.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/mastery/MetricsBody.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/mastery/PerformanceCell.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/mastery/PerformanceRow.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/mastery/ReleaseBody.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/mastery/StandardRow.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/mastery/StudentHeader.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/mastery/StudentMasteryTable.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/mastery/StudentReleaseRow.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/pairing/GroupPairs.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/pairing/InnerStudentList.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/pairing/NewPairing.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/pairing/PairingBoard.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/pairing/StudentItem.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/pairing/StudentList.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/progress/MasteryProgressionBar.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/progress/ProgressThresholdCellHeaders.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/progress/StudentProgress.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/progress/StudentProgressBar.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/progress/StudentProgressCells.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/progress/StudentProgressRow.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/progress/StudentProgressSortArrow.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/settings/BranchReleaseModal.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/settings/CohortBlockReleaseRow.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/settings/CohortContentTab.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/settings/CohortInfo.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/settings/CohortSettingsResync.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/settings/CohortSettingsTabs.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/settings/CohortVisibilitySection.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/settings/CurriculumSettingsTab.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/settings/ReleaseVersionModal.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/settings/ReleaseVersionRow.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/settings/UserCohortKebab.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/settings/UserImport.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/settings/UserKebab.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/submissions_dashboard/AnswerStatusRollup.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/submissions_dashboard/HeaderStandardContainer.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/submissions_dashboard/StandardContainer.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboard.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardChallengeItem.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardContentFileRow.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardStudentColumn.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardStudentNameBar.tsx (100%) rename {app => scripts/app}/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardTable.tsx (100%) rename {app => scripts/app}/javascript/components/content_files/ActionMenus.tsx (100%) rename {app => scripts/app}/javascript/components/content_files/Lesson.tsx (100%) rename {app => scripts/app}/javascript/components/content_files/MarkdownRenderer.tsx (100%) rename {app => scripts/app}/javascript/components/content_files/PDFRenderer.tsx (100%) rename {app => scripts/app}/javascript/components/content_files/SideBar.tsx (100%) rename {app => scripts/app}/javascript/components/content_files/SubmissionRenderer.tsx (100%) rename {app => scripts/app}/javascript/components/content_files/checkpoints/Checkpoint.tsx (100%) rename {app => scripts/app}/javascript/components/content_files/checkpoints/CheckpointActionBar.tsx (100%) rename {app => scripts/app}/javascript/components/content_files/checkpoints/CheckpointDetails.tsx (100%) rename {app => scripts/app}/javascript/components/content_files/checkpoints/CheckpointLanding.tsx (100%) rename {app => scripts/app}/javascript/components/content_files/checkpoints/CheckpointLandingAttribute.tsx (100%) rename {app => scripts/app}/javascript/components/content_files/checkpoints/CheckpointPairs.tsx (100%) rename {app => scripts/app}/javascript/components/content_files/checkpoints/PairAvatars.tsx (100%) rename {app => scripts/app}/javascript/components/content_files/checkpoints/student_scores/CheckpointStudentRow.tsx (100%) rename {app => scripts/app}/javascript/components/content_files/checkpoints/student_scores/CheckpointStudentScores.tsx (100%) rename {app => scripts/app}/javascript/components/curriculum/CheckpointSummary.tsx (100%) rename {app => scripts/app}/javascript/components/curriculum/CohortCurriculum.tsx (100%) rename {app => scripts/app}/javascript/components/curriculum/CurriculumStandardCard.tsx (100%) rename {app => scripts/app}/javascript/components/curriculum/ProgressIndicators.tsx (100%) rename {app => scripts/app}/javascript/components/curriculum/StandardBeans.tsx (100%) rename {app => scripts/app}/javascript/components/curriculum/StandardsRenderer.tsx (100%) rename {app => scripts/app}/javascript/components/curriculum/StudentOverallProgressDoughnut.tsx (100%) rename {app => scripts/app}/javascript/components/lib/ace.ts (100%) rename {app => scripts/app}/javascript/components/notifications/NotificationsIcon.tsx (100%) rename {app => scripts/app}/javascript/components/shared/ActionMenu/ActionMenu.tsx (100%) rename {app => scripts/app}/javascript/components/shared/Button/Button.tsx (100%) rename {app => scripts/app}/javascript/components/shared/ChallengePoints/ChallengePoints.tsx (100%) rename {app => scripts/app}/javascript/components/shared/ChallengePoints/PartialCreditBaton.tsx (100%) rename {app => scripts/app}/javascript/components/shared/ChallengePoints/SpinText.tsx (100%) rename {app => scripts/app}/javascript/components/shared/ChallengePoints/components/IntegerPicker/IntegerPicker.tsx (100%) rename {app => scripts/app}/javascript/components/shared/DonutRing/DonutRing.tsx (100%) rename {app => scripts/app}/javascript/components/shared/DonutRing/components/ColorDonut/ColorDonut.tsx (100%) rename {app => scripts/app}/javascript/components/shared/DonutRing/components/CompleteDonut/CompleteDonut.tsx (100%) rename {app => scripts/app}/javascript/components/shared/DonutRing/components/UngradedDonut/UngradedDonut.tsx (100%) rename {app => scripts/app}/javascript/components/shared/DonutRing/components/UngradedDonut/UngradedDonut/UngradedDonut.tsx (100%) rename {app => scripts/app}/javascript/components/shared/ErrorMessagesTable/ErrorMessagesTable.tsx (100%) rename {app => scripts/app}/javascript/components/shared/FlashAlert/FlashAlert.tsx (100%) rename {app => scripts/app}/javascript/components/shared/FormatNumber/FormatNumber.tsx (100%) rename {app => scripts/app}/javascript/components/shared/Icons/AlertSign.tsx (100%) rename {app => scripts/app}/javascript/components/shared/Icons/Clear.tsx (100%) rename {app => scripts/app}/javascript/components/shared/Icons/CloseButton.tsx (100%) rename {app => scripts/app}/javascript/components/shared/Icons/Done.tsx (100%) rename {app => scripts/app}/javascript/components/shared/Icons/KeyboardArrowDown.tsx (100%) rename {app => scripts/app}/javascript/components/shared/Icons/KeyboardArrowUp.tsx (100%) rename {app => scripts/app}/javascript/components/shared/Icons/SettingsCog.tsx (100%) rename {app => scripts/app}/javascript/components/shared/Icons/StatusCircle.tsx (100%) rename {app => scripts/app}/javascript/components/shared/MasteryProgressBar/MasteryProgressBar.tsx (100%) rename {app => scripts/app}/javascript/components/shared/Modal/Modal.tsx (100%) rename {app => scripts/app}/javascript/components/shared/Pagination/Pagination.tsx (100%) rename {app => scripts/app}/javascript/components/shared/PercentageProgressBar/PercentageProgressBar.tsx (100%) rename {app => scripts/app}/javascript/components/shared/Pill/Pill.tsx (100%) rename {app => scripts/app}/javascript/components/shared/PointGradeButtons/PointGradeButtons.tsx (100%) rename {app => scripts/app}/javascript/components/shared/PointGradeButtons/SpinText.tsx (100%) rename {app => scripts/app}/javascript/components/shared/ProgressBar/ProgressBar.tsx (100%) rename {app => scripts/app}/javascript/components/shared/ProgressThresholdsKey/ProgressThresholdsKey.tsx (100%) rename {app => scripts/app}/javascript/components/shared/ProgressThresholdsModal/ProgressThresholdsModal.tsx (100%) rename {app => scripts/app}/javascript/components/shared/ProgressThresholdsSlider/ProgressThresholdsSlider.tsx (100%) rename {app => scripts/app}/javascript/components/shared/SearchBar/SearchBar.tsx (100%) rename {app => scripts/app}/javascript/components/shared/Slideshow/Slideshow.tsx (100%) rename {app => scripts/app}/javascript/components/shared/UngradedDonut/UngradedDonut.tsx (100%) rename {app => scripts/app}/javascript/components/shared/UniversalList/UniversalList.tsx (100%) rename {app => scripts/app}/javascript/components/shared/UniversalRow/UniversalRow.tsx (100%) rename {app => scripts/app}/javascript/components/shared/UniversalTable/UniversalTable.tsx (100%) rename {app => scripts/app}/javascript/components/standards/CompletionScoringBlock.tsx (100%) rename {app => scripts/app}/javascript/components/standards/MasteryScoringBlock.tsx (100%) rename {app => scripts/app}/javascript/components/standards/StandardCard.tsx (100%) rename {app => scripts/app}/javascript/components/standards/StandardScoreButton.tsx (100%) rename {app => scripts/app}/javascript/components/standards/StandardScoringBlock.tsx (100%) rename {app => scripts/app}/javascript/components/standards/StandardTopicsRollups.tsx (100%) rename {app => scripts/app}/javascript/components/users/UsersIndex.tsx (100%) rename {app => scripts/app}/javascript/components/vendor/ReactTooltip.js (100%) rename {app => scripts/app}/javascript/generated/routes.ts (100%) rename {app => scripts/app}/javascript/globals.ts (100%) rename {app => scripts/app}/javascript/lib/http.ts (100%) rename {app => scripts/app}/javascript/lib/utils.ts (100%) rename {app => scripts/app}/javascript/packs/application.js (100%) rename {app => scripts/app}/javascript/packs/server_rendering.js (100%) rename {app => scripts/app}/jobs/application_job.rb (100%) rename {app => scripts/app}/jobs/branch_release_notifier_job.rb (100%) rename {app => scripts/app}/jobs/checkpoint_paired_submission_job.rb (100%) rename {app => scripts/app}/jobs/content_file_default_visibility_job.rb (100%) rename {app => scripts/app}/jobs/content_file_visit_job.rb (100%) rename {app => scripts/app}/jobs/create_api_interaction_job.rb (100%) rename {app => scripts/app}/jobs/create_release_job.rb (100%) rename {app => scripts/app}/jobs/evaluate_code_snippet_job.rb (100%) rename {app => scripts/app}/jobs/evaluate_custom_snippet_job.rb (100%) rename {app => scripts/app}/jobs/evaluate_project_job.rb (100%) rename {app => scripts/app}/jobs/grade_timed_checkpoint_job.rb (100%) rename {app => scripts/app}/jobs/import_student_work_job.rb (100%) rename {app => scripts/app}/jobs/java_code_evaluation_job.rb (100%) rename {app => scripts/app}/jobs/javascript_code_evaluation_job.rb (100%) rename {app => scripts/app}/jobs/progress_csv_job.rb (100%) rename {app => scripts/app}/jobs/python_code_evaluation_job.rb (100%) rename {app => scripts/app}/jobs/release_notifier_job.rb (100%) rename {app => scripts/app}/jobs/resync_course_job.rb (100%) rename {app => scripts/app}/jobs/set_block_caches_job.rb (100%) rename {app => scripts/app}/jobs/slack_challenge_performance_job.rb (100%) rename {app => scripts/app}/jobs/slack_dev_notify_job.rb (100%) rename {app => scripts/app}/jobs/slack_ds_prep_job.rb (100%) rename {app => scripts/app}/jobs/slack_job.rb (100%) rename {app => scripts/app}/jobs/slack_se_prep_job.rb (100%) rename {app => scripts/app}/jobs/slack_student_job.rb (100%) rename {app => scripts/app}/jobs/student_progress_auth_job.rb (100%) rename {app => scripts/app}/jobs/switch_to_branch_job.rb (100%) rename {app => scripts/app}/mailers/application_mailer.rb (100%) rename {app => scripts/app}/mailers/user_mailer.rb (100%) rename {app => scripts/app}/models/activity.rb (100%) rename {app => scripts/app}/models/api_interaction.rb (100%) rename {app => scripts/app}/models/application_record.rb (100%) rename {app => scripts/app}/models/block.rb (100%) rename {app => scripts/app}/models/challenge.rb (100%) rename {app => scripts/app}/models/checkpoint_submission.rb (100%) rename {app => scripts/app}/models/cohort.rb (100%) rename {app => scripts/app}/models/cohort_release.rb (100%) rename {app => scripts/app}/models/cohort_user.rb (100%) rename {app => scripts/app}/models/concerns/findable_by_uid.rb (100%) rename {app => scripts/app}/models/concerns/read_only_model.rb (100%) rename {app => scripts/app}/models/content_file.rb (100%) rename {app => scripts/app}/models/content_visibility.rb (100%) rename {app => scripts/app}/models/job_result.rb (100%) rename {app => scripts/app}/models/lesson_visit.rb (100%) rename {app => scripts/app}/models/notification.rb (100%) rename {app => scripts/app}/models/pairing.rb (100%) rename {app => scripts/app}/models/performance.rb (100%) rename {app => scripts/app}/models/release.rb (100%) rename {app => scripts/app}/models/resync_job_result.rb (100%) rename {app => scripts/app}/models/section.rb (100%) rename {app => scripts/app}/models/standard.rb (100%) rename {app => scripts/app}/models/submitted_challenge_answer.rb (100%) rename {app => scripts/app}/models/unit.rb (100%) rename {app => scripts/app}/models/user.rb (100%) rename {app => scripts/app}/models/user_last_viewed_standard_path.rb (100%) rename {app => scripts/app}/policies/activity_policy.rb (100%) rename {app => scripts/app}/policies/application_policy.rb (100%) rename {app => scripts/app}/policies/block_policy.rb (100%) rename {app => scripts/app}/policies/checkpoint_submission_policy.rb (100%) rename {app => scripts/app}/policies/cohort_policy.rb (100%) rename {app => scripts/app}/policies/cohort_release_policy.rb (100%) rename {app => scripts/app}/policies/cohort_user_policy.rb (100%) rename {app => scripts/app}/policies/content_file_policy.rb (100%) rename {app => scripts/app}/policies/notification_policy.rb (100%) rename {app => scripts/app}/policies/performance_policy.rb (100%) rename {app => scripts/app}/policies/release_policy.rb (100%) rename {app => scripts/app}/policies/submitted_challenge_answer_policy.rb (100%) rename {app => scripts/app}/policies/user_policy.rb (100%) rename {app => scripts/app}/presenters/activity_presenter.rb (100%) rename {app => scripts/app}/presenters/block_presenter/for_block.rb (100%) rename {app => scripts/app}/presenters/block_presenter/for_cohort_releases.rb (100%) rename {app => scripts/app}/presenters/block_presenter/for_cohort_releases_new.rb (100%) rename {app => scripts/app}/presenters/block_presenter/for_releases.rb (100%) rename {app => scripts/app}/presenters/challenge_with_submitted_challenge_answers_presenter.rb (100%) rename {app => scripts/app}/presenters/checkpoint_submission_presenter.rb (100%) rename {app => scripts/app}/presenters/checkpoint_submission_presenter/for_index.rb (100%) rename {app => scripts/app}/presenters/checkpoint_submission_presenter/for_student_row.rb (100%) rename {app => scripts/app}/presenters/cohort_release_presenter/for_cohort_setup.rb (100%) rename {app => scripts/app}/presenters/cohort_setup/visibility.rb (100%) rename {app => scripts/app}/presenters/content_file_presenter/for_curriculum_last_viewed.rb (100%) rename {app => scripts/app}/presenters/content_file_presenter/for_footer.rb (100%) rename {app => scripts/app}/presenters/content_file_presenter/for_show.rb (100%) rename {app => scripts/app}/presenters/content_file_presenter/for_sidebar.rb (100%) rename {app => scripts/app}/presenters/performance_presenter.rb (100%) rename {app => scripts/app}/presenters/standard_card_component_props.rb (100%) rename {app => scripts/app}/presenters/standard_presenter/for_challenge_detail_view.rb (100%) rename {app => scripts/app}/presenters/standard_presenter/for_checkpoint_submission.rb (100%) rename {app => scripts/app}/presenters/standard_presenter/for_standard_card.rb (100%) rename {app => scripts/app}/presenters/standard_presenter/for_submissions_dashboard.rb (100%) rename {app => scripts/app}/presenters/stat_progress_presenter.rb (100%) rename {app => scripts/app}/presenters/student_progress_presenter.rb (100%) rename {app => scripts/app}/presenters/submissions_dashboard_presenter.rb (100%) rename {app => scripts/app}/presenters/submitted_challenge_answer_presenter.rb (100%) rename {app => scripts/app}/presenters/user_presenter/for_avatar.rb (100%) rename {app => scripts/app}/services/activity_aggregator_service.rb (100%) rename {app => scripts/app}/services/assessment_service.rb (100%) rename {app => scripts/app}/services/auto_assign_release_service.rb (100%) rename {app => scripts/app}/services/checkpoint_submission_service.rb (100%) rename {app => scripts/app}/services/cohort_standard_progress_service.rb (100%) rename {app => scripts/app}/services/cohort_student_progress_service.rb (100%) rename {app => scripts/app}/services/completion_mode_percent_service.rb (100%) rename {app => scripts/app}/services/course_validator.rb (100%) rename {app => scripts/app}/services/create_submitted_challenge_answer_service.rb (100%) rename {app => scripts/app}/services/curriculum_progress_service.rb (100%) rename {app => scripts/app}/services/download_github_repository_service.rb (100%) rename {app => scripts/app}/services/download_gitlab_repository_service.rb (100%) rename {app => scripts/app}/services/download_repository_service.rb (100%) rename {app => scripts/app}/services/download_s3_repository_service.rb (100%) rename {app => scripts/app}/services/encoded_image_link_service.rb (100%) rename {app => scripts/app}/services/git_url_service.rb (100%) rename {app => scripts/app}/services/mastery_average_service.rb (100%) rename {app => scripts/app}/services/mastery_mode_percent_service.rb (100%) rename {app => scripts/app}/services/mock_mixpanel.rb (100%) rename {app => scripts/app}/services/notification_service.rb (100%) rename {app => scripts/app}/services/platform_one_auth_resolver_service.rb (100%) rename {app => scripts/app}/services/preview_content_file_service.rb (100%) rename {app => scripts/app}/services/release_destroyer_service.rb (100%) rename {app => scripts/app}/services/release_helper_service.rb (100%) rename {app => scripts/app}/services/resync_course_service.rb (100%) rename {app => scripts/app}/services/s3_asset_uploader_service.rb (100%) rename {app => scripts/app}/services/segment_track_service.rb (100%) rename {app => scripts/app}/services/sql_challenge_db_service.rb (100%) rename {app => scripts/app}/services/standard_submissions_service.rb (100%) rename {app => scripts/app}/views/api_interactions.html.haml (100%) rename {app => scripts/app}/views/api_token.html.haml (100%) rename {app => scripts/app}/views/apitome/docs/_headers.html.erb (100%) rename {app => scripts/app}/views/apitome/docs/_params.html.erb (100%) rename {app => scripts/app}/views/blocks/blockpagev2.html.haml (100%) rename {app => scripts/app}/views/blocks/index.html.haml (100%) rename {app => scripts/app}/views/blocks/new.html.haml (100%) rename {app => scripts/app}/views/blocks/releases/new.html.haml (100%) rename {app => scripts/app}/views/blocks/show.html.haml (100%) rename {app => scripts/app}/views/cohorts/_cohort_edit_form.html.haml (100%) rename {app => scripts/app}/views/cohorts/_cohort_info.html.haml (100%) rename {app => scripts/app}/views/cohorts/_completion_progress_donut.html.haml (100%) rename {app => scripts/app}/views/cohorts/_user_table.html.haml (100%) rename {app => scripts/app}/views/cohorts/activity_dashboard.html.haml (100%) rename {app => scripts/app}/views/cohorts/blocks/content_files/_footer.html.haml (100%) rename {app => scripts/app}/views/cohorts/blocks/content_files/show.html.haml (100%) rename {app => scripts/app}/views/cohorts/cohort_releases/index.html.haml (100%) rename {app => scripts/app}/views/cohorts/content.html.haml (100%) rename {app => scripts/app}/views/cohorts/content_files/checkpoint_submissions/show.html.haml (100%) rename {app => scripts/app}/views/cohorts/course_stats.html.haml (100%) rename {app => scripts/app}/views/cohorts/edit.html.haml (100%) rename {app => scripts/app}/views/cohorts/error.html.haml (100%) rename {app => scripts/app}/views/cohorts/feed.html.haml (100%) rename {app => scripts/app}/views/cohorts/index.html.haml (100%) rename {app => scripts/app}/views/cohorts/new.html.haml (100%) rename {app => scripts/app}/views/cohorts/partnerup.html.haml (100%) rename {app => scripts/app}/views/cohorts/setup.html.haml (100%) rename {app => scripts/app}/views/cohorts/show.html.haml (100%) rename {app => scripts/app}/views/cohorts/standards/checkpoint_submissions/index.html.haml (100%) rename {app => scripts/app}/views/cohorts/unit_progress.html.haml (100%) rename {app => scripts/app}/views/cohorts/users.html.haml (100%) rename {app => scripts/app}/views/cohorts/users/challenges/show.html.haml (100%) rename {app => scripts/app}/views/cohorts/users/mastery/index.html.haml (100%) rename {app => scripts/app}/views/cohorts/users/submissions_dashboard.html.haml (100%) rename {app => scripts/app}/views/error_404.html.haml (100%) rename {app => scripts/app}/views/error_500.html.haml (100%) rename {app => scripts/app}/views/home/index.html.haml (100%) rename {app => scripts/app}/views/layouts/_primary_navigation.html.haml (100%) rename {app => scripts/app}/views/layouts/_secondary_navigation.html.haml (100%) rename {app => scripts/app}/views/layouts/application.html.haml (100%) rename {app => scripts/app}/views/layouts/mailer.html.erb (100%) rename {app => scripts/app}/views/layouts/mailer.text.erb (100%) rename {app => scripts/app}/views/permalinks/permalink.html.haml (100%) rename {app => scripts/app}/views/shared/_content_file_js.html.haml (100%) rename {app => scripts/app}/views/shared/_hopscotch_callbacks_js.html.haml (100%) rename {app => scripts/app}/views/shared/_intercom_js.html.haml (100%) rename {app => scripts/app}/views/shared/_segment_js.html.haml (100%) rename {app => scripts/app}/views/user_mailer/send_file.html (100%) rename {app => scripts/app}/views/user_mailer/user_import_work.html.haml (100%) rename {app => scripts/app}/views/users/edit.html.haml (100%) rename {app => scripts/app}/views/users/edit_user.html.haml (100%) rename {app => scripts/app}/views/users/index.html.haml (100%) rename {app => scripts/app}/views/users/new.html.haml (100%) rename babel.config.js => scripts/babel.config.js (100%) rename {bin => scripts/bin}/bundle (100%) rename {bin => scripts/bin}/rails (100%) rename {bin => scripts/bin}/rake (100%) rename {bin => scripts/bin}/setup (100%) rename {bin => scripts/bin}/update (100%) rename {bin => scripts/bin}/webpack (100%) rename {bin => scripts/bin}/webpack-dev-server (100%) rename {bin => scripts/bin}/yarn (100%) rename config.ru => scripts/config.ru (100%) rename {config => scripts/config}/application.rb (100%) rename {config => scripts/config}/boot.rb (100%) rename {config => scripts/config}/database.yml (100%) rename {config => scripts/config}/environment.rb (100%) rename {config => scripts/config}/environments/development.rb (100%) rename {config => scripts/config}/environments/production.rb (100%) rename {config => scripts/config}/environments/test.rb (100%) rename {config => scripts/config}/get-routes-audit.md (100%) rename {config => scripts/config}/honeybadger.yml (100%) rename {config => scripts/config}/initializers/apitome.rb (100%) rename {config => scripts/config}/initializers/application_controller_renderer.rb (100%) rename {config => scripts/config}/initializers/assets.rb (100%) rename {config => scripts/config}/initializers/auth_api.rb (100%) rename {config => scripts/config}/initializers/aws.rb (100%) rename {config => scripts/config}/initializers/backtrace_silencers.rb (100%) rename {config => scripts/config}/initializers/content_security_policy.rb (100%) rename {config => scripts/config}/initializers/cookies_serializer.rb (100%) rename {config => scripts/config}/initializers/filter_parameter_logging.rb (100%) rename {config => scripts/config}/initializers/inflections.rb (100%) rename {config => scripts/config}/initializers/mime_types.rb (100%) rename {config => scripts/config}/initializers/new_framework_defaults_5_1.rb (100%) rename {config => scripts/config}/initializers/new_framework_defaults_5_2.rb (100%) rename {config => scripts/config}/initializers/octokit.rb (100%) rename {config => scripts/config}/initializers/pagy.rb (100%) rename {config => scripts/config}/initializers/pundit.rb (100%) rename {config => scripts/config}/initializers/rack_attack.rb (100%) rename {config => scripts/config}/initializers/segment.rb (100%) rename {config => scripts/config}/initializers/sidekiq.rb (100%) rename {config => scripts/config}/initializers/wrap_parameters.rb (100%) rename {config => scripts/config}/locales/en.yml (100%) rename {config => scripts/config}/puma.rb (100%) rename {config => scripts/config}/routes.rb (100%) rename {config => scripts/config}/secrets.yml (100%) rename {config => scripts/config}/sidekiq.yml (100%) rename {config => scripts/config}/spring.rb (100%) rename {config => scripts/config}/storage.yml (100%) rename {config => scripts/config}/webpack/development.js (100%) rename {config => scripts/config}/webpack/environment.js (100%) rename {config => scripts/config}/webpack/loaders/typescript.js (100%) rename {config => scripts/config}/webpack/production.js (100%) rename {config => scripts/config}/webpack/test.js (100%) rename {config => scripts/config}/webpacker.yml (100%) rename {db => scripts/db}/drawio_schema_with_explanations.xml (100%) rename {db => scripts/db}/migrate/20171003191909_create_users.rb (100%) rename {db => scripts/db}/migrate/20171005135550_add_admin_to_users.rb (100%) rename {db => scripts/db}/migrate/20171005140042_rename_users_profile_image_url.rb (100%) rename {db => scripts/db}/migrate/20171006195948_create_blocks.rb (100%) rename {db => scripts/db}/migrate/20171009194124_create_releases.rb (100%) rename {db => scripts/db}/migrate/20171011232501_add_sync_errors_to_block.rb (100%) rename {db => scripts/db}/migrate/20171012200106_create_standards.rb (100%) rename {db => scripts/db}/migrate/20171016192627_create_cohorts.rb (100%) rename {db => scripts/db}/migrate/20171017205306_create_cohort_users.rb (100%) rename {db => scripts/db}/migrate/20171017221501_remove_presence_indices_from_label_and_pretty_name_on_cohorts.rb (100%) rename {db => scripts/db}/migrate/20171019165527_create_content_files.rb (100%) rename {db => scripts/db}/migrate/20171019192005_create_cohort_releases.rb (100%) rename {db => scripts/db}/migrate/20171023211301_create_challenges.rb (100%) rename {db => scripts/db}/migrate/20171024202210_create_checkpoint_submissions.rb (100%) rename {db => scripts/db}/migrate/20171024203630_create_submitted_challenge_answers.rb (100%) rename {db => scripts/db}/migrate/20171025211916_create_performances.rb (100%) rename {db => scripts/db}/migrate/20171025223250_add_autoscore_to_content_files.rb (100%) rename {db => scripts/db}/migrate/20171026193413_add_title_to_content_files.rb (100%) rename {db => scripts/db}/migrate/20171102144822_cohort_release_unique_index.rb (100%) rename {db => scripts/db}/migrate/20171102165314_add_unique_constraint_to_block_title.rb (100%) rename {db => scripts/db}/migrate/20171102171128_add_position_to_cohort_releases.rb (100%) rename {db => scripts/db}/migrate/20171127223701_create_activities.rb (100%) rename {db => scripts/db}/migrate/20171130183523_create_user_last_viewed_standard_path.rb (100%) rename {db => scripts/db}/migrate/20171130185636_add_uid_to_content_files.rb (100%) rename {db => scripts/db}/migrate/20171205211624_add_slack_data_to_user.rb (100%) rename {db => scripts/db}/migrate/20180104213519_add_standard_uid_to_performances.rb (100%) rename {db => scripts/db}/migrate/20180110174447_add_type_relative_display_name_to_content_files.rb (100%) rename {db => scripts/db}/migrate/20180110223429_add_auth_roles_to_user.rb (100%) rename {db => scripts/db}/migrate/20180110224150_denormalize_submitted_challenge_answers.rb (100%) rename {db => scripts/db}/migrate/20180110233303_add_roles_to_cohort_user.rb (100%) rename {db => scripts/db}/migrate/20180112234504_add_last_viewed_cohort_id_to_users.rb (100%) rename {db => scripts/db}/migrate/20180116174519_add_github_user_name_to_user.rb (100%) rename {db => scripts/db}/migrate/20180116181937_add_taught_in_learn_to_cohorts.rb (100%) rename {db => scripts/db}/migrate/20180116213927_remove_forge_admin_and_role.rb (100%) rename {db => scripts/db}/migrate/20180119184121_add_cohort_id_to_submitted_challenge_answer.rb (100%) rename {db => scripts/db}/migrate/20180124221642_denormalize_checkpoint_submissions.rb (100%) rename {db => scripts/db}/migrate/20180125212203_rename_taught_in_learn.rb (100%) rename {db => scripts/db}/migrate/20180125222044_change_learn_v2_default.rb (100%) rename {db => scripts/db}/migrate/20180131220605_create_notifications.rb (100%) rename {db => scripts/db}/migrate/20180202225951_add_github_sha_to_releases.rb (100%) rename {db => scripts/db}/migrate/20180209175941_add_use_latest_release_to_cohort_releases.rb (100%) rename {db => scripts/db}/migrate/20180313220132_add_docker_directory_path_to_challenges.rb (100%) rename {db => scripts/db}/migrate/20180316222140_rename_cohort_title_to_name.rb (100%) rename {db => scripts/db}/migrate/20180320162849_add_deleted_at_to_cohorts.rb (100%) rename {db => scripts/db}/migrate/20180402212114_remove_pretty_name_from_cohort.rb (100%) rename {db => scripts/db}/migrate/20180412214504_add_used_by_application_to_cohorts.rb (100%) rename {db => scripts/db}/migrate/20180412223312_populate_used_by_application.rb (100%) rename {db => scripts/db}/migrate/20180504193033_add_feature_branch_columns_to_releases.rb (100%) rename {db => scripts/db}/migrate/20180504200226_add_pending_release_id_to_cohort_releases.rb (100%) rename {db => scripts/db}/migrate/20180813205413_add_readme_text_to_release.rb (100%) rename {db => scripts/db}/migrate/20180813213358_add_mode_to_cohort.rb (100%) rename {db => scripts/db}/migrate/20180813214453_populate_mode_cohorts.rb (100%) rename {db => scripts/db}/migrate/20180817181129_add_cohort_id_to_user_last_viewed_standard_path.rb (100%) rename {db => scripts/db}/migrate/20180824200753_create_lesson_visits.rb (100%) rename {db => scripts/db}/migrate/20181112215710_add_preferred_campus_to_users.rb (100%) rename {db => scripts/db}/migrate/20181114190340_create_job_results.rb (100%) rename {db => scripts/db}/migrate/20181120221622_create_sections.rb (100%) rename {db => scripts/db}/migrate/20181121202104_add_section_id_to_cohort_releases.rb (100%) rename {db => scripts/db}/migrate/20181203215524_add_challenge_completion_to_performance.rb (100%) rename {db => scripts/db}/migrate/20181213180900_add_show_tests_to_challenges.rb (100%) rename {db => scripts/db}/migrate/20181214175640_create_content_visibilities.rb (100%) rename {db => scripts/db}/migrate/20181220005015_add_default_visibility_to_content_files.rb (100%) rename {db => scripts/db}/migrate/20190410171829_create_pairings.rb (100%) rename {db => scripts/db}/migrate/20190423171448_add_data_path_to_challenge.rb (100%) rename {db => scripts/db}/migrate/20190510193410_add_last_setup_visit_to_cohort_users.rb (100%) rename {db => scripts/db}/migrate/20190520223958_add_max_attempts_to_content_files.rb (100%) rename {db => scripts/db}/migrate/20190529170059_add_allowed_attempts_to_challenge.rb (100%) rename {db => scripts/db}/migrate/20190624222000_remove_max_attempts_from_challenges.rb (100%) rename {db => scripts/db}/migrate/20190625173725_add_points_and_success_criteria_to_challenges.rb (100%) rename {db => scripts/db}/migrate/20190709170851_drop_learn_version_columns_on_cohorts.rb (100%) rename {db => scripts/db}/migrate/20190829203949_add_settings_to_cohorts.rb (100%) rename {db => scripts/db}/migrate/20190910161219_add_points_to_submitted_challenge_answer.rb (100%) rename {db => scripts/db}/migrate/20190910161303_add_points_to_checkpoint_submissions.rb (100%) rename {db => scripts/db}/migrate/20190919173956_change_success_criteria_to_rubric_on_challenges.rb (100%) rename {db => scripts/db}/migrate/20191001214559_add_topics_to_challenges.rb (100%) rename {db => scripts/db}/migrate/20191001221324_add_perf_data_to_submissions.rb (100%) rename {db => scripts/db}/migrate/20191008211403_add_release_id_to_challenges.rb (100%) rename {db => scripts/db}/migrate/20191009214248_add_user_id_to_release.rb (100%) rename {db => scripts/db}/migrate/20191024200444_add_visibility_type_to_content_visibilities.rb (100%) rename {db => scripts/db}/migrate/20191031212058_add_api_token_to_user.rb (100%) rename {db => scripts/db}/migrate/20191108211234_add_preview_to_releases.rb (100%) rename {db => scripts/db}/migrate/20191114211938_create_api_interactions.rb (100%) rename {db => scripts/db}/migrate/20191119225902_add_sandbox_boolean_to_cohorts.rb (100%) rename {db => scripts/db}/migrate/20191206230913_add_sync_warnings.rb (100%) rename {db => scripts/db}/migrate/20191209165026_add_metadata_to_api_interactions.rb (100%) rename {db => scripts/db}/migrate/20191218232717_add_assign_partial_credig_to_challenges.rb (100%) rename {db => scripts/db}/migrate/20200108184027_add_end_time_to_checkpoint_submissions.rb (100%) rename {db => scripts/db}/migrate/20200110201253_change_cohort_default_percentage.rb (100%) rename {db => scripts/db}/migrate/20200213201649_add_time_limit_to_content_file.rb (100%) rename {db => scripts/db}/migrate/20200310222235_add_submitted_at_to_checkpoint_submissions.rb (100%) rename {db => scripts/db}/migrate/20200408212051_add_allow_paired_submissions_to_cohort.rb (100%) rename {db => scripts/db}/migrate/20200416155234_add_pair_submission_ids_to_checkpoint_submissinos.rb (100%) rename {db => scripts/db}/migrate/20200430165251_add_external_to_challenge.rb (100%) rename {db => scripts/db}/migrate/20200702155846_add_cache_to_blocks.rb (100%) rename {db => scripts/db}/migrate/20200707164932_add_archived_at_to_blocks.rb (100%) rename {db => scripts/db}/migrate/20200720213420_add_block_location_details_to_blocks.rb (100%) rename {db => scripts/db}/migrate/20200724195251_add_whitelabeled_to_cohorts.rb (100%) rename {db => scripts/db}/migrate/20200729214247_remove_block_uniqueness_pg_columns.rb (100%) rename {db => scripts/db}/migrate/20200811215713_add_student_import_status_to_cohorts.rb (100%) rename {db => scripts/db}/migrate/20200818172419_addd_docker_directory_zip_to_challenges.rb (100%) rename {db => scripts/db}/migrate/20200828165130_default_block_org_tog_school.rb (100%) rename {db => scripts/db}/migrate/20200925230149_remove_null_constraints_from_users.rb (100%) rename {db => scripts/db}/migrate/20200929004708_remove_null_email_from_users.rb (100%) rename {db => scripts/db}/schema.rb (100%) rename {db => scripts/db}/seeds.rb (100%) create mode 100644 scripts/delete-blocks rename {doc => scripts/doc}/api.md (100%) rename {doc => scripts/doc}/api/cohorts/creating_a_new_cohort.json (100%) rename {doc => scripts/doc}/api/cohorts/viewing_curriculum_details.json (100%) rename {doc => scripts/doc}/api/content/update_content_visibility.json (100%) rename {doc => scripts/doc}/api/enrollments/creating_a_user_and_their_enrollment.json (100%) rename {doc => scripts/doc}/api/enrollments/unenrolling_a_user_from_a_cohort.json (100%) rename {doc => scripts/doc}/api/enrollments/updating_a_user's_enrollment_roles.json (100%) rename {doc => scripts/doc}/api/enrollments/viewing_cohort_enrollments.json (100%) rename {doc => scripts/doc}/api/index.json (100%) rename {doc => scripts/doc}/api/units/update_unit_visibility.json (100%) rename {doc => scripts/doc}/api/users/regenerate_user_token.json (100%) rename entrypoint-server.sh => scripts/entrypoint-server.sh (100%) rename {gems => scripts/gems}/block-parser/Dockerfile (100%) rename {gems => scripts/gems}/block-parser/Gemfile (100%) rename {gems => scripts/gems}/block-parser/Gemfile.lock (100%) rename {gems => scripts/gems}/block-parser/README.md (100%) rename {gems => scripts/gems}/block-parser/Rakefile (100%) rename {gems => scripts/gems}/block-parser/bin/console (100%) rename {gems => scripts/gems}/block-parser/bin/parse_block (100%) rename {gems => scripts/gems}/block-parser/bin/setup (100%) rename {gems => scripts/gems}/block-parser/block_parser-0.1.0.gem (100%) rename {gems => scripts/gems}/block-parser/block_parser.gemspec (100%) rename {gems => scripts/gems}/block-parser/build (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser.rb (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser/build_challenge.rb (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser/build_html.rb (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser/build_html_from_md_json.rb (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser/build_image_link.rb (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser/build_link.rb (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser/build_title_from_filename_and_html.rb (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser/challenge_validators/challenge.rb (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser/challenge_validators/challenge_validator.rb (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser/challenge_validators/checkbox_challenge_validator.rb (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser/challenge_validators/code_snippet_challenge_validator.rb (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser/challenge_validators/custom_snippet_challenge_validator.rb (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser/challenge_validators/local_snippet_challenge_validator.rb (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser/challenge_validators/multiple_choice_challenge_validator.rb (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser/challenge_validators/number_challenge_validator.rb (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser/challenge_validators/paragraph_challenge_validator.rb (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser/challenge_validators/poll_challenge_validator.rb (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser/challenge_validators/project_challenge_validator.rb (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser/challenge_validators/short_answer_challenge_validator.rb (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser/challenge_validators/testable_project_challenge_validator.rb (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser/convert_md_to_json.rb (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser/parse_directory.rb (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser/parse_markdown_file.rb (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser/parse_standards.rb (100%) rename {gems => scripts/gems}/block-parser/lib/block_parser/version.rb (100%) rename {gems => scripts/gems}/block-parser/pkg/block_parser-0.1.0.gem (100%) rename {gems => scripts/gems}/block-parser/spec/build_challenge_spec.rb (100%) rename {gems => scripts/gems}/block-parser/spec/build_html_from_md_json_spec.rb (100%) rename {gems => scripts/gems}/block-parser/spec/build_html_spec.rb (100%) rename {gems => scripts/gems}/block-parser/spec/build_image_link_spec.rb (100%) rename {gems => scripts/gems}/block-parser/spec/build_link_spec.rb (100%) rename {gems => scripts/gems}/block-parser/spec/build_title_from_filename_and_html_spec.rb (100%) rename {gems => scripts/gems}/block-parser/spec/challenge_validators/challenge_spec.rb (100%) rename {gems => scripts/gems}/block-parser/spec/challenge_validators/challenge_validator_spec.rb (100%) rename {gems => scripts/gems}/block-parser/spec/challenge_validators/checkbox_challenge_validator_spec.rb (100%) rename {gems => scripts/gems}/block-parser/spec/challenge_validators/code_snippet_challenge_validator_spec.rb (100%) rename {gems => scripts/gems}/block-parser/spec/challenge_validators/custom_snippet_challenge_validator_spec.rb (100%) rename {gems => scripts/gems}/block-parser/spec/challenge_validators/multiple_choice_challenge_validator_spec.rb (100%) rename {gems => scripts/gems}/block-parser/spec/challenge_validators/number_challenge_validator_spec.rb (100%) rename {gems => scripts/gems}/block-parser/spec/challenge_validators/project_challenge_validator_spec.rb (100%) rename {gems => scripts/gems}/block-parser/spec/challenge_validators/short_answer_challenge_validator_spec.rb (100%) rename {gems => scripts/gems}/block-parser/spec/challenge_validators/testable_project_challenge_validator_spec.rb (100%) rename {gems => scripts/gems}/block-parser/spec/convert_md_to_json_spec.rb (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/checkpoint-with-bad-challenge-tag/bad-challenges.md (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/checkpoint-with-bad-challenge-tag/config.yaml (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/checkpoint-without-challenges-block-repo/config.yaml (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/checkpoint-without-challenges-block-repo/no-challenges.md (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/invalid-config-test-block-repo/config.yaml (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/no-lessons-nor-checkpoints/config.yaml (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/no-lessons-nor-checkpoints/resources.md (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/no-standards-config-test-block-repo/config.yaml (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/sample-iframe.md (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/test-block-repo-yml/config.yml (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/test-block-repo-yml/dummy.pdf (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/test-block-repo-yml/folder/sibling.md (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/test-block-repo-yml/folder/target.md (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/test-block-repo-yml/images/galvanize-logo.png (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/test-block-repo-yml/images/register_klass.gif (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/test-block-repo-yml/lessoN.md (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/test-block-repo-yml/markdown-smoketest.md (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/test-block-repo-yml/target.md (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/test-block-repo/README.md (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/test-block-repo/config.yaml (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/test-block-repo/folder/sibling.md (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/test-block-repo/folder/target.md (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/test-block-repo/images/galvanize-logo.png (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/test-block-repo/images/register_klass.gif (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/test-block-repo/ipynb-test.ipynb (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/test-block-repo/ipynb-test.md (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/test-block-repo/lessoN.md (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/test-block-repo/markdown-smoketest.md (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/test-block-repo/target.md (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/test-block-two-configs/config.yaml (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/test-block-two-configs/config.yml (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/valid-custom-snippet-challenge-directory/Dockerfile (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/valid-custom-snippet-challenge-directory/test.sh (100%) rename {gems => scripts/gems}/block-parser/spec/fixtures/valid-yaml-array-test-block-repo/config.yaml (100%) rename {gems => scripts/gems}/block-parser/spec/parse_directory_spec.rb (100%) rename {gems => scripts/gems}/block-parser/spec/parse_markdown_file_spec.rb (100%) rename {gems => scripts/gems}/block-parser/spec/parse_standards_spec.rb (100%) rename {gems => scripts/gems}/block-parser/spec/spec_helper.rb (100%) rename {gems => scripts/gems}/block-parser/spec/support/freeloader.rb (100%) rename {gems => scripts/gems}/block-parser/spec/support/mocktokit.rb (100%) rename {gems => scripts/gems}/block-parser/spec/tmp/.keep (100%) rename {gems => scripts/gems}/block-parser/validate-block (100%) rename {lib => scripts/lib}/tasks/challenge_release_ids.rake (100%) rename {lib => scripts/lib}/tasks/checkpoint_resubmission.rake (100%) rename {lib => scripts/lib}/tasks/checkpoint_submission_points.rake (100%) rename {lib => scripts/lib}/tasks/content_visibility_update.rake (100%) rename {lib => scripts/lib}/tasks/course_progress.rake (100%) rename {lib => scripts/lib}/tasks/course_yaml_backfill.rake (100%) rename {lib => scripts/lib}/tasks/grade_checkpoints.rake (100%) rename {lib => scripts/lib}/tasks/object_space_count.rake (100%) rename {lib => scripts/lib}/tasks/prep_notifier.rake (100%) rename {lib => scripts/lib}/tasks/set_block_caches.rake (100%) rename {lib => scripts/lib}/tasks/spec.rake (100%) rename {lib => scripts/lib}/tasks/ts_routes.rake (100%) rename lintspec.sh => scripts/lintspec.sh (100%) rename package.json => scripts/package.json (100%) rename postcss.config.js => scripts/postcss.config.js (100%) rename {public => scripts/public}/404.html (100%) rename {public => scripts/public}/422.html (100%) rename {public => scripts/public}/500.html (100%) rename {public => scripts/public}/apple-touch-icon-152x152.png (100%) rename {public => scripts/public}/apple-touch-icon-precomposed-152x152.png (100%) rename {public => scripts/public}/apple-touch-icon-precomposed.png (100%) rename {public => scripts/public}/apple-touch-icon.png (100%) rename {public => scripts/public}/assets/images/hopscotch-sprite-green.png (100%) rename {public => scripts/public}/assets/images/hopscotch-sprite-orange.png (100%) rename {public => scripts/public}/assets/images/jupyter-logo.png (100%) rename {public => scripts/public}/assets/images/svg/checkpoint-is-rejected.svg (100%) rename {public => scripts/public}/assets/images/svg/checkpoint-is-scored.svg (100%) rename {public => scripts/public}/assets/images/svg/checkpoint-is-submitted.svg (100%) rename {public => scripts/public}/assets/images/svg/github-icon.svg (100%) rename {public => scripts/public}/assets/images/svg/gitlab-icon-rgb.svg (100%) rename {public => scripts/public}/assets/images/svg/octicon-git-branch.svg (100%) rename {public => scripts/public}/assets/images/svg/redpriority_high-24px.svg (100%) rename {public => scripts/public}/assets/images/svg/svg-link_off-24px.svg (100%) rename {public => scripts/public}/assets/images/svg/svg-sprite-action-symbol.svg (100%) rename {public => scripts/public}/assets/images/svg/svg-sprite-alert-symbol.svg (100%) rename {public => scripts/public}/assets/images/svg/svg-sprite-av-symbol.svg (100%) rename {public => scripts/public}/assets/images/svg/svg-sprite-content-symbol.svg (100%) rename {public => scripts/public}/assets/images/svg/svg-sprite-custom-symbol.svg (100%) rename {public => scripts/public}/assets/images/svg/svg-sprite-custom_material-symbol.svg (100%) rename {public => scripts/public}/assets/images/svg/svg-sprite-device-symbol.svg (100%) rename {public => scripts/public}/assets/images/svg/svg-sprite-file-symbol.svg (100%) rename {public => scripts/public}/assets/images/svg/svg-sprite-hardware-symbol.svg (100%) rename {public => scripts/public}/assets/images/svg/svg-sprite-navigation-symbol.svg (100%) rename {public => scripts/public}/assets/images/svg/svg-sprite-notification-symbol.svg (100%) rename {public => scripts/public}/assets/images/svg/svg-sprite-social-symbol.svg (100%) rename {public => scripts/public}/favicon.ico (100%) rename {public => scripts/public}/javascripts/apitome/application.js (100%) rename {public => scripts/public}/robots.txt (100%) rename {public => scripts/public}/sandbox/chai.js (100%) rename {public => scripts/public}/sandbox/challenge-worker.js (100%) rename {public => scripts/public}/sandbox/jasmine/boot.js (100%) rename {public => scripts/public}/sandbox/jasmine/jasmine.js (100%) rename {public => scripts/public}/sandbox/mocha/boot.js (100%) rename {public => scripts/public}/sandbox/mocha/mocha.js (100%) rename {public => scripts/public}/sandbox/mocha/test.html (100%) rename {public => scripts/public}/sandbox/sandbox.html (100%) rename {public => scripts/public}/sandbox/stacktrace.js (100%) rename {public => scripts/public}/sandbox/worker.js (100%) rename {public => scripts/public}/stylesheets/apitome/application.css (100%) rename requirements.txt => scripts/requirements.txt (100%) rename scripts/{ => scripts}/sh/cohort_curriculum.sh (100%) rename scripts/{ => scripts}/sh/content_file_mark_hidden.sh (100%) rename scripts/{ => scripts}/sh/content_file_mark_visible.sh (100%) rename scripts/{ => scripts}/sh/unit_mark_hidden.sh (100%) rename scripts/{ => scripts}/sh/unit_mark_visible.sh (100%) rename scripts/{ => scripts}/sql/checkpoint_answers.sql (100%) rename scripts/{ => scripts}/sql/cohort_challenges_with_answers.sql (100%) rename scripts/{ => scripts}/sql/cohort_prune_for_testing.sql (100%) rename scripts/{ => scripts}/sql/percent_metrics.sql (100%) rename scripts/{ => scripts}/sql/scrub_cohort_data.sql (100%) create mode 100644 scripts/serviceentry.yaml rename {spec => scripts/spec}/component_props/activity_feed_item_component_props_spec.rb (100%) rename {spec => scripts/spec}/component_props/notifications_component_props_spec.rb (100%) rename {spec => scripts/spec}/component_props/standard_card_component_props_spec.rb (100%) rename {spec => scripts/spec}/controllers/api/v1/blocks/releases_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/api/v1/blocks_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/api/v1/cohorts/blocks/content_files_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/api/v1/cohorts/blocks/units_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/api/v1/cohorts/cohorts_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/api/v1/cohorts/users_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/api/v1/content_files_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/api/v1/users_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/application_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/blocks/releases_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/blocks_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/cohorts/blocks/content_files_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/cohorts/checkpoint_submissions/activities_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/cohorts/cohort_releases_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/cohorts/content_files/checkpoint_submissions_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/cohorts/content_files/submitted_challenge_answers_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/cohorts/content_files_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/cohorts/pairings_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/cohorts/standards_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/cohorts/submitted_challenge_answers/activities_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/cohorts/users/challenges_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/cohorts/users/performances_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/cohorts/users_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/cohorts_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/home_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/notifications_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/permalinks_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/sessions_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/users_controller_spec.rb (100%) rename {spec => scripts/spec}/controllers/webhooks/assessments_service/submitted_challenge_answers_controller_spec.rb (100%) rename {spec => scripts/spec}/exporters/performance_exporter_spec.rb (100%) rename {spec => scripts/spec}/factories.rb (100%) rename {spec => scripts/spec}/features/blocks/management_feature_spec.rb (100%) rename {spec => scripts/spec}/features/cohorts/activity_dashboard_spec.rb (100%) rename {spec => scripts/spec}/features/cohorts/checkpoint_submissions_spec.rb (100%) rename {spec => scripts/spec}/features/cohorts/curriculum_feature_spec.rb (100%) rename {spec => scripts/spec}/features/cohorts/feed_feature_spec.rb (100%) rename {spec => scripts/spec}/features/cohorts/management_feature_spec.rb (100%) rename {spec => scripts/spec}/features/cohorts/sandboxes_spec.rb (100%) rename {spec => scripts/spec}/features/cohorts/student_progress_spec.rb (100%) rename {spec => scripts/spec}/features/cohorts/submissions_spec.rb (100%) rename {spec => scripts/spec}/features/cohorts/users/challenges_feature_spec.rb (100%) rename {spec => scripts/spec}/features/cohorts/users/submissions_dashboard_feature_spec.rb (100%) rename {spec => scripts/spec}/features/content_files/checkpoint_assessments_spec.rb (100%) rename {spec => scripts/spec}/features/content_files/checkpoint_submissions_spec.rb (100%) rename {spec => scripts/spec}/features/content_files/navigation_feature_spec.rb (100%) rename {spec => scripts/spec}/features/content_files/permalinks_spec.rb (100%) rename {spec => scripts/spec}/features/content_files/view_feature_spec.rb (100%) rename {spec => scripts/spec}/features/home/header_feature_spec.rb (100%) rename {spec => scripts/spec}/features_helper.rb (100%) rename {spec => scripts/spec}/finders/block_finder_spec.rb (100%) rename {spec => scripts/spec}/finders/checkpoint_submission_finder_spec.rb (100%) rename {spec => scripts/spec}/finders/cohort_user_finder_spec.rb (100%) rename {spec => scripts/spec}/finders/content_file_finder_spec.rb (100%) rename {spec => scripts/spec}/finders/performance_finder_spec.rb (100%) rename {spec => scripts/spec}/finders/release_finder_spec.rb (100%) rename {spec => scripts/spec}/finders/standard_finder_spec.rb (100%) rename {spec => scripts/spec}/finders/submitted_challenge_answer_finder_spec.rb (100%) rename {spec => scripts/spec}/finders/user_finder_spec.rb (100%) rename {spec => scripts/spec}/fixtures/preview-content-file/preview.md (100%) rename {spec => scripts/spec}/fixtures/test-block-repo/._docker_directories_test-docker-folder.zip (100%) rename {spec => scripts/spec}/fixtures/test-block-repo/README.md (100%) rename {spec => scripts/spec}/fixtures/test-block-repo/challenges-smoketest.md (100%) rename {spec => scripts/spec}/fixtures/test-block-repo/config.yaml (100%) rename {spec => scripts/spec}/fixtures/test-block-repo/docker_directories/test-docker-folder/Dockerfile (100%) rename {spec => scripts/spec}/fixtures/test-block-repo/docker_directories/test-docker-folder/test.sh (100%) rename {spec => scripts/spec}/fixtures/test-block-repo/folder/sibling.md (100%) rename {spec => scripts/spec}/fixtures/test-block-repo/folder/target.md (100%) rename {spec => scripts/spec}/fixtures/test-block-repo/images/galvanize-logo.png (100%) rename {spec => scripts/spec}/fixtures/test-block-repo/images/register_klass.gif (100%) rename {spec => scripts/spec}/fixtures/test-block-repo/markdown-smoketesT.md (100%) rename {spec => scripts/spec}/fixtures/test-block-repo/target.md (100%) rename {spec => scripts/spec}/fixtures/test-block-repo/test.sql (100%) rename {spec => scripts/spec}/fixtures/vcr_cassettes/github-branch-success.yml (100%) rename {spec => scripts/spec}/fixtures/vcr_cassettes/github-course-yaml-not-found.yml (100%) rename {spec => scripts/spec}/fixtures/vcr_cassettes/github-course-yaml-success-2.yml (100%) rename {spec => scripts/spec}/fixtures/vcr_cassettes/github-course-yaml-success.yml (100%) rename {spec => scripts/spec}/fixtures/vcr_cassettes/github-not-found.yml (100%) rename {spec => scripts/spec}/fixtures/vcr_cassettes/github-repo-success.yml (100%) rename {spec => scripts/spec}/fixtures/vcr_cassettes/gitlab-course-yaml-branch-failure.yml (100%) rename {spec => scripts/spec}/fixtures/vcr_cassettes/gitlab-course-yaml-success.yml (100%) rename {spec => scripts/spec}/fixtures/vcr_cassettes/gitlab-not-found.yml (100%) rename {spec => scripts/spec}/fixtures/vcr_cassettes/gitlab-success.yml (100%) rename {spec => scripts/spec}/fixtures/vcr_cassettes/resync-course-job-success.yml (100%) rename {spec => scripts/spec}/helpers/json_helper_spec.rb (100%) rename {spec => scripts/spec}/helpers/mastery_mode_percent_helper_spec.rb (100%) rename {spec => scripts/spec}/helpers/standard_navigation_helper_spec.rb (100%) rename {spec => scripts/spec}/integration_helper.rb (100%) rename {spec => scripts/spec}/jobs/branch_release_notifier_job_spec.rb (100%) rename {spec => scripts/spec}/jobs/checkpoint_paired_submission_job_spec.rb (100%) rename {spec => scripts/spec}/jobs/content_file_default_visibility_job_spec.rb (100%) rename {spec => scripts/spec}/jobs/content_file_visit_job_spec.rb (100%) rename {spec => scripts/spec}/jobs/create_api_interaction_job_spec.rb (100%) rename {spec => scripts/spec}/jobs/create_release_job_spec.rb (100%) rename {spec => scripts/spec}/jobs/evaluate_code_snippet_job_spec.rb (100%) rename {spec => scripts/spec}/jobs/evaluate_custom_snippet_job_spec.rb (100%) rename {spec => scripts/spec}/jobs/evaluate_project_job_spec.rb (100%) rename {spec => scripts/spec}/jobs/grade_timed_checkpoint_job_spec.rb (100%) rename {spec => scripts/spec}/jobs/import_student_work_job_spec.rb (100%) rename {spec => scripts/spec}/jobs/release_notifier_job_spec.rb (100%) rename {spec => scripts/spec}/jobs/resync_course_job_spec.rb (100%) rename {spec => scripts/spec}/jobs/set_block_caches_job_spec.rb (100%) rename {spec => scripts/spec}/jobs/slack_ds_prep_job_spec.rb (100%) rename {spec => scripts/spec}/jobs/slack_se_prep_job_spec.rb (100%) rename {spec => scripts/spec}/jobs/slack_student_job_spec.rb (100%) rename {spec => scripts/spec}/jobs/switch_to_branch_job_spec.rb (100%) rename {spec => scripts/spec}/models/activity_spec.rb (100%) rename {spec => scripts/spec}/models/api_interaction_spec.rb (100%) rename {spec => scripts/spec}/models/block_spec.rb (100%) rename {spec => scripts/spec}/models/challenge_spec.rb (100%) rename {spec => scripts/spec}/models/checkpoint_submission_spec.rb (100%) rename {spec => scripts/spec}/models/cohort_release_spec.rb (100%) rename {spec => scripts/spec}/models/cohort_spec.rb (100%) rename {spec => scripts/spec}/models/cohort_user_spec.rb (100%) rename {spec => scripts/spec}/models/content_file_spec.rb (100%) rename {spec => scripts/spec}/models/content_visibility_spec.rb (100%) rename {spec => scripts/spec}/models/lesson_visit_spec.rb (100%) rename {spec => scripts/spec}/models/notification_spec.rb (100%) rename {spec => scripts/spec}/models/pairing_spec.rb (100%) rename {spec => scripts/spec}/models/performance_spec.rb (100%) rename {spec => scripts/spec}/models/release_spec.rb (100%) rename {spec => scripts/spec}/models/resync_job_result_spec.rb (100%) rename {spec => scripts/spec}/models/section_spec.rb (100%) rename {spec => scripts/spec}/models/standard_spec.rb (100%) rename {spec => scripts/spec}/models/submitted_challenge_answer_spec.rb (100%) rename {spec => scripts/spec}/models/user_last_viewed_standard_path_spec.rb (100%) rename {spec => scripts/spec}/models/user_spec.rb (100%) rename {spec => scripts/spec}/policies/cohort_policy_spec.rb (100%) rename {spec => scripts/spec}/policies/content_file_policy_spec.rb (100%) rename {spec => scripts/spec}/policies/user_policy_spec.rb (100%) rename {spec => scripts/spec}/presenters/block_presenter/for_cohort_releases_new_spec.rb (100%) rename {spec => scripts/spec}/presenters/block_presenter/for_cohort_releases_spec.rb (100%) rename {spec => scripts/spec}/presenters/block_presenter/for_releases_spec.rb (100%) rename {spec => scripts/spec}/presenters/challenge_with_submitted_challenge_answers_presenter_spec.rb (100%) rename {spec => scripts/spec}/presenters/checkpoint_submission_presenter/for_index_spec.rb (100%) rename {spec => scripts/spec}/presenters/checkpoint_submission_presenter_spec.rb (100%) rename {spec => scripts/spec}/presenters/content_file_presenter/for_curriculum_last_viewed_spec.rb (100%) rename {spec => scripts/spec}/presenters/content_file_presenter/for_show_spec.rb (100%) rename {spec => scripts/spec}/presenters/content_file_presenter/for_sidebar_spec.rb (100%) rename {spec => scripts/spec}/presenters/standard_presenter/for_checkpoint_submission_spec.rb (100%) rename {spec => scripts/spec}/presenters/standard_presenter/for_standard_card_spec.rb (100%) rename {spec => scripts/spec}/presenters/student_progress_presenter_spec.rb (100%) rename {spec => scripts/spec}/presenters/submissions_dashboard_presenter_spec.rb (100%) rename {spec => scripts/spec}/presenters/submitted_challenge_answer_presenter_spec.rb (100%) rename {spec => scripts/spec}/services/activity_aggregator_service_spec.rb (100%) rename {spec => scripts/spec}/services/assessment_service_spec.rb (100%) rename {spec => scripts/spec}/services/auto_assign_release_service_spec.rb (100%) rename {spec => scripts/spec}/services/checkpoint_submission_service_spec.rb (100%) rename {spec => scripts/spec}/services/cohort_standard_progress_service_spec.rb (100%) rename {spec => scripts/spec}/services/course_validator_spec.rb (100%) rename {spec => scripts/spec}/services/curriculum_progress_service_spec.rb (100%) rename {spec => scripts/spec}/services/download_repository_service_spec.rb (100%) rename {spec => scripts/spec}/services/git_url_service_spec.rb (100%) rename {spec => scripts/spec}/services/mastery_average_service_spec.rb (100%) rename {spec => scripts/spec}/services/notification_service_spec.rb (100%) rename {spec => scripts/spec}/services/platform_one_auth_resolver_service_spec.rb (100%) rename {spec => scripts/spec}/services/preview_content_file_service_spec.rb (100%) rename {spec => scripts/spec}/services/release_destroyer_service_spec.rb (100%) rename {spec => scripts/spec}/services/resync_course_service_spec.rb (100%) rename {spec => scripts/spec}/services/s3_asset_uploader_service_spec.rb (100%) rename {spec => scripts/spec}/services/standard_submissions_service_spec.rb (100%) rename {spec => scripts/spec}/spec_helper.rb (100%) rename {spec => scripts/spec}/support/json_spec_matchers.rb (100%) rename {spec => scripts/spec}/support/mocktokit.rb (100%) rename {spec => scripts/spec}/support/object_creation_methods.rb (100%) rename tsconfig.json => scripts/tsconfig.json (100%) rename {vendor => scripts/vendor}/assets/javascripts/bootstrap-datepicker.js (100%) rename {vendor => scripts/vendor}/assets/javascripts/hopscotch.js (100%) rename {vendor => scripts/vendor}/assets/javascripts/react-tooltip.js (100%) rename {vendor => scripts/vendor}/assets/stylesheets/bootstrap-datepicker.css (100%) rename {vendor => scripts/vendor}/assets/stylesheets/hopscotch.css (100%) rename yarn.lock => scripts/yarn.lock (100%) diff --git a/.Dockerfile.swp b/.Dockerfile.swp new file mode 100644 index 0000000000000000000000000000000000000000..e38d85e67f1c1580477d7e6a7572442646f48eab GIT binary patch literal 20480 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 I#zBmK1JXg1W&i*H literal 0 HcmV?d00001 diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 837f2f3..0000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,97 +0,0 @@ -version: 2.0 - -defaults: &defaults - docker: - - image: circleci/ruby:2.6.0-node-browsers - environment: - - PG_HOST: localhost - - PG_USER: ubuntu - - RAILS_ENV: test - - RACK_ENV: test - - image: circleci/postgres:9.5-alpine - environment: - POSTGRES_USER: ubuntu - POSTGRES_DB: forge_test - - image: redis - working_directory: ~/forge - -jobs: - install_dependencies: - <<: *defaults - parallelism: 1 - steps: - - checkout - - attach_workspace: - at: ~/forge - - restore_cache: - key: v1-bundle-{{ checksum "Gemfile.lock" }} - - run: bundle install --path vendor/bundle - - save_cache: - key: v1-bundle-{{ checksum "Gemfile.lock" }} - paths: - - ~/forge/vendor/bundle - - persist_to_workspace: - root: . - paths: vendor/bundle - - restore_cache: - key: v1-yarn-{{ checksum "package.json" }} - - run: - name: Yarn Install JS Dependencies - command: yarn install - - save_cache: - key: v1-yarn-{{ checksum "package.json" }} - paths: - - ~/forge/node_modules - - persist_to_workspace: - root: . - paths: node_modules - - lint: - <<: *defaults - parallelism: 1 - steps: - - checkout - - attach_workspace: - at: ~/forge - - run: bundle --path vendor/bundle - - run: - name: Run Rubocop - command: bundle exec rubocop - - run: - name: Run tsc - command: ./node_modules/.bin/tsc --version && ./node_modules/.bin/tsc - - rake_test: - <<: *defaults - parallelism: 1 - steps: - - checkout - - attach_workspace: - at: ~/forge - - run: bundle --path vendor/bundle - - run: - name: Create DB - command: bundle exec rake db:create db:schema:load - environment: - DATABASE_URL: "postgres://ubuntu@localhost:5432/forge_test" - - run: - name: Run Rspec Tests - command: | - TESTFILES=$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings) - bundle exec rspec --profile 10 --format RspecJunitFormatter --out ~/forge/test-results/rspec.xml --format progress -- ${TESTFILES} - environment: - DATABASE_URL: "postgres://ubuntu@localhost:5432/forge_test" - - store_test_results: - path: ~/forge/test-results - -workflows: - version: 2 - build-and-deploy: - jobs: - - install_dependencies - - lint: - requires: - - install_dependencies - - rake_test: - requires: - - install_dependencies diff --git a/Dockerfile b/Dockerfile index 613216e..26c4aa2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,34 +1,57 @@ -# Stage 1: Install libararies -FROM centos:8 as builder +### Iron Bank Settings +# ARG BASE_REGISTRY=registry1.dsop.io +# ARG BASE_IMAGE=ironbank/opensource/ruby/ruby26 +# ARG BASE_TAG=2.6.6 + +### Platform 1 Pipeline Settings +ARG BASE_REGISTRY=registry.il2.dsop.io +ARG BASE_IMAGE=platform-one/devops/pipeline-templates/ironbank/ruby26 +ARG BASE_TAG=2.6.6.212 + +# Stage 1: Build redis from source. +FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} as builder USER 0 -## Setup the yarn repo. -#RUN curl --silent --location https://dl.yarnpkg.com/rpm/yarn.repo | tee /etc/yum.repos.d/yarn.repo -#RUN rpm --import https://dl.yarnpkg.com/rpm/pubkey.gpg - -## Install the required packages. -RUN dnf update -y && \ - dnf install -y \ - redis -# make \ -# patch \ -# git \ -# yarn \ -# zlib-devel \ -# libpq-devel \ -# libxml2-devel \ -# libxslt-devel \ -# gcc +# Install what we can via dnf +RUN dnf update -y && dnf install -y \ + autoconf \ + automake \ + bzip2 \ + curl \ + diffutils \ + gcc-c++ \ + libedit \ + libffi-devel \ + libtool \ + make \ + openssl-devel \ + patch \ + readline \ + zlib \ + zlib-devel + +# Uncomment to test in Platform 1 +RUN curl -O https://download.redis.io/releases/redis-6.0.9.tar.gz + +# Build redis from source +#COPY redis-6.0.9.tar.gz . +RUN tar xzf redis-6.0.9.tar.gz +WORKDIR redis-6.0.9/deps +RUN make hiredis jemalloc linenoise lua +WORKDIR .. +RUN make +RUN make install +WORKDIR .. # Stage 2: Setup the Image. -FROM registry.il2.dsop.io/platform-one/devops/pipeline-templates/ironbank/ruby26:2.6.6.212 +FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} USER 0 RUN curl --silent --location https://dl.yarnpkg.com/rpm/yarn.repo | tee /etc/yum.repos.d/yarn.repo RUN rpm --import https://dl.yarnpkg.com/rpm/pubkey.gpg -RUN dnf update -y && \ - dnf install -y \ +RUN dnf update -y && dnf install -y \ + curl \ make \ patch \ git \ @@ -41,7 +64,7 @@ RUN dnf update -y && \ gcc-c++ # Redis CLI Binary. -COPY --from=builder /usr/bin/redis-cli /usr/bin/redis-cli +COPY --from=builder /usr/local/bin/redis-cli /usr/local/bin/redis-cli ## Patch Binary. #COPY --from=builder /usr/bin/patch /usr/bin/patch @@ -130,13 +153,13 @@ COPY --from=builder /usr/bin/redis-cli /usr/bin/redis-cli #COPY --from=builder /usr/include /usr/include # Install Node -ADD .nvmrc . -RUN curl -L https://raw.githubusercontent.com/tj/n/master/bin/n -o n +RUN curl -L -O https://raw.githubusercontent.com/tj/n/master/bin/n +COPY ./scripts/.nvmrc . RUN bash n auto # Setup our environment -WORKDIR /usr/src/app -ADD . . +WORKDIR /app +ADD ./scripts . # Add write permissions. RUN chown -R 1001 . @@ -163,7 +186,7 @@ RUN bundle exec rake assets:precompile RUN bundle exec rake assets:clean # Add the node_modules to the path. -ENV PATH /usr/src/app/node_modules/.bin:$PATH +ENV PATH /app/node_modules/.bin:$PATH # Set the entry point. -ENTRYPOINT ["./entrypoint-server.sh"] \ No newline at end of file +ENTRYPOINT ["./entrypoint-server.sh"] diff --git a/Dockerfile.base b/Dockerfile.base deleted file mode 100644 index dc797ed..0000000 --- a/Dockerfile.base +++ /dev/null @@ -1,47 +0,0 @@ -FROM bitnami/ruby:2.6.6 - -# Install what we can through OS package management -RUN apt-get -y update -RUN apt-get -y install --no-install-recommends \ - curl \ - software-properties-common \ - postgresql-client\ - libpq-dev \ - libxml2-dev \ - libxslt1-dev \ - qt5-default \ - libqt5webkit5-dev \ - xvfb - -# Install the right version of nodejs -RUN curl -sL https://deb.nodesource.com/setup_12.x | bash - -RUN apt-get -y install --no-install-recommends nodejs -RUN apt-get -q clean -RUN npm cache clean -f -RUN npm install -g n -RUN n stable -RUN update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10 - -# Copy in all the application dependencies -ADD package.json /usr/src/app/package.json -RUN npm install - -# Set the user -RUN groupadd -r ruby -RUN useradd --no-log-init -r -g ruby ruby -# USER ruby -RUN whoami - -# Setup our environment -WORKDIR /usr/src/app -ENV RAILS_ENV production - -# Stuff that changes -ADD . . -ADD Gemfile /usr/src/app/Gemfile -ADD Gemfile.lock /usr/src/app/Gemfile.lock -# RUN gem install bundler --version 2.1.4 -RUN gem install rake -v '13.0.1' --source 'https://rubygems.org/' -RUN bundle install -ENV PATH /usr/src/app/node_modules/.bin:$PATH -CMD ["./entrypoint-server.sh"] diff --git a/Dockerfile.old b/Dockerfile.old new file mode 100644 index 0000000..613216e --- /dev/null +++ b/Dockerfile.old @@ -0,0 +1,169 @@ +# Stage 1: Install libararies +FROM centos:8 as builder +USER 0 + +## Setup the yarn repo. +#RUN curl --silent --location https://dl.yarnpkg.com/rpm/yarn.repo | tee /etc/yum.repos.d/yarn.repo +#RUN rpm --import https://dl.yarnpkg.com/rpm/pubkey.gpg + +## Install the required packages. +RUN dnf update -y && \ + dnf install -y \ + redis +# make \ +# patch \ +# git \ +# yarn \ +# zlib-devel \ +# libpq-devel \ +# libxml2-devel \ +# libxslt-devel \ +# gcc + +# Stage 2: Setup the Image. +FROM registry.il2.dsop.io/platform-one/devops/pipeline-templates/ironbank/ruby26:2.6.6.212 +USER 0 + +RUN curl --silent --location https://dl.yarnpkg.com/rpm/yarn.repo | tee /etc/yum.repos.d/yarn.repo +RUN rpm --import https://dl.yarnpkg.com/rpm/pubkey.gpg + +RUN dnf update -y && \ + dnf install -y \ + make \ + patch \ + git \ + yarn \ + zlib-devel \ + libpq-devel \ + libxml2-devel \ + libxslt-devel \ + gcc \ + gcc-c++ + +# Redis CLI Binary. +COPY --from=builder /usr/bin/redis-cli /usr/bin/redis-cli + +## Patch Binary. +#COPY --from=builder /usr/bin/patch /usr/bin/patch +# +## Make Binary. +#COPY --from=builder /usr/bin/make /usr/bin/make +# +## Git Binaries. +#COPY --from=builder /usr/bin/git* /usr/bin/ +# +## Yarn Binaries. +#COPY --from=builder /usr/share/yarn /usr/share/yarn +#RUN ln -s /usr/share/yarn/bin/yarn /usr/bin/yarn +#RUN ln -s /usr/share/yarn/bin/yarn /usr/bin/yarnpkg +# +## libz Dependencies. +#COPY --from=builder /usr/lib64/libz* /usr/lib64/ +# +## Postgres Dependencies +#COPY --from=builder /usr/bin/pkgconf /usr/bin/pkgconf +#COPY --from=builder /usr/bin/pg_config /usr/bin/pg_config +#COPY --from=builder /usr/lib64/libpq* /usr/lib64/ +#COPY --from=builder /usr/lib64/libpkgconf* /usr/lib64/ +#COPY --from=builder /usr/include/libpq /usr/include/libpq +#COPY --from=builder /usr/include/libpq* /usr/include/ +#COPY --from=builder /usr/include/pg* /usr/include/ +#COPY --from=builder /usr/include/pgsql /usr/include/pgsql +#COPY --from=builder /usr/include/postgres* /usr/include/ +# +## libxml2 Dependencies. +#COPY --from=builder /usr/lib64/libxml* /usr/lib64/ +#COPY --from=builder /usr/lib64/liblz* /usr/lib64/ +#COPY --from=builder /usr/lib64/libm-2* /usr/lib64/ +#COPY --from=builder /usr/lib64/libm.so* /usr/lib64/ +#COPY --from=builder /usr/include/lzma /usr/include/lzma +#COPY --from=builder /usr/include/zlib* /usr/include/ +#COPY --from=builder /usr/include/zconf* /usr/include/ +#COPY --from=builder /usr/include/libxml2 /usr/include/libxml2 +#COPY --from=builder /usr/lib64/xml2Conf.sh /usr/lib64/xml2Conf.sh +# +## libxslt Dependencies. +#COPY --from=builder /usr/lib64/libxslt* /usr/lib64/ +#COPY --from=builder /usr/lib64/libexslt* /usr/lib64/ +#COPY --from=builder /usr/include/libxslt /usr/include/libxslt +#COPY --from=builder /usr/include/libexslt /usr/include/libexslt +#COPY --from=builder /usr/include/gcrypt* /usr/include/ +#COPY --from=builder /usr/include/gpg* /usr/include/ +#COPY --from=builder /usr/lib64/xsltConf.sh /usr/lib64/xsltConf.sh + +## GCC Dependencies. +#COPY --from=builder /usr/bin/gcc* /usr/bin/ +#COPY --from=builder /usr/lib/gcc /usr/lib/gcc +#COPY --from=builder /usr/bin/as /usr/bin/as +#COPY --from=builder /usr/bin/ld /usr/bin/ld +#COPY --from=builder /usr/libexec/gcc /usr/libexec/gcc +#COPY --from=builder /usr/lib64/libmpc* /usr/lib64/ +#COPY --from=builder /usr/lib64/libopcodes* /usr/lib64/ +#COPY --from=builder /usr/lib64/libbfd* /usr/lib64/ +#COPY --from=builder /usr/lib64/libc.so* /usr/lib64/ +#COPY --from=builder /usr/lib64/libc_nonshared* /usr/lib64/ +#COPY --from=builder /usr/lib64/libcrypt* /usr/lib64/ +#COPY --from=builder /usr/lib64/libgomp* /usr/lib64/ +#COPY --from=builder /usr/lib64/libgpg* /usr/lib64/ +#COPY --from=builder /usr/lib64/libgcrypt* /usr/lib64/ +#COPY --from=builder /usr/lib64/libgcc* /usr/lib64/ +#COPY --from=builder /usr/lib64/crt* /usr/lib64/ +#COPY --from=builder /usr/lib64/libm-2* /usr/lib64/ +#COPY --from=builder /usr/lib64/libm.so* /usr/lib64/ +#COPY --from=builder /usr/lib64/libmcheck* /usr/lib64/ +#COPY --from=builder /usr/lib64/Mcrt1* /usr/lib64/ +#COPY --from=builder /usr/lib64/Scrt1* /usr/lib64/ +#COPY --from=builder /usr/lib64/gcrt* /usr/lib64/ +#COPY --from=builder /usr/lib64/libanl* /usr/lib64/ +#COPY --from=builder /usr/lib64/libdl* /usr/lib64/ +#COPY --from=builder /usr/lib64/libg* /usr/lib64/ +#COPY --from=builder /usr/lib64/libisl* /usr/lib64/ +#COPY --from=builder /usr/lib64/liblzma* /usr/lib64/ +#COPY --from=builder /usr/lib64/libmvec* /usr/lib64/ +#COPY --from=builder /usr/lib64/libpthread* /usr/lib64/ +#COPY --from=builder /usr/lib64/libresolv* /usr/lib64/ +#COPY --from=builder /usr/lib64/librt* /usr/lib64/ +#COPY --from=builder /usr/lib64/libthread_db* /usr/lib64/ +#COPY --from=builder /usr/lib64/libutil* /usr/lib64/ +#COPY --from=builder /usr/lib64/libz* /usr/lib64/ +#COPY --from=builder /usr/lib64/rcrt* /usr/lib64/ +#COPY --from=builder /usr/include /usr/include + +# Install Node +ADD .nvmrc . +RUN curl -L https://raw.githubusercontent.com/tj/n/master/bin/n -o n +RUN bash n auto + +# Setup our environment +WORKDIR /usr/src/app +ADD . . + +# Add write permissions. +RUN chown -R 1001 . + +# Become the ruby user +USER 1001 + +# Set the Rails environment variable. +ENV RAILS_ENV production + +# Install Rails Dependecies. +RUN gem install bundler:2.1.4 + +# Run the bundle install +RUN bundle install + +## Run Yarn Install +RUN yarn install + +# Precompile assets +RUN bundle exec rake assets:precompile + +# Asset Clean +RUN bundle exec rake assets:clean + +# Add the node_modules to the path. +ENV PATH /usr/src/app/node_modules/.bin:$PATH + +# Set the entry point. +ENTRYPOINT ["./entrypoint-server.sh"] \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..ec2a93f --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,14 @@ +@Library('DCCSCR@master') _ +dccscrPipeline(version: "0.1.0") + +/* The above format is required for all production submissions. +* The version will be the image tag associated with this container for this branch. +* +* You may limit the job to the build stage or the scanning stage only: +* dccscrPipeline(version: "1.4.2", scan: false) +* dccscrPipeline(version: "1.0.0", build: false) +* +* You may also use a different branch of the jenkins-shared-library. +* Only do this if you know what you are doing: +* @Library('DCCSCR@feature1_branch') _ */ + diff --git a/download.json b/download.json new file mode 100644 index 0000000..39b3156 --- /dev/null +++ b/download.json @@ -0,0 +1,13 @@ +{ "resources": + [ + { + "url" : "https://download.redis.io/releases/redis-6.0.9.tar.gz", + "filename": "redis-6.0.9.tar.gz", + "validation": + { + "type": "sha256", + "value": "dc2bdcf81c620e9f09cfd12e85d3bc631c897b2db7a55218fd8a65eaa37f86dd" + } + } + ] +} diff --git a/.browserslistrc b/scripts/.browserslistrc similarity index 100% rename from .browserslistrc rename to scripts/.browserslistrc diff --git a/.env.example b/scripts/.env.example similarity index 100% rename from .env.example rename to scripts/.env.example diff --git a/.eslintrc.json b/scripts/.eslintrc.json similarity index 100% rename from .eslintrc.json rename to scripts/.eslintrc.json diff --git a/.haml-lint.yml b/scripts/.haml-lint.yml similarity index 100% rename from .haml-lint.yml rename to scripts/.haml-lint.yml diff --git a/.nvmrc b/scripts/.nvmrc similarity index 100% rename from .nvmrc rename to scripts/.nvmrc diff --git a/.overcommit.yml b/scripts/.overcommit.yml similarity index 100% rename from .overcommit.yml rename to scripts/.overcommit.yml diff --git a/.postcssrc.yml b/scripts/.postcssrc.yml similarity index 100% rename from .postcssrc.yml rename to scripts/.postcssrc.yml diff --git a/.rubocop.yml b/scripts/.rubocop.yml similarity index 100% rename from .rubocop.yml rename to scripts/.rubocop.yml diff --git a/.ruby-version b/scripts/.ruby-version similarity index 100% rename from .ruby-version rename to scripts/.ruby-version diff --git a/.stylelintrc b/scripts/.stylelintrc similarity index 100% rename from .stylelintrc rename to scripts/.stylelintrc diff --git a/Gemfile b/scripts/Gemfile similarity index 100% rename from Gemfile rename to scripts/Gemfile diff --git a/Gemfile.lock b/scripts/Gemfile.lock similarity index 100% rename from Gemfile.lock rename to scripts/Gemfile.lock diff --git a/Procfile b/scripts/Procfile similarity index 100% rename from Procfile rename to scripts/Procfile diff --git a/Procfile.local b/scripts/Procfile.local similarity index 100% rename from Procfile.local rename to scripts/Procfile.local diff --git a/README.md b/scripts/README.md similarity index 100% rename from README.md rename to scripts/README.md diff --git a/Rakefile b/scripts/Rakefile similarity index 100% rename from Rakefile rename to scripts/Rakefile diff --git a/app.json b/scripts/app.json similarity index 100% rename from app.json rename to scripts/app.json diff --git a/app/assets/config/manifest.js b/scripts/app/assets/config/manifest.js similarity index 100% rename from app/assets/config/manifest.js rename to scripts/app/assets/config/manifest.js diff --git a/app/assets/images/favicon.ico b/scripts/app/assets/images/favicon.ico similarity index 100% rename from app/assets/images/favicon.ico rename to scripts/app/assets/images/favicon.ico diff --git a/app/assets/images/loader-black.svg b/scripts/app/assets/images/loader-black.svg similarity index 100% rename from app/assets/images/loader-black.svg rename to scripts/app/assets/images/loader-black.svg diff --git a/app/assets/images/loader-cyan.svg b/scripts/app/assets/images/loader-cyan.svg similarity index 100% rename from app/assets/images/loader-cyan.svg rename to scripts/app/assets/images/loader-cyan.svg diff --git a/app/assets/images/loader-white.svg b/scripts/app/assets/images/loader-white.svg similarity index 100% rename from app/assets/images/loader-white.svg rename to scripts/app/assets/images/loader-white.svg diff --git a/app/assets/images/lost.jpg b/scripts/app/assets/images/lost.jpg similarity index 100% rename from app/assets/images/lost.jpg rename to scripts/app/assets/images/lost.jpg diff --git a/app/assets/images/spinner.gif b/scripts/app/assets/images/spinner.gif similarity index 100% rename from app/assets/images/spinner.gif rename to scripts/app/assets/images/spinner.gif diff --git a/app/assets/images/svg/baseline-notes-24px.svg b/scripts/app/assets/images/svg/baseline-notes-24px.svg similarity index 100% rename from app/assets/images/svg/baseline-notes-24px.svg rename to scripts/app/assets/images/svg/baseline-notes-24px.svg diff --git a/app/assets/images/svg/g-learn-lockup.svg b/scripts/app/assets/images/svg/g-learn-lockup.svg similarity index 100% rename from app/assets/images/svg/g-learn-lockup.svg rename to scripts/app/assets/images/svg/g-learn-lockup.svg diff --git a/app/assets/images/svg/galvanize-logo.svg b/scripts/app/assets/images/svg/galvanize-logo.svg similarity index 100% rename from app/assets/images/svg/galvanize-logo.svg rename to scripts/app/assets/images/svg/galvanize-logo.svg diff --git a/app/assets/images/svg/github-icon.svg b/scripts/app/assets/images/svg/github-icon.svg similarity index 100% rename from app/assets/images/svg/github-icon.svg rename to scripts/app/assets/images/svg/github-icon.svg diff --git a/app/assets/images/svg/mobile-logo.svg b/scripts/app/assets/images/svg/mobile-logo.svg similarity index 100% rename from app/assets/images/svg/mobile-logo.svg rename to scripts/app/assets/images/svg/mobile-logo.svg diff --git a/app/assets/images/svg/octicon-git-branch.svg b/scripts/app/assets/images/svg/octicon-git-branch.svg similarity index 100% rename from app/assets/images/svg/octicon-git-branch.svg rename to scripts/app/assets/images/svg/octicon-git-branch.svg diff --git a/app/assets/images/svg/svg-sprite-action-symbol.svg b/scripts/app/assets/images/svg/svg-sprite-action-symbol.svg similarity index 100% rename from app/assets/images/svg/svg-sprite-action-symbol.svg rename to scripts/app/assets/images/svg/svg-sprite-action-symbol.svg diff --git a/app/assets/images/svg/svg-sprite-av-symbol.svg b/scripts/app/assets/images/svg/svg-sprite-av-symbol.svg similarity index 100% rename from app/assets/images/svg/svg-sprite-av-symbol.svg rename to scripts/app/assets/images/svg/svg-sprite-av-symbol.svg diff --git a/app/assets/images/svg/svg-sprite-device-symbol.svg b/scripts/app/assets/images/svg/svg-sprite-device-symbol.svg similarity index 100% rename from app/assets/images/svg/svg-sprite-device-symbol.svg rename to scripts/app/assets/images/svg/svg-sprite-device-symbol.svg diff --git a/app/assets/images/svg/svg-sprite-image-symbol.svg b/scripts/app/assets/images/svg/svg-sprite-image-symbol.svg similarity index 100% rename from app/assets/images/svg/svg-sprite-image-symbol.svg rename to scripts/app/assets/images/svg/svg-sprite-image-symbol.svg diff --git a/app/assets/images/svg/svg-sprite-navigation-symbol.svg b/scripts/app/assets/images/svg/svg-sprite-navigation-symbol.svg similarity index 100% rename from app/assets/images/svg/svg-sprite-navigation-symbol.svg rename to scripts/app/assets/images/svg/svg-sprite-navigation-symbol.svg diff --git a/app/assets/javascripts/application.js b/scripts/app/assets/javascripts/application.js similarity index 100% rename from app/assets/javascripts/application.js rename to scripts/app/assets/javascripts/application.js diff --git a/app/assets/javascripts/mobile.js b/scripts/app/assets/javascripts/mobile.js similarity index 100% rename from app/assets/javascripts/mobile.js rename to scripts/app/assets/javascripts/mobile.js diff --git a/app/assets/stylesheets/application.scss b/scripts/app/assets/stylesheets/application.scss similarity index 100% rename from app/assets/stylesheets/application.scss rename to scripts/app/assets/stylesheets/application.scss diff --git a/app/assets/stylesheets/base.scss b/scripts/app/assets/stylesheets/base.scss similarity index 100% rename from app/assets/stylesheets/base.scss rename to scripts/app/assets/stylesheets/base.scss diff --git a/app/assets/stylesheets/bootstrap-custom.scss b/scripts/app/assets/stylesheets/bootstrap-custom.scss similarity index 100% rename from app/assets/stylesheets/bootstrap-custom.scss rename to scripts/app/assets/stylesheets/bootstrap-custom.scss diff --git a/app/assets/stylesheets/cohorts.scss b/scripts/app/assets/stylesheets/cohorts.scss similarity index 100% rename from app/assets/stylesheets/cohorts.scss rename to scripts/app/assets/stylesheets/cohorts.scss diff --git a/app/assets/stylesheets/components/_404-container.scss b/scripts/app/assets/stylesheets/components/_404-container.scss similarity index 100% rename from app/assets/stylesheets/components/_404-container.scss rename to scripts/app/assets/stylesheets/components/_404-container.scss diff --git a/app/assets/stylesheets/components/_action-menu.scss b/scripts/app/assets/stylesheets/components/_action-menu.scss similarity index 100% rename from app/assets/stylesheets/components/_action-menu.scss rename to scripts/app/assets/stylesheets/components/_action-menu.scss diff --git a/app/assets/stylesheets/components/_activity-dashboard.scss b/scripts/app/assets/stylesheets/components/_activity-dashboard.scss similarity index 100% rename from app/assets/stylesheets/components/_activity-dashboard.scss rename to scripts/app/assets/stylesheets/components/_activity-dashboard.scss diff --git a/app/assets/stylesheets/components/_activity-feed.scss b/scripts/app/assets/stylesheets/components/_activity-feed.scss similarity index 100% rename from app/assets/stylesheets/components/_activity-feed.scss rename to scripts/app/assets/stylesheets/components/_activity-feed.scss diff --git a/app/assets/stylesheets/components/_api-interactions.scss b/scripts/app/assets/stylesheets/components/_api-interactions.scss similarity index 100% rename from app/assets/stylesheets/components/_api-interactions.scss rename to scripts/app/assets/stylesheets/components/_api-interactions.scss diff --git a/app/assets/stylesheets/components/_api_token.scss b/scripts/app/assets/stylesheets/components/_api_token.scss similarity index 100% rename from app/assets/stylesheets/components/_api_token.scss rename to scripts/app/assets/stylesheets/components/_api_token.scss diff --git a/app/assets/stylesheets/components/_auth-style-search.scss b/scripts/app/assets/stylesheets/components/_auth-style-search.scss similarity index 100% rename from app/assets/stylesheets/components/_auth-style-search.scss rename to scripts/app/assets/stylesheets/components/_auth-style-search.scss diff --git a/app/assets/stylesheets/components/_blocks-index.scss b/scripts/app/assets/stylesheets/components/_blocks-index.scss similarity index 100% rename from app/assets/stylesheets/components/_blocks-index.scss rename to scripts/app/assets/stylesheets/components/_blocks-index.scss diff --git a/app/assets/stylesheets/components/_blocks-stats.scss b/scripts/app/assets/stylesheets/components/_blocks-stats.scss similarity index 100% rename from app/assets/stylesheets/components/_blocks-stats.scss rename to scripts/app/assets/stylesheets/components/_blocks-stats.scss diff --git a/app/assets/stylesheets/components/_button.scss b/scripts/app/assets/stylesheets/components/_button.scss similarity index 100% rename from app/assets/stylesheets/components/_button.scss rename to scripts/app/assets/stylesheets/components/_button.scss diff --git a/app/assets/stylesheets/components/_callouts.scss b/scripts/app/assets/stylesheets/components/_callouts.scss similarity index 100% rename from app/assets/stylesheets/components/_callouts.scss rename to scripts/app/assets/stylesheets/components/_callouts.scss diff --git a/app/assets/stylesheets/components/_challenge-block.scss b/scripts/app/assets/stylesheets/components/_challenge-block.scss similarity index 100% rename from app/assets/stylesheets/components/_challenge-block.scss rename to scripts/app/assets/stylesheets/components/_challenge-block.scss diff --git a/app/assets/stylesheets/components/_challenge_status.scss b/scripts/app/assets/stylesheets/components/_challenge_status.scss similarity index 100% rename from app/assets/stylesheets/components/_challenge_status.scss rename to scripts/app/assets/stylesheets/components/_challenge_status.scss diff --git a/app/assets/stylesheets/components/_checkbox-input.scss b/scripts/app/assets/stylesheets/components/_checkbox-input.scss similarity index 100% rename from app/assets/stylesheets/components/_checkbox-input.scss rename to scripts/app/assets/stylesheets/components/_checkbox-input.scss diff --git a/app/assets/stylesheets/components/_checkpoint-landing.scss b/scripts/app/assets/stylesheets/components/_checkpoint-landing.scss similarity index 100% rename from app/assets/stylesheets/components/_checkpoint-landing.scss rename to scripts/app/assets/stylesheets/components/_checkpoint-landing.scss diff --git a/app/assets/stylesheets/components/_checkpoint-submission.scss b/scripts/app/assets/stylesheets/components/_checkpoint-submission.scss similarity index 100% rename from app/assets/stylesheets/components/_checkpoint-submission.scss rename to scripts/app/assets/stylesheets/components/_checkpoint-submission.scss diff --git a/app/assets/stylesheets/components/_checkpoint-submissions-columns-student.scss b/scripts/app/assets/stylesheets/components/_checkpoint-submissions-columns-student.scss similarity index 100% rename from app/assets/stylesheets/components/_checkpoint-submissions-columns-student.scss rename to scripts/app/assets/stylesheets/components/_checkpoint-submissions-columns-student.scss diff --git a/app/assets/stylesheets/components/_checkpoint-submissions-columns.scss b/scripts/app/assets/stylesheets/components/_checkpoint-submissions-columns.scss similarity index 100% rename from app/assets/stylesheets/components/_checkpoint-submissions-columns.scss rename to scripts/app/assets/stylesheets/components/_checkpoint-submissions-columns.scss diff --git a/app/assets/stylesheets/components/_checkpoint-submissions-index.scss b/scripts/app/assets/stylesheets/components/_checkpoint-submissions-index.scss similarity index 100% rename from app/assets/stylesheets/components/_checkpoint-submissions-index.scss rename to scripts/app/assets/stylesheets/components/_checkpoint-submissions-index.scss diff --git a/app/assets/stylesheets/components/_checkpoint_student_scores.scss b/scripts/app/assets/stylesheets/components/_checkpoint_student_scores.scss similarity index 100% rename from app/assets/stylesheets/components/_checkpoint_student_scores.scss rename to scripts/app/assets/stylesheets/components/_checkpoint_student_scores.scss diff --git a/app/assets/stylesheets/components/_checkpoint_submisstion_state.scss b/scripts/app/assets/stylesheets/components/_checkpoint_submisstion_state.scss similarity index 100% rename from app/assets/stylesheets/components/_checkpoint_submisstion_state.scss rename to scripts/app/assets/stylesheets/components/_checkpoint_submisstion_state.scss diff --git a/app/assets/stylesheets/components/_checkpoint_toolbar.scss b/scripts/app/assets/stylesheets/components/_checkpoint_toolbar.scss similarity index 100% rename from app/assets/stylesheets/components/_checkpoint_toolbar.scss rename to scripts/app/assets/stylesheets/components/_checkpoint_toolbar.scss diff --git a/app/assets/stylesheets/components/_code-block.scss b/scripts/app/assets/stylesheets/components/_code-block.scss similarity index 100% rename from app/assets/stylesheets/components/_code-block.scss rename to scripts/app/assets/stylesheets/components/_code-block.scss diff --git a/app/assets/stylesheets/components/_cohort-submissions-table.scss b/scripts/app/assets/stylesheets/components/_cohort-submissions-table.scss similarity index 100% rename from app/assets/stylesheets/components/_cohort-submissions-table.scss rename to scripts/app/assets/stylesheets/components/_cohort-submissions-table.scss diff --git a/app/assets/stylesheets/components/_cohort_releases.scss b/scripts/app/assets/stylesheets/components/_cohort_releases.scss similarity index 100% rename from app/assets/stylesheets/components/_cohort_releases.scss rename to scripts/app/assets/stylesheets/components/_cohort_releases.scss diff --git a/app/assets/stylesheets/components/_cohorts.scss b/scripts/app/assets/stylesheets/components/_cohorts.scss similarity index 100% rename from app/assets/stylesheets/components/_cohorts.scss rename to scripts/app/assets/stylesheets/components/_cohorts.scss diff --git a/app/assets/stylesheets/components/_content-file-show.scss b/scripts/app/assets/stylesheets/components/_content-file-show.scss similarity index 100% rename from app/assets/stylesheets/components/_content-file-show.scss rename to scripts/app/assets/stylesheets/components/_content-file-show.scss diff --git a/app/assets/stylesheets/components/_content-file-sidebar.scss b/scripts/app/assets/stylesheets/components/_content-file-sidebar.scss similarity index 100% rename from app/assets/stylesheets/components/_content-file-sidebar.scss rename to scripts/app/assets/stylesheets/components/_content-file-sidebar.scss diff --git a/app/assets/stylesheets/components/_curriculum-checkpoint-summary.scss b/scripts/app/assets/stylesheets/components/_curriculum-checkpoint-summary.scss similarity index 100% rename from app/assets/stylesheets/components/_curriculum-checkpoint-summary.scss rename to scripts/app/assets/stylesheets/components/_curriculum-checkpoint-summary.scss diff --git a/app/assets/stylesheets/components/_curriculum-progress.scss b/scripts/app/assets/stylesheets/components/_curriculum-progress.scss similarity index 100% rename from app/assets/stylesheets/components/_curriculum-progress.scss rename to scripts/app/assets/stylesheets/components/_curriculum-progress.scss diff --git a/app/assets/stylesheets/components/_curriculum.scss b/scripts/app/assets/stylesheets/components/_curriculum.scss similarity index 100% rename from app/assets/stylesheets/components/_curriculum.scss rename to scripts/app/assets/stylesheets/components/_curriculum.scss diff --git a/app/assets/stylesheets/components/_dropdown-component.scss b/scripts/app/assets/stylesheets/components/_dropdown-component.scss similarity index 100% rename from app/assets/stylesheets/components/_dropdown-component.scss rename to scripts/app/assets/stylesheets/components/_dropdown-component.scss diff --git a/app/assets/stylesheets/components/_external-link.scss b/scripts/app/assets/stylesheets/components/_external-link.scss similarity index 100% rename from app/assets/stylesheets/components/_external-link.scss rename to scripts/app/assets/stylesheets/components/_external-link.scss diff --git a/app/assets/stylesheets/components/_flash-message.scss b/scripts/app/assets/stylesheets/components/_flash-message.scss similarity index 100% rename from app/assets/stylesheets/components/_flash-message.scss rename to scripts/app/assets/stylesheets/components/_flash-message.scss diff --git a/app/assets/stylesheets/components/_footer.scss b/scripts/app/assets/stylesheets/components/_footer.scss similarity index 100% rename from app/assets/stylesheets/components/_footer.scss rename to scripts/app/assets/stylesheets/components/_footer.scss diff --git a/app/assets/stylesheets/components/_grade-buttons.scss b/scripts/app/assets/stylesheets/components/_grade-buttons.scss similarity index 100% rename from app/assets/stylesheets/components/_grade-buttons.scss rename to scripts/app/assets/stylesheets/components/_grade-buttons.scss diff --git a/app/assets/stylesheets/components/_integer_picker.scss b/scripts/app/assets/stylesheets/components/_integer_picker.scss similarity index 100% rename from app/assets/stylesheets/components/_integer_picker.scss rename to scripts/app/assets/stylesheets/components/_integer_picker.scss diff --git a/app/assets/stylesheets/components/_lp-style-button.scss b/scripts/app/assets/stylesheets/components/_lp-style-button.scss similarity index 100% rename from app/assets/stylesheets/components/_lp-style-button.scss rename to scripts/app/assets/stylesheets/components/_lp-style-button.scss diff --git a/app/assets/stylesheets/components/_mastery-table.scss b/scripts/app/assets/stylesheets/components/_mastery-table.scss similarity index 100% rename from app/assets/stylesheets/components/_mastery-table.scss rename to scripts/app/assets/stylesheets/components/_mastery-table.scss diff --git a/app/assets/stylesheets/components/_modal.scss b/scripts/app/assets/stylesheets/components/_modal.scss similarity index 100% rename from app/assets/stylesheets/components/_modal.scss rename to scripts/app/assets/stylesheets/components/_modal.scss diff --git a/app/assets/stylesheets/components/_navigation-dropdown.scss b/scripts/app/assets/stylesheets/components/_navigation-dropdown.scss similarity index 100% rename from app/assets/stylesheets/components/_navigation-dropdown.scss rename to scripts/app/assets/stylesheets/components/_navigation-dropdown.scss diff --git a/app/assets/stylesheets/components/_notifications.scss b/scripts/app/assets/stylesheets/components/_notifications.scss similarity index 100% rename from app/assets/stylesheets/components/_notifications.scss rename to scripts/app/assets/stylesheets/components/_notifications.scss diff --git a/app/assets/stylesheets/components/_pagination.scss b/scripts/app/assets/stylesheets/components/_pagination.scss similarity index 100% rename from app/assets/stylesheets/components/_pagination.scss rename to scripts/app/assets/stylesheets/components/_pagination.scss diff --git a/app/assets/stylesheets/components/_pill.scss b/scripts/app/assets/stylesheets/components/_pill.scss similarity index 100% rename from app/assets/stylesheets/components/_pill.scss rename to scripts/app/assets/stylesheets/components/_pill.scss diff --git a/app/assets/stylesheets/components/_point_grade_buttons.scss b/scripts/app/assets/stylesheets/components/_point_grade_buttons.scss similarity index 100% rename from app/assets/stylesheets/components/_point_grade_buttons.scss rename to scripts/app/assets/stylesheets/components/_point_grade_buttons.scss diff --git a/app/assets/stylesheets/components/_primary-header.scss b/scripts/app/assets/stylesheets/components/_primary-header.scss similarity index 100% rename from app/assets/stylesheets/components/_primary-header.scss rename to scripts/app/assets/stylesheets/components/_primary-header.scss diff --git a/app/assets/stylesheets/components/_primary-navigation.scss b/scripts/app/assets/stylesheets/components/_primary-navigation.scss similarity index 100% rename from app/assets/stylesheets/components/_primary-navigation.scss rename to scripts/app/assets/stylesheets/components/_primary-navigation.scss diff --git a/app/assets/stylesheets/components/_progress.scss b/scripts/app/assets/stylesheets/components/_progress.scss similarity index 100% rename from app/assets/stylesheets/components/_progress.scss rename to scripts/app/assets/stylesheets/components/_progress.scss diff --git a/app/assets/stylesheets/components/_progress_thresholds_key.scss b/scripts/app/assets/stylesheets/components/_progress_thresholds_key.scss similarity index 100% rename from app/assets/stylesheets/components/_progress_thresholds_key.scss rename to scripts/app/assets/stylesheets/components/_progress_thresholds_key.scss diff --git a/app/assets/stylesheets/components/_progress_thresholds_modal.scss b/scripts/app/assets/stylesheets/components/_progress_thresholds_modal.scss similarity index 100% rename from app/assets/stylesheets/components/_progress_thresholds_modal.scss rename to scripts/app/assets/stylesheets/components/_progress_thresholds_modal.scss diff --git a/app/assets/stylesheets/components/_progress_thresholds_slider.scss b/scripts/app/assets/stylesheets/components/_progress_thresholds_slider.scss similarity index 100% rename from app/assets/stylesheets/components/_progress_thresholds_slider.scss rename to scripts/app/assets/stylesheets/components/_progress_thresholds_slider.scss diff --git a/app/assets/stylesheets/components/_search-bar.scss b/scripts/app/assets/stylesheets/components/_search-bar.scss similarity index 100% rename from app/assets/stylesheets/components/_search-bar.scss rename to scripts/app/assets/stylesheets/components/_search-bar.scss diff --git a/app/assets/stylesheets/components/_secondary-navigation.scss b/scripts/app/assets/stylesheets/components/_secondary-navigation.scss similarity index 100% rename from app/assets/stylesheets/components/_secondary-navigation.scss rename to scripts/app/assets/stylesheets/components/_secondary-navigation.scss diff --git a/app/assets/stylesheets/components/_slideshow.scss b/scripts/app/assets/stylesheets/components/_slideshow.scss similarity index 100% rename from app/assets/stylesheets/components/_slideshow.scss rename to scripts/app/assets/stylesheets/components/_slideshow.scss diff --git a/app/assets/stylesheets/components/_sort-dropdown-component.scss b/scripts/app/assets/stylesheets/components/_sort-dropdown-component.scss similarity index 100% rename from app/assets/stylesheets/components/_sort-dropdown-component.scss rename to scripts/app/assets/stylesheets/components/_sort-dropdown-component.scss diff --git a/app/assets/stylesheets/components/_standard-card.scss b/scripts/app/assets/stylesheets/components/_standard-card.scss similarity index 100% rename from app/assets/stylesheets/components/_standard-card.scss rename to scripts/app/assets/stylesheets/components/_standard-card.scss diff --git a/app/assets/stylesheets/components/_standard-cards.scss b/scripts/app/assets/stylesheets/components/_standard-cards.scss similarity index 100% rename from app/assets/stylesheets/components/_standard-cards.scss rename to scripts/app/assets/stylesheets/components/_standard-cards.scss diff --git a/app/assets/stylesheets/components/_standards-mastery-beans.scss b/scripts/app/assets/stylesheets/components/_standards-mastery-beans.scss similarity index 100% rename from app/assets/stylesheets/components/_standards-mastery-beans.scss rename to scripts/app/assets/stylesheets/components/_standards-mastery-beans.scss diff --git a/app/assets/stylesheets/components/_status_picker.scss b/scripts/app/assets/stylesheets/components/_status_picker.scss similarity index 100% rename from app/assets/stylesheets/components/_status_picker.scss rename to scripts/app/assets/stylesheets/components/_status_picker.scss diff --git a/app/assets/stylesheets/components/_student-mastery-table.scss b/scripts/app/assets/stylesheets/components/_student-mastery-table.scss similarity index 100% rename from app/assets/stylesheets/components/_student-mastery-table.scss rename to scripts/app/assets/stylesheets/components/_student-mastery-table.scss diff --git a/app/assets/stylesheets/components/_student-name-bar.scss b/scripts/app/assets/stylesheets/components/_student-name-bar.scss similarity index 100% rename from app/assets/stylesheets/components/_student-name-bar.scss rename to scripts/app/assets/stylesheets/components/_student-name-bar.scss diff --git a/app/assets/stylesheets/components/_submissions-dashboard-table.scss b/scripts/app/assets/stylesheets/components/_submissions-dashboard-table.scss similarity index 100% rename from app/assets/stylesheets/components/_submissions-dashboard-table.scss rename to scripts/app/assets/stylesheets/components/_submissions-dashboard-table.scss diff --git a/app/assets/stylesheets/components/_svg-icon.scss b/scripts/app/assets/stylesheets/components/_svg-icon.scss similarity index 100% rename from app/assets/stylesheets/components/_svg-icon.scss rename to scripts/app/assets/stylesheets/components/_svg-icon.scss diff --git a/app/assets/stylesheets/components/_thresholds.scss b/scripts/app/assets/stylesheets/components/_thresholds.scss similarity index 100% rename from app/assets/stylesheets/components/_thresholds.scss rename to scripts/app/assets/stylesheets/components/_thresholds.scss diff --git a/app/assets/stylesheets/components/_universal-list.scss b/scripts/app/assets/stylesheets/components/_universal-list.scss similarity index 100% rename from app/assets/stylesheets/components/_universal-list.scss rename to scripts/app/assets/stylesheets/components/_universal-list.scss diff --git a/app/assets/stylesheets/components/_universal-row.scss b/scripts/app/assets/stylesheets/components/_universal-row.scss similarity index 100% rename from app/assets/stylesheets/components/_universal-row.scss rename to scripts/app/assets/stylesheets/components/_universal-row.scss diff --git a/app/assets/stylesheets/components/_universal-table.scss b/scripts/app/assets/stylesheets/components/_universal-table.scss similarity index 100% rename from app/assets/stylesheets/components/_universal-table.scss rename to scripts/app/assets/stylesheets/components/_universal-table.scss diff --git a/app/assets/stylesheets/components/_user-avatar.scss b/scripts/app/assets/stylesheets/components/_user-avatar.scss similarity index 100% rename from app/assets/stylesheets/components/_user-avatar.scss rename to scripts/app/assets/stylesheets/components/_user-avatar.scss diff --git a/app/assets/stylesheets/components/_video-player.scss b/scripts/app/assets/stylesheets/components/_video-player.scss similarity index 100% rename from app/assets/stylesheets/components/_video-player.scss rename to scripts/app/assets/stylesheets/components/_video-player.scss diff --git a/app/assets/stylesheets/components/badge.scss b/scripts/app/assets/stylesheets/components/badge.scss similarity index 100% rename from app/assets/stylesheets/components/badge.scss rename to scripts/app/assets/stylesheets/components/badge.scss diff --git a/app/assets/stylesheets/components/challenge-detail-comments.scss b/scripts/app/assets/stylesheets/components/challenge-detail-comments.scss similarity index 100% rename from app/assets/stylesheets/components/challenge-detail-comments.scss rename to scripts/app/assets/stylesheets/components/challenge-detail-comments.scss diff --git a/app/assets/stylesheets/components/challenge-detail-view.scss b/scripts/app/assets/stylesheets/components/challenge-detail-view.scss similarity index 100% rename from app/assets/stylesheets/components/challenge-detail-view.scss rename to scripts/app/assets/stylesheets/components/challenge-detail-view.scss diff --git a/app/assets/stylesheets/components/challenge-timeline.scss b/scripts/app/assets/stylesheets/components/challenge-timeline.scss similarity index 100% rename from app/assets/stylesheets/components/challenge-timeline.scss rename to scripts/app/assets/stylesheets/components/challenge-timeline.scss diff --git a/app/assets/stylesheets/components/new-comment-form.scss b/scripts/app/assets/stylesheets/components/new-comment-form.scss similarity index 100% rename from app/assets/stylesheets/components/new-comment-form.scss rename to scripts/app/assets/stylesheets/components/new-comment-form.scss diff --git a/app/assets/stylesheets/components/partnerup.scss b/scripts/app/assets/stylesheets/components/partnerup.scss similarity index 100% rename from app/assets/stylesheets/components/partnerup.scss rename to scripts/app/assets/stylesheets/components/partnerup.scss diff --git a/app/assets/stylesheets/components/progress-table.scss b/scripts/app/assets/stylesheets/components/progress-table.scss similarity index 100% rename from app/assets/stylesheets/components/progress-table.scss rename to scripts/app/assets/stylesheets/components/progress-table.scss diff --git a/app/assets/stylesheets/hopscotch-overrides.scss b/scripts/app/assets/stylesheets/hopscotch-overrides.scss similarity index 100% rename from app/assets/stylesheets/hopscotch-overrides.scss rename to scripts/app/assets/stylesheets/hopscotch-overrides.scss diff --git a/app/assets/stylesheets/mixins.scss b/scripts/app/assets/stylesheets/mixins.scss similarity index 100% rename from app/assets/stylesheets/mixins.scss rename to scripts/app/assets/stylesheets/mixins.scss diff --git a/app/assets/stylesheets/mobile.scss b/scripts/app/assets/stylesheets/mobile.scss similarity index 100% rename from app/assets/stylesheets/mobile.scss rename to scripts/app/assets/stylesheets/mobile.scss diff --git a/app/assets/stylesheets/mobile/_submissions-dashboard-table.scss b/scripts/app/assets/stylesheets/mobile/_submissions-dashboard-table.scss similarity index 100% rename from app/assets/stylesheets/mobile/_submissions-dashboard-table.scss rename to scripts/app/assets/stylesheets/mobile/_submissions-dashboard-table.scss diff --git a/app/assets/stylesheets/typography.scss b/scripts/app/assets/stylesheets/typography.scss similarity index 100% rename from app/assets/stylesheets/typography.scss rename to scripts/app/assets/stylesheets/typography.scss diff --git a/app/assets/stylesheets/variables.scss b/scripts/app/assets/stylesheets/variables.scss similarity index 100% rename from app/assets/stylesheets/variables.scss rename to scripts/app/assets/stylesheets/variables.scss diff --git a/app/component_props/activity_feed_item_component_props.rb b/scripts/app/component_props/activity_feed_item_component_props.rb similarity index 100% rename from app/component_props/activity_feed_item_component_props.rb rename to scripts/app/component_props/activity_feed_item_component_props.rb diff --git a/app/component_props/notifications_component_props.rb b/scripts/app/component_props/notifications_component_props.rb similarity index 100% rename from app/component_props/notifications_component_props.rb rename to scripts/app/component_props/notifications_component_props.rb diff --git a/app/component_props/standard_card_component_props.rb b/scripts/app/component_props/standard_card_component_props.rb similarity index 100% rename from app/component_props/standard_card_component_props.rb rename to scripts/app/component_props/standard_card_component_props.rb diff --git a/app/controllers/api/application_controller.rb b/scripts/app/controllers/api/application_controller.rb similarity index 100% rename from app/controllers/api/application_controller.rb rename to scripts/app/controllers/api/application_controller.rb diff --git a/app/controllers/api/v1/blocks/releases_controller.rb b/scripts/app/controllers/api/v1/blocks/releases_controller.rb similarity index 100% rename from app/controllers/api/v1/blocks/releases_controller.rb rename to scripts/app/controllers/api/v1/blocks/releases_controller.rb diff --git a/app/controllers/api/v1/blocks_controller.rb b/scripts/app/controllers/api/v1/blocks_controller.rb similarity index 100% rename from app/controllers/api/v1/blocks_controller.rb rename to scripts/app/controllers/api/v1/blocks_controller.rb diff --git a/app/controllers/api/v1/cohorts/blocks/content_files_controller.rb b/scripts/app/controllers/api/v1/cohorts/blocks/content_files_controller.rb similarity index 100% rename from app/controllers/api/v1/cohorts/blocks/content_files_controller.rb rename to scripts/app/controllers/api/v1/cohorts/blocks/content_files_controller.rb diff --git a/app/controllers/api/v1/cohorts/blocks/units_controller.rb b/scripts/app/controllers/api/v1/cohorts/blocks/units_controller.rb similarity index 100% rename from app/controllers/api/v1/cohorts/blocks/units_controller.rb rename to scripts/app/controllers/api/v1/cohorts/blocks/units_controller.rb diff --git a/app/controllers/api/v1/cohorts/cohorts_controller.rb b/scripts/app/controllers/api/v1/cohorts/cohorts_controller.rb similarity index 100% rename from app/controllers/api/v1/cohorts/cohorts_controller.rb rename to scripts/app/controllers/api/v1/cohorts/cohorts_controller.rb diff --git a/app/controllers/api/v1/cohorts/users_controller.rb b/scripts/app/controllers/api/v1/cohorts/users_controller.rb similarity index 100% rename from app/controllers/api/v1/cohorts/users_controller.rb rename to scripts/app/controllers/api/v1/cohorts/users_controller.rb diff --git a/app/controllers/api/v1/content_files_controller.rb b/scripts/app/controllers/api/v1/content_files_controller.rb similarity index 100% rename from app/controllers/api/v1/content_files_controller.rb rename to scripts/app/controllers/api/v1/content_files_controller.rb diff --git a/app/controllers/api/v1/pineapple_controller.rb b/scripts/app/controllers/api/v1/pineapple_controller.rb similarity index 100% rename from app/controllers/api/v1/pineapple_controller.rb rename to scripts/app/controllers/api/v1/pineapple_controller.rb diff --git a/app/controllers/api/v1/releases_controller.rb b/scripts/app/controllers/api/v1/releases_controller.rb similarity index 100% rename from app/controllers/api/v1/releases_controller.rb rename to scripts/app/controllers/api/v1/releases_controller.rb diff --git a/app/controllers/api/v1/users_controller.rb b/scripts/app/controllers/api/v1/users_controller.rb similarity index 100% rename from app/controllers/api/v1/users_controller.rb rename to scripts/app/controllers/api/v1/users_controller.rb diff --git a/app/controllers/application_controller.rb b/scripts/app/controllers/application_controller.rb similarity index 100% rename from app/controllers/application_controller.rb rename to scripts/app/controllers/application_controller.rb diff --git a/app/controllers/blocks/releases_controller.rb b/scripts/app/controllers/blocks/releases_controller.rb similarity index 100% rename from app/controllers/blocks/releases_controller.rb rename to scripts/app/controllers/blocks/releases_controller.rb diff --git a/app/controllers/blocks_controller.rb b/scripts/app/controllers/blocks_controller.rb similarity index 100% rename from app/controllers/blocks_controller.rb rename to scripts/app/controllers/blocks_controller.rb diff --git a/app/controllers/cohorts/blocks/content_files_controller.rb b/scripts/app/controllers/cohorts/blocks/content_files_controller.rb similarity index 100% rename from app/controllers/cohorts/blocks/content_files_controller.rb rename to scripts/app/controllers/cohorts/blocks/content_files_controller.rb diff --git a/app/controllers/cohorts/checkpoint_submissions/activities_controller.rb b/scripts/app/controllers/cohorts/checkpoint_submissions/activities_controller.rb similarity index 100% rename from app/controllers/cohorts/checkpoint_submissions/activities_controller.rb rename to scripts/app/controllers/cohorts/checkpoint_submissions/activities_controller.rb diff --git a/app/controllers/cohorts/cohort_releases_controller.rb b/scripts/app/controllers/cohorts/cohort_releases_controller.rb similarity index 100% rename from app/controllers/cohorts/cohort_releases_controller.rb rename to scripts/app/controllers/cohorts/cohort_releases_controller.rb diff --git a/app/controllers/cohorts/content_files/checkpoint_submissions_controller.rb b/scripts/app/controllers/cohorts/content_files/checkpoint_submissions_controller.rb similarity index 100% rename from app/controllers/cohorts/content_files/checkpoint_submissions_controller.rb rename to scripts/app/controllers/cohorts/content_files/checkpoint_submissions_controller.rb diff --git a/app/controllers/cohorts/content_files/submitted_challenge_answers_controller.rb b/scripts/app/controllers/cohorts/content_files/submitted_challenge_answers_controller.rb similarity index 100% rename from app/controllers/cohorts/content_files/submitted_challenge_answers_controller.rb rename to scripts/app/controllers/cohorts/content_files/submitted_challenge_answers_controller.rb diff --git a/app/controllers/cohorts/content_files_controller.rb b/scripts/app/controllers/cohorts/content_files_controller.rb similarity index 100% rename from app/controllers/cohorts/content_files_controller.rb rename to scripts/app/controllers/cohorts/content_files_controller.rb diff --git a/app/controllers/cohorts/pairings_controller.rb b/scripts/app/controllers/cohorts/pairings_controller.rb similarity index 100% rename from app/controllers/cohorts/pairings_controller.rb rename to scripts/app/controllers/cohorts/pairings_controller.rb diff --git a/app/controllers/cohorts/standards_controller.rb b/scripts/app/controllers/cohorts/standards_controller.rb similarity index 100% rename from app/controllers/cohorts/standards_controller.rb rename to scripts/app/controllers/cohorts/standards_controller.rb diff --git a/app/controllers/cohorts/submitted_challenge_answers/activities_controller.rb b/scripts/app/controllers/cohorts/submitted_challenge_answers/activities_controller.rb similarity index 100% rename from app/controllers/cohorts/submitted_challenge_answers/activities_controller.rb rename to scripts/app/controllers/cohorts/submitted_challenge_answers/activities_controller.rb diff --git a/app/controllers/cohorts/users/challenges_controller.rb b/scripts/app/controllers/cohorts/users/challenges_controller.rb similarity index 100% rename from app/controllers/cohorts/users/challenges_controller.rb rename to scripts/app/controllers/cohorts/users/challenges_controller.rb diff --git a/app/controllers/cohorts/users/performances_controller.rb b/scripts/app/controllers/cohorts/users/performances_controller.rb similarity index 100% rename from app/controllers/cohorts/users/performances_controller.rb rename to scripts/app/controllers/cohorts/users/performances_controller.rb diff --git a/app/controllers/cohorts/users_controller.rb b/scripts/app/controllers/cohorts/users_controller.rb similarity index 100% rename from app/controllers/cohorts/users_controller.rb rename to scripts/app/controllers/cohorts/users_controller.rb diff --git a/app/controllers/cohorts_controller.rb b/scripts/app/controllers/cohorts_controller.rb similarity index 100% rename from app/controllers/cohorts_controller.rb rename to scripts/app/controllers/cohorts_controller.rb diff --git a/app/controllers/concerns/api/content_visibility_crud.rb b/scripts/app/controllers/concerns/api/content_visibility_crud.rb similarity index 100% rename from app/controllers/concerns/api/content_visibility_crud.rb rename to scripts/app/controllers/concerns/api/content_visibility_crud.rb diff --git a/app/controllers/concerns/api/exception_handler.rb b/scripts/app/controllers/concerns/api/exception_handler.rb similarity index 100% rename from app/controllers/concerns/api/exception_handler.rb rename to scripts/app/controllers/concerns/api/exception_handler.rb diff --git a/app/controllers/concerns/api/response.rb b/scripts/app/controllers/concerns/api/response.rb similarity index 100% rename from app/controllers/concerns/api/response.rb rename to scripts/app/controllers/concerns/api/response.rb diff --git a/app/controllers/home_controller.rb b/scripts/app/controllers/home_controller.rb similarity index 100% rename from app/controllers/home_controller.rb rename to scripts/app/controllers/home_controller.rb diff --git a/app/controllers/notifications_controller.rb b/scripts/app/controllers/notifications_controller.rb similarity index 100% rename from app/controllers/notifications_controller.rb rename to scripts/app/controllers/notifications_controller.rb diff --git a/app/controllers/permalinks_controller.rb b/scripts/app/controllers/permalinks_controller.rb similarity index 100% rename from app/controllers/permalinks_controller.rb rename to scripts/app/controllers/permalinks_controller.rb diff --git a/app/controllers/sessions_controller.rb b/scripts/app/controllers/sessions_controller.rb similarity index 100% rename from app/controllers/sessions_controller.rb rename to scripts/app/controllers/sessions_controller.rb diff --git a/app/controllers/users_controller.rb b/scripts/app/controllers/users_controller.rb similarity index 100% rename from app/controllers/users_controller.rb rename to scripts/app/controllers/users_controller.rb diff --git a/app/controllers/webhooks/assessments_service/submitted_challenge_answers_controller.rb b/scripts/app/controllers/webhooks/assessments_service/submitted_challenge_answers_controller.rb similarity index 100% rename from app/controllers/webhooks/assessments_service/submitted_challenge_answers_controller.rb rename to scripts/app/controllers/webhooks/assessments_service/submitted_challenge_answers_controller.rb diff --git a/app/exporters/performance_exporter.rb b/scripts/app/exporters/performance_exporter.rb similarity index 100% rename from app/exporters/performance_exporter.rb rename to scripts/app/exporters/performance_exporter.rb diff --git a/app/exporters/progress_exporter.rb b/scripts/app/exporters/progress_exporter.rb similarity index 100% rename from app/exporters/progress_exporter.rb rename to scripts/app/exporters/progress_exporter.rb diff --git a/app/finders/block_finder.rb b/scripts/app/finders/block_finder.rb similarity index 100% rename from app/finders/block_finder.rb rename to scripts/app/finders/block_finder.rb diff --git a/app/finders/checkpoint_submission_finder.rb b/scripts/app/finders/checkpoint_submission_finder.rb similarity index 100% rename from app/finders/checkpoint_submission_finder.rb rename to scripts/app/finders/checkpoint_submission_finder.rb diff --git a/app/finders/cohort_user_finder.rb b/scripts/app/finders/cohort_user_finder.rb similarity index 100% rename from app/finders/cohort_user_finder.rb rename to scripts/app/finders/cohort_user_finder.rb diff --git a/app/finders/content_file_finder.rb b/scripts/app/finders/content_file_finder.rb similarity index 100% rename from app/finders/content_file_finder.rb rename to scripts/app/finders/content_file_finder.rb diff --git a/app/finders/performance_finder.rb b/scripts/app/finders/performance_finder.rb similarity index 100% rename from app/finders/performance_finder.rb rename to scripts/app/finders/performance_finder.rb diff --git a/app/finders/release_finder.rb b/scripts/app/finders/release_finder.rb similarity index 100% rename from app/finders/release_finder.rb rename to scripts/app/finders/release_finder.rb diff --git a/app/finders/standard_finder.rb b/scripts/app/finders/standard_finder.rb similarity index 100% rename from app/finders/standard_finder.rb rename to scripts/app/finders/standard_finder.rb diff --git a/app/finders/submitted_challenge_answer_finder.rb b/scripts/app/finders/submitted_challenge_answer_finder.rb similarity index 100% rename from app/finders/submitted_challenge_answer_finder.rb rename to scripts/app/finders/submitted_challenge_answer_finder.rb diff --git a/app/finders/user_finder.rb b/scripts/app/finders/user_finder.rb similarity index 100% rename from app/finders/user_finder.rb rename to scripts/app/finders/user_finder.rb diff --git a/app/helpers/application_helper.rb b/scripts/app/helpers/application_helper.rb similarity index 100% rename from app/helpers/application_helper.rb rename to scripts/app/helpers/application_helper.rb diff --git a/app/helpers/json_helper.rb b/scripts/app/helpers/json_helper.rb similarity index 100% rename from app/helpers/json_helper.rb rename to scripts/app/helpers/json_helper.rb diff --git a/app/helpers/secondary_navigation_helper.rb b/scripts/app/helpers/secondary_navigation_helper.rb similarity index 100% rename from app/helpers/secondary_navigation_helper.rb rename to scripts/app/helpers/secondary_navigation_helper.rb diff --git a/app/helpers/standard_navigation_helper.rb b/scripts/app/helpers/standard_navigation_helper.rb similarity index 100% rename from app/helpers/standard_navigation_helper.rb rename to scripts/app/helpers/standard_navigation_helper.rb diff --git a/app/javascript/api.d.ts b/scripts/app/javascript/api.d.ts similarity index 100% rename from app/javascript/api.d.ts rename to scripts/app/javascript/api.d.ts diff --git a/app/javascript/components/AceEditor.tsx b/scripts/app/javascript/components/AceEditor.tsx similarity index 100% rename from app/javascript/components/AceEditor.tsx rename to scripts/app/javascript/components/AceEditor.tsx diff --git a/app/javascript/components/Badge.tsx b/scripts/app/javascript/components/Badge.tsx similarity index 100% rename from app/javascript/components/Badge.tsx rename to scripts/app/javascript/components/Badge.tsx diff --git a/app/javascript/components/Button.tsx b/scripts/app/javascript/components/Button.tsx similarity index 100% rename from app/javascript/components/Button.tsx rename to scripts/app/javascript/components/Button.tsx diff --git a/app/javascript/components/ButtonTo.tsx b/scripts/app/javascript/components/ButtonTo.tsx similarity index 100% rename from app/javascript/components/ButtonTo.tsx rename to scripts/app/javascript/components/ButtonTo.tsx diff --git a/app/javascript/components/Dropdown.tsx b/scripts/app/javascript/components/Dropdown.tsx similarity index 100% rename from app/javascript/components/Dropdown.tsx rename to scripts/app/javascript/components/Dropdown.tsx diff --git a/app/javascript/components/Icon.tsx b/scripts/app/javascript/components/Icon.tsx similarity index 100% rename from app/javascript/components/Icon.tsx rename to scripts/app/javascript/components/Icon.tsx diff --git a/app/javascript/components/Loading.tsx b/scripts/app/javascript/components/Loading.tsx similarity index 100% rename from app/javascript/components/Loading.tsx rename to scripts/app/javascript/components/Loading.tsx diff --git a/app/javascript/components/Marked.tsx b/scripts/app/javascript/components/Marked.tsx similarity index 100% rename from app/javascript/components/Marked.tsx rename to scripts/app/javascript/components/Marked.tsx diff --git a/app/javascript/components/Menu.tsx b/scripts/app/javascript/components/Menu.tsx similarity index 100% rename from app/javascript/components/Menu.tsx rename to scripts/app/javascript/components/Menu.tsx diff --git a/app/javascript/components/Notifications.tsx b/scripts/app/javascript/components/Notifications.tsx similarity index 100% rename from app/javascript/components/Notifications.tsx rename to scripts/app/javascript/components/Notifications.tsx diff --git a/app/javascript/components/ProcessingIcon.tsx b/scripts/app/javascript/components/ProcessingIcon.tsx similarity index 100% rename from app/javascript/components/ProcessingIcon.tsx rename to scripts/app/javascript/components/ProcessingIcon.tsx diff --git a/app/javascript/components/RowKebab.tsx b/scripts/app/javascript/components/RowKebab.tsx similarity index 100% rename from app/javascript/components/RowKebab.tsx rename to scripts/app/javascript/components/RowKebab.tsx diff --git a/app/javascript/components/ScoreCircle.tsx b/scripts/app/javascript/components/ScoreCircle.tsx similarity index 100% rename from app/javascript/components/ScoreCircle.tsx rename to scripts/app/javascript/components/ScoreCircle.tsx diff --git a/app/javascript/components/SidebarProgress.tsx b/scripts/app/javascript/components/SidebarProgress.tsx similarity index 100% rename from app/javascript/components/SidebarProgress.tsx rename to scripts/app/javascript/components/SidebarProgress.tsx diff --git a/app/javascript/components/SortDropdown.tsx b/scripts/app/javascript/components/SortDropdown.tsx similarity index 100% rename from app/javascript/components/SortDropdown.tsx rename to scripts/app/javascript/components/SortDropdown.tsx diff --git a/app/javascript/components/StandardBean.tsx b/scripts/app/javascript/components/StandardBean.tsx similarity index 100% rename from app/javascript/components/StandardBean.tsx rename to scripts/app/javascript/components/StandardBean.tsx diff --git a/app/javascript/components/SvgRenderer.tsx b/scripts/app/javascript/components/SvgRenderer.tsx similarity index 100% rename from app/javascript/components/SvgRenderer.tsx rename to scripts/app/javascript/components/SvgRenderer.tsx diff --git a/app/javascript/components/Timestamp.tsx b/scripts/app/javascript/components/Timestamp.tsx similarity index 100% rename from app/javascript/components/Timestamp.tsx rename to scripts/app/javascript/components/Timestamp.tsx diff --git a/app/javascript/components/UserAvatar.tsx b/scripts/app/javascript/components/UserAvatar.tsx similarity index 100% rename from app/javascript/components/UserAvatar.tsx rename to scripts/app/javascript/components/UserAvatar.tsx diff --git a/app/javascript/components/activities/NewActivityForm.tsx b/scripts/app/javascript/components/activities/NewActivityForm.tsx similarity index 100% rename from app/javascript/components/activities/NewActivityForm.tsx rename to scripts/app/javascript/components/activities/NewActivityForm.tsx diff --git a/app/javascript/components/api/ApiInteractions.tsx b/scripts/app/javascript/components/api/ApiInteractions.tsx similarity index 100% rename from app/javascript/components/api/ApiInteractions.tsx rename to scripts/app/javascript/components/api/ApiInteractions.tsx diff --git a/app/javascript/components/api/ApiToken.tsx b/scripts/app/javascript/components/api/ApiToken.tsx similarity index 100% rename from app/javascript/components/api/ApiToken.tsx rename to scripts/app/javascript/components/api/ApiToken.tsx diff --git a/app/javascript/components/blocks/BlockPage-v2.tsx b/scripts/app/javascript/components/blocks/BlockPage-v2.tsx similarity index 100% rename from app/javascript/components/blocks/BlockPage-v2.tsx rename to scripts/app/javascript/components/blocks/BlockPage-v2.tsx diff --git a/app/javascript/components/blocks/BlocksIndex-v2.tsx b/scripts/app/javascript/components/blocks/BlocksIndex-v2.tsx similarity index 100% rename from app/javascript/components/blocks/BlocksIndex-v2.tsx rename to scripts/app/javascript/components/blocks/BlocksIndex-v2.tsx diff --git a/app/javascript/components/blocks/BlocksNewModal.tsx b/scripts/app/javascript/components/blocks/BlocksNewModal.tsx similarity index 100% rename from app/javascript/components/blocks/BlocksNewModal.tsx rename to scripts/app/javascript/components/blocks/BlocksNewModal.tsx diff --git a/app/javascript/components/blocks/BlocksNewRelease.tsx b/scripts/app/javascript/components/blocks/BlocksNewRelease.tsx similarity index 100% rename from app/javascript/components/blocks/BlocksNewRelease.tsx rename to scripts/app/javascript/components/blocks/BlocksNewRelease.tsx diff --git a/app/javascript/components/blocks/BlocksRow.tsx b/scripts/app/javascript/components/blocks/BlocksRow.tsx similarity index 100% rename from app/javascript/components/blocks/BlocksRow.tsx rename to scripts/app/javascript/components/blocks/BlocksRow.tsx diff --git a/app/javascript/components/blocks/BlocksShow.tsx b/scripts/app/javascript/components/blocks/BlocksShow.tsx similarity index 100% rename from app/javascript/components/blocks/BlocksShow.tsx rename to scripts/app/javascript/components/blocks/BlocksShow.tsx diff --git a/app/javascript/components/blocks/BlocksStats.tsx b/scripts/app/javascript/components/blocks/BlocksStats.tsx similarity index 100% rename from app/javascript/components/blocks/BlocksStats.tsx rename to scripts/app/javascript/components/blocks/BlocksStats.tsx diff --git a/app/javascript/components/blocks/CohortsTooltip.tsx b/scripts/app/javascript/components/blocks/CohortsTooltip.tsx similarity index 100% rename from app/javascript/components/blocks/CohortsTooltip.tsx rename to scripts/app/javascript/components/blocks/CohortsTooltip.tsx diff --git a/app/javascript/components/challenges/AvatarBar.tsx b/scripts/app/javascript/components/challenges/AvatarBar.tsx similarity index 100% rename from app/javascript/components/challenges/AvatarBar.tsx rename to scripts/app/javascript/components/challenges/AvatarBar.tsx diff --git a/app/javascript/components/challenges/ChallengeDetailView.tsx b/scripts/app/javascript/components/challenges/ChallengeDetailView.tsx similarity index 100% rename from app/javascript/components/challenges/ChallengeDetailView.tsx rename to scripts/app/javascript/components/challenges/ChallengeDetailView.tsx diff --git a/app/javascript/components/challenges/ChallengeShow.tsx b/scripts/app/javascript/components/challenges/ChallengeShow.tsx similarity index 100% rename from app/javascript/components/challenges/ChallengeShow.tsx rename to scripts/app/javascript/components/challenges/ChallengeShow.tsx diff --git a/app/javascript/components/challenges/challenge_block/ChallengeActionBlock.tsx b/scripts/app/javascript/components/challenges/challenge_block/ChallengeActionBlock.tsx similarity index 100% rename from app/javascript/components/challenges/challenge_block/ChallengeActionBlock.tsx rename to scripts/app/javascript/components/challenges/challenge_block/ChallengeActionBlock.tsx diff --git a/app/javascript/components/challenges/challenge_block/ChallengeBlock.tsx b/scripts/app/javascript/components/challenges/challenge_block/ChallengeBlock.tsx similarity index 100% rename from app/javascript/components/challenges/challenge_block/ChallengeBlock.tsx rename to scripts/app/javascript/components/challenges/challenge_block/ChallengeBlock.tsx diff --git a/app/javascript/components/challenges/challenge_block/ChallengeDetailActivities.tsx b/scripts/app/javascript/components/challenges/challenge_block/ChallengeDetailActivities.tsx similarity index 100% rename from app/javascript/components/challenges/challenge_block/ChallengeDetailActivities.tsx rename to scripts/app/javascript/components/challenges/challenge_block/ChallengeDetailActivities.tsx diff --git a/app/javascript/components/challenges/challenge_block/ChallengeExplanationBlock.tsx b/scripts/app/javascript/components/challenges/challenge_block/ChallengeExplanationBlock.tsx similarity index 100% rename from app/javascript/components/challenges/challenge_block/ChallengeExplanationBlock.tsx rename to scripts/app/javascript/components/challenges/challenge_block/ChallengeExplanationBlock.tsx diff --git a/app/javascript/components/challenges/challenge_block/ChallengeFeedbackBlock.tsx b/scripts/app/javascript/components/challenges/challenge_block/ChallengeFeedbackBlock.tsx similarity index 100% rename from app/javascript/components/challenges/challenge_block/ChallengeFeedbackBlock.tsx rename to scripts/app/javascript/components/challenges/challenge_block/ChallengeFeedbackBlock.tsx diff --git a/app/javascript/components/challenges/challenge_block/ChallengeHintsBlock.tsx b/scripts/app/javascript/components/challenges/challenge_block/ChallengeHintsBlock.tsx similarity index 100% rename from app/javascript/components/challenges/challenge_block/ChallengeHintsBlock.tsx rename to scripts/app/javascript/components/challenges/challenge_block/ChallengeHintsBlock.tsx diff --git a/app/javascript/components/challenges/challenge_block/ChallengeInputs.tsx b/scripts/app/javascript/components/challenges/challenge_block/ChallengeInputs.tsx similarity index 100% rename from app/javascript/components/challenges/challenge_block/ChallengeInputs.tsx rename to scripts/app/javascript/components/challenges/challenge_block/ChallengeInputs.tsx diff --git a/app/javascript/components/challenges/challenge_block/ChallengeLocalTestResults.tsx b/scripts/app/javascript/components/challenges/challenge_block/ChallengeLocalTestResults.tsx similarity index 100% rename from app/javascript/components/challenges/challenge_block/ChallengeLocalTestResults.tsx rename to scripts/app/javascript/components/challenges/challenge_block/ChallengeLocalTestResults.tsx diff --git a/app/javascript/components/challenges/challenge_block/ChallengeRubricBlock.tsx b/scripts/app/javascript/components/challenges/challenge_block/ChallengeRubricBlock.tsx similarity index 100% rename from app/javascript/components/challenges/challenge_block/ChallengeRubricBlock.tsx rename to scripts/app/javascript/components/challenges/challenge_block/ChallengeRubricBlock.tsx diff --git a/app/javascript/components/challenges/challenge_block/ChallengeStatus.tsx b/scripts/app/javascript/components/challenges/challenge_block/ChallengeStatus.tsx similarity index 100% rename from app/javascript/components/challenges/challenge_block/ChallengeStatus.tsx rename to scripts/app/javascript/components/challenges/challenge_block/ChallengeStatus.tsx diff --git a/app/javascript/components/challenges/challenge_block/ChallengeStatusBar.tsx b/scripts/app/javascript/components/challenges/challenge_block/ChallengeStatusBar.tsx similarity index 100% rename from app/javascript/components/challenges/challenge_block/ChallengeStatusBar.tsx rename to scripts/app/javascript/components/challenges/challenge_block/ChallengeStatusBar.tsx diff --git a/app/javascript/components/challenges/challenge_block/ChallengeTestResults.tsx b/scripts/app/javascript/components/challenges/challenge_block/ChallengeTestResults.tsx similarity index 100% rename from app/javascript/components/challenges/challenge_block/ChallengeTestResults.tsx rename to scripts/app/javascript/components/challenges/challenge_block/ChallengeTestResults.tsx diff --git a/app/javascript/components/challenges/challenge_block/ChallengeTests.tsx b/scripts/app/javascript/components/challenges/challenge_block/ChallengeTests.tsx similarity index 100% rename from app/javascript/components/challenges/challenge_block/ChallengeTests.tsx rename to scripts/app/javascript/components/challenges/challenge_block/ChallengeTests.tsx diff --git a/app/javascript/components/challenges/challenge_block/ChallengeTimeLine.tsx b/scripts/app/javascript/components/challenges/challenge_block/ChallengeTimeLine.tsx similarity index 100% rename from app/javascript/components/challenges/challenge_block/ChallengeTimeLine.tsx rename to scripts/app/javascript/components/challenges/challenge_block/ChallengeTimeLine.tsx diff --git a/app/javascript/components/challenges/challenge_block/GradeIndicator.tsx b/scripts/app/javascript/components/challenges/challenge_block/GradeIndicator.tsx similarity index 100% rename from app/javascript/components/challenges/challenge_block/GradeIndicator.tsx rename to scripts/app/javascript/components/challenges/challenge_block/GradeIndicator.tsx diff --git a/app/javascript/components/challenges/challenge_block/GradedTimestamp.tsx b/scripts/app/javascript/components/challenges/challenge_block/GradedTimestamp.tsx similarity index 100% rename from app/javascript/components/challenges/challenge_block/GradedTimestamp.tsx rename to scripts/app/javascript/components/challenges/challenge_block/GradedTimestamp.tsx diff --git a/app/javascript/components/challenges/challenge_block/StatusPicker.tsx b/scripts/app/javascript/components/challenges/challenge_block/StatusPicker.tsx similarity index 100% rename from app/javascript/components/challenges/challenge_block/StatusPicker.tsx rename to scripts/app/javascript/components/challenges/challenge_block/StatusPicker.tsx diff --git a/app/javascript/components/challenges/local/run-local-challenge.ts b/scripts/app/javascript/components/challenges/local/run-local-challenge.ts similarity index 100% rename from app/javascript/components/challenges/local/run-local-challenge.ts rename to scripts/app/javascript/components/challenges/local/run-local-challenge.ts diff --git a/app/javascript/components/challenges/local/sandbox.ts b/scripts/app/javascript/components/challenges/local/sandbox.ts similarity index 100% rename from app/javascript/components/challenges/local/sandbox.ts rename to scripts/app/javascript/components/challenges/local/sandbox.ts diff --git a/app/javascript/components/challenges/local/stack-traces.ts b/scripts/app/javascript/components/challenges/local/stack-traces.ts similarity index 100% rename from app/javascript/components/challenges/local/stack-traces.ts rename to scripts/app/javascript/components/challenges/local/stack-traces.ts diff --git a/app/javascript/components/checkpoints/CheckpointAfterSubmitButton.tsx b/scripts/app/javascript/components/checkpoints/CheckpointAfterSubmitButton.tsx similarity index 100% rename from app/javascript/components/checkpoints/CheckpointAfterSubmitButton.tsx rename to scripts/app/javascript/components/checkpoints/CheckpointAfterSubmitButton.tsx diff --git a/app/javascript/components/checkpoints/CheckpointAfterSubmitModal.tsx b/scripts/app/javascript/components/checkpoints/CheckpointAfterSubmitModal.tsx similarity index 100% rename from app/javascript/components/checkpoints/CheckpointAfterSubmitModal.tsx rename to scripts/app/javascript/components/checkpoints/CheckpointAfterSubmitModal.tsx diff --git a/app/javascript/components/checkpoints/CheckpointAfterSubmitModalError.tsx b/scripts/app/javascript/components/checkpoints/CheckpointAfterSubmitModalError.tsx similarity index 100% rename from app/javascript/components/checkpoints/CheckpointAfterSubmitModalError.tsx rename to scripts/app/javascript/components/checkpoints/CheckpointAfterSubmitModalError.tsx diff --git a/app/javascript/components/checkpoints/CheckpointSubmissionChallenges.tsx b/scripts/app/javascript/components/checkpoints/CheckpointSubmissionChallenges.tsx similarity index 100% rename from app/javascript/components/checkpoints/CheckpointSubmissionChallenges.tsx rename to scripts/app/javascript/components/checkpoints/CheckpointSubmissionChallenges.tsx diff --git a/app/javascript/components/checkpoints/CheckpointSubmissionShow.tsx b/scripts/app/javascript/components/checkpoints/CheckpointSubmissionShow.tsx similarity index 100% rename from app/javascript/components/checkpoints/CheckpointSubmissionShow.tsx rename to scripts/app/javascript/components/checkpoints/CheckpointSubmissionShow.tsx diff --git a/app/javascript/components/checkpoints/CheckpointSubmissionState.tsx b/scripts/app/javascript/components/checkpoints/CheckpointSubmissionState.tsx similarity index 100% rename from app/javascript/components/checkpoints/CheckpointSubmissionState.tsx rename to scripts/app/javascript/components/checkpoints/CheckpointSubmissionState.tsx diff --git a/app/javascript/components/checkpoints/CheckpointSubmissionStudentNameBar.tsx b/scripts/app/javascript/components/checkpoints/CheckpointSubmissionStudentNameBar.tsx similarity index 100% rename from app/javascript/components/checkpoints/CheckpointSubmissionStudentNameBar.tsx rename to scripts/app/javascript/components/checkpoints/CheckpointSubmissionStudentNameBar.tsx diff --git a/app/javascript/components/cohorts/CohortsIndex.tsx b/scripts/app/javascript/components/cohorts/CohortsIndex.tsx similarity index 100% rename from app/javascript/components/cohorts/CohortsIndex.tsx rename to scripts/app/javascript/components/cohorts/CohortsIndex.tsx diff --git a/app/javascript/components/cohorts/UsersNew.tsx b/scripts/app/javascript/components/cohorts/UsersNew.tsx similarity index 100% rename from app/javascript/components/cohorts/UsersNew.tsx rename to scripts/app/javascript/components/cohorts/UsersNew.tsx diff --git a/app/javascript/components/cohorts/activity_dashboard/ActivityDashboard.tsx b/scripts/app/javascript/components/cohorts/activity_dashboard/ActivityDashboard.tsx similarity index 100% rename from app/javascript/components/cohorts/activity_dashboard/ActivityDashboard.tsx rename to scripts/app/javascript/components/cohorts/activity_dashboard/ActivityDashboard.tsx diff --git a/app/javascript/components/cohorts/activity_feed/ActivityFeed.tsx b/scripts/app/javascript/components/cohorts/activity_feed/ActivityFeed.tsx similarity index 100% rename from app/javascript/components/cohorts/activity_feed/ActivityFeed.tsx rename to scripts/app/javascript/components/cohorts/activity_feed/ActivityFeed.tsx diff --git a/app/javascript/components/cohorts/cohort_releases/ReleaseVersionsTable.tsx b/scripts/app/javascript/components/cohorts/cohort_releases/ReleaseVersionsTable.tsx similarity index 100% rename from app/javascript/components/cohorts/cohort_releases/ReleaseVersionsTable.tsx rename to scripts/app/javascript/components/cohorts/cohort_releases/ReleaseVersionsTable.tsx diff --git a/app/javascript/components/cohorts/cohort_submissions/CohortSubmissions.tsx b/scripts/app/javascript/components/cohorts/cohort_submissions/CohortSubmissions.tsx similarity index 100% rename from app/javascript/components/cohorts/cohort_submissions/CohortSubmissions.tsx rename to scripts/app/javascript/components/cohorts/cohort_submissions/CohortSubmissions.tsx diff --git a/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsChallengeItem.tsx b/scripts/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsChallengeItem.tsx similarity index 100% rename from app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsChallengeItem.tsx rename to scripts/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsChallengeItem.tsx diff --git a/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsLessonRow.tsx b/scripts/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsLessonRow.tsx similarity index 100% rename from app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsLessonRow.tsx rename to scripts/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsLessonRow.tsx diff --git a/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsPerformanceModal.tsx b/scripts/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsPerformanceModal.tsx similarity index 100% rename from app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsPerformanceModal.tsx rename to scripts/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsPerformanceModal.tsx diff --git a/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsStandardRow.tsx b/scripts/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsStandardRow.tsx similarity index 100% rename from app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsStandardRow.tsx rename to scripts/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsStandardRow.tsx diff --git a/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsStudentColumn.tsx b/scripts/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsStudentColumn.tsx similarity index 100% rename from app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsStudentColumn.tsx rename to scripts/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsStudentColumn.tsx diff --git a/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsStudentNameBar.tsx b/scripts/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsStudentNameBar.tsx similarity index 100% rename from app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsStudentNameBar.tsx rename to scripts/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsStudentNameBar.tsx diff --git a/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsStudentStandard.tsx b/scripts/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsStudentStandard.tsx similarity index 100% rename from app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsStudentStandard.tsx rename to scripts/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsStudentStandard.tsx diff --git a/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsTable.tsx b/scripts/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsTable.tsx similarity index 100% rename from app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsTable.tsx rename to scripts/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsTable.tsx diff --git a/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsUnitPercent.tsx b/scripts/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsUnitPercent.tsx similarity index 100% rename from app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsUnitPercent.tsx rename to scripts/app/javascript/components/cohorts/cohort_submissions/CohortSubmissionsUnitPercent.tsx diff --git a/app/javascript/components/cohorts/mastery/MasteryTable.tsx b/scripts/app/javascript/components/cohorts/mastery/MasteryTable.tsx similarity index 100% rename from app/javascript/components/cohorts/mastery/MasteryTable.tsx rename to scripts/app/javascript/components/cohorts/mastery/MasteryTable.tsx diff --git a/app/javascript/components/cohorts/mastery/MetricRow.tsx b/scripts/app/javascript/components/cohorts/mastery/MetricRow.tsx similarity index 100% rename from app/javascript/components/cohorts/mastery/MetricRow.tsx rename to scripts/app/javascript/components/cohorts/mastery/MetricRow.tsx diff --git a/app/javascript/components/cohorts/mastery/MetricsBody.tsx b/scripts/app/javascript/components/cohorts/mastery/MetricsBody.tsx similarity index 100% rename from app/javascript/components/cohorts/mastery/MetricsBody.tsx rename to scripts/app/javascript/components/cohorts/mastery/MetricsBody.tsx diff --git a/app/javascript/components/cohorts/mastery/PerformanceCell.tsx b/scripts/app/javascript/components/cohorts/mastery/PerformanceCell.tsx similarity index 100% rename from app/javascript/components/cohorts/mastery/PerformanceCell.tsx rename to scripts/app/javascript/components/cohorts/mastery/PerformanceCell.tsx diff --git a/app/javascript/components/cohorts/mastery/PerformanceRow.tsx b/scripts/app/javascript/components/cohorts/mastery/PerformanceRow.tsx similarity index 100% rename from app/javascript/components/cohorts/mastery/PerformanceRow.tsx rename to scripts/app/javascript/components/cohorts/mastery/PerformanceRow.tsx diff --git a/app/javascript/components/cohorts/mastery/ReleaseBody.tsx b/scripts/app/javascript/components/cohorts/mastery/ReleaseBody.tsx similarity index 100% rename from app/javascript/components/cohorts/mastery/ReleaseBody.tsx rename to scripts/app/javascript/components/cohorts/mastery/ReleaseBody.tsx diff --git a/app/javascript/components/cohorts/mastery/StandardRow.tsx b/scripts/app/javascript/components/cohorts/mastery/StandardRow.tsx similarity index 100% rename from app/javascript/components/cohorts/mastery/StandardRow.tsx rename to scripts/app/javascript/components/cohorts/mastery/StandardRow.tsx diff --git a/app/javascript/components/cohorts/mastery/StudentHeader.tsx b/scripts/app/javascript/components/cohorts/mastery/StudentHeader.tsx similarity index 100% rename from app/javascript/components/cohorts/mastery/StudentHeader.tsx rename to scripts/app/javascript/components/cohorts/mastery/StudentHeader.tsx diff --git a/app/javascript/components/cohorts/mastery/StudentMasteryTable.tsx b/scripts/app/javascript/components/cohorts/mastery/StudentMasteryTable.tsx similarity index 100% rename from app/javascript/components/cohorts/mastery/StudentMasteryTable.tsx rename to scripts/app/javascript/components/cohorts/mastery/StudentMasteryTable.tsx diff --git a/app/javascript/components/cohorts/mastery/StudentReleaseRow.tsx b/scripts/app/javascript/components/cohorts/mastery/StudentReleaseRow.tsx similarity index 100% rename from app/javascript/components/cohorts/mastery/StudentReleaseRow.tsx rename to scripts/app/javascript/components/cohorts/mastery/StudentReleaseRow.tsx diff --git a/app/javascript/components/cohorts/pairing/GroupPairs.tsx b/scripts/app/javascript/components/cohorts/pairing/GroupPairs.tsx similarity index 100% rename from app/javascript/components/cohorts/pairing/GroupPairs.tsx rename to scripts/app/javascript/components/cohorts/pairing/GroupPairs.tsx diff --git a/app/javascript/components/cohorts/pairing/InnerStudentList.tsx b/scripts/app/javascript/components/cohorts/pairing/InnerStudentList.tsx similarity index 100% rename from app/javascript/components/cohorts/pairing/InnerStudentList.tsx rename to scripts/app/javascript/components/cohorts/pairing/InnerStudentList.tsx diff --git a/app/javascript/components/cohorts/pairing/NewPairing.tsx b/scripts/app/javascript/components/cohorts/pairing/NewPairing.tsx similarity index 100% rename from app/javascript/components/cohorts/pairing/NewPairing.tsx rename to scripts/app/javascript/components/cohorts/pairing/NewPairing.tsx diff --git a/app/javascript/components/cohorts/pairing/PairingBoard.tsx b/scripts/app/javascript/components/cohorts/pairing/PairingBoard.tsx similarity index 100% rename from app/javascript/components/cohorts/pairing/PairingBoard.tsx rename to scripts/app/javascript/components/cohorts/pairing/PairingBoard.tsx diff --git a/app/javascript/components/cohorts/pairing/StudentItem.tsx b/scripts/app/javascript/components/cohorts/pairing/StudentItem.tsx similarity index 100% rename from app/javascript/components/cohorts/pairing/StudentItem.tsx rename to scripts/app/javascript/components/cohorts/pairing/StudentItem.tsx diff --git a/app/javascript/components/cohorts/pairing/StudentList.tsx b/scripts/app/javascript/components/cohorts/pairing/StudentList.tsx similarity index 100% rename from app/javascript/components/cohorts/pairing/StudentList.tsx rename to scripts/app/javascript/components/cohorts/pairing/StudentList.tsx diff --git a/app/javascript/components/cohorts/progress/MasteryProgressionBar.tsx b/scripts/app/javascript/components/cohorts/progress/MasteryProgressionBar.tsx similarity index 100% rename from app/javascript/components/cohorts/progress/MasteryProgressionBar.tsx rename to scripts/app/javascript/components/cohorts/progress/MasteryProgressionBar.tsx diff --git a/app/javascript/components/cohorts/progress/ProgressThresholdCellHeaders.tsx b/scripts/app/javascript/components/cohorts/progress/ProgressThresholdCellHeaders.tsx similarity index 100% rename from app/javascript/components/cohorts/progress/ProgressThresholdCellHeaders.tsx rename to scripts/app/javascript/components/cohorts/progress/ProgressThresholdCellHeaders.tsx diff --git a/app/javascript/components/cohorts/progress/StudentProgress.tsx b/scripts/app/javascript/components/cohorts/progress/StudentProgress.tsx similarity index 100% rename from app/javascript/components/cohorts/progress/StudentProgress.tsx rename to scripts/app/javascript/components/cohorts/progress/StudentProgress.tsx diff --git a/app/javascript/components/cohorts/progress/StudentProgressBar.tsx b/scripts/app/javascript/components/cohorts/progress/StudentProgressBar.tsx similarity index 100% rename from app/javascript/components/cohorts/progress/StudentProgressBar.tsx rename to scripts/app/javascript/components/cohorts/progress/StudentProgressBar.tsx diff --git a/app/javascript/components/cohorts/progress/StudentProgressCells.tsx b/scripts/app/javascript/components/cohorts/progress/StudentProgressCells.tsx similarity index 100% rename from app/javascript/components/cohorts/progress/StudentProgressCells.tsx rename to scripts/app/javascript/components/cohorts/progress/StudentProgressCells.tsx diff --git a/app/javascript/components/cohorts/progress/StudentProgressRow.tsx b/scripts/app/javascript/components/cohorts/progress/StudentProgressRow.tsx similarity index 100% rename from app/javascript/components/cohorts/progress/StudentProgressRow.tsx rename to scripts/app/javascript/components/cohorts/progress/StudentProgressRow.tsx diff --git a/app/javascript/components/cohorts/progress/StudentProgressSortArrow.tsx b/scripts/app/javascript/components/cohorts/progress/StudentProgressSortArrow.tsx similarity index 100% rename from app/javascript/components/cohorts/progress/StudentProgressSortArrow.tsx rename to scripts/app/javascript/components/cohorts/progress/StudentProgressSortArrow.tsx diff --git a/app/javascript/components/cohorts/settings/BranchReleaseModal.tsx b/scripts/app/javascript/components/cohorts/settings/BranchReleaseModal.tsx similarity index 100% rename from app/javascript/components/cohorts/settings/BranchReleaseModal.tsx rename to scripts/app/javascript/components/cohorts/settings/BranchReleaseModal.tsx diff --git a/app/javascript/components/cohorts/settings/CohortBlockReleaseRow.tsx b/scripts/app/javascript/components/cohorts/settings/CohortBlockReleaseRow.tsx similarity index 100% rename from app/javascript/components/cohorts/settings/CohortBlockReleaseRow.tsx rename to scripts/app/javascript/components/cohorts/settings/CohortBlockReleaseRow.tsx diff --git a/app/javascript/components/cohorts/settings/CohortContentTab.tsx b/scripts/app/javascript/components/cohorts/settings/CohortContentTab.tsx similarity index 100% rename from app/javascript/components/cohorts/settings/CohortContentTab.tsx rename to scripts/app/javascript/components/cohorts/settings/CohortContentTab.tsx diff --git a/app/javascript/components/cohorts/settings/CohortInfo.tsx b/scripts/app/javascript/components/cohorts/settings/CohortInfo.tsx similarity index 100% rename from app/javascript/components/cohorts/settings/CohortInfo.tsx rename to scripts/app/javascript/components/cohorts/settings/CohortInfo.tsx diff --git a/app/javascript/components/cohorts/settings/CohortSettingsResync.tsx b/scripts/app/javascript/components/cohorts/settings/CohortSettingsResync.tsx similarity index 100% rename from app/javascript/components/cohorts/settings/CohortSettingsResync.tsx rename to scripts/app/javascript/components/cohorts/settings/CohortSettingsResync.tsx diff --git a/app/javascript/components/cohorts/settings/CohortSettingsTabs.tsx b/scripts/app/javascript/components/cohorts/settings/CohortSettingsTabs.tsx similarity index 100% rename from app/javascript/components/cohorts/settings/CohortSettingsTabs.tsx rename to scripts/app/javascript/components/cohorts/settings/CohortSettingsTabs.tsx diff --git a/app/javascript/components/cohorts/settings/CohortVisibilitySection.tsx b/scripts/app/javascript/components/cohorts/settings/CohortVisibilitySection.tsx similarity index 100% rename from app/javascript/components/cohorts/settings/CohortVisibilitySection.tsx rename to scripts/app/javascript/components/cohorts/settings/CohortVisibilitySection.tsx diff --git a/app/javascript/components/cohorts/settings/CurriculumSettingsTab.tsx b/scripts/app/javascript/components/cohorts/settings/CurriculumSettingsTab.tsx similarity index 100% rename from app/javascript/components/cohorts/settings/CurriculumSettingsTab.tsx rename to scripts/app/javascript/components/cohorts/settings/CurriculumSettingsTab.tsx diff --git a/app/javascript/components/cohorts/settings/ReleaseVersionModal.tsx b/scripts/app/javascript/components/cohorts/settings/ReleaseVersionModal.tsx similarity index 100% rename from app/javascript/components/cohorts/settings/ReleaseVersionModal.tsx rename to scripts/app/javascript/components/cohorts/settings/ReleaseVersionModal.tsx diff --git a/app/javascript/components/cohorts/settings/ReleaseVersionRow.tsx b/scripts/app/javascript/components/cohorts/settings/ReleaseVersionRow.tsx similarity index 100% rename from app/javascript/components/cohorts/settings/ReleaseVersionRow.tsx rename to scripts/app/javascript/components/cohorts/settings/ReleaseVersionRow.tsx diff --git a/app/javascript/components/cohorts/settings/UserCohortKebab.tsx b/scripts/app/javascript/components/cohorts/settings/UserCohortKebab.tsx similarity index 100% rename from app/javascript/components/cohorts/settings/UserCohortKebab.tsx rename to scripts/app/javascript/components/cohorts/settings/UserCohortKebab.tsx diff --git a/app/javascript/components/cohorts/settings/UserImport.tsx b/scripts/app/javascript/components/cohorts/settings/UserImport.tsx similarity index 100% rename from app/javascript/components/cohorts/settings/UserImport.tsx rename to scripts/app/javascript/components/cohorts/settings/UserImport.tsx diff --git a/app/javascript/components/cohorts/settings/UserKebab.tsx b/scripts/app/javascript/components/cohorts/settings/UserKebab.tsx similarity index 100% rename from app/javascript/components/cohorts/settings/UserKebab.tsx rename to scripts/app/javascript/components/cohorts/settings/UserKebab.tsx diff --git a/app/javascript/components/cohorts/submissions_dashboard/AnswerStatusRollup.tsx b/scripts/app/javascript/components/cohorts/submissions_dashboard/AnswerStatusRollup.tsx similarity index 100% rename from app/javascript/components/cohorts/submissions_dashboard/AnswerStatusRollup.tsx rename to scripts/app/javascript/components/cohorts/submissions_dashboard/AnswerStatusRollup.tsx diff --git a/app/javascript/components/cohorts/submissions_dashboard/HeaderStandardContainer.tsx b/scripts/app/javascript/components/cohorts/submissions_dashboard/HeaderStandardContainer.tsx similarity index 100% rename from app/javascript/components/cohorts/submissions_dashboard/HeaderStandardContainer.tsx rename to scripts/app/javascript/components/cohorts/submissions_dashboard/HeaderStandardContainer.tsx diff --git a/app/javascript/components/cohorts/submissions_dashboard/StandardContainer.tsx b/scripts/app/javascript/components/cohorts/submissions_dashboard/StandardContainer.tsx similarity index 100% rename from app/javascript/components/cohorts/submissions_dashboard/StandardContainer.tsx rename to scripts/app/javascript/components/cohorts/submissions_dashboard/StandardContainer.tsx diff --git a/app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboard.tsx b/scripts/app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboard.tsx similarity index 100% rename from app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboard.tsx rename to scripts/app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboard.tsx diff --git a/app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardChallengeItem.tsx b/scripts/app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardChallengeItem.tsx similarity index 100% rename from app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardChallengeItem.tsx rename to scripts/app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardChallengeItem.tsx diff --git a/app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardContentFileRow.tsx b/scripts/app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardContentFileRow.tsx similarity index 100% rename from app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardContentFileRow.tsx rename to scripts/app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardContentFileRow.tsx diff --git a/app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardStudentColumn.tsx b/scripts/app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardStudentColumn.tsx similarity index 100% rename from app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardStudentColumn.tsx rename to scripts/app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardStudentColumn.tsx diff --git a/app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardStudentNameBar.tsx b/scripts/app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardStudentNameBar.tsx similarity index 100% rename from app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardStudentNameBar.tsx rename to scripts/app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardStudentNameBar.tsx diff --git a/app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardTable.tsx b/scripts/app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardTable.tsx similarity index 100% rename from app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardTable.tsx rename to scripts/app/javascript/components/cohorts/submissions_dashboard/SubmissionsDashboardTable.tsx diff --git a/app/javascript/components/content_files/ActionMenus.tsx b/scripts/app/javascript/components/content_files/ActionMenus.tsx similarity index 100% rename from app/javascript/components/content_files/ActionMenus.tsx rename to scripts/app/javascript/components/content_files/ActionMenus.tsx diff --git a/app/javascript/components/content_files/Lesson.tsx b/scripts/app/javascript/components/content_files/Lesson.tsx similarity index 100% rename from app/javascript/components/content_files/Lesson.tsx rename to scripts/app/javascript/components/content_files/Lesson.tsx diff --git a/app/javascript/components/content_files/MarkdownRenderer.tsx b/scripts/app/javascript/components/content_files/MarkdownRenderer.tsx similarity index 100% rename from app/javascript/components/content_files/MarkdownRenderer.tsx rename to scripts/app/javascript/components/content_files/MarkdownRenderer.tsx diff --git a/app/javascript/components/content_files/PDFRenderer.tsx b/scripts/app/javascript/components/content_files/PDFRenderer.tsx similarity index 100% rename from app/javascript/components/content_files/PDFRenderer.tsx rename to scripts/app/javascript/components/content_files/PDFRenderer.tsx diff --git a/app/javascript/components/content_files/SideBar.tsx b/scripts/app/javascript/components/content_files/SideBar.tsx similarity index 100% rename from app/javascript/components/content_files/SideBar.tsx rename to scripts/app/javascript/components/content_files/SideBar.tsx diff --git a/app/javascript/components/content_files/SubmissionRenderer.tsx b/scripts/app/javascript/components/content_files/SubmissionRenderer.tsx similarity index 100% rename from app/javascript/components/content_files/SubmissionRenderer.tsx rename to scripts/app/javascript/components/content_files/SubmissionRenderer.tsx diff --git a/app/javascript/components/content_files/checkpoints/Checkpoint.tsx b/scripts/app/javascript/components/content_files/checkpoints/Checkpoint.tsx similarity index 100% rename from app/javascript/components/content_files/checkpoints/Checkpoint.tsx rename to scripts/app/javascript/components/content_files/checkpoints/Checkpoint.tsx diff --git a/app/javascript/components/content_files/checkpoints/CheckpointActionBar.tsx b/scripts/app/javascript/components/content_files/checkpoints/CheckpointActionBar.tsx similarity index 100% rename from app/javascript/components/content_files/checkpoints/CheckpointActionBar.tsx rename to scripts/app/javascript/components/content_files/checkpoints/CheckpointActionBar.tsx diff --git a/app/javascript/components/content_files/checkpoints/CheckpointDetails.tsx b/scripts/app/javascript/components/content_files/checkpoints/CheckpointDetails.tsx similarity index 100% rename from app/javascript/components/content_files/checkpoints/CheckpointDetails.tsx rename to scripts/app/javascript/components/content_files/checkpoints/CheckpointDetails.tsx diff --git a/app/javascript/components/content_files/checkpoints/CheckpointLanding.tsx b/scripts/app/javascript/components/content_files/checkpoints/CheckpointLanding.tsx similarity index 100% rename from app/javascript/components/content_files/checkpoints/CheckpointLanding.tsx rename to scripts/app/javascript/components/content_files/checkpoints/CheckpointLanding.tsx diff --git a/app/javascript/components/content_files/checkpoints/CheckpointLandingAttribute.tsx b/scripts/app/javascript/components/content_files/checkpoints/CheckpointLandingAttribute.tsx similarity index 100% rename from app/javascript/components/content_files/checkpoints/CheckpointLandingAttribute.tsx rename to scripts/app/javascript/components/content_files/checkpoints/CheckpointLandingAttribute.tsx diff --git a/app/javascript/components/content_files/checkpoints/CheckpointPairs.tsx b/scripts/app/javascript/components/content_files/checkpoints/CheckpointPairs.tsx similarity index 100% rename from app/javascript/components/content_files/checkpoints/CheckpointPairs.tsx rename to scripts/app/javascript/components/content_files/checkpoints/CheckpointPairs.tsx diff --git a/app/javascript/components/content_files/checkpoints/PairAvatars.tsx b/scripts/app/javascript/components/content_files/checkpoints/PairAvatars.tsx similarity index 100% rename from app/javascript/components/content_files/checkpoints/PairAvatars.tsx rename to scripts/app/javascript/components/content_files/checkpoints/PairAvatars.tsx diff --git a/app/javascript/components/content_files/checkpoints/student_scores/CheckpointStudentRow.tsx b/scripts/app/javascript/components/content_files/checkpoints/student_scores/CheckpointStudentRow.tsx similarity index 100% rename from app/javascript/components/content_files/checkpoints/student_scores/CheckpointStudentRow.tsx rename to scripts/app/javascript/components/content_files/checkpoints/student_scores/CheckpointStudentRow.tsx diff --git a/app/javascript/components/content_files/checkpoints/student_scores/CheckpointStudentScores.tsx b/scripts/app/javascript/components/content_files/checkpoints/student_scores/CheckpointStudentScores.tsx similarity index 100% rename from app/javascript/components/content_files/checkpoints/student_scores/CheckpointStudentScores.tsx rename to scripts/app/javascript/components/content_files/checkpoints/student_scores/CheckpointStudentScores.tsx diff --git a/app/javascript/components/curriculum/CheckpointSummary.tsx b/scripts/app/javascript/components/curriculum/CheckpointSummary.tsx similarity index 100% rename from app/javascript/components/curriculum/CheckpointSummary.tsx rename to scripts/app/javascript/components/curriculum/CheckpointSummary.tsx diff --git a/app/javascript/components/curriculum/CohortCurriculum.tsx b/scripts/app/javascript/components/curriculum/CohortCurriculum.tsx similarity index 100% rename from app/javascript/components/curriculum/CohortCurriculum.tsx rename to scripts/app/javascript/components/curriculum/CohortCurriculum.tsx diff --git a/app/javascript/components/curriculum/CurriculumStandardCard.tsx b/scripts/app/javascript/components/curriculum/CurriculumStandardCard.tsx similarity index 100% rename from app/javascript/components/curriculum/CurriculumStandardCard.tsx rename to scripts/app/javascript/components/curriculum/CurriculumStandardCard.tsx diff --git a/app/javascript/components/curriculum/ProgressIndicators.tsx b/scripts/app/javascript/components/curriculum/ProgressIndicators.tsx similarity index 100% rename from app/javascript/components/curriculum/ProgressIndicators.tsx rename to scripts/app/javascript/components/curriculum/ProgressIndicators.tsx diff --git a/app/javascript/components/curriculum/StandardBeans.tsx b/scripts/app/javascript/components/curriculum/StandardBeans.tsx similarity index 100% rename from app/javascript/components/curriculum/StandardBeans.tsx rename to scripts/app/javascript/components/curriculum/StandardBeans.tsx diff --git a/app/javascript/components/curriculum/StandardsRenderer.tsx b/scripts/app/javascript/components/curriculum/StandardsRenderer.tsx similarity index 100% rename from app/javascript/components/curriculum/StandardsRenderer.tsx rename to scripts/app/javascript/components/curriculum/StandardsRenderer.tsx diff --git a/app/javascript/components/curriculum/StudentOverallProgressDoughnut.tsx b/scripts/app/javascript/components/curriculum/StudentOverallProgressDoughnut.tsx similarity index 100% rename from app/javascript/components/curriculum/StudentOverallProgressDoughnut.tsx rename to scripts/app/javascript/components/curriculum/StudentOverallProgressDoughnut.tsx diff --git a/app/javascript/components/lib/ace.ts b/scripts/app/javascript/components/lib/ace.ts similarity index 100% rename from app/javascript/components/lib/ace.ts rename to scripts/app/javascript/components/lib/ace.ts diff --git a/app/javascript/components/notifications/NotificationsIcon.tsx b/scripts/app/javascript/components/notifications/NotificationsIcon.tsx similarity index 100% rename from app/javascript/components/notifications/NotificationsIcon.tsx rename to scripts/app/javascript/components/notifications/NotificationsIcon.tsx diff --git a/app/javascript/components/shared/ActionMenu/ActionMenu.tsx b/scripts/app/javascript/components/shared/ActionMenu/ActionMenu.tsx similarity index 100% rename from app/javascript/components/shared/ActionMenu/ActionMenu.tsx rename to scripts/app/javascript/components/shared/ActionMenu/ActionMenu.tsx diff --git a/app/javascript/components/shared/Button/Button.tsx b/scripts/app/javascript/components/shared/Button/Button.tsx similarity index 100% rename from app/javascript/components/shared/Button/Button.tsx rename to scripts/app/javascript/components/shared/Button/Button.tsx diff --git a/app/javascript/components/shared/ChallengePoints/ChallengePoints.tsx b/scripts/app/javascript/components/shared/ChallengePoints/ChallengePoints.tsx similarity index 100% rename from app/javascript/components/shared/ChallengePoints/ChallengePoints.tsx rename to scripts/app/javascript/components/shared/ChallengePoints/ChallengePoints.tsx diff --git a/app/javascript/components/shared/ChallengePoints/PartialCreditBaton.tsx b/scripts/app/javascript/components/shared/ChallengePoints/PartialCreditBaton.tsx similarity index 100% rename from app/javascript/components/shared/ChallengePoints/PartialCreditBaton.tsx rename to scripts/app/javascript/components/shared/ChallengePoints/PartialCreditBaton.tsx diff --git a/app/javascript/components/shared/ChallengePoints/SpinText.tsx b/scripts/app/javascript/components/shared/ChallengePoints/SpinText.tsx similarity index 100% rename from app/javascript/components/shared/ChallengePoints/SpinText.tsx rename to scripts/app/javascript/components/shared/ChallengePoints/SpinText.tsx diff --git a/app/javascript/components/shared/ChallengePoints/components/IntegerPicker/IntegerPicker.tsx b/scripts/app/javascript/components/shared/ChallengePoints/components/IntegerPicker/IntegerPicker.tsx similarity index 100% rename from app/javascript/components/shared/ChallengePoints/components/IntegerPicker/IntegerPicker.tsx rename to scripts/app/javascript/components/shared/ChallengePoints/components/IntegerPicker/IntegerPicker.tsx diff --git a/app/javascript/components/shared/DonutRing/DonutRing.tsx b/scripts/app/javascript/components/shared/DonutRing/DonutRing.tsx similarity index 100% rename from app/javascript/components/shared/DonutRing/DonutRing.tsx rename to scripts/app/javascript/components/shared/DonutRing/DonutRing.tsx diff --git a/app/javascript/components/shared/DonutRing/components/ColorDonut/ColorDonut.tsx b/scripts/app/javascript/components/shared/DonutRing/components/ColorDonut/ColorDonut.tsx similarity index 100% rename from app/javascript/components/shared/DonutRing/components/ColorDonut/ColorDonut.tsx rename to scripts/app/javascript/components/shared/DonutRing/components/ColorDonut/ColorDonut.tsx diff --git a/app/javascript/components/shared/DonutRing/components/CompleteDonut/CompleteDonut.tsx b/scripts/app/javascript/components/shared/DonutRing/components/CompleteDonut/CompleteDonut.tsx similarity index 100% rename from app/javascript/components/shared/DonutRing/components/CompleteDonut/CompleteDonut.tsx rename to scripts/app/javascript/components/shared/DonutRing/components/CompleteDonut/CompleteDonut.tsx diff --git a/app/javascript/components/shared/DonutRing/components/UngradedDonut/UngradedDonut.tsx b/scripts/app/javascript/components/shared/DonutRing/components/UngradedDonut/UngradedDonut.tsx similarity index 100% rename from app/javascript/components/shared/DonutRing/components/UngradedDonut/UngradedDonut.tsx rename to scripts/app/javascript/components/shared/DonutRing/components/UngradedDonut/UngradedDonut.tsx diff --git a/app/javascript/components/shared/DonutRing/components/UngradedDonut/UngradedDonut/UngradedDonut.tsx b/scripts/app/javascript/components/shared/DonutRing/components/UngradedDonut/UngradedDonut/UngradedDonut.tsx similarity index 100% rename from app/javascript/components/shared/DonutRing/components/UngradedDonut/UngradedDonut/UngradedDonut.tsx rename to scripts/app/javascript/components/shared/DonutRing/components/UngradedDonut/UngradedDonut/UngradedDonut.tsx diff --git a/app/javascript/components/shared/ErrorMessagesTable/ErrorMessagesTable.tsx b/scripts/app/javascript/components/shared/ErrorMessagesTable/ErrorMessagesTable.tsx similarity index 100% rename from app/javascript/components/shared/ErrorMessagesTable/ErrorMessagesTable.tsx rename to scripts/app/javascript/components/shared/ErrorMessagesTable/ErrorMessagesTable.tsx diff --git a/app/javascript/components/shared/FlashAlert/FlashAlert.tsx b/scripts/app/javascript/components/shared/FlashAlert/FlashAlert.tsx similarity index 100% rename from app/javascript/components/shared/FlashAlert/FlashAlert.tsx rename to scripts/app/javascript/components/shared/FlashAlert/FlashAlert.tsx diff --git a/app/javascript/components/shared/FormatNumber/FormatNumber.tsx b/scripts/app/javascript/components/shared/FormatNumber/FormatNumber.tsx similarity index 100% rename from app/javascript/components/shared/FormatNumber/FormatNumber.tsx rename to scripts/app/javascript/components/shared/FormatNumber/FormatNumber.tsx diff --git a/app/javascript/components/shared/Icons/AlertSign.tsx b/scripts/app/javascript/components/shared/Icons/AlertSign.tsx similarity index 100% rename from app/javascript/components/shared/Icons/AlertSign.tsx rename to scripts/app/javascript/components/shared/Icons/AlertSign.tsx diff --git a/app/javascript/components/shared/Icons/Clear.tsx b/scripts/app/javascript/components/shared/Icons/Clear.tsx similarity index 100% rename from app/javascript/components/shared/Icons/Clear.tsx rename to scripts/app/javascript/components/shared/Icons/Clear.tsx diff --git a/app/javascript/components/shared/Icons/CloseButton.tsx b/scripts/app/javascript/components/shared/Icons/CloseButton.tsx similarity index 100% rename from app/javascript/components/shared/Icons/CloseButton.tsx rename to scripts/app/javascript/components/shared/Icons/CloseButton.tsx diff --git a/app/javascript/components/shared/Icons/Done.tsx b/scripts/app/javascript/components/shared/Icons/Done.tsx similarity index 100% rename from app/javascript/components/shared/Icons/Done.tsx rename to scripts/app/javascript/components/shared/Icons/Done.tsx diff --git a/app/javascript/components/shared/Icons/KeyboardArrowDown.tsx b/scripts/app/javascript/components/shared/Icons/KeyboardArrowDown.tsx similarity index 100% rename from app/javascript/components/shared/Icons/KeyboardArrowDown.tsx rename to scripts/app/javascript/components/shared/Icons/KeyboardArrowDown.tsx diff --git a/app/javascript/components/shared/Icons/KeyboardArrowUp.tsx b/scripts/app/javascript/components/shared/Icons/KeyboardArrowUp.tsx similarity index 100% rename from app/javascript/components/shared/Icons/KeyboardArrowUp.tsx rename to scripts/app/javascript/components/shared/Icons/KeyboardArrowUp.tsx diff --git a/app/javascript/components/shared/Icons/SettingsCog.tsx b/scripts/app/javascript/components/shared/Icons/SettingsCog.tsx similarity index 100% rename from app/javascript/components/shared/Icons/SettingsCog.tsx rename to scripts/app/javascript/components/shared/Icons/SettingsCog.tsx diff --git a/app/javascript/components/shared/Icons/StatusCircle.tsx b/scripts/app/javascript/components/shared/Icons/StatusCircle.tsx similarity index 100% rename from app/javascript/components/shared/Icons/StatusCircle.tsx rename to scripts/app/javascript/components/shared/Icons/StatusCircle.tsx diff --git a/app/javascript/components/shared/MasteryProgressBar/MasteryProgressBar.tsx b/scripts/app/javascript/components/shared/MasteryProgressBar/MasteryProgressBar.tsx similarity index 100% rename from app/javascript/components/shared/MasteryProgressBar/MasteryProgressBar.tsx rename to scripts/app/javascript/components/shared/MasteryProgressBar/MasteryProgressBar.tsx diff --git a/app/javascript/components/shared/Modal/Modal.tsx b/scripts/app/javascript/components/shared/Modal/Modal.tsx similarity index 100% rename from app/javascript/components/shared/Modal/Modal.tsx rename to scripts/app/javascript/components/shared/Modal/Modal.tsx diff --git a/app/javascript/components/shared/Pagination/Pagination.tsx b/scripts/app/javascript/components/shared/Pagination/Pagination.tsx similarity index 100% rename from app/javascript/components/shared/Pagination/Pagination.tsx rename to scripts/app/javascript/components/shared/Pagination/Pagination.tsx diff --git a/app/javascript/components/shared/PercentageProgressBar/PercentageProgressBar.tsx b/scripts/app/javascript/components/shared/PercentageProgressBar/PercentageProgressBar.tsx similarity index 100% rename from app/javascript/components/shared/PercentageProgressBar/PercentageProgressBar.tsx rename to scripts/app/javascript/components/shared/PercentageProgressBar/PercentageProgressBar.tsx diff --git a/app/javascript/components/shared/Pill/Pill.tsx b/scripts/app/javascript/components/shared/Pill/Pill.tsx similarity index 100% rename from app/javascript/components/shared/Pill/Pill.tsx rename to scripts/app/javascript/components/shared/Pill/Pill.tsx diff --git a/app/javascript/components/shared/PointGradeButtons/PointGradeButtons.tsx b/scripts/app/javascript/components/shared/PointGradeButtons/PointGradeButtons.tsx similarity index 100% rename from app/javascript/components/shared/PointGradeButtons/PointGradeButtons.tsx rename to scripts/app/javascript/components/shared/PointGradeButtons/PointGradeButtons.tsx diff --git a/app/javascript/components/shared/PointGradeButtons/SpinText.tsx b/scripts/app/javascript/components/shared/PointGradeButtons/SpinText.tsx similarity index 100% rename from app/javascript/components/shared/PointGradeButtons/SpinText.tsx rename to scripts/app/javascript/components/shared/PointGradeButtons/SpinText.tsx diff --git a/app/javascript/components/shared/ProgressBar/ProgressBar.tsx b/scripts/app/javascript/components/shared/ProgressBar/ProgressBar.tsx similarity index 100% rename from app/javascript/components/shared/ProgressBar/ProgressBar.tsx rename to scripts/app/javascript/components/shared/ProgressBar/ProgressBar.tsx diff --git a/app/javascript/components/shared/ProgressThresholdsKey/ProgressThresholdsKey.tsx b/scripts/app/javascript/components/shared/ProgressThresholdsKey/ProgressThresholdsKey.tsx similarity index 100% rename from app/javascript/components/shared/ProgressThresholdsKey/ProgressThresholdsKey.tsx rename to scripts/app/javascript/components/shared/ProgressThresholdsKey/ProgressThresholdsKey.tsx diff --git a/app/javascript/components/shared/ProgressThresholdsModal/ProgressThresholdsModal.tsx b/scripts/app/javascript/components/shared/ProgressThresholdsModal/ProgressThresholdsModal.tsx similarity index 100% rename from app/javascript/components/shared/ProgressThresholdsModal/ProgressThresholdsModal.tsx rename to scripts/app/javascript/components/shared/ProgressThresholdsModal/ProgressThresholdsModal.tsx diff --git a/app/javascript/components/shared/ProgressThresholdsSlider/ProgressThresholdsSlider.tsx b/scripts/app/javascript/components/shared/ProgressThresholdsSlider/ProgressThresholdsSlider.tsx similarity index 100% rename from app/javascript/components/shared/ProgressThresholdsSlider/ProgressThresholdsSlider.tsx rename to scripts/app/javascript/components/shared/ProgressThresholdsSlider/ProgressThresholdsSlider.tsx diff --git a/app/javascript/components/shared/SearchBar/SearchBar.tsx b/scripts/app/javascript/components/shared/SearchBar/SearchBar.tsx similarity index 100% rename from app/javascript/components/shared/SearchBar/SearchBar.tsx rename to scripts/app/javascript/components/shared/SearchBar/SearchBar.tsx diff --git a/app/javascript/components/shared/Slideshow/Slideshow.tsx b/scripts/app/javascript/components/shared/Slideshow/Slideshow.tsx similarity index 100% rename from app/javascript/components/shared/Slideshow/Slideshow.tsx rename to scripts/app/javascript/components/shared/Slideshow/Slideshow.tsx diff --git a/app/javascript/components/shared/UngradedDonut/UngradedDonut.tsx b/scripts/app/javascript/components/shared/UngradedDonut/UngradedDonut.tsx similarity index 100% rename from app/javascript/components/shared/UngradedDonut/UngradedDonut.tsx rename to scripts/app/javascript/components/shared/UngradedDonut/UngradedDonut.tsx diff --git a/app/javascript/components/shared/UniversalList/UniversalList.tsx b/scripts/app/javascript/components/shared/UniversalList/UniversalList.tsx similarity index 100% rename from app/javascript/components/shared/UniversalList/UniversalList.tsx rename to scripts/app/javascript/components/shared/UniversalList/UniversalList.tsx diff --git a/app/javascript/components/shared/UniversalRow/UniversalRow.tsx b/scripts/app/javascript/components/shared/UniversalRow/UniversalRow.tsx similarity index 100% rename from app/javascript/components/shared/UniversalRow/UniversalRow.tsx rename to scripts/app/javascript/components/shared/UniversalRow/UniversalRow.tsx diff --git a/app/javascript/components/shared/UniversalTable/UniversalTable.tsx b/scripts/app/javascript/components/shared/UniversalTable/UniversalTable.tsx similarity index 100% rename from app/javascript/components/shared/UniversalTable/UniversalTable.tsx rename to scripts/app/javascript/components/shared/UniversalTable/UniversalTable.tsx diff --git a/app/javascript/components/standards/CompletionScoringBlock.tsx b/scripts/app/javascript/components/standards/CompletionScoringBlock.tsx similarity index 100% rename from app/javascript/components/standards/CompletionScoringBlock.tsx rename to scripts/app/javascript/components/standards/CompletionScoringBlock.tsx diff --git a/app/javascript/components/standards/MasteryScoringBlock.tsx b/scripts/app/javascript/components/standards/MasteryScoringBlock.tsx similarity index 100% rename from app/javascript/components/standards/MasteryScoringBlock.tsx rename to scripts/app/javascript/components/standards/MasteryScoringBlock.tsx diff --git a/app/javascript/components/standards/StandardCard.tsx b/scripts/app/javascript/components/standards/StandardCard.tsx similarity index 100% rename from app/javascript/components/standards/StandardCard.tsx rename to scripts/app/javascript/components/standards/StandardCard.tsx diff --git a/app/javascript/components/standards/StandardScoreButton.tsx b/scripts/app/javascript/components/standards/StandardScoreButton.tsx similarity index 100% rename from app/javascript/components/standards/StandardScoreButton.tsx rename to scripts/app/javascript/components/standards/StandardScoreButton.tsx diff --git a/app/javascript/components/standards/StandardScoringBlock.tsx b/scripts/app/javascript/components/standards/StandardScoringBlock.tsx similarity index 100% rename from app/javascript/components/standards/StandardScoringBlock.tsx rename to scripts/app/javascript/components/standards/StandardScoringBlock.tsx diff --git a/app/javascript/components/standards/StandardTopicsRollups.tsx b/scripts/app/javascript/components/standards/StandardTopicsRollups.tsx similarity index 100% rename from app/javascript/components/standards/StandardTopicsRollups.tsx rename to scripts/app/javascript/components/standards/StandardTopicsRollups.tsx diff --git a/app/javascript/components/users/UsersIndex.tsx b/scripts/app/javascript/components/users/UsersIndex.tsx similarity index 100% rename from app/javascript/components/users/UsersIndex.tsx rename to scripts/app/javascript/components/users/UsersIndex.tsx diff --git a/app/javascript/components/vendor/ReactTooltip.js b/scripts/app/javascript/components/vendor/ReactTooltip.js similarity index 100% rename from app/javascript/components/vendor/ReactTooltip.js rename to scripts/app/javascript/components/vendor/ReactTooltip.js diff --git a/app/javascript/generated/routes.ts b/scripts/app/javascript/generated/routes.ts similarity index 100% rename from app/javascript/generated/routes.ts rename to scripts/app/javascript/generated/routes.ts diff --git a/app/javascript/globals.ts b/scripts/app/javascript/globals.ts similarity index 100% rename from app/javascript/globals.ts rename to scripts/app/javascript/globals.ts diff --git a/app/javascript/lib/http.ts b/scripts/app/javascript/lib/http.ts similarity index 100% rename from app/javascript/lib/http.ts rename to scripts/app/javascript/lib/http.ts diff --git a/app/javascript/lib/utils.ts b/scripts/app/javascript/lib/utils.ts similarity index 100% rename from app/javascript/lib/utils.ts rename to scripts/app/javascript/lib/utils.ts diff --git a/app/javascript/packs/application.js b/scripts/app/javascript/packs/application.js similarity index 100% rename from app/javascript/packs/application.js rename to scripts/app/javascript/packs/application.js diff --git a/app/javascript/packs/server_rendering.js b/scripts/app/javascript/packs/server_rendering.js similarity index 100% rename from app/javascript/packs/server_rendering.js rename to scripts/app/javascript/packs/server_rendering.js diff --git a/app/jobs/application_job.rb b/scripts/app/jobs/application_job.rb similarity index 100% rename from app/jobs/application_job.rb rename to scripts/app/jobs/application_job.rb diff --git a/app/jobs/branch_release_notifier_job.rb b/scripts/app/jobs/branch_release_notifier_job.rb similarity index 100% rename from app/jobs/branch_release_notifier_job.rb rename to scripts/app/jobs/branch_release_notifier_job.rb diff --git a/app/jobs/checkpoint_paired_submission_job.rb b/scripts/app/jobs/checkpoint_paired_submission_job.rb similarity index 100% rename from app/jobs/checkpoint_paired_submission_job.rb rename to scripts/app/jobs/checkpoint_paired_submission_job.rb diff --git a/app/jobs/content_file_default_visibility_job.rb b/scripts/app/jobs/content_file_default_visibility_job.rb similarity index 100% rename from app/jobs/content_file_default_visibility_job.rb rename to scripts/app/jobs/content_file_default_visibility_job.rb diff --git a/app/jobs/content_file_visit_job.rb b/scripts/app/jobs/content_file_visit_job.rb similarity index 100% rename from app/jobs/content_file_visit_job.rb rename to scripts/app/jobs/content_file_visit_job.rb diff --git a/app/jobs/create_api_interaction_job.rb b/scripts/app/jobs/create_api_interaction_job.rb similarity index 100% rename from app/jobs/create_api_interaction_job.rb rename to scripts/app/jobs/create_api_interaction_job.rb diff --git a/app/jobs/create_release_job.rb b/scripts/app/jobs/create_release_job.rb similarity index 100% rename from app/jobs/create_release_job.rb rename to scripts/app/jobs/create_release_job.rb diff --git a/app/jobs/evaluate_code_snippet_job.rb b/scripts/app/jobs/evaluate_code_snippet_job.rb similarity index 100% rename from app/jobs/evaluate_code_snippet_job.rb rename to scripts/app/jobs/evaluate_code_snippet_job.rb diff --git a/app/jobs/evaluate_custom_snippet_job.rb b/scripts/app/jobs/evaluate_custom_snippet_job.rb similarity index 100% rename from app/jobs/evaluate_custom_snippet_job.rb rename to scripts/app/jobs/evaluate_custom_snippet_job.rb diff --git a/app/jobs/evaluate_project_job.rb b/scripts/app/jobs/evaluate_project_job.rb similarity index 100% rename from app/jobs/evaluate_project_job.rb rename to scripts/app/jobs/evaluate_project_job.rb diff --git a/app/jobs/grade_timed_checkpoint_job.rb b/scripts/app/jobs/grade_timed_checkpoint_job.rb similarity index 100% rename from app/jobs/grade_timed_checkpoint_job.rb rename to scripts/app/jobs/grade_timed_checkpoint_job.rb diff --git a/app/jobs/import_student_work_job.rb b/scripts/app/jobs/import_student_work_job.rb similarity index 100% rename from app/jobs/import_student_work_job.rb rename to scripts/app/jobs/import_student_work_job.rb diff --git a/app/jobs/java_code_evaluation_job.rb b/scripts/app/jobs/java_code_evaluation_job.rb similarity index 100% rename from app/jobs/java_code_evaluation_job.rb rename to scripts/app/jobs/java_code_evaluation_job.rb diff --git a/app/jobs/javascript_code_evaluation_job.rb b/scripts/app/jobs/javascript_code_evaluation_job.rb similarity index 100% rename from app/jobs/javascript_code_evaluation_job.rb rename to scripts/app/jobs/javascript_code_evaluation_job.rb diff --git a/app/jobs/progress_csv_job.rb b/scripts/app/jobs/progress_csv_job.rb similarity index 100% rename from app/jobs/progress_csv_job.rb rename to scripts/app/jobs/progress_csv_job.rb diff --git a/app/jobs/python_code_evaluation_job.rb b/scripts/app/jobs/python_code_evaluation_job.rb similarity index 100% rename from app/jobs/python_code_evaluation_job.rb rename to scripts/app/jobs/python_code_evaluation_job.rb diff --git a/app/jobs/release_notifier_job.rb b/scripts/app/jobs/release_notifier_job.rb similarity index 100% rename from app/jobs/release_notifier_job.rb rename to scripts/app/jobs/release_notifier_job.rb diff --git a/app/jobs/resync_course_job.rb b/scripts/app/jobs/resync_course_job.rb similarity index 100% rename from app/jobs/resync_course_job.rb rename to scripts/app/jobs/resync_course_job.rb diff --git a/app/jobs/set_block_caches_job.rb b/scripts/app/jobs/set_block_caches_job.rb similarity index 100% rename from app/jobs/set_block_caches_job.rb rename to scripts/app/jobs/set_block_caches_job.rb diff --git a/app/jobs/slack_challenge_performance_job.rb b/scripts/app/jobs/slack_challenge_performance_job.rb similarity index 100% rename from app/jobs/slack_challenge_performance_job.rb rename to scripts/app/jobs/slack_challenge_performance_job.rb diff --git a/app/jobs/slack_dev_notify_job.rb b/scripts/app/jobs/slack_dev_notify_job.rb similarity index 100% rename from app/jobs/slack_dev_notify_job.rb rename to scripts/app/jobs/slack_dev_notify_job.rb diff --git a/app/jobs/slack_ds_prep_job.rb b/scripts/app/jobs/slack_ds_prep_job.rb similarity index 100% rename from app/jobs/slack_ds_prep_job.rb rename to scripts/app/jobs/slack_ds_prep_job.rb diff --git a/app/jobs/slack_job.rb b/scripts/app/jobs/slack_job.rb similarity index 100% rename from app/jobs/slack_job.rb rename to scripts/app/jobs/slack_job.rb diff --git a/app/jobs/slack_se_prep_job.rb b/scripts/app/jobs/slack_se_prep_job.rb similarity index 100% rename from app/jobs/slack_se_prep_job.rb rename to scripts/app/jobs/slack_se_prep_job.rb diff --git a/app/jobs/slack_student_job.rb b/scripts/app/jobs/slack_student_job.rb similarity index 100% rename from app/jobs/slack_student_job.rb rename to scripts/app/jobs/slack_student_job.rb diff --git a/app/jobs/student_progress_auth_job.rb b/scripts/app/jobs/student_progress_auth_job.rb similarity index 100% rename from app/jobs/student_progress_auth_job.rb rename to scripts/app/jobs/student_progress_auth_job.rb diff --git a/app/jobs/switch_to_branch_job.rb b/scripts/app/jobs/switch_to_branch_job.rb similarity index 100% rename from app/jobs/switch_to_branch_job.rb rename to scripts/app/jobs/switch_to_branch_job.rb diff --git a/app/mailers/application_mailer.rb b/scripts/app/mailers/application_mailer.rb similarity index 100% rename from app/mailers/application_mailer.rb rename to scripts/app/mailers/application_mailer.rb diff --git a/app/mailers/user_mailer.rb b/scripts/app/mailers/user_mailer.rb similarity index 100% rename from app/mailers/user_mailer.rb rename to scripts/app/mailers/user_mailer.rb diff --git a/app/models/activity.rb b/scripts/app/models/activity.rb similarity index 100% rename from app/models/activity.rb rename to scripts/app/models/activity.rb diff --git a/app/models/api_interaction.rb b/scripts/app/models/api_interaction.rb similarity index 100% rename from app/models/api_interaction.rb rename to scripts/app/models/api_interaction.rb diff --git a/app/models/application_record.rb b/scripts/app/models/application_record.rb similarity index 100% rename from app/models/application_record.rb rename to scripts/app/models/application_record.rb diff --git a/app/models/block.rb b/scripts/app/models/block.rb similarity index 100% rename from app/models/block.rb rename to scripts/app/models/block.rb diff --git a/app/models/challenge.rb b/scripts/app/models/challenge.rb similarity index 100% rename from app/models/challenge.rb rename to scripts/app/models/challenge.rb diff --git a/app/models/checkpoint_submission.rb b/scripts/app/models/checkpoint_submission.rb similarity index 100% rename from app/models/checkpoint_submission.rb rename to scripts/app/models/checkpoint_submission.rb diff --git a/app/models/cohort.rb b/scripts/app/models/cohort.rb similarity index 100% rename from app/models/cohort.rb rename to scripts/app/models/cohort.rb diff --git a/app/models/cohort_release.rb b/scripts/app/models/cohort_release.rb similarity index 100% rename from app/models/cohort_release.rb rename to scripts/app/models/cohort_release.rb diff --git a/app/models/cohort_user.rb b/scripts/app/models/cohort_user.rb similarity index 100% rename from app/models/cohort_user.rb rename to scripts/app/models/cohort_user.rb diff --git a/app/models/concerns/findable_by_uid.rb b/scripts/app/models/concerns/findable_by_uid.rb similarity index 100% rename from app/models/concerns/findable_by_uid.rb rename to scripts/app/models/concerns/findable_by_uid.rb diff --git a/app/models/concerns/read_only_model.rb b/scripts/app/models/concerns/read_only_model.rb similarity index 100% rename from app/models/concerns/read_only_model.rb rename to scripts/app/models/concerns/read_only_model.rb diff --git a/app/models/content_file.rb b/scripts/app/models/content_file.rb similarity index 100% rename from app/models/content_file.rb rename to scripts/app/models/content_file.rb diff --git a/app/models/content_visibility.rb b/scripts/app/models/content_visibility.rb similarity index 100% rename from app/models/content_visibility.rb rename to scripts/app/models/content_visibility.rb diff --git a/app/models/job_result.rb b/scripts/app/models/job_result.rb similarity index 100% rename from app/models/job_result.rb rename to scripts/app/models/job_result.rb diff --git a/app/models/lesson_visit.rb b/scripts/app/models/lesson_visit.rb similarity index 100% rename from app/models/lesson_visit.rb rename to scripts/app/models/lesson_visit.rb diff --git a/app/models/notification.rb b/scripts/app/models/notification.rb similarity index 100% rename from app/models/notification.rb rename to scripts/app/models/notification.rb diff --git a/app/models/pairing.rb b/scripts/app/models/pairing.rb similarity index 100% rename from app/models/pairing.rb rename to scripts/app/models/pairing.rb diff --git a/app/models/performance.rb b/scripts/app/models/performance.rb similarity index 100% rename from app/models/performance.rb rename to scripts/app/models/performance.rb diff --git a/app/models/release.rb b/scripts/app/models/release.rb similarity index 100% rename from app/models/release.rb rename to scripts/app/models/release.rb diff --git a/app/models/resync_job_result.rb b/scripts/app/models/resync_job_result.rb similarity index 100% rename from app/models/resync_job_result.rb rename to scripts/app/models/resync_job_result.rb diff --git a/app/models/section.rb b/scripts/app/models/section.rb similarity index 100% rename from app/models/section.rb rename to scripts/app/models/section.rb diff --git a/app/models/standard.rb b/scripts/app/models/standard.rb similarity index 100% rename from app/models/standard.rb rename to scripts/app/models/standard.rb diff --git a/app/models/submitted_challenge_answer.rb b/scripts/app/models/submitted_challenge_answer.rb similarity index 100% rename from app/models/submitted_challenge_answer.rb rename to scripts/app/models/submitted_challenge_answer.rb diff --git a/app/models/unit.rb b/scripts/app/models/unit.rb similarity index 100% rename from app/models/unit.rb rename to scripts/app/models/unit.rb diff --git a/app/models/user.rb b/scripts/app/models/user.rb similarity index 100% rename from app/models/user.rb rename to scripts/app/models/user.rb diff --git a/app/models/user_last_viewed_standard_path.rb b/scripts/app/models/user_last_viewed_standard_path.rb similarity index 100% rename from app/models/user_last_viewed_standard_path.rb rename to scripts/app/models/user_last_viewed_standard_path.rb diff --git a/app/policies/activity_policy.rb b/scripts/app/policies/activity_policy.rb similarity index 100% rename from app/policies/activity_policy.rb rename to scripts/app/policies/activity_policy.rb diff --git a/app/policies/application_policy.rb b/scripts/app/policies/application_policy.rb similarity index 100% rename from app/policies/application_policy.rb rename to scripts/app/policies/application_policy.rb diff --git a/app/policies/block_policy.rb b/scripts/app/policies/block_policy.rb similarity index 100% rename from app/policies/block_policy.rb rename to scripts/app/policies/block_policy.rb diff --git a/app/policies/checkpoint_submission_policy.rb b/scripts/app/policies/checkpoint_submission_policy.rb similarity index 100% rename from app/policies/checkpoint_submission_policy.rb rename to scripts/app/policies/checkpoint_submission_policy.rb diff --git a/app/policies/cohort_policy.rb b/scripts/app/policies/cohort_policy.rb similarity index 100% rename from app/policies/cohort_policy.rb rename to scripts/app/policies/cohort_policy.rb diff --git a/app/policies/cohort_release_policy.rb b/scripts/app/policies/cohort_release_policy.rb similarity index 100% rename from app/policies/cohort_release_policy.rb rename to scripts/app/policies/cohort_release_policy.rb diff --git a/app/policies/cohort_user_policy.rb b/scripts/app/policies/cohort_user_policy.rb similarity index 100% rename from app/policies/cohort_user_policy.rb rename to scripts/app/policies/cohort_user_policy.rb diff --git a/app/policies/content_file_policy.rb b/scripts/app/policies/content_file_policy.rb similarity index 100% rename from app/policies/content_file_policy.rb rename to scripts/app/policies/content_file_policy.rb diff --git a/app/policies/notification_policy.rb b/scripts/app/policies/notification_policy.rb similarity index 100% rename from app/policies/notification_policy.rb rename to scripts/app/policies/notification_policy.rb diff --git a/app/policies/performance_policy.rb b/scripts/app/policies/performance_policy.rb similarity index 100% rename from app/policies/performance_policy.rb rename to scripts/app/policies/performance_policy.rb diff --git a/app/policies/release_policy.rb b/scripts/app/policies/release_policy.rb similarity index 100% rename from app/policies/release_policy.rb rename to scripts/app/policies/release_policy.rb diff --git a/app/policies/submitted_challenge_answer_policy.rb b/scripts/app/policies/submitted_challenge_answer_policy.rb similarity index 100% rename from app/policies/submitted_challenge_answer_policy.rb rename to scripts/app/policies/submitted_challenge_answer_policy.rb diff --git a/app/policies/user_policy.rb b/scripts/app/policies/user_policy.rb similarity index 100% rename from app/policies/user_policy.rb rename to scripts/app/policies/user_policy.rb diff --git a/app/presenters/activity_presenter.rb b/scripts/app/presenters/activity_presenter.rb similarity index 100% rename from app/presenters/activity_presenter.rb rename to scripts/app/presenters/activity_presenter.rb diff --git a/app/presenters/block_presenter/for_block.rb b/scripts/app/presenters/block_presenter/for_block.rb similarity index 100% rename from app/presenters/block_presenter/for_block.rb rename to scripts/app/presenters/block_presenter/for_block.rb diff --git a/app/presenters/block_presenter/for_cohort_releases.rb b/scripts/app/presenters/block_presenter/for_cohort_releases.rb similarity index 100% rename from app/presenters/block_presenter/for_cohort_releases.rb rename to scripts/app/presenters/block_presenter/for_cohort_releases.rb diff --git a/app/presenters/block_presenter/for_cohort_releases_new.rb b/scripts/app/presenters/block_presenter/for_cohort_releases_new.rb similarity index 100% rename from app/presenters/block_presenter/for_cohort_releases_new.rb rename to scripts/app/presenters/block_presenter/for_cohort_releases_new.rb diff --git a/app/presenters/block_presenter/for_releases.rb b/scripts/app/presenters/block_presenter/for_releases.rb similarity index 100% rename from app/presenters/block_presenter/for_releases.rb rename to scripts/app/presenters/block_presenter/for_releases.rb diff --git a/app/presenters/challenge_with_submitted_challenge_answers_presenter.rb b/scripts/app/presenters/challenge_with_submitted_challenge_answers_presenter.rb similarity index 100% rename from app/presenters/challenge_with_submitted_challenge_answers_presenter.rb rename to scripts/app/presenters/challenge_with_submitted_challenge_answers_presenter.rb diff --git a/app/presenters/checkpoint_submission_presenter.rb b/scripts/app/presenters/checkpoint_submission_presenter.rb similarity index 100% rename from app/presenters/checkpoint_submission_presenter.rb rename to scripts/app/presenters/checkpoint_submission_presenter.rb diff --git a/app/presenters/checkpoint_submission_presenter/for_index.rb b/scripts/app/presenters/checkpoint_submission_presenter/for_index.rb similarity index 100% rename from app/presenters/checkpoint_submission_presenter/for_index.rb rename to scripts/app/presenters/checkpoint_submission_presenter/for_index.rb diff --git a/app/presenters/checkpoint_submission_presenter/for_student_row.rb b/scripts/app/presenters/checkpoint_submission_presenter/for_student_row.rb similarity index 100% rename from app/presenters/checkpoint_submission_presenter/for_student_row.rb rename to scripts/app/presenters/checkpoint_submission_presenter/for_student_row.rb diff --git a/app/presenters/cohort_release_presenter/for_cohort_setup.rb b/scripts/app/presenters/cohort_release_presenter/for_cohort_setup.rb similarity index 100% rename from app/presenters/cohort_release_presenter/for_cohort_setup.rb rename to scripts/app/presenters/cohort_release_presenter/for_cohort_setup.rb diff --git a/app/presenters/cohort_setup/visibility.rb b/scripts/app/presenters/cohort_setup/visibility.rb similarity index 100% rename from app/presenters/cohort_setup/visibility.rb rename to scripts/app/presenters/cohort_setup/visibility.rb diff --git a/app/presenters/content_file_presenter/for_curriculum_last_viewed.rb b/scripts/app/presenters/content_file_presenter/for_curriculum_last_viewed.rb similarity index 100% rename from app/presenters/content_file_presenter/for_curriculum_last_viewed.rb rename to scripts/app/presenters/content_file_presenter/for_curriculum_last_viewed.rb diff --git a/app/presenters/content_file_presenter/for_footer.rb b/scripts/app/presenters/content_file_presenter/for_footer.rb similarity index 100% rename from app/presenters/content_file_presenter/for_footer.rb rename to scripts/app/presenters/content_file_presenter/for_footer.rb diff --git a/app/presenters/content_file_presenter/for_show.rb b/scripts/app/presenters/content_file_presenter/for_show.rb similarity index 100% rename from app/presenters/content_file_presenter/for_show.rb rename to scripts/app/presenters/content_file_presenter/for_show.rb diff --git a/app/presenters/content_file_presenter/for_sidebar.rb b/scripts/app/presenters/content_file_presenter/for_sidebar.rb similarity index 100% rename from app/presenters/content_file_presenter/for_sidebar.rb rename to scripts/app/presenters/content_file_presenter/for_sidebar.rb diff --git a/app/presenters/performance_presenter.rb b/scripts/app/presenters/performance_presenter.rb similarity index 100% rename from app/presenters/performance_presenter.rb rename to scripts/app/presenters/performance_presenter.rb diff --git a/app/presenters/standard_card_component_props.rb b/scripts/app/presenters/standard_card_component_props.rb similarity index 100% rename from app/presenters/standard_card_component_props.rb rename to scripts/app/presenters/standard_card_component_props.rb diff --git a/app/presenters/standard_presenter/for_challenge_detail_view.rb b/scripts/app/presenters/standard_presenter/for_challenge_detail_view.rb similarity index 100% rename from app/presenters/standard_presenter/for_challenge_detail_view.rb rename to scripts/app/presenters/standard_presenter/for_challenge_detail_view.rb diff --git a/app/presenters/standard_presenter/for_checkpoint_submission.rb b/scripts/app/presenters/standard_presenter/for_checkpoint_submission.rb similarity index 100% rename from app/presenters/standard_presenter/for_checkpoint_submission.rb rename to scripts/app/presenters/standard_presenter/for_checkpoint_submission.rb diff --git a/app/presenters/standard_presenter/for_standard_card.rb b/scripts/app/presenters/standard_presenter/for_standard_card.rb similarity index 100% rename from app/presenters/standard_presenter/for_standard_card.rb rename to scripts/app/presenters/standard_presenter/for_standard_card.rb diff --git a/app/presenters/standard_presenter/for_submissions_dashboard.rb b/scripts/app/presenters/standard_presenter/for_submissions_dashboard.rb similarity index 100% rename from app/presenters/standard_presenter/for_submissions_dashboard.rb rename to scripts/app/presenters/standard_presenter/for_submissions_dashboard.rb diff --git a/app/presenters/stat_progress_presenter.rb b/scripts/app/presenters/stat_progress_presenter.rb similarity index 100% rename from app/presenters/stat_progress_presenter.rb rename to scripts/app/presenters/stat_progress_presenter.rb diff --git a/app/presenters/student_progress_presenter.rb b/scripts/app/presenters/student_progress_presenter.rb similarity index 100% rename from app/presenters/student_progress_presenter.rb rename to scripts/app/presenters/student_progress_presenter.rb diff --git a/app/presenters/submissions_dashboard_presenter.rb b/scripts/app/presenters/submissions_dashboard_presenter.rb similarity index 100% rename from app/presenters/submissions_dashboard_presenter.rb rename to scripts/app/presenters/submissions_dashboard_presenter.rb diff --git a/app/presenters/submitted_challenge_answer_presenter.rb b/scripts/app/presenters/submitted_challenge_answer_presenter.rb similarity index 100% rename from app/presenters/submitted_challenge_answer_presenter.rb rename to scripts/app/presenters/submitted_challenge_answer_presenter.rb diff --git a/app/presenters/user_presenter/for_avatar.rb b/scripts/app/presenters/user_presenter/for_avatar.rb similarity index 100% rename from app/presenters/user_presenter/for_avatar.rb rename to scripts/app/presenters/user_presenter/for_avatar.rb diff --git a/app/services/activity_aggregator_service.rb b/scripts/app/services/activity_aggregator_service.rb similarity index 100% rename from app/services/activity_aggregator_service.rb rename to scripts/app/services/activity_aggregator_service.rb diff --git a/app/services/assessment_service.rb b/scripts/app/services/assessment_service.rb similarity index 100% rename from app/services/assessment_service.rb rename to scripts/app/services/assessment_service.rb diff --git a/app/services/auto_assign_release_service.rb b/scripts/app/services/auto_assign_release_service.rb similarity index 100% rename from app/services/auto_assign_release_service.rb rename to scripts/app/services/auto_assign_release_service.rb diff --git a/app/services/checkpoint_submission_service.rb b/scripts/app/services/checkpoint_submission_service.rb similarity index 100% rename from app/services/checkpoint_submission_service.rb rename to scripts/app/services/checkpoint_submission_service.rb diff --git a/app/services/cohort_standard_progress_service.rb b/scripts/app/services/cohort_standard_progress_service.rb similarity index 100% rename from app/services/cohort_standard_progress_service.rb rename to scripts/app/services/cohort_standard_progress_service.rb diff --git a/app/services/cohort_student_progress_service.rb b/scripts/app/services/cohort_student_progress_service.rb similarity index 100% rename from app/services/cohort_student_progress_service.rb rename to scripts/app/services/cohort_student_progress_service.rb diff --git a/app/services/completion_mode_percent_service.rb b/scripts/app/services/completion_mode_percent_service.rb similarity index 100% rename from app/services/completion_mode_percent_service.rb rename to scripts/app/services/completion_mode_percent_service.rb diff --git a/app/services/course_validator.rb b/scripts/app/services/course_validator.rb similarity index 100% rename from app/services/course_validator.rb rename to scripts/app/services/course_validator.rb diff --git a/app/services/create_submitted_challenge_answer_service.rb b/scripts/app/services/create_submitted_challenge_answer_service.rb similarity index 100% rename from app/services/create_submitted_challenge_answer_service.rb rename to scripts/app/services/create_submitted_challenge_answer_service.rb diff --git a/app/services/curriculum_progress_service.rb b/scripts/app/services/curriculum_progress_service.rb similarity index 100% rename from app/services/curriculum_progress_service.rb rename to scripts/app/services/curriculum_progress_service.rb diff --git a/app/services/download_github_repository_service.rb b/scripts/app/services/download_github_repository_service.rb similarity index 100% rename from app/services/download_github_repository_service.rb rename to scripts/app/services/download_github_repository_service.rb diff --git a/app/services/download_gitlab_repository_service.rb b/scripts/app/services/download_gitlab_repository_service.rb similarity index 100% rename from app/services/download_gitlab_repository_service.rb rename to scripts/app/services/download_gitlab_repository_service.rb diff --git a/app/services/download_repository_service.rb b/scripts/app/services/download_repository_service.rb similarity index 100% rename from app/services/download_repository_service.rb rename to scripts/app/services/download_repository_service.rb diff --git a/app/services/download_s3_repository_service.rb b/scripts/app/services/download_s3_repository_service.rb similarity index 100% rename from app/services/download_s3_repository_service.rb rename to scripts/app/services/download_s3_repository_service.rb diff --git a/app/services/encoded_image_link_service.rb b/scripts/app/services/encoded_image_link_service.rb similarity index 100% rename from app/services/encoded_image_link_service.rb rename to scripts/app/services/encoded_image_link_service.rb diff --git a/app/services/git_url_service.rb b/scripts/app/services/git_url_service.rb similarity index 100% rename from app/services/git_url_service.rb rename to scripts/app/services/git_url_service.rb diff --git a/app/services/mastery_average_service.rb b/scripts/app/services/mastery_average_service.rb similarity index 100% rename from app/services/mastery_average_service.rb rename to scripts/app/services/mastery_average_service.rb diff --git a/app/services/mastery_mode_percent_service.rb b/scripts/app/services/mastery_mode_percent_service.rb similarity index 100% rename from app/services/mastery_mode_percent_service.rb rename to scripts/app/services/mastery_mode_percent_service.rb diff --git a/app/services/mock_mixpanel.rb b/scripts/app/services/mock_mixpanel.rb similarity index 100% rename from app/services/mock_mixpanel.rb rename to scripts/app/services/mock_mixpanel.rb diff --git a/app/services/notification_service.rb b/scripts/app/services/notification_service.rb similarity index 100% rename from app/services/notification_service.rb rename to scripts/app/services/notification_service.rb diff --git a/app/services/platform_one_auth_resolver_service.rb b/scripts/app/services/platform_one_auth_resolver_service.rb similarity index 100% rename from app/services/platform_one_auth_resolver_service.rb rename to scripts/app/services/platform_one_auth_resolver_service.rb diff --git a/app/services/preview_content_file_service.rb b/scripts/app/services/preview_content_file_service.rb similarity index 100% rename from app/services/preview_content_file_service.rb rename to scripts/app/services/preview_content_file_service.rb diff --git a/app/services/release_destroyer_service.rb b/scripts/app/services/release_destroyer_service.rb similarity index 100% rename from app/services/release_destroyer_service.rb rename to scripts/app/services/release_destroyer_service.rb diff --git a/app/services/release_helper_service.rb b/scripts/app/services/release_helper_service.rb similarity index 100% rename from app/services/release_helper_service.rb rename to scripts/app/services/release_helper_service.rb diff --git a/app/services/resync_course_service.rb b/scripts/app/services/resync_course_service.rb similarity index 100% rename from app/services/resync_course_service.rb rename to scripts/app/services/resync_course_service.rb diff --git a/app/services/s3_asset_uploader_service.rb b/scripts/app/services/s3_asset_uploader_service.rb similarity index 100% rename from app/services/s3_asset_uploader_service.rb rename to scripts/app/services/s3_asset_uploader_service.rb diff --git a/app/services/segment_track_service.rb b/scripts/app/services/segment_track_service.rb similarity index 100% rename from app/services/segment_track_service.rb rename to scripts/app/services/segment_track_service.rb diff --git a/app/services/sql_challenge_db_service.rb b/scripts/app/services/sql_challenge_db_service.rb similarity index 100% rename from app/services/sql_challenge_db_service.rb rename to scripts/app/services/sql_challenge_db_service.rb diff --git a/app/services/standard_submissions_service.rb b/scripts/app/services/standard_submissions_service.rb similarity index 100% rename from app/services/standard_submissions_service.rb rename to scripts/app/services/standard_submissions_service.rb diff --git a/app/views/api_interactions.html.haml b/scripts/app/views/api_interactions.html.haml similarity index 100% rename from app/views/api_interactions.html.haml rename to scripts/app/views/api_interactions.html.haml diff --git a/app/views/api_token.html.haml b/scripts/app/views/api_token.html.haml similarity index 100% rename from app/views/api_token.html.haml rename to scripts/app/views/api_token.html.haml diff --git a/app/views/apitome/docs/_headers.html.erb b/scripts/app/views/apitome/docs/_headers.html.erb similarity index 100% rename from app/views/apitome/docs/_headers.html.erb rename to scripts/app/views/apitome/docs/_headers.html.erb diff --git a/app/views/apitome/docs/_params.html.erb b/scripts/app/views/apitome/docs/_params.html.erb similarity index 100% rename from app/views/apitome/docs/_params.html.erb rename to scripts/app/views/apitome/docs/_params.html.erb diff --git a/app/views/blocks/blockpagev2.html.haml b/scripts/app/views/blocks/blockpagev2.html.haml similarity index 100% rename from app/views/blocks/blockpagev2.html.haml rename to scripts/app/views/blocks/blockpagev2.html.haml diff --git a/app/views/blocks/index.html.haml b/scripts/app/views/blocks/index.html.haml similarity index 100% rename from app/views/blocks/index.html.haml rename to scripts/app/views/blocks/index.html.haml diff --git a/app/views/blocks/new.html.haml b/scripts/app/views/blocks/new.html.haml similarity index 100% rename from app/views/blocks/new.html.haml rename to scripts/app/views/blocks/new.html.haml diff --git a/app/views/blocks/releases/new.html.haml b/scripts/app/views/blocks/releases/new.html.haml similarity index 100% rename from app/views/blocks/releases/new.html.haml rename to scripts/app/views/blocks/releases/new.html.haml diff --git a/app/views/blocks/show.html.haml b/scripts/app/views/blocks/show.html.haml similarity index 100% rename from app/views/blocks/show.html.haml rename to scripts/app/views/blocks/show.html.haml diff --git a/app/views/cohorts/_cohort_edit_form.html.haml b/scripts/app/views/cohorts/_cohort_edit_form.html.haml similarity index 100% rename from app/views/cohorts/_cohort_edit_form.html.haml rename to scripts/app/views/cohorts/_cohort_edit_form.html.haml diff --git a/app/views/cohorts/_cohort_info.html.haml b/scripts/app/views/cohorts/_cohort_info.html.haml similarity index 100% rename from app/views/cohorts/_cohort_info.html.haml rename to scripts/app/views/cohorts/_cohort_info.html.haml diff --git a/app/views/cohorts/_completion_progress_donut.html.haml b/scripts/app/views/cohorts/_completion_progress_donut.html.haml similarity index 100% rename from app/views/cohorts/_completion_progress_donut.html.haml rename to scripts/app/views/cohorts/_completion_progress_donut.html.haml diff --git a/app/views/cohorts/_user_table.html.haml b/scripts/app/views/cohorts/_user_table.html.haml similarity index 100% rename from app/views/cohorts/_user_table.html.haml rename to scripts/app/views/cohorts/_user_table.html.haml diff --git a/app/views/cohorts/activity_dashboard.html.haml b/scripts/app/views/cohorts/activity_dashboard.html.haml similarity index 100% rename from app/views/cohorts/activity_dashboard.html.haml rename to scripts/app/views/cohorts/activity_dashboard.html.haml diff --git a/app/views/cohorts/blocks/content_files/_footer.html.haml b/scripts/app/views/cohorts/blocks/content_files/_footer.html.haml similarity index 100% rename from app/views/cohorts/blocks/content_files/_footer.html.haml rename to scripts/app/views/cohorts/blocks/content_files/_footer.html.haml diff --git a/app/views/cohorts/blocks/content_files/show.html.haml b/scripts/app/views/cohorts/blocks/content_files/show.html.haml similarity index 100% rename from app/views/cohorts/blocks/content_files/show.html.haml rename to scripts/app/views/cohorts/blocks/content_files/show.html.haml diff --git a/app/views/cohorts/cohort_releases/index.html.haml b/scripts/app/views/cohorts/cohort_releases/index.html.haml similarity index 100% rename from app/views/cohorts/cohort_releases/index.html.haml rename to scripts/app/views/cohorts/cohort_releases/index.html.haml diff --git a/app/views/cohorts/content.html.haml b/scripts/app/views/cohorts/content.html.haml similarity index 100% rename from app/views/cohorts/content.html.haml rename to scripts/app/views/cohorts/content.html.haml diff --git a/app/views/cohorts/content_files/checkpoint_submissions/show.html.haml b/scripts/app/views/cohorts/content_files/checkpoint_submissions/show.html.haml similarity index 100% rename from app/views/cohorts/content_files/checkpoint_submissions/show.html.haml rename to scripts/app/views/cohorts/content_files/checkpoint_submissions/show.html.haml diff --git a/app/views/cohorts/course_stats.html.haml b/scripts/app/views/cohorts/course_stats.html.haml similarity index 100% rename from app/views/cohorts/course_stats.html.haml rename to scripts/app/views/cohorts/course_stats.html.haml diff --git a/app/views/cohorts/edit.html.haml b/scripts/app/views/cohorts/edit.html.haml similarity index 100% rename from app/views/cohorts/edit.html.haml rename to scripts/app/views/cohorts/edit.html.haml diff --git a/app/views/cohorts/error.html.haml b/scripts/app/views/cohorts/error.html.haml similarity index 100% rename from app/views/cohorts/error.html.haml rename to scripts/app/views/cohorts/error.html.haml diff --git a/app/views/cohorts/feed.html.haml b/scripts/app/views/cohorts/feed.html.haml similarity index 100% rename from app/views/cohorts/feed.html.haml rename to scripts/app/views/cohorts/feed.html.haml diff --git a/app/views/cohorts/index.html.haml b/scripts/app/views/cohorts/index.html.haml similarity index 100% rename from app/views/cohorts/index.html.haml rename to scripts/app/views/cohorts/index.html.haml diff --git a/app/views/cohorts/new.html.haml b/scripts/app/views/cohorts/new.html.haml similarity index 100% rename from app/views/cohorts/new.html.haml rename to scripts/app/views/cohorts/new.html.haml diff --git a/app/views/cohorts/partnerup.html.haml b/scripts/app/views/cohorts/partnerup.html.haml similarity index 100% rename from app/views/cohorts/partnerup.html.haml rename to scripts/app/views/cohorts/partnerup.html.haml diff --git a/app/views/cohorts/setup.html.haml b/scripts/app/views/cohorts/setup.html.haml similarity index 100% rename from app/views/cohorts/setup.html.haml rename to scripts/app/views/cohorts/setup.html.haml diff --git a/app/views/cohorts/show.html.haml b/scripts/app/views/cohorts/show.html.haml similarity index 100% rename from app/views/cohorts/show.html.haml rename to scripts/app/views/cohorts/show.html.haml diff --git a/app/views/cohorts/standards/checkpoint_submissions/index.html.haml b/scripts/app/views/cohorts/standards/checkpoint_submissions/index.html.haml similarity index 100% rename from app/views/cohorts/standards/checkpoint_submissions/index.html.haml rename to scripts/app/views/cohorts/standards/checkpoint_submissions/index.html.haml diff --git a/app/views/cohorts/unit_progress.html.haml b/scripts/app/views/cohorts/unit_progress.html.haml similarity index 100% rename from app/views/cohorts/unit_progress.html.haml rename to scripts/app/views/cohorts/unit_progress.html.haml diff --git a/app/views/cohorts/users.html.haml b/scripts/app/views/cohorts/users.html.haml similarity index 100% rename from app/views/cohorts/users.html.haml rename to scripts/app/views/cohorts/users.html.haml diff --git a/app/views/cohorts/users/challenges/show.html.haml b/scripts/app/views/cohorts/users/challenges/show.html.haml similarity index 100% rename from app/views/cohorts/users/challenges/show.html.haml rename to scripts/app/views/cohorts/users/challenges/show.html.haml diff --git a/app/views/cohorts/users/mastery/index.html.haml b/scripts/app/views/cohorts/users/mastery/index.html.haml similarity index 100% rename from app/views/cohorts/users/mastery/index.html.haml rename to scripts/app/views/cohorts/users/mastery/index.html.haml diff --git a/app/views/cohorts/users/submissions_dashboard.html.haml b/scripts/app/views/cohorts/users/submissions_dashboard.html.haml similarity index 100% rename from app/views/cohorts/users/submissions_dashboard.html.haml rename to scripts/app/views/cohorts/users/submissions_dashboard.html.haml diff --git a/app/views/error_404.html.haml b/scripts/app/views/error_404.html.haml similarity index 100% rename from app/views/error_404.html.haml rename to scripts/app/views/error_404.html.haml diff --git a/app/views/error_500.html.haml b/scripts/app/views/error_500.html.haml similarity index 100% rename from app/views/error_500.html.haml rename to scripts/app/views/error_500.html.haml diff --git a/app/views/home/index.html.haml b/scripts/app/views/home/index.html.haml similarity index 100% rename from app/views/home/index.html.haml rename to scripts/app/views/home/index.html.haml diff --git a/app/views/layouts/_primary_navigation.html.haml b/scripts/app/views/layouts/_primary_navigation.html.haml similarity index 100% rename from app/views/layouts/_primary_navigation.html.haml rename to scripts/app/views/layouts/_primary_navigation.html.haml diff --git a/app/views/layouts/_secondary_navigation.html.haml b/scripts/app/views/layouts/_secondary_navigation.html.haml similarity index 100% rename from app/views/layouts/_secondary_navigation.html.haml rename to scripts/app/views/layouts/_secondary_navigation.html.haml diff --git a/app/views/layouts/application.html.haml b/scripts/app/views/layouts/application.html.haml similarity index 100% rename from app/views/layouts/application.html.haml rename to scripts/app/views/layouts/application.html.haml diff --git a/app/views/layouts/mailer.html.erb b/scripts/app/views/layouts/mailer.html.erb similarity index 100% rename from app/views/layouts/mailer.html.erb rename to scripts/app/views/layouts/mailer.html.erb diff --git a/app/views/layouts/mailer.text.erb b/scripts/app/views/layouts/mailer.text.erb similarity index 100% rename from app/views/layouts/mailer.text.erb rename to scripts/app/views/layouts/mailer.text.erb diff --git a/app/views/permalinks/permalink.html.haml b/scripts/app/views/permalinks/permalink.html.haml similarity index 100% rename from app/views/permalinks/permalink.html.haml rename to scripts/app/views/permalinks/permalink.html.haml diff --git a/app/views/shared/_content_file_js.html.haml b/scripts/app/views/shared/_content_file_js.html.haml similarity index 100% rename from app/views/shared/_content_file_js.html.haml rename to scripts/app/views/shared/_content_file_js.html.haml diff --git a/app/views/shared/_hopscotch_callbacks_js.html.haml b/scripts/app/views/shared/_hopscotch_callbacks_js.html.haml similarity index 100% rename from app/views/shared/_hopscotch_callbacks_js.html.haml rename to scripts/app/views/shared/_hopscotch_callbacks_js.html.haml diff --git a/app/views/shared/_intercom_js.html.haml b/scripts/app/views/shared/_intercom_js.html.haml similarity index 100% rename from app/views/shared/_intercom_js.html.haml rename to scripts/app/views/shared/_intercom_js.html.haml diff --git a/app/views/shared/_segment_js.html.haml b/scripts/app/views/shared/_segment_js.html.haml similarity index 100% rename from app/views/shared/_segment_js.html.haml rename to scripts/app/views/shared/_segment_js.html.haml diff --git a/app/views/user_mailer/send_file.html b/scripts/app/views/user_mailer/send_file.html similarity index 100% rename from app/views/user_mailer/send_file.html rename to scripts/app/views/user_mailer/send_file.html diff --git a/app/views/user_mailer/user_import_work.html.haml b/scripts/app/views/user_mailer/user_import_work.html.haml similarity index 100% rename from app/views/user_mailer/user_import_work.html.haml rename to scripts/app/views/user_mailer/user_import_work.html.haml diff --git a/app/views/users/edit.html.haml b/scripts/app/views/users/edit.html.haml similarity index 100% rename from app/views/users/edit.html.haml rename to scripts/app/views/users/edit.html.haml diff --git a/app/views/users/edit_user.html.haml b/scripts/app/views/users/edit_user.html.haml similarity index 100% rename from app/views/users/edit_user.html.haml rename to scripts/app/views/users/edit_user.html.haml diff --git a/app/views/users/index.html.haml b/scripts/app/views/users/index.html.haml similarity index 100% rename from app/views/users/index.html.haml rename to scripts/app/views/users/index.html.haml diff --git a/app/views/users/new.html.haml b/scripts/app/views/users/new.html.haml similarity index 100% rename from app/views/users/new.html.haml rename to scripts/app/views/users/new.html.haml diff --git a/babel.config.js b/scripts/babel.config.js similarity index 100% rename from babel.config.js rename to scripts/babel.config.js diff --git a/bin/bundle b/scripts/bin/bundle similarity index 100% rename from bin/bundle rename to scripts/bin/bundle diff --git a/bin/rails b/scripts/bin/rails similarity index 100% rename from bin/rails rename to scripts/bin/rails diff --git a/bin/rake b/scripts/bin/rake similarity index 100% rename from bin/rake rename to scripts/bin/rake diff --git a/bin/setup b/scripts/bin/setup similarity index 100% rename from bin/setup rename to scripts/bin/setup diff --git a/bin/update b/scripts/bin/update similarity index 100% rename from bin/update rename to scripts/bin/update diff --git a/bin/webpack b/scripts/bin/webpack similarity index 100% rename from bin/webpack rename to scripts/bin/webpack diff --git a/bin/webpack-dev-server b/scripts/bin/webpack-dev-server similarity index 100% rename from bin/webpack-dev-server rename to scripts/bin/webpack-dev-server diff --git a/bin/yarn b/scripts/bin/yarn similarity index 100% rename from bin/yarn rename to scripts/bin/yarn diff --git a/config.ru b/scripts/config.ru similarity index 100% rename from config.ru rename to scripts/config.ru diff --git a/config/application.rb b/scripts/config/application.rb similarity index 100% rename from config/application.rb rename to scripts/config/application.rb diff --git a/config/boot.rb b/scripts/config/boot.rb similarity index 100% rename from config/boot.rb rename to scripts/config/boot.rb diff --git a/config/database.yml b/scripts/config/database.yml similarity index 100% rename from config/database.yml rename to scripts/config/database.yml diff --git a/config/environment.rb b/scripts/config/environment.rb similarity index 100% rename from config/environment.rb rename to scripts/config/environment.rb diff --git a/config/environments/development.rb b/scripts/config/environments/development.rb similarity index 100% rename from config/environments/development.rb rename to scripts/config/environments/development.rb diff --git a/config/environments/production.rb b/scripts/config/environments/production.rb similarity index 100% rename from config/environments/production.rb rename to scripts/config/environments/production.rb diff --git a/config/environments/test.rb b/scripts/config/environments/test.rb similarity index 100% rename from config/environments/test.rb rename to scripts/config/environments/test.rb diff --git a/config/get-routes-audit.md b/scripts/config/get-routes-audit.md similarity index 100% rename from config/get-routes-audit.md rename to scripts/config/get-routes-audit.md diff --git a/config/honeybadger.yml b/scripts/config/honeybadger.yml similarity index 100% rename from config/honeybadger.yml rename to scripts/config/honeybadger.yml diff --git a/config/initializers/apitome.rb b/scripts/config/initializers/apitome.rb similarity index 100% rename from config/initializers/apitome.rb rename to scripts/config/initializers/apitome.rb diff --git a/config/initializers/application_controller_renderer.rb b/scripts/config/initializers/application_controller_renderer.rb similarity index 100% rename from config/initializers/application_controller_renderer.rb rename to scripts/config/initializers/application_controller_renderer.rb diff --git a/config/initializers/assets.rb b/scripts/config/initializers/assets.rb similarity index 100% rename from config/initializers/assets.rb rename to scripts/config/initializers/assets.rb diff --git a/config/initializers/auth_api.rb b/scripts/config/initializers/auth_api.rb similarity index 100% rename from config/initializers/auth_api.rb rename to scripts/config/initializers/auth_api.rb diff --git a/config/initializers/aws.rb b/scripts/config/initializers/aws.rb similarity index 100% rename from config/initializers/aws.rb rename to scripts/config/initializers/aws.rb diff --git a/config/initializers/backtrace_silencers.rb b/scripts/config/initializers/backtrace_silencers.rb similarity index 100% rename from config/initializers/backtrace_silencers.rb rename to scripts/config/initializers/backtrace_silencers.rb diff --git a/config/initializers/content_security_policy.rb b/scripts/config/initializers/content_security_policy.rb similarity index 100% rename from config/initializers/content_security_policy.rb rename to scripts/config/initializers/content_security_policy.rb diff --git a/config/initializers/cookies_serializer.rb b/scripts/config/initializers/cookies_serializer.rb similarity index 100% rename from config/initializers/cookies_serializer.rb rename to scripts/config/initializers/cookies_serializer.rb diff --git a/config/initializers/filter_parameter_logging.rb b/scripts/config/initializers/filter_parameter_logging.rb similarity index 100% rename from config/initializers/filter_parameter_logging.rb rename to scripts/config/initializers/filter_parameter_logging.rb diff --git a/config/initializers/inflections.rb b/scripts/config/initializers/inflections.rb similarity index 100% rename from config/initializers/inflections.rb rename to scripts/config/initializers/inflections.rb diff --git a/config/initializers/mime_types.rb b/scripts/config/initializers/mime_types.rb similarity index 100% rename from config/initializers/mime_types.rb rename to scripts/config/initializers/mime_types.rb diff --git a/config/initializers/new_framework_defaults_5_1.rb b/scripts/config/initializers/new_framework_defaults_5_1.rb similarity index 100% rename from config/initializers/new_framework_defaults_5_1.rb rename to scripts/config/initializers/new_framework_defaults_5_1.rb diff --git a/config/initializers/new_framework_defaults_5_2.rb b/scripts/config/initializers/new_framework_defaults_5_2.rb similarity index 100% rename from config/initializers/new_framework_defaults_5_2.rb rename to scripts/config/initializers/new_framework_defaults_5_2.rb diff --git a/config/initializers/octokit.rb b/scripts/config/initializers/octokit.rb similarity index 100% rename from config/initializers/octokit.rb rename to scripts/config/initializers/octokit.rb diff --git a/config/initializers/pagy.rb b/scripts/config/initializers/pagy.rb similarity index 100% rename from config/initializers/pagy.rb rename to scripts/config/initializers/pagy.rb diff --git a/config/initializers/pundit.rb b/scripts/config/initializers/pundit.rb similarity index 100% rename from config/initializers/pundit.rb rename to scripts/config/initializers/pundit.rb diff --git a/config/initializers/rack_attack.rb b/scripts/config/initializers/rack_attack.rb similarity index 100% rename from config/initializers/rack_attack.rb rename to scripts/config/initializers/rack_attack.rb diff --git a/config/initializers/segment.rb b/scripts/config/initializers/segment.rb similarity index 100% rename from config/initializers/segment.rb rename to scripts/config/initializers/segment.rb diff --git a/config/initializers/sidekiq.rb b/scripts/config/initializers/sidekiq.rb similarity index 100% rename from config/initializers/sidekiq.rb rename to scripts/config/initializers/sidekiq.rb diff --git a/config/initializers/wrap_parameters.rb b/scripts/config/initializers/wrap_parameters.rb similarity index 100% rename from config/initializers/wrap_parameters.rb rename to scripts/config/initializers/wrap_parameters.rb diff --git a/config/locales/en.yml b/scripts/config/locales/en.yml similarity index 100% rename from config/locales/en.yml rename to scripts/config/locales/en.yml diff --git a/config/puma.rb b/scripts/config/puma.rb similarity index 100% rename from config/puma.rb rename to scripts/config/puma.rb diff --git a/config/routes.rb b/scripts/config/routes.rb similarity index 100% rename from config/routes.rb rename to scripts/config/routes.rb diff --git a/config/secrets.yml b/scripts/config/secrets.yml similarity index 100% rename from config/secrets.yml rename to scripts/config/secrets.yml diff --git a/config/sidekiq.yml b/scripts/config/sidekiq.yml similarity index 100% rename from config/sidekiq.yml rename to scripts/config/sidekiq.yml diff --git a/config/spring.rb b/scripts/config/spring.rb similarity index 100% rename from config/spring.rb rename to scripts/config/spring.rb diff --git a/config/storage.yml b/scripts/config/storage.yml similarity index 100% rename from config/storage.yml rename to scripts/config/storage.yml diff --git a/config/webpack/development.js b/scripts/config/webpack/development.js similarity index 100% rename from config/webpack/development.js rename to scripts/config/webpack/development.js diff --git a/config/webpack/environment.js b/scripts/config/webpack/environment.js similarity index 100% rename from config/webpack/environment.js rename to scripts/config/webpack/environment.js diff --git a/config/webpack/loaders/typescript.js b/scripts/config/webpack/loaders/typescript.js similarity index 100% rename from config/webpack/loaders/typescript.js rename to scripts/config/webpack/loaders/typescript.js diff --git a/config/webpack/production.js b/scripts/config/webpack/production.js similarity index 100% rename from config/webpack/production.js rename to scripts/config/webpack/production.js diff --git a/config/webpack/test.js b/scripts/config/webpack/test.js similarity index 100% rename from config/webpack/test.js rename to scripts/config/webpack/test.js diff --git a/config/webpacker.yml b/scripts/config/webpacker.yml similarity index 100% rename from config/webpacker.yml rename to scripts/config/webpacker.yml diff --git a/db/drawio_schema_with_explanations.xml b/scripts/db/drawio_schema_with_explanations.xml similarity index 100% rename from db/drawio_schema_with_explanations.xml rename to scripts/db/drawio_schema_with_explanations.xml diff --git a/db/migrate/20171003191909_create_users.rb b/scripts/db/migrate/20171003191909_create_users.rb similarity index 100% rename from db/migrate/20171003191909_create_users.rb rename to scripts/db/migrate/20171003191909_create_users.rb diff --git a/db/migrate/20171005135550_add_admin_to_users.rb b/scripts/db/migrate/20171005135550_add_admin_to_users.rb similarity index 100% rename from db/migrate/20171005135550_add_admin_to_users.rb rename to scripts/db/migrate/20171005135550_add_admin_to_users.rb diff --git a/db/migrate/20171005140042_rename_users_profile_image_url.rb b/scripts/db/migrate/20171005140042_rename_users_profile_image_url.rb similarity index 100% rename from db/migrate/20171005140042_rename_users_profile_image_url.rb rename to scripts/db/migrate/20171005140042_rename_users_profile_image_url.rb diff --git a/db/migrate/20171006195948_create_blocks.rb b/scripts/db/migrate/20171006195948_create_blocks.rb similarity index 100% rename from db/migrate/20171006195948_create_blocks.rb rename to scripts/db/migrate/20171006195948_create_blocks.rb diff --git a/db/migrate/20171009194124_create_releases.rb b/scripts/db/migrate/20171009194124_create_releases.rb similarity index 100% rename from db/migrate/20171009194124_create_releases.rb rename to scripts/db/migrate/20171009194124_create_releases.rb diff --git a/db/migrate/20171011232501_add_sync_errors_to_block.rb b/scripts/db/migrate/20171011232501_add_sync_errors_to_block.rb similarity index 100% rename from db/migrate/20171011232501_add_sync_errors_to_block.rb rename to scripts/db/migrate/20171011232501_add_sync_errors_to_block.rb diff --git a/db/migrate/20171012200106_create_standards.rb b/scripts/db/migrate/20171012200106_create_standards.rb similarity index 100% rename from db/migrate/20171012200106_create_standards.rb rename to scripts/db/migrate/20171012200106_create_standards.rb diff --git a/db/migrate/20171016192627_create_cohorts.rb b/scripts/db/migrate/20171016192627_create_cohorts.rb similarity index 100% rename from db/migrate/20171016192627_create_cohorts.rb rename to scripts/db/migrate/20171016192627_create_cohorts.rb diff --git a/db/migrate/20171017205306_create_cohort_users.rb b/scripts/db/migrate/20171017205306_create_cohort_users.rb similarity index 100% rename from db/migrate/20171017205306_create_cohort_users.rb rename to scripts/db/migrate/20171017205306_create_cohort_users.rb diff --git a/db/migrate/20171017221501_remove_presence_indices_from_label_and_pretty_name_on_cohorts.rb b/scripts/db/migrate/20171017221501_remove_presence_indices_from_label_and_pretty_name_on_cohorts.rb similarity index 100% rename from db/migrate/20171017221501_remove_presence_indices_from_label_and_pretty_name_on_cohorts.rb rename to scripts/db/migrate/20171017221501_remove_presence_indices_from_label_and_pretty_name_on_cohorts.rb diff --git a/db/migrate/20171019165527_create_content_files.rb b/scripts/db/migrate/20171019165527_create_content_files.rb similarity index 100% rename from db/migrate/20171019165527_create_content_files.rb rename to scripts/db/migrate/20171019165527_create_content_files.rb diff --git a/db/migrate/20171019192005_create_cohort_releases.rb b/scripts/db/migrate/20171019192005_create_cohort_releases.rb similarity index 100% rename from db/migrate/20171019192005_create_cohort_releases.rb rename to scripts/db/migrate/20171019192005_create_cohort_releases.rb diff --git a/db/migrate/20171023211301_create_challenges.rb b/scripts/db/migrate/20171023211301_create_challenges.rb similarity index 100% rename from db/migrate/20171023211301_create_challenges.rb rename to scripts/db/migrate/20171023211301_create_challenges.rb diff --git a/db/migrate/20171024202210_create_checkpoint_submissions.rb b/scripts/db/migrate/20171024202210_create_checkpoint_submissions.rb similarity index 100% rename from db/migrate/20171024202210_create_checkpoint_submissions.rb rename to scripts/db/migrate/20171024202210_create_checkpoint_submissions.rb diff --git a/db/migrate/20171024203630_create_submitted_challenge_answers.rb b/scripts/db/migrate/20171024203630_create_submitted_challenge_answers.rb similarity index 100% rename from db/migrate/20171024203630_create_submitted_challenge_answers.rb rename to scripts/db/migrate/20171024203630_create_submitted_challenge_answers.rb diff --git a/db/migrate/20171025211916_create_performances.rb b/scripts/db/migrate/20171025211916_create_performances.rb similarity index 100% rename from db/migrate/20171025211916_create_performances.rb rename to scripts/db/migrate/20171025211916_create_performances.rb diff --git a/db/migrate/20171025223250_add_autoscore_to_content_files.rb b/scripts/db/migrate/20171025223250_add_autoscore_to_content_files.rb similarity index 100% rename from db/migrate/20171025223250_add_autoscore_to_content_files.rb rename to scripts/db/migrate/20171025223250_add_autoscore_to_content_files.rb diff --git a/db/migrate/20171026193413_add_title_to_content_files.rb b/scripts/db/migrate/20171026193413_add_title_to_content_files.rb similarity index 100% rename from db/migrate/20171026193413_add_title_to_content_files.rb rename to scripts/db/migrate/20171026193413_add_title_to_content_files.rb diff --git a/db/migrate/20171102144822_cohort_release_unique_index.rb b/scripts/db/migrate/20171102144822_cohort_release_unique_index.rb similarity index 100% rename from db/migrate/20171102144822_cohort_release_unique_index.rb rename to scripts/db/migrate/20171102144822_cohort_release_unique_index.rb diff --git a/db/migrate/20171102165314_add_unique_constraint_to_block_title.rb b/scripts/db/migrate/20171102165314_add_unique_constraint_to_block_title.rb similarity index 100% rename from db/migrate/20171102165314_add_unique_constraint_to_block_title.rb rename to scripts/db/migrate/20171102165314_add_unique_constraint_to_block_title.rb diff --git a/db/migrate/20171102171128_add_position_to_cohort_releases.rb b/scripts/db/migrate/20171102171128_add_position_to_cohort_releases.rb similarity index 100% rename from db/migrate/20171102171128_add_position_to_cohort_releases.rb rename to scripts/db/migrate/20171102171128_add_position_to_cohort_releases.rb diff --git a/db/migrate/20171127223701_create_activities.rb b/scripts/db/migrate/20171127223701_create_activities.rb similarity index 100% rename from db/migrate/20171127223701_create_activities.rb rename to scripts/db/migrate/20171127223701_create_activities.rb diff --git a/db/migrate/20171130183523_create_user_last_viewed_standard_path.rb b/scripts/db/migrate/20171130183523_create_user_last_viewed_standard_path.rb similarity index 100% rename from db/migrate/20171130183523_create_user_last_viewed_standard_path.rb rename to scripts/db/migrate/20171130183523_create_user_last_viewed_standard_path.rb diff --git a/db/migrate/20171130185636_add_uid_to_content_files.rb b/scripts/db/migrate/20171130185636_add_uid_to_content_files.rb similarity index 100% rename from db/migrate/20171130185636_add_uid_to_content_files.rb rename to scripts/db/migrate/20171130185636_add_uid_to_content_files.rb diff --git a/db/migrate/20171205211624_add_slack_data_to_user.rb b/scripts/db/migrate/20171205211624_add_slack_data_to_user.rb similarity index 100% rename from db/migrate/20171205211624_add_slack_data_to_user.rb rename to scripts/db/migrate/20171205211624_add_slack_data_to_user.rb diff --git a/db/migrate/20180104213519_add_standard_uid_to_performances.rb b/scripts/db/migrate/20180104213519_add_standard_uid_to_performances.rb similarity index 100% rename from db/migrate/20180104213519_add_standard_uid_to_performances.rb rename to scripts/db/migrate/20180104213519_add_standard_uid_to_performances.rb diff --git a/db/migrate/20180110174447_add_type_relative_display_name_to_content_files.rb b/scripts/db/migrate/20180110174447_add_type_relative_display_name_to_content_files.rb similarity index 100% rename from db/migrate/20180110174447_add_type_relative_display_name_to_content_files.rb rename to scripts/db/migrate/20180110174447_add_type_relative_display_name_to_content_files.rb diff --git a/db/migrate/20180110223429_add_auth_roles_to_user.rb b/scripts/db/migrate/20180110223429_add_auth_roles_to_user.rb similarity index 100% rename from db/migrate/20180110223429_add_auth_roles_to_user.rb rename to scripts/db/migrate/20180110223429_add_auth_roles_to_user.rb diff --git a/db/migrate/20180110224150_denormalize_submitted_challenge_answers.rb b/scripts/db/migrate/20180110224150_denormalize_submitted_challenge_answers.rb similarity index 100% rename from db/migrate/20180110224150_denormalize_submitted_challenge_answers.rb rename to scripts/db/migrate/20180110224150_denormalize_submitted_challenge_answers.rb diff --git a/db/migrate/20180110233303_add_roles_to_cohort_user.rb b/scripts/db/migrate/20180110233303_add_roles_to_cohort_user.rb similarity index 100% rename from db/migrate/20180110233303_add_roles_to_cohort_user.rb rename to scripts/db/migrate/20180110233303_add_roles_to_cohort_user.rb diff --git a/db/migrate/20180112234504_add_last_viewed_cohort_id_to_users.rb b/scripts/db/migrate/20180112234504_add_last_viewed_cohort_id_to_users.rb similarity index 100% rename from db/migrate/20180112234504_add_last_viewed_cohort_id_to_users.rb rename to scripts/db/migrate/20180112234504_add_last_viewed_cohort_id_to_users.rb diff --git a/db/migrate/20180116174519_add_github_user_name_to_user.rb b/scripts/db/migrate/20180116174519_add_github_user_name_to_user.rb similarity index 100% rename from db/migrate/20180116174519_add_github_user_name_to_user.rb rename to scripts/db/migrate/20180116174519_add_github_user_name_to_user.rb diff --git a/db/migrate/20180116181937_add_taught_in_learn_to_cohorts.rb b/scripts/db/migrate/20180116181937_add_taught_in_learn_to_cohorts.rb similarity index 100% rename from db/migrate/20180116181937_add_taught_in_learn_to_cohorts.rb rename to scripts/db/migrate/20180116181937_add_taught_in_learn_to_cohorts.rb diff --git a/db/migrate/20180116213927_remove_forge_admin_and_role.rb b/scripts/db/migrate/20180116213927_remove_forge_admin_and_role.rb similarity index 100% rename from db/migrate/20180116213927_remove_forge_admin_and_role.rb rename to scripts/db/migrate/20180116213927_remove_forge_admin_and_role.rb diff --git a/db/migrate/20180119184121_add_cohort_id_to_submitted_challenge_answer.rb b/scripts/db/migrate/20180119184121_add_cohort_id_to_submitted_challenge_answer.rb similarity index 100% rename from db/migrate/20180119184121_add_cohort_id_to_submitted_challenge_answer.rb rename to scripts/db/migrate/20180119184121_add_cohort_id_to_submitted_challenge_answer.rb diff --git a/db/migrate/20180124221642_denormalize_checkpoint_submissions.rb b/scripts/db/migrate/20180124221642_denormalize_checkpoint_submissions.rb similarity index 100% rename from db/migrate/20180124221642_denormalize_checkpoint_submissions.rb rename to scripts/db/migrate/20180124221642_denormalize_checkpoint_submissions.rb diff --git a/db/migrate/20180125212203_rename_taught_in_learn.rb b/scripts/db/migrate/20180125212203_rename_taught_in_learn.rb similarity index 100% rename from db/migrate/20180125212203_rename_taught_in_learn.rb rename to scripts/db/migrate/20180125212203_rename_taught_in_learn.rb diff --git a/db/migrate/20180125222044_change_learn_v2_default.rb b/scripts/db/migrate/20180125222044_change_learn_v2_default.rb similarity index 100% rename from db/migrate/20180125222044_change_learn_v2_default.rb rename to scripts/db/migrate/20180125222044_change_learn_v2_default.rb diff --git a/db/migrate/20180131220605_create_notifications.rb b/scripts/db/migrate/20180131220605_create_notifications.rb similarity index 100% rename from db/migrate/20180131220605_create_notifications.rb rename to scripts/db/migrate/20180131220605_create_notifications.rb diff --git a/db/migrate/20180202225951_add_github_sha_to_releases.rb b/scripts/db/migrate/20180202225951_add_github_sha_to_releases.rb similarity index 100% rename from db/migrate/20180202225951_add_github_sha_to_releases.rb rename to scripts/db/migrate/20180202225951_add_github_sha_to_releases.rb diff --git a/db/migrate/20180209175941_add_use_latest_release_to_cohort_releases.rb b/scripts/db/migrate/20180209175941_add_use_latest_release_to_cohort_releases.rb similarity index 100% rename from db/migrate/20180209175941_add_use_latest_release_to_cohort_releases.rb rename to scripts/db/migrate/20180209175941_add_use_latest_release_to_cohort_releases.rb diff --git a/db/migrate/20180313220132_add_docker_directory_path_to_challenges.rb b/scripts/db/migrate/20180313220132_add_docker_directory_path_to_challenges.rb similarity index 100% rename from db/migrate/20180313220132_add_docker_directory_path_to_challenges.rb rename to scripts/db/migrate/20180313220132_add_docker_directory_path_to_challenges.rb diff --git a/db/migrate/20180316222140_rename_cohort_title_to_name.rb b/scripts/db/migrate/20180316222140_rename_cohort_title_to_name.rb similarity index 100% rename from db/migrate/20180316222140_rename_cohort_title_to_name.rb rename to scripts/db/migrate/20180316222140_rename_cohort_title_to_name.rb diff --git a/db/migrate/20180320162849_add_deleted_at_to_cohorts.rb b/scripts/db/migrate/20180320162849_add_deleted_at_to_cohorts.rb similarity index 100% rename from db/migrate/20180320162849_add_deleted_at_to_cohorts.rb rename to scripts/db/migrate/20180320162849_add_deleted_at_to_cohorts.rb diff --git a/db/migrate/20180402212114_remove_pretty_name_from_cohort.rb b/scripts/db/migrate/20180402212114_remove_pretty_name_from_cohort.rb similarity index 100% rename from db/migrate/20180402212114_remove_pretty_name_from_cohort.rb rename to scripts/db/migrate/20180402212114_remove_pretty_name_from_cohort.rb diff --git a/db/migrate/20180412214504_add_used_by_application_to_cohorts.rb b/scripts/db/migrate/20180412214504_add_used_by_application_to_cohorts.rb similarity index 100% rename from db/migrate/20180412214504_add_used_by_application_to_cohorts.rb rename to scripts/db/migrate/20180412214504_add_used_by_application_to_cohorts.rb diff --git a/db/migrate/20180412223312_populate_used_by_application.rb b/scripts/db/migrate/20180412223312_populate_used_by_application.rb similarity index 100% rename from db/migrate/20180412223312_populate_used_by_application.rb rename to scripts/db/migrate/20180412223312_populate_used_by_application.rb diff --git a/db/migrate/20180504193033_add_feature_branch_columns_to_releases.rb b/scripts/db/migrate/20180504193033_add_feature_branch_columns_to_releases.rb similarity index 100% rename from db/migrate/20180504193033_add_feature_branch_columns_to_releases.rb rename to scripts/db/migrate/20180504193033_add_feature_branch_columns_to_releases.rb diff --git a/db/migrate/20180504200226_add_pending_release_id_to_cohort_releases.rb b/scripts/db/migrate/20180504200226_add_pending_release_id_to_cohort_releases.rb similarity index 100% rename from db/migrate/20180504200226_add_pending_release_id_to_cohort_releases.rb rename to scripts/db/migrate/20180504200226_add_pending_release_id_to_cohort_releases.rb diff --git a/db/migrate/20180813205413_add_readme_text_to_release.rb b/scripts/db/migrate/20180813205413_add_readme_text_to_release.rb similarity index 100% rename from db/migrate/20180813205413_add_readme_text_to_release.rb rename to scripts/db/migrate/20180813205413_add_readme_text_to_release.rb diff --git a/db/migrate/20180813213358_add_mode_to_cohort.rb b/scripts/db/migrate/20180813213358_add_mode_to_cohort.rb similarity index 100% rename from db/migrate/20180813213358_add_mode_to_cohort.rb rename to scripts/db/migrate/20180813213358_add_mode_to_cohort.rb diff --git a/db/migrate/20180813214453_populate_mode_cohorts.rb b/scripts/db/migrate/20180813214453_populate_mode_cohorts.rb similarity index 100% rename from db/migrate/20180813214453_populate_mode_cohorts.rb rename to scripts/db/migrate/20180813214453_populate_mode_cohorts.rb diff --git a/db/migrate/20180817181129_add_cohort_id_to_user_last_viewed_standard_path.rb b/scripts/db/migrate/20180817181129_add_cohort_id_to_user_last_viewed_standard_path.rb similarity index 100% rename from db/migrate/20180817181129_add_cohort_id_to_user_last_viewed_standard_path.rb rename to scripts/db/migrate/20180817181129_add_cohort_id_to_user_last_viewed_standard_path.rb diff --git a/db/migrate/20180824200753_create_lesson_visits.rb b/scripts/db/migrate/20180824200753_create_lesson_visits.rb similarity index 100% rename from db/migrate/20180824200753_create_lesson_visits.rb rename to scripts/db/migrate/20180824200753_create_lesson_visits.rb diff --git a/db/migrate/20181112215710_add_preferred_campus_to_users.rb b/scripts/db/migrate/20181112215710_add_preferred_campus_to_users.rb similarity index 100% rename from db/migrate/20181112215710_add_preferred_campus_to_users.rb rename to scripts/db/migrate/20181112215710_add_preferred_campus_to_users.rb diff --git a/db/migrate/20181114190340_create_job_results.rb b/scripts/db/migrate/20181114190340_create_job_results.rb similarity index 100% rename from db/migrate/20181114190340_create_job_results.rb rename to scripts/db/migrate/20181114190340_create_job_results.rb diff --git a/db/migrate/20181120221622_create_sections.rb b/scripts/db/migrate/20181120221622_create_sections.rb similarity index 100% rename from db/migrate/20181120221622_create_sections.rb rename to scripts/db/migrate/20181120221622_create_sections.rb diff --git a/db/migrate/20181121202104_add_section_id_to_cohort_releases.rb b/scripts/db/migrate/20181121202104_add_section_id_to_cohort_releases.rb similarity index 100% rename from db/migrate/20181121202104_add_section_id_to_cohort_releases.rb rename to scripts/db/migrate/20181121202104_add_section_id_to_cohort_releases.rb diff --git a/db/migrate/20181203215524_add_challenge_completion_to_performance.rb b/scripts/db/migrate/20181203215524_add_challenge_completion_to_performance.rb similarity index 100% rename from db/migrate/20181203215524_add_challenge_completion_to_performance.rb rename to scripts/db/migrate/20181203215524_add_challenge_completion_to_performance.rb diff --git a/db/migrate/20181213180900_add_show_tests_to_challenges.rb b/scripts/db/migrate/20181213180900_add_show_tests_to_challenges.rb similarity index 100% rename from db/migrate/20181213180900_add_show_tests_to_challenges.rb rename to scripts/db/migrate/20181213180900_add_show_tests_to_challenges.rb diff --git a/db/migrate/20181214175640_create_content_visibilities.rb b/scripts/db/migrate/20181214175640_create_content_visibilities.rb similarity index 100% rename from db/migrate/20181214175640_create_content_visibilities.rb rename to scripts/db/migrate/20181214175640_create_content_visibilities.rb diff --git a/db/migrate/20181220005015_add_default_visibility_to_content_files.rb b/scripts/db/migrate/20181220005015_add_default_visibility_to_content_files.rb similarity index 100% rename from db/migrate/20181220005015_add_default_visibility_to_content_files.rb rename to scripts/db/migrate/20181220005015_add_default_visibility_to_content_files.rb diff --git a/db/migrate/20190410171829_create_pairings.rb b/scripts/db/migrate/20190410171829_create_pairings.rb similarity index 100% rename from db/migrate/20190410171829_create_pairings.rb rename to scripts/db/migrate/20190410171829_create_pairings.rb diff --git a/db/migrate/20190423171448_add_data_path_to_challenge.rb b/scripts/db/migrate/20190423171448_add_data_path_to_challenge.rb similarity index 100% rename from db/migrate/20190423171448_add_data_path_to_challenge.rb rename to scripts/db/migrate/20190423171448_add_data_path_to_challenge.rb diff --git a/db/migrate/20190510193410_add_last_setup_visit_to_cohort_users.rb b/scripts/db/migrate/20190510193410_add_last_setup_visit_to_cohort_users.rb similarity index 100% rename from db/migrate/20190510193410_add_last_setup_visit_to_cohort_users.rb rename to scripts/db/migrate/20190510193410_add_last_setup_visit_to_cohort_users.rb diff --git a/db/migrate/20190520223958_add_max_attempts_to_content_files.rb b/scripts/db/migrate/20190520223958_add_max_attempts_to_content_files.rb similarity index 100% rename from db/migrate/20190520223958_add_max_attempts_to_content_files.rb rename to scripts/db/migrate/20190520223958_add_max_attempts_to_content_files.rb diff --git a/db/migrate/20190529170059_add_allowed_attempts_to_challenge.rb b/scripts/db/migrate/20190529170059_add_allowed_attempts_to_challenge.rb similarity index 100% rename from db/migrate/20190529170059_add_allowed_attempts_to_challenge.rb rename to scripts/db/migrate/20190529170059_add_allowed_attempts_to_challenge.rb diff --git a/db/migrate/20190624222000_remove_max_attempts_from_challenges.rb b/scripts/db/migrate/20190624222000_remove_max_attempts_from_challenges.rb similarity index 100% rename from db/migrate/20190624222000_remove_max_attempts_from_challenges.rb rename to scripts/db/migrate/20190624222000_remove_max_attempts_from_challenges.rb diff --git a/db/migrate/20190625173725_add_points_and_success_criteria_to_challenges.rb b/scripts/db/migrate/20190625173725_add_points_and_success_criteria_to_challenges.rb similarity index 100% rename from db/migrate/20190625173725_add_points_and_success_criteria_to_challenges.rb rename to scripts/db/migrate/20190625173725_add_points_and_success_criteria_to_challenges.rb diff --git a/db/migrate/20190709170851_drop_learn_version_columns_on_cohorts.rb b/scripts/db/migrate/20190709170851_drop_learn_version_columns_on_cohorts.rb similarity index 100% rename from db/migrate/20190709170851_drop_learn_version_columns_on_cohorts.rb rename to scripts/db/migrate/20190709170851_drop_learn_version_columns_on_cohorts.rb diff --git a/db/migrate/20190829203949_add_settings_to_cohorts.rb b/scripts/db/migrate/20190829203949_add_settings_to_cohorts.rb similarity index 100% rename from db/migrate/20190829203949_add_settings_to_cohorts.rb rename to scripts/db/migrate/20190829203949_add_settings_to_cohorts.rb diff --git a/db/migrate/20190910161219_add_points_to_submitted_challenge_answer.rb b/scripts/db/migrate/20190910161219_add_points_to_submitted_challenge_answer.rb similarity index 100% rename from db/migrate/20190910161219_add_points_to_submitted_challenge_answer.rb rename to scripts/db/migrate/20190910161219_add_points_to_submitted_challenge_answer.rb diff --git a/db/migrate/20190910161303_add_points_to_checkpoint_submissions.rb b/scripts/db/migrate/20190910161303_add_points_to_checkpoint_submissions.rb similarity index 100% rename from db/migrate/20190910161303_add_points_to_checkpoint_submissions.rb rename to scripts/db/migrate/20190910161303_add_points_to_checkpoint_submissions.rb diff --git a/db/migrate/20190919173956_change_success_criteria_to_rubric_on_challenges.rb b/scripts/db/migrate/20190919173956_change_success_criteria_to_rubric_on_challenges.rb similarity index 100% rename from db/migrate/20190919173956_change_success_criteria_to_rubric_on_challenges.rb rename to scripts/db/migrate/20190919173956_change_success_criteria_to_rubric_on_challenges.rb diff --git a/db/migrate/20191001214559_add_topics_to_challenges.rb b/scripts/db/migrate/20191001214559_add_topics_to_challenges.rb similarity index 100% rename from db/migrate/20191001214559_add_topics_to_challenges.rb rename to scripts/db/migrate/20191001214559_add_topics_to_challenges.rb diff --git a/db/migrate/20191001221324_add_perf_data_to_submissions.rb b/scripts/db/migrate/20191001221324_add_perf_data_to_submissions.rb similarity index 100% rename from db/migrate/20191001221324_add_perf_data_to_submissions.rb rename to scripts/db/migrate/20191001221324_add_perf_data_to_submissions.rb diff --git a/db/migrate/20191008211403_add_release_id_to_challenges.rb b/scripts/db/migrate/20191008211403_add_release_id_to_challenges.rb similarity index 100% rename from db/migrate/20191008211403_add_release_id_to_challenges.rb rename to scripts/db/migrate/20191008211403_add_release_id_to_challenges.rb diff --git a/db/migrate/20191009214248_add_user_id_to_release.rb b/scripts/db/migrate/20191009214248_add_user_id_to_release.rb similarity index 100% rename from db/migrate/20191009214248_add_user_id_to_release.rb rename to scripts/db/migrate/20191009214248_add_user_id_to_release.rb diff --git a/db/migrate/20191024200444_add_visibility_type_to_content_visibilities.rb b/scripts/db/migrate/20191024200444_add_visibility_type_to_content_visibilities.rb similarity index 100% rename from db/migrate/20191024200444_add_visibility_type_to_content_visibilities.rb rename to scripts/db/migrate/20191024200444_add_visibility_type_to_content_visibilities.rb diff --git a/db/migrate/20191031212058_add_api_token_to_user.rb b/scripts/db/migrate/20191031212058_add_api_token_to_user.rb similarity index 100% rename from db/migrate/20191031212058_add_api_token_to_user.rb rename to scripts/db/migrate/20191031212058_add_api_token_to_user.rb diff --git a/db/migrate/20191108211234_add_preview_to_releases.rb b/scripts/db/migrate/20191108211234_add_preview_to_releases.rb similarity index 100% rename from db/migrate/20191108211234_add_preview_to_releases.rb rename to scripts/db/migrate/20191108211234_add_preview_to_releases.rb diff --git a/db/migrate/20191114211938_create_api_interactions.rb b/scripts/db/migrate/20191114211938_create_api_interactions.rb similarity index 100% rename from db/migrate/20191114211938_create_api_interactions.rb rename to scripts/db/migrate/20191114211938_create_api_interactions.rb diff --git a/db/migrate/20191119225902_add_sandbox_boolean_to_cohorts.rb b/scripts/db/migrate/20191119225902_add_sandbox_boolean_to_cohorts.rb similarity index 100% rename from db/migrate/20191119225902_add_sandbox_boolean_to_cohorts.rb rename to scripts/db/migrate/20191119225902_add_sandbox_boolean_to_cohorts.rb diff --git a/db/migrate/20191206230913_add_sync_warnings.rb b/scripts/db/migrate/20191206230913_add_sync_warnings.rb similarity index 100% rename from db/migrate/20191206230913_add_sync_warnings.rb rename to scripts/db/migrate/20191206230913_add_sync_warnings.rb diff --git a/db/migrate/20191209165026_add_metadata_to_api_interactions.rb b/scripts/db/migrate/20191209165026_add_metadata_to_api_interactions.rb similarity index 100% rename from db/migrate/20191209165026_add_metadata_to_api_interactions.rb rename to scripts/db/migrate/20191209165026_add_metadata_to_api_interactions.rb diff --git a/db/migrate/20191218232717_add_assign_partial_credig_to_challenges.rb b/scripts/db/migrate/20191218232717_add_assign_partial_credig_to_challenges.rb similarity index 100% rename from db/migrate/20191218232717_add_assign_partial_credig_to_challenges.rb rename to scripts/db/migrate/20191218232717_add_assign_partial_credig_to_challenges.rb diff --git a/db/migrate/20200108184027_add_end_time_to_checkpoint_submissions.rb b/scripts/db/migrate/20200108184027_add_end_time_to_checkpoint_submissions.rb similarity index 100% rename from db/migrate/20200108184027_add_end_time_to_checkpoint_submissions.rb rename to scripts/db/migrate/20200108184027_add_end_time_to_checkpoint_submissions.rb diff --git a/db/migrate/20200110201253_change_cohort_default_percentage.rb b/scripts/db/migrate/20200110201253_change_cohort_default_percentage.rb similarity index 100% rename from db/migrate/20200110201253_change_cohort_default_percentage.rb rename to scripts/db/migrate/20200110201253_change_cohort_default_percentage.rb diff --git a/db/migrate/20200213201649_add_time_limit_to_content_file.rb b/scripts/db/migrate/20200213201649_add_time_limit_to_content_file.rb similarity index 100% rename from db/migrate/20200213201649_add_time_limit_to_content_file.rb rename to scripts/db/migrate/20200213201649_add_time_limit_to_content_file.rb diff --git a/db/migrate/20200310222235_add_submitted_at_to_checkpoint_submissions.rb b/scripts/db/migrate/20200310222235_add_submitted_at_to_checkpoint_submissions.rb similarity index 100% rename from db/migrate/20200310222235_add_submitted_at_to_checkpoint_submissions.rb rename to scripts/db/migrate/20200310222235_add_submitted_at_to_checkpoint_submissions.rb diff --git a/db/migrate/20200408212051_add_allow_paired_submissions_to_cohort.rb b/scripts/db/migrate/20200408212051_add_allow_paired_submissions_to_cohort.rb similarity index 100% rename from db/migrate/20200408212051_add_allow_paired_submissions_to_cohort.rb rename to scripts/db/migrate/20200408212051_add_allow_paired_submissions_to_cohort.rb diff --git a/db/migrate/20200416155234_add_pair_submission_ids_to_checkpoint_submissinos.rb b/scripts/db/migrate/20200416155234_add_pair_submission_ids_to_checkpoint_submissinos.rb similarity index 100% rename from db/migrate/20200416155234_add_pair_submission_ids_to_checkpoint_submissinos.rb rename to scripts/db/migrate/20200416155234_add_pair_submission_ids_to_checkpoint_submissinos.rb diff --git a/db/migrate/20200430165251_add_external_to_challenge.rb b/scripts/db/migrate/20200430165251_add_external_to_challenge.rb similarity index 100% rename from db/migrate/20200430165251_add_external_to_challenge.rb rename to scripts/db/migrate/20200430165251_add_external_to_challenge.rb diff --git a/db/migrate/20200702155846_add_cache_to_blocks.rb b/scripts/db/migrate/20200702155846_add_cache_to_blocks.rb similarity index 100% rename from db/migrate/20200702155846_add_cache_to_blocks.rb rename to scripts/db/migrate/20200702155846_add_cache_to_blocks.rb diff --git a/db/migrate/20200707164932_add_archived_at_to_blocks.rb b/scripts/db/migrate/20200707164932_add_archived_at_to_blocks.rb similarity index 100% rename from db/migrate/20200707164932_add_archived_at_to_blocks.rb rename to scripts/db/migrate/20200707164932_add_archived_at_to_blocks.rb diff --git a/db/migrate/20200720213420_add_block_location_details_to_blocks.rb b/scripts/db/migrate/20200720213420_add_block_location_details_to_blocks.rb similarity index 100% rename from db/migrate/20200720213420_add_block_location_details_to_blocks.rb rename to scripts/db/migrate/20200720213420_add_block_location_details_to_blocks.rb diff --git a/db/migrate/20200724195251_add_whitelabeled_to_cohorts.rb b/scripts/db/migrate/20200724195251_add_whitelabeled_to_cohorts.rb similarity index 100% rename from db/migrate/20200724195251_add_whitelabeled_to_cohorts.rb rename to scripts/db/migrate/20200724195251_add_whitelabeled_to_cohorts.rb diff --git a/db/migrate/20200729214247_remove_block_uniqueness_pg_columns.rb b/scripts/db/migrate/20200729214247_remove_block_uniqueness_pg_columns.rb similarity index 100% rename from db/migrate/20200729214247_remove_block_uniqueness_pg_columns.rb rename to scripts/db/migrate/20200729214247_remove_block_uniqueness_pg_columns.rb diff --git a/db/migrate/20200811215713_add_student_import_status_to_cohorts.rb b/scripts/db/migrate/20200811215713_add_student_import_status_to_cohorts.rb similarity index 100% rename from db/migrate/20200811215713_add_student_import_status_to_cohorts.rb rename to scripts/db/migrate/20200811215713_add_student_import_status_to_cohorts.rb diff --git a/db/migrate/20200818172419_addd_docker_directory_zip_to_challenges.rb b/scripts/db/migrate/20200818172419_addd_docker_directory_zip_to_challenges.rb similarity index 100% rename from db/migrate/20200818172419_addd_docker_directory_zip_to_challenges.rb rename to scripts/db/migrate/20200818172419_addd_docker_directory_zip_to_challenges.rb diff --git a/db/migrate/20200828165130_default_block_org_tog_school.rb b/scripts/db/migrate/20200828165130_default_block_org_tog_school.rb similarity index 100% rename from db/migrate/20200828165130_default_block_org_tog_school.rb rename to scripts/db/migrate/20200828165130_default_block_org_tog_school.rb diff --git a/db/migrate/20200925230149_remove_null_constraints_from_users.rb b/scripts/db/migrate/20200925230149_remove_null_constraints_from_users.rb similarity index 100% rename from db/migrate/20200925230149_remove_null_constraints_from_users.rb rename to scripts/db/migrate/20200925230149_remove_null_constraints_from_users.rb diff --git a/db/migrate/20200929004708_remove_null_email_from_users.rb b/scripts/db/migrate/20200929004708_remove_null_email_from_users.rb similarity index 100% rename from db/migrate/20200929004708_remove_null_email_from_users.rb rename to scripts/db/migrate/20200929004708_remove_null_email_from_users.rb diff --git a/db/schema.rb b/scripts/db/schema.rb similarity index 100% rename from db/schema.rb rename to scripts/db/schema.rb diff --git a/db/seeds.rb b/scripts/db/seeds.rb similarity index 100% rename from db/seeds.rb rename to scripts/db/seeds.rb diff --git a/scripts/delete-blocks b/scripts/delete-blocks new file mode 100644 index 0000000..3e3bb40 --- /dev/null +++ b/scripts/delete-blocks @@ -0,0 +1,11 @@ + + +delete from submitted_challenge_answers where true; +delete from challenges where true; +delete from content_files where true; +delete from job_results where true; +delete from sections where true; +delete from standards where true; +delete from cohort_releases where true; +delete from releases where true; +delete from blocks where true; diff --git a/doc/api.md b/scripts/doc/api.md similarity index 100% rename from doc/api.md rename to scripts/doc/api.md diff --git a/doc/api/cohorts/creating_a_new_cohort.json b/scripts/doc/api/cohorts/creating_a_new_cohort.json similarity index 100% rename from doc/api/cohorts/creating_a_new_cohort.json rename to scripts/doc/api/cohorts/creating_a_new_cohort.json diff --git a/doc/api/cohorts/viewing_curriculum_details.json b/scripts/doc/api/cohorts/viewing_curriculum_details.json similarity index 100% rename from doc/api/cohorts/viewing_curriculum_details.json rename to scripts/doc/api/cohorts/viewing_curriculum_details.json diff --git a/doc/api/content/update_content_visibility.json b/scripts/doc/api/content/update_content_visibility.json similarity index 100% rename from doc/api/content/update_content_visibility.json rename to scripts/doc/api/content/update_content_visibility.json diff --git a/doc/api/enrollments/creating_a_user_and_their_enrollment.json b/scripts/doc/api/enrollments/creating_a_user_and_their_enrollment.json similarity index 100% rename from doc/api/enrollments/creating_a_user_and_their_enrollment.json rename to scripts/doc/api/enrollments/creating_a_user_and_their_enrollment.json diff --git a/doc/api/enrollments/unenrolling_a_user_from_a_cohort.json b/scripts/doc/api/enrollments/unenrolling_a_user_from_a_cohort.json similarity index 100% rename from doc/api/enrollments/unenrolling_a_user_from_a_cohort.json rename to scripts/doc/api/enrollments/unenrolling_a_user_from_a_cohort.json diff --git a/doc/api/enrollments/updating_a_user's_enrollment_roles.json b/scripts/doc/api/enrollments/updating_a_user's_enrollment_roles.json similarity index 100% rename from doc/api/enrollments/updating_a_user's_enrollment_roles.json rename to scripts/doc/api/enrollments/updating_a_user's_enrollment_roles.json diff --git a/doc/api/enrollments/viewing_cohort_enrollments.json b/scripts/doc/api/enrollments/viewing_cohort_enrollments.json similarity index 100% rename from doc/api/enrollments/viewing_cohort_enrollments.json rename to scripts/doc/api/enrollments/viewing_cohort_enrollments.json diff --git a/doc/api/index.json b/scripts/doc/api/index.json similarity index 100% rename from doc/api/index.json rename to scripts/doc/api/index.json diff --git a/doc/api/units/update_unit_visibility.json b/scripts/doc/api/units/update_unit_visibility.json similarity index 100% rename from doc/api/units/update_unit_visibility.json rename to scripts/doc/api/units/update_unit_visibility.json diff --git a/doc/api/users/regenerate_user_token.json b/scripts/doc/api/users/regenerate_user_token.json similarity index 100% rename from doc/api/users/regenerate_user_token.json rename to scripts/doc/api/users/regenerate_user_token.json diff --git a/entrypoint-server.sh b/scripts/entrypoint-server.sh similarity index 100% rename from entrypoint-server.sh rename to scripts/entrypoint-server.sh diff --git a/gems/block-parser/Dockerfile b/scripts/gems/block-parser/Dockerfile similarity index 100% rename from gems/block-parser/Dockerfile rename to scripts/gems/block-parser/Dockerfile diff --git a/gems/block-parser/Gemfile b/scripts/gems/block-parser/Gemfile similarity index 100% rename from gems/block-parser/Gemfile rename to scripts/gems/block-parser/Gemfile diff --git a/gems/block-parser/Gemfile.lock b/scripts/gems/block-parser/Gemfile.lock similarity index 100% rename from gems/block-parser/Gemfile.lock rename to scripts/gems/block-parser/Gemfile.lock diff --git a/gems/block-parser/README.md b/scripts/gems/block-parser/README.md similarity index 100% rename from gems/block-parser/README.md rename to scripts/gems/block-parser/README.md diff --git a/gems/block-parser/Rakefile b/scripts/gems/block-parser/Rakefile similarity index 100% rename from gems/block-parser/Rakefile rename to scripts/gems/block-parser/Rakefile diff --git a/gems/block-parser/bin/console b/scripts/gems/block-parser/bin/console similarity index 100% rename from gems/block-parser/bin/console rename to scripts/gems/block-parser/bin/console diff --git a/gems/block-parser/bin/parse_block b/scripts/gems/block-parser/bin/parse_block similarity index 100% rename from gems/block-parser/bin/parse_block rename to scripts/gems/block-parser/bin/parse_block diff --git a/gems/block-parser/bin/setup b/scripts/gems/block-parser/bin/setup similarity index 100% rename from gems/block-parser/bin/setup rename to scripts/gems/block-parser/bin/setup diff --git a/gems/block-parser/block_parser-0.1.0.gem b/scripts/gems/block-parser/block_parser-0.1.0.gem similarity index 100% rename from gems/block-parser/block_parser-0.1.0.gem rename to scripts/gems/block-parser/block_parser-0.1.0.gem diff --git a/gems/block-parser/block_parser.gemspec b/scripts/gems/block-parser/block_parser.gemspec similarity index 100% rename from gems/block-parser/block_parser.gemspec rename to scripts/gems/block-parser/block_parser.gemspec diff --git a/gems/block-parser/build b/scripts/gems/block-parser/build similarity index 100% rename from gems/block-parser/build rename to scripts/gems/block-parser/build diff --git a/gems/block-parser/lib/block_parser.rb b/scripts/gems/block-parser/lib/block_parser.rb similarity index 100% rename from gems/block-parser/lib/block_parser.rb rename to scripts/gems/block-parser/lib/block_parser.rb diff --git a/gems/block-parser/lib/block_parser/build_challenge.rb b/scripts/gems/block-parser/lib/block_parser/build_challenge.rb similarity index 100% rename from gems/block-parser/lib/block_parser/build_challenge.rb rename to scripts/gems/block-parser/lib/block_parser/build_challenge.rb diff --git a/gems/block-parser/lib/block_parser/build_html.rb b/scripts/gems/block-parser/lib/block_parser/build_html.rb similarity index 100% rename from gems/block-parser/lib/block_parser/build_html.rb rename to scripts/gems/block-parser/lib/block_parser/build_html.rb diff --git a/gems/block-parser/lib/block_parser/build_html_from_md_json.rb b/scripts/gems/block-parser/lib/block_parser/build_html_from_md_json.rb similarity index 100% rename from gems/block-parser/lib/block_parser/build_html_from_md_json.rb rename to scripts/gems/block-parser/lib/block_parser/build_html_from_md_json.rb diff --git a/gems/block-parser/lib/block_parser/build_image_link.rb b/scripts/gems/block-parser/lib/block_parser/build_image_link.rb similarity index 100% rename from gems/block-parser/lib/block_parser/build_image_link.rb rename to scripts/gems/block-parser/lib/block_parser/build_image_link.rb diff --git a/gems/block-parser/lib/block_parser/build_link.rb b/scripts/gems/block-parser/lib/block_parser/build_link.rb similarity index 100% rename from gems/block-parser/lib/block_parser/build_link.rb rename to scripts/gems/block-parser/lib/block_parser/build_link.rb diff --git a/gems/block-parser/lib/block_parser/build_title_from_filename_and_html.rb b/scripts/gems/block-parser/lib/block_parser/build_title_from_filename_and_html.rb similarity index 100% rename from gems/block-parser/lib/block_parser/build_title_from_filename_and_html.rb rename to scripts/gems/block-parser/lib/block_parser/build_title_from_filename_and_html.rb diff --git a/gems/block-parser/lib/block_parser/challenge_validators/challenge.rb b/scripts/gems/block-parser/lib/block_parser/challenge_validators/challenge.rb similarity index 100% rename from gems/block-parser/lib/block_parser/challenge_validators/challenge.rb rename to scripts/gems/block-parser/lib/block_parser/challenge_validators/challenge.rb diff --git a/gems/block-parser/lib/block_parser/challenge_validators/challenge_validator.rb b/scripts/gems/block-parser/lib/block_parser/challenge_validators/challenge_validator.rb similarity index 100% rename from gems/block-parser/lib/block_parser/challenge_validators/challenge_validator.rb rename to scripts/gems/block-parser/lib/block_parser/challenge_validators/challenge_validator.rb diff --git a/gems/block-parser/lib/block_parser/challenge_validators/checkbox_challenge_validator.rb b/scripts/gems/block-parser/lib/block_parser/challenge_validators/checkbox_challenge_validator.rb similarity index 100% rename from gems/block-parser/lib/block_parser/challenge_validators/checkbox_challenge_validator.rb rename to scripts/gems/block-parser/lib/block_parser/challenge_validators/checkbox_challenge_validator.rb diff --git a/gems/block-parser/lib/block_parser/challenge_validators/code_snippet_challenge_validator.rb b/scripts/gems/block-parser/lib/block_parser/challenge_validators/code_snippet_challenge_validator.rb similarity index 100% rename from gems/block-parser/lib/block_parser/challenge_validators/code_snippet_challenge_validator.rb rename to scripts/gems/block-parser/lib/block_parser/challenge_validators/code_snippet_challenge_validator.rb diff --git a/gems/block-parser/lib/block_parser/challenge_validators/custom_snippet_challenge_validator.rb b/scripts/gems/block-parser/lib/block_parser/challenge_validators/custom_snippet_challenge_validator.rb similarity index 100% rename from gems/block-parser/lib/block_parser/challenge_validators/custom_snippet_challenge_validator.rb rename to scripts/gems/block-parser/lib/block_parser/challenge_validators/custom_snippet_challenge_validator.rb diff --git a/gems/block-parser/lib/block_parser/challenge_validators/local_snippet_challenge_validator.rb b/scripts/gems/block-parser/lib/block_parser/challenge_validators/local_snippet_challenge_validator.rb similarity index 100% rename from gems/block-parser/lib/block_parser/challenge_validators/local_snippet_challenge_validator.rb rename to scripts/gems/block-parser/lib/block_parser/challenge_validators/local_snippet_challenge_validator.rb diff --git a/gems/block-parser/lib/block_parser/challenge_validators/multiple_choice_challenge_validator.rb b/scripts/gems/block-parser/lib/block_parser/challenge_validators/multiple_choice_challenge_validator.rb similarity index 100% rename from gems/block-parser/lib/block_parser/challenge_validators/multiple_choice_challenge_validator.rb rename to scripts/gems/block-parser/lib/block_parser/challenge_validators/multiple_choice_challenge_validator.rb diff --git a/gems/block-parser/lib/block_parser/challenge_validators/number_challenge_validator.rb b/scripts/gems/block-parser/lib/block_parser/challenge_validators/number_challenge_validator.rb similarity index 100% rename from gems/block-parser/lib/block_parser/challenge_validators/number_challenge_validator.rb rename to scripts/gems/block-parser/lib/block_parser/challenge_validators/number_challenge_validator.rb diff --git a/gems/block-parser/lib/block_parser/challenge_validators/paragraph_challenge_validator.rb b/scripts/gems/block-parser/lib/block_parser/challenge_validators/paragraph_challenge_validator.rb similarity index 100% rename from gems/block-parser/lib/block_parser/challenge_validators/paragraph_challenge_validator.rb rename to scripts/gems/block-parser/lib/block_parser/challenge_validators/paragraph_challenge_validator.rb diff --git a/gems/block-parser/lib/block_parser/challenge_validators/poll_challenge_validator.rb b/scripts/gems/block-parser/lib/block_parser/challenge_validators/poll_challenge_validator.rb similarity index 100% rename from gems/block-parser/lib/block_parser/challenge_validators/poll_challenge_validator.rb rename to scripts/gems/block-parser/lib/block_parser/challenge_validators/poll_challenge_validator.rb diff --git a/gems/block-parser/lib/block_parser/challenge_validators/project_challenge_validator.rb b/scripts/gems/block-parser/lib/block_parser/challenge_validators/project_challenge_validator.rb similarity index 100% rename from gems/block-parser/lib/block_parser/challenge_validators/project_challenge_validator.rb rename to scripts/gems/block-parser/lib/block_parser/challenge_validators/project_challenge_validator.rb diff --git a/gems/block-parser/lib/block_parser/challenge_validators/short_answer_challenge_validator.rb b/scripts/gems/block-parser/lib/block_parser/challenge_validators/short_answer_challenge_validator.rb similarity index 100% rename from gems/block-parser/lib/block_parser/challenge_validators/short_answer_challenge_validator.rb rename to scripts/gems/block-parser/lib/block_parser/challenge_validators/short_answer_challenge_validator.rb diff --git a/gems/block-parser/lib/block_parser/challenge_validators/testable_project_challenge_validator.rb b/scripts/gems/block-parser/lib/block_parser/challenge_validators/testable_project_challenge_validator.rb similarity index 100% rename from gems/block-parser/lib/block_parser/challenge_validators/testable_project_challenge_validator.rb rename to scripts/gems/block-parser/lib/block_parser/challenge_validators/testable_project_challenge_validator.rb diff --git a/gems/block-parser/lib/block_parser/convert_md_to_json.rb b/scripts/gems/block-parser/lib/block_parser/convert_md_to_json.rb similarity index 100% rename from gems/block-parser/lib/block_parser/convert_md_to_json.rb rename to scripts/gems/block-parser/lib/block_parser/convert_md_to_json.rb diff --git a/gems/block-parser/lib/block_parser/parse_directory.rb b/scripts/gems/block-parser/lib/block_parser/parse_directory.rb similarity index 100% rename from gems/block-parser/lib/block_parser/parse_directory.rb rename to scripts/gems/block-parser/lib/block_parser/parse_directory.rb diff --git a/gems/block-parser/lib/block_parser/parse_markdown_file.rb b/scripts/gems/block-parser/lib/block_parser/parse_markdown_file.rb similarity index 100% rename from gems/block-parser/lib/block_parser/parse_markdown_file.rb rename to scripts/gems/block-parser/lib/block_parser/parse_markdown_file.rb diff --git a/gems/block-parser/lib/block_parser/parse_standards.rb b/scripts/gems/block-parser/lib/block_parser/parse_standards.rb similarity index 100% rename from gems/block-parser/lib/block_parser/parse_standards.rb rename to scripts/gems/block-parser/lib/block_parser/parse_standards.rb diff --git a/gems/block-parser/lib/block_parser/version.rb b/scripts/gems/block-parser/lib/block_parser/version.rb similarity index 100% rename from gems/block-parser/lib/block_parser/version.rb rename to scripts/gems/block-parser/lib/block_parser/version.rb diff --git a/gems/block-parser/pkg/block_parser-0.1.0.gem b/scripts/gems/block-parser/pkg/block_parser-0.1.0.gem similarity index 100% rename from gems/block-parser/pkg/block_parser-0.1.0.gem rename to scripts/gems/block-parser/pkg/block_parser-0.1.0.gem diff --git a/gems/block-parser/spec/build_challenge_spec.rb b/scripts/gems/block-parser/spec/build_challenge_spec.rb similarity index 100% rename from gems/block-parser/spec/build_challenge_spec.rb rename to scripts/gems/block-parser/spec/build_challenge_spec.rb diff --git a/gems/block-parser/spec/build_html_from_md_json_spec.rb b/scripts/gems/block-parser/spec/build_html_from_md_json_spec.rb similarity index 100% rename from gems/block-parser/spec/build_html_from_md_json_spec.rb rename to scripts/gems/block-parser/spec/build_html_from_md_json_spec.rb diff --git a/gems/block-parser/spec/build_html_spec.rb b/scripts/gems/block-parser/spec/build_html_spec.rb similarity index 100% rename from gems/block-parser/spec/build_html_spec.rb rename to scripts/gems/block-parser/spec/build_html_spec.rb diff --git a/gems/block-parser/spec/build_image_link_spec.rb b/scripts/gems/block-parser/spec/build_image_link_spec.rb similarity index 100% rename from gems/block-parser/spec/build_image_link_spec.rb rename to scripts/gems/block-parser/spec/build_image_link_spec.rb diff --git a/gems/block-parser/spec/build_link_spec.rb b/scripts/gems/block-parser/spec/build_link_spec.rb similarity index 100% rename from gems/block-parser/spec/build_link_spec.rb rename to scripts/gems/block-parser/spec/build_link_spec.rb diff --git a/gems/block-parser/spec/build_title_from_filename_and_html_spec.rb b/scripts/gems/block-parser/spec/build_title_from_filename_and_html_spec.rb similarity index 100% rename from gems/block-parser/spec/build_title_from_filename_and_html_spec.rb rename to scripts/gems/block-parser/spec/build_title_from_filename_and_html_spec.rb diff --git a/gems/block-parser/spec/challenge_validators/challenge_spec.rb b/scripts/gems/block-parser/spec/challenge_validators/challenge_spec.rb similarity index 100% rename from gems/block-parser/spec/challenge_validators/challenge_spec.rb rename to scripts/gems/block-parser/spec/challenge_validators/challenge_spec.rb diff --git a/gems/block-parser/spec/challenge_validators/challenge_validator_spec.rb b/scripts/gems/block-parser/spec/challenge_validators/challenge_validator_spec.rb similarity index 100% rename from gems/block-parser/spec/challenge_validators/challenge_validator_spec.rb rename to scripts/gems/block-parser/spec/challenge_validators/challenge_validator_spec.rb diff --git a/gems/block-parser/spec/challenge_validators/checkbox_challenge_validator_spec.rb b/scripts/gems/block-parser/spec/challenge_validators/checkbox_challenge_validator_spec.rb similarity index 100% rename from gems/block-parser/spec/challenge_validators/checkbox_challenge_validator_spec.rb rename to scripts/gems/block-parser/spec/challenge_validators/checkbox_challenge_validator_spec.rb diff --git a/gems/block-parser/spec/challenge_validators/code_snippet_challenge_validator_spec.rb b/scripts/gems/block-parser/spec/challenge_validators/code_snippet_challenge_validator_spec.rb similarity index 100% rename from gems/block-parser/spec/challenge_validators/code_snippet_challenge_validator_spec.rb rename to scripts/gems/block-parser/spec/challenge_validators/code_snippet_challenge_validator_spec.rb diff --git a/gems/block-parser/spec/challenge_validators/custom_snippet_challenge_validator_spec.rb b/scripts/gems/block-parser/spec/challenge_validators/custom_snippet_challenge_validator_spec.rb similarity index 100% rename from gems/block-parser/spec/challenge_validators/custom_snippet_challenge_validator_spec.rb rename to scripts/gems/block-parser/spec/challenge_validators/custom_snippet_challenge_validator_spec.rb diff --git a/gems/block-parser/spec/challenge_validators/multiple_choice_challenge_validator_spec.rb b/scripts/gems/block-parser/spec/challenge_validators/multiple_choice_challenge_validator_spec.rb similarity index 100% rename from gems/block-parser/spec/challenge_validators/multiple_choice_challenge_validator_spec.rb rename to scripts/gems/block-parser/spec/challenge_validators/multiple_choice_challenge_validator_spec.rb diff --git a/gems/block-parser/spec/challenge_validators/number_challenge_validator_spec.rb b/scripts/gems/block-parser/spec/challenge_validators/number_challenge_validator_spec.rb similarity index 100% rename from gems/block-parser/spec/challenge_validators/number_challenge_validator_spec.rb rename to scripts/gems/block-parser/spec/challenge_validators/number_challenge_validator_spec.rb diff --git a/gems/block-parser/spec/challenge_validators/project_challenge_validator_spec.rb b/scripts/gems/block-parser/spec/challenge_validators/project_challenge_validator_spec.rb similarity index 100% rename from gems/block-parser/spec/challenge_validators/project_challenge_validator_spec.rb rename to scripts/gems/block-parser/spec/challenge_validators/project_challenge_validator_spec.rb diff --git a/gems/block-parser/spec/challenge_validators/short_answer_challenge_validator_spec.rb b/scripts/gems/block-parser/spec/challenge_validators/short_answer_challenge_validator_spec.rb similarity index 100% rename from gems/block-parser/spec/challenge_validators/short_answer_challenge_validator_spec.rb rename to scripts/gems/block-parser/spec/challenge_validators/short_answer_challenge_validator_spec.rb diff --git a/gems/block-parser/spec/challenge_validators/testable_project_challenge_validator_spec.rb b/scripts/gems/block-parser/spec/challenge_validators/testable_project_challenge_validator_spec.rb similarity index 100% rename from gems/block-parser/spec/challenge_validators/testable_project_challenge_validator_spec.rb rename to scripts/gems/block-parser/spec/challenge_validators/testable_project_challenge_validator_spec.rb diff --git a/gems/block-parser/spec/convert_md_to_json_spec.rb b/scripts/gems/block-parser/spec/convert_md_to_json_spec.rb similarity index 100% rename from gems/block-parser/spec/convert_md_to_json_spec.rb rename to scripts/gems/block-parser/spec/convert_md_to_json_spec.rb diff --git a/gems/block-parser/spec/fixtures/checkpoint-with-bad-challenge-tag/bad-challenges.md b/scripts/gems/block-parser/spec/fixtures/checkpoint-with-bad-challenge-tag/bad-challenges.md similarity index 100% rename from gems/block-parser/spec/fixtures/checkpoint-with-bad-challenge-tag/bad-challenges.md rename to scripts/gems/block-parser/spec/fixtures/checkpoint-with-bad-challenge-tag/bad-challenges.md diff --git a/gems/block-parser/spec/fixtures/checkpoint-with-bad-challenge-tag/config.yaml b/scripts/gems/block-parser/spec/fixtures/checkpoint-with-bad-challenge-tag/config.yaml similarity index 100% rename from gems/block-parser/spec/fixtures/checkpoint-with-bad-challenge-tag/config.yaml rename to scripts/gems/block-parser/spec/fixtures/checkpoint-with-bad-challenge-tag/config.yaml diff --git a/gems/block-parser/spec/fixtures/checkpoint-without-challenges-block-repo/config.yaml b/scripts/gems/block-parser/spec/fixtures/checkpoint-without-challenges-block-repo/config.yaml similarity index 100% rename from gems/block-parser/spec/fixtures/checkpoint-without-challenges-block-repo/config.yaml rename to scripts/gems/block-parser/spec/fixtures/checkpoint-without-challenges-block-repo/config.yaml diff --git a/gems/block-parser/spec/fixtures/checkpoint-without-challenges-block-repo/no-challenges.md b/scripts/gems/block-parser/spec/fixtures/checkpoint-without-challenges-block-repo/no-challenges.md similarity index 100% rename from gems/block-parser/spec/fixtures/checkpoint-without-challenges-block-repo/no-challenges.md rename to scripts/gems/block-parser/spec/fixtures/checkpoint-without-challenges-block-repo/no-challenges.md diff --git a/gems/block-parser/spec/fixtures/invalid-config-test-block-repo/config.yaml b/scripts/gems/block-parser/spec/fixtures/invalid-config-test-block-repo/config.yaml similarity index 100% rename from gems/block-parser/spec/fixtures/invalid-config-test-block-repo/config.yaml rename to scripts/gems/block-parser/spec/fixtures/invalid-config-test-block-repo/config.yaml diff --git a/gems/block-parser/spec/fixtures/no-lessons-nor-checkpoints/config.yaml b/scripts/gems/block-parser/spec/fixtures/no-lessons-nor-checkpoints/config.yaml similarity index 100% rename from gems/block-parser/spec/fixtures/no-lessons-nor-checkpoints/config.yaml rename to scripts/gems/block-parser/spec/fixtures/no-lessons-nor-checkpoints/config.yaml diff --git a/gems/block-parser/spec/fixtures/no-lessons-nor-checkpoints/resources.md b/scripts/gems/block-parser/spec/fixtures/no-lessons-nor-checkpoints/resources.md similarity index 100% rename from gems/block-parser/spec/fixtures/no-lessons-nor-checkpoints/resources.md rename to scripts/gems/block-parser/spec/fixtures/no-lessons-nor-checkpoints/resources.md diff --git a/gems/block-parser/spec/fixtures/no-standards-config-test-block-repo/config.yaml b/scripts/gems/block-parser/spec/fixtures/no-standards-config-test-block-repo/config.yaml similarity index 100% rename from gems/block-parser/spec/fixtures/no-standards-config-test-block-repo/config.yaml rename to scripts/gems/block-parser/spec/fixtures/no-standards-config-test-block-repo/config.yaml diff --git a/gems/block-parser/spec/fixtures/sample-iframe.md b/scripts/gems/block-parser/spec/fixtures/sample-iframe.md similarity index 100% rename from gems/block-parser/spec/fixtures/sample-iframe.md rename to scripts/gems/block-parser/spec/fixtures/sample-iframe.md diff --git a/gems/block-parser/spec/fixtures/test-block-repo-yml/config.yml b/scripts/gems/block-parser/spec/fixtures/test-block-repo-yml/config.yml similarity index 100% rename from gems/block-parser/spec/fixtures/test-block-repo-yml/config.yml rename to scripts/gems/block-parser/spec/fixtures/test-block-repo-yml/config.yml diff --git a/gems/block-parser/spec/fixtures/test-block-repo-yml/dummy.pdf b/scripts/gems/block-parser/spec/fixtures/test-block-repo-yml/dummy.pdf similarity index 100% rename from gems/block-parser/spec/fixtures/test-block-repo-yml/dummy.pdf rename to scripts/gems/block-parser/spec/fixtures/test-block-repo-yml/dummy.pdf diff --git a/gems/block-parser/spec/fixtures/test-block-repo-yml/folder/sibling.md b/scripts/gems/block-parser/spec/fixtures/test-block-repo-yml/folder/sibling.md similarity index 100% rename from gems/block-parser/spec/fixtures/test-block-repo-yml/folder/sibling.md rename to scripts/gems/block-parser/spec/fixtures/test-block-repo-yml/folder/sibling.md diff --git a/gems/block-parser/spec/fixtures/test-block-repo-yml/folder/target.md b/scripts/gems/block-parser/spec/fixtures/test-block-repo-yml/folder/target.md similarity index 100% rename from gems/block-parser/spec/fixtures/test-block-repo-yml/folder/target.md rename to scripts/gems/block-parser/spec/fixtures/test-block-repo-yml/folder/target.md diff --git a/gems/block-parser/spec/fixtures/test-block-repo-yml/images/galvanize-logo.png b/scripts/gems/block-parser/spec/fixtures/test-block-repo-yml/images/galvanize-logo.png similarity index 100% rename from gems/block-parser/spec/fixtures/test-block-repo-yml/images/galvanize-logo.png rename to scripts/gems/block-parser/spec/fixtures/test-block-repo-yml/images/galvanize-logo.png diff --git a/gems/block-parser/spec/fixtures/test-block-repo-yml/images/register_klass.gif b/scripts/gems/block-parser/spec/fixtures/test-block-repo-yml/images/register_klass.gif similarity index 100% rename from gems/block-parser/spec/fixtures/test-block-repo-yml/images/register_klass.gif rename to scripts/gems/block-parser/spec/fixtures/test-block-repo-yml/images/register_klass.gif diff --git a/gems/block-parser/spec/fixtures/test-block-repo-yml/lessoN.md b/scripts/gems/block-parser/spec/fixtures/test-block-repo-yml/lessoN.md similarity index 100% rename from gems/block-parser/spec/fixtures/test-block-repo-yml/lessoN.md rename to scripts/gems/block-parser/spec/fixtures/test-block-repo-yml/lessoN.md diff --git a/gems/block-parser/spec/fixtures/test-block-repo-yml/markdown-smoketest.md b/scripts/gems/block-parser/spec/fixtures/test-block-repo-yml/markdown-smoketest.md similarity index 100% rename from gems/block-parser/spec/fixtures/test-block-repo-yml/markdown-smoketest.md rename to scripts/gems/block-parser/spec/fixtures/test-block-repo-yml/markdown-smoketest.md diff --git a/gems/block-parser/spec/fixtures/test-block-repo-yml/target.md b/scripts/gems/block-parser/spec/fixtures/test-block-repo-yml/target.md similarity index 100% rename from gems/block-parser/spec/fixtures/test-block-repo-yml/target.md rename to scripts/gems/block-parser/spec/fixtures/test-block-repo-yml/target.md diff --git a/gems/block-parser/spec/fixtures/test-block-repo/README.md b/scripts/gems/block-parser/spec/fixtures/test-block-repo/README.md similarity index 100% rename from gems/block-parser/spec/fixtures/test-block-repo/README.md rename to scripts/gems/block-parser/spec/fixtures/test-block-repo/README.md diff --git a/gems/block-parser/spec/fixtures/test-block-repo/config.yaml b/scripts/gems/block-parser/spec/fixtures/test-block-repo/config.yaml similarity index 100% rename from gems/block-parser/spec/fixtures/test-block-repo/config.yaml rename to scripts/gems/block-parser/spec/fixtures/test-block-repo/config.yaml diff --git a/gems/block-parser/spec/fixtures/test-block-repo/folder/sibling.md b/scripts/gems/block-parser/spec/fixtures/test-block-repo/folder/sibling.md similarity index 100% rename from gems/block-parser/spec/fixtures/test-block-repo/folder/sibling.md rename to scripts/gems/block-parser/spec/fixtures/test-block-repo/folder/sibling.md diff --git a/gems/block-parser/spec/fixtures/test-block-repo/folder/target.md b/scripts/gems/block-parser/spec/fixtures/test-block-repo/folder/target.md similarity index 100% rename from gems/block-parser/spec/fixtures/test-block-repo/folder/target.md rename to scripts/gems/block-parser/spec/fixtures/test-block-repo/folder/target.md diff --git a/gems/block-parser/spec/fixtures/test-block-repo/images/galvanize-logo.png b/scripts/gems/block-parser/spec/fixtures/test-block-repo/images/galvanize-logo.png similarity index 100% rename from gems/block-parser/spec/fixtures/test-block-repo/images/galvanize-logo.png rename to scripts/gems/block-parser/spec/fixtures/test-block-repo/images/galvanize-logo.png diff --git a/gems/block-parser/spec/fixtures/test-block-repo/images/register_klass.gif b/scripts/gems/block-parser/spec/fixtures/test-block-repo/images/register_klass.gif similarity index 100% rename from gems/block-parser/spec/fixtures/test-block-repo/images/register_klass.gif rename to scripts/gems/block-parser/spec/fixtures/test-block-repo/images/register_klass.gif diff --git a/gems/block-parser/spec/fixtures/test-block-repo/ipynb-test.ipynb b/scripts/gems/block-parser/spec/fixtures/test-block-repo/ipynb-test.ipynb similarity index 100% rename from gems/block-parser/spec/fixtures/test-block-repo/ipynb-test.ipynb rename to scripts/gems/block-parser/spec/fixtures/test-block-repo/ipynb-test.ipynb diff --git a/gems/block-parser/spec/fixtures/test-block-repo/ipynb-test.md b/scripts/gems/block-parser/spec/fixtures/test-block-repo/ipynb-test.md similarity index 100% rename from gems/block-parser/spec/fixtures/test-block-repo/ipynb-test.md rename to scripts/gems/block-parser/spec/fixtures/test-block-repo/ipynb-test.md diff --git a/gems/block-parser/spec/fixtures/test-block-repo/lessoN.md b/scripts/gems/block-parser/spec/fixtures/test-block-repo/lessoN.md similarity index 100% rename from gems/block-parser/spec/fixtures/test-block-repo/lessoN.md rename to scripts/gems/block-parser/spec/fixtures/test-block-repo/lessoN.md diff --git a/gems/block-parser/spec/fixtures/test-block-repo/markdown-smoketest.md b/scripts/gems/block-parser/spec/fixtures/test-block-repo/markdown-smoketest.md similarity index 100% rename from gems/block-parser/spec/fixtures/test-block-repo/markdown-smoketest.md rename to scripts/gems/block-parser/spec/fixtures/test-block-repo/markdown-smoketest.md diff --git a/gems/block-parser/spec/fixtures/test-block-repo/target.md b/scripts/gems/block-parser/spec/fixtures/test-block-repo/target.md similarity index 100% rename from gems/block-parser/spec/fixtures/test-block-repo/target.md rename to scripts/gems/block-parser/spec/fixtures/test-block-repo/target.md diff --git a/gems/block-parser/spec/fixtures/test-block-two-configs/config.yaml b/scripts/gems/block-parser/spec/fixtures/test-block-two-configs/config.yaml similarity index 100% rename from gems/block-parser/spec/fixtures/test-block-two-configs/config.yaml rename to scripts/gems/block-parser/spec/fixtures/test-block-two-configs/config.yaml diff --git a/gems/block-parser/spec/fixtures/test-block-two-configs/config.yml b/scripts/gems/block-parser/spec/fixtures/test-block-two-configs/config.yml similarity index 100% rename from gems/block-parser/spec/fixtures/test-block-two-configs/config.yml rename to scripts/gems/block-parser/spec/fixtures/test-block-two-configs/config.yml diff --git a/gems/block-parser/spec/fixtures/valid-custom-snippet-challenge-directory/Dockerfile b/scripts/gems/block-parser/spec/fixtures/valid-custom-snippet-challenge-directory/Dockerfile similarity index 100% rename from gems/block-parser/spec/fixtures/valid-custom-snippet-challenge-directory/Dockerfile rename to scripts/gems/block-parser/spec/fixtures/valid-custom-snippet-challenge-directory/Dockerfile diff --git a/gems/block-parser/spec/fixtures/valid-custom-snippet-challenge-directory/test.sh b/scripts/gems/block-parser/spec/fixtures/valid-custom-snippet-challenge-directory/test.sh similarity index 100% rename from gems/block-parser/spec/fixtures/valid-custom-snippet-challenge-directory/test.sh rename to scripts/gems/block-parser/spec/fixtures/valid-custom-snippet-challenge-directory/test.sh diff --git a/gems/block-parser/spec/fixtures/valid-yaml-array-test-block-repo/config.yaml b/scripts/gems/block-parser/spec/fixtures/valid-yaml-array-test-block-repo/config.yaml similarity index 100% rename from gems/block-parser/spec/fixtures/valid-yaml-array-test-block-repo/config.yaml rename to scripts/gems/block-parser/spec/fixtures/valid-yaml-array-test-block-repo/config.yaml diff --git a/gems/block-parser/spec/parse_directory_spec.rb b/scripts/gems/block-parser/spec/parse_directory_spec.rb similarity index 100% rename from gems/block-parser/spec/parse_directory_spec.rb rename to scripts/gems/block-parser/spec/parse_directory_spec.rb diff --git a/gems/block-parser/spec/parse_markdown_file_spec.rb b/scripts/gems/block-parser/spec/parse_markdown_file_spec.rb similarity index 100% rename from gems/block-parser/spec/parse_markdown_file_spec.rb rename to scripts/gems/block-parser/spec/parse_markdown_file_spec.rb diff --git a/gems/block-parser/spec/parse_standards_spec.rb b/scripts/gems/block-parser/spec/parse_standards_spec.rb similarity index 100% rename from gems/block-parser/spec/parse_standards_spec.rb rename to scripts/gems/block-parser/spec/parse_standards_spec.rb diff --git a/gems/block-parser/spec/spec_helper.rb b/scripts/gems/block-parser/spec/spec_helper.rb similarity index 100% rename from gems/block-parser/spec/spec_helper.rb rename to scripts/gems/block-parser/spec/spec_helper.rb diff --git a/gems/block-parser/spec/support/freeloader.rb b/scripts/gems/block-parser/spec/support/freeloader.rb similarity index 100% rename from gems/block-parser/spec/support/freeloader.rb rename to scripts/gems/block-parser/spec/support/freeloader.rb diff --git a/gems/block-parser/spec/support/mocktokit.rb b/scripts/gems/block-parser/spec/support/mocktokit.rb similarity index 100% rename from gems/block-parser/spec/support/mocktokit.rb rename to scripts/gems/block-parser/spec/support/mocktokit.rb diff --git a/gems/block-parser/spec/tmp/.keep b/scripts/gems/block-parser/spec/tmp/.keep similarity index 100% rename from gems/block-parser/spec/tmp/.keep rename to scripts/gems/block-parser/spec/tmp/.keep diff --git a/gems/block-parser/validate-block b/scripts/gems/block-parser/validate-block similarity index 100% rename from gems/block-parser/validate-block rename to scripts/gems/block-parser/validate-block diff --git a/lib/tasks/challenge_release_ids.rake b/scripts/lib/tasks/challenge_release_ids.rake similarity index 100% rename from lib/tasks/challenge_release_ids.rake rename to scripts/lib/tasks/challenge_release_ids.rake diff --git a/lib/tasks/checkpoint_resubmission.rake b/scripts/lib/tasks/checkpoint_resubmission.rake similarity index 100% rename from lib/tasks/checkpoint_resubmission.rake rename to scripts/lib/tasks/checkpoint_resubmission.rake diff --git a/lib/tasks/checkpoint_submission_points.rake b/scripts/lib/tasks/checkpoint_submission_points.rake similarity index 100% rename from lib/tasks/checkpoint_submission_points.rake rename to scripts/lib/tasks/checkpoint_submission_points.rake diff --git a/lib/tasks/content_visibility_update.rake b/scripts/lib/tasks/content_visibility_update.rake similarity index 100% rename from lib/tasks/content_visibility_update.rake rename to scripts/lib/tasks/content_visibility_update.rake diff --git a/lib/tasks/course_progress.rake b/scripts/lib/tasks/course_progress.rake similarity index 100% rename from lib/tasks/course_progress.rake rename to scripts/lib/tasks/course_progress.rake diff --git a/lib/tasks/course_yaml_backfill.rake b/scripts/lib/tasks/course_yaml_backfill.rake similarity index 100% rename from lib/tasks/course_yaml_backfill.rake rename to scripts/lib/tasks/course_yaml_backfill.rake diff --git a/lib/tasks/grade_checkpoints.rake b/scripts/lib/tasks/grade_checkpoints.rake similarity index 100% rename from lib/tasks/grade_checkpoints.rake rename to scripts/lib/tasks/grade_checkpoints.rake diff --git a/lib/tasks/object_space_count.rake b/scripts/lib/tasks/object_space_count.rake similarity index 100% rename from lib/tasks/object_space_count.rake rename to scripts/lib/tasks/object_space_count.rake diff --git a/lib/tasks/prep_notifier.rake b/scripts/lib/tasks/prep_notifier.rake similarity index 100% rename from lib/tasks/prep_notifier.rake rename to scripts/lib/tasks/prep_notifier.rake diff --git a/lib/tasks/set_block_caches.rake b/scripts/lib/tasks/set_block_caches.rake similarity index 100% rename from lib/tasks/set_block_caches.rake rename to scripts/lib/tasks/set_block_caches.rake diff --git a/lib/tasks/spec.rake b/scripts/lib/tasks/spec.rake similarity index 100% rename from lib/tasks/spec.rake rename to scripts/lib/tasks/spec.rake diff --git a/lib/tasks/ts_routes.rake b/scripts/lib/tasks/ts_routes.rake similarity index 100% rename from lib/tasks/ts_routes.rake rename to scripts/lib/tasks/ts_routes.rake diff --git a/lintspec.sh b/scripts/lintspec.sh similarity index 100% rename from lintspec.sh rename to scripts/lintspec.sh diff --git a/package.json b/scripts/package.json similarity index 100% rename from package.json rename to scripts/package.json diff --git a/postcss.config.js b/scripts/postcss.config.js similarity index 100% rename from postcss.config.js rename to scripts/postcss.config.js diff --git a/public/404.html b/scripts/public/404.html similarity index 100% rename from public/404.html rename to scripts/public/404.html diff --git a/public/422.html b/scripts/public/422.html similarity index 100% rename from public/422.html rename to scripts/public/422.html diff --git a/public/500.html b/scripts/public/500.html similarity index 100% rename from public/500.html rename to scripts/public/500.html diff --git a/public/apple-touch-icon-152x152.png b/scripts/public/apple-touch-icon-152x152.png similarity index 100% rename from public/apple-touch-icon-152x152.png rename to scripts/public/apple-touch-icon-152x152.png diff --git a/public/apple-touch-icon-precomposed-152x152.png b/scripts/public/apple-touch-icon-precomposed-152x152.png similarity index 100% rename from public/apple-touch-icon-precomposed-152x152.png rename to scripts/public/apple-touch-icon-precomposed-152x152.png diff --git a/public/apple-touch-icon-precomposed.png b/scripts/public/apple-touch-icon-precomposed.png similarity index 100% rename from public/apple-touch-icon-precomposed.png rename to scripts/public/apple-touch-icon-precomposed.png diff --git a/public/apple-touch-icon.png b/scripts/public/apple-touch-icon.png similarity index 100% rename from public/apple-touch-icon.png rename to scripts/public/apple-touch-icon.png diff --git a/public/assets/images/hopscotch-sprite-green.png b/scripts/public/assets/images/hopscotch-sprite-green.png similarity index 100% rename from public/assets/images/hopscotch-sprite-green.png rename to scripts/public/assets/images/hopscotch-sprite-green.png diff --git a/public/assets/images/hopscotch-sprite-orange.png b/scripts/public/assets/images/hopscotch-sprite-orange.png similarity index 100% rename from public/assets/images/hopscotch-sprite-orange.png rename to scripts/public/assets/images/hopscotch-sprite-orange.png diff --git a/public/assets/images/jupyter-logo.png b/scripts/public/assets/images/jupyter-logo.png similarity index 100% rename from public/assets/images/jupyter-logo.png rename to scripts/public/assets/images/jupyter-logo.png diff --git a/public/assets/images/svg/checkpoint-is-rejected.svg b/scripts/public/assets/images/svg/checkpoint-is-rejected.svg similarity index 100% rename from public/assets/images/svg/checkpoint-is-rejected.svg rename to scripts/public/assets/images/svg/checkpoint-is-rejected.svg diff --git a/public/assets/images/svg/checkpoint-is-scored.svg b/scripts/public/assets/images/svg/checkpoint-is-scored.svg similarity index 100% rename from public/assets/images/svg/checkpoint-is-scored.svg rename to scripts/public/assets/images/svg/checkpoint-is-scored.svg diff --git a/public/assets/images/svg/checkpoint-is-submitted.svg b/scripts/public/assets/images/svg/checkpoint-is-submitted.svg similarity index 100% rename from public/assets/images/svg/checkpoint-is-submitted.svg rename to scripts/public/assets/images/svg/checkpoint-is-submitted.svg diff --git a/public/assets/images/svg/github-icon.svg b/scripts/public/assets/images/svg/github-icon.svg similarity index 100% rename from public/assets/images/svg/github-icon.svg rename to scripts/public/assets/images/svg/github-icon.svg diff --git a/public/assets/images/svg/gitlab-icon-rgb.svg b/scripts/public/assets/images/svg/gitlab-icon-rgb.svg similarity index 100% rename from public/assets/images/svg/gitlab-icon-rgb.svg rename to scripts/public/assets/images/svg/gitlab-icon-rgb.svg diff --git a/public/assets/images/svg/octicon-git-branch.svg b/scripts/public/assets/images/svg/octicon-git-branch.svg similarity index 100% rename from public/assets/images/svg/octicon-git-branch.svg rename to scripts/public/assets/images/svg/octicon-git-branch.svg diff --git a/public/assets/images/svg/redpriority_high-24px.svg b/scripts/public/assets/images/svg/redpriority_high-24px.svg similarity index 100% rename from public/assets/images/svg/redpriority_high-24px.svg rename to scripts/public/assets/images/svg/redpriority_high-24px.svg diff --git a/public/assets/images/svg/svg-link_off-24px.svg b/scripts/public/assets/images/svg/svg-link_off-24px.svg similarity index 100% rename from public/assets/images/svg/svg-link_off-24px.svg rename to scripts/public/assets/images/svg/svg-link_off-24px.svg diff --git a/public/assets/images/svg/svg-sprite-action-symbol.svg b/scripts/public/assets/images/svg/svg-sprite-action-symbol.svg similarity index 100% rename from public/assets/images/svg/svg-sprite-action-symbol.svg rename to scripts/public/assets/images/svg/svg-sprite-action-symbol.svg diff --git a/public/assets/images/svg/svg-sprite-alert-symbol.svg b/scripts/public/assets/images/svg/svg-sprite-alert-symbol.svg similarity index 100% rename from public/assets/images/svg/svg-sprite-alert-symbol.svg rename to scripts/public/assets/images/svg/svg-sprite-alert-symbol.svg diff --git a/public/assets/images/svg/svg-sprite-av-symbol.svg b/scripts/public/assets/images/svg/svg-sprite-av-symbol.svg similarity index 100% rename from public/assets/images/svg/svg-sprite-av-symbol.svg rename to scripts/public/assets/images/svg/svg-sprite-av-symbol.svg diff --git a/public/assets/images/svg/svg-sprite-content-symbol.svg b/scripts/public/assets/images/svg/svg-sprite-content-symbol.svg similarity index 100% rename from public/assets/images/svg/svg-sprite-content-symbol.svg rename to scripts/public/assets/images/svg/svg-sprite-content-symbol.svg diff --git a/public/assets/images/svg/svg-sprite-custom-symbol.svg b/scripts/public/assets/images/svg/svg-sprite-custom-symbol.svg similarity index 100% rename from public/assets/images/svg/svg-sprite-custom-symbol.svg rename to scripts/public/assets/images/svg/svg-sprite-custom-symbol.svg diff --git a/public/assets/images/svg/svg-sprite-custom_material-symbol.svg b/scripts/public/assets/images/svg/svg-sprite-custom_material-symbol.svg similarity index 100% rename from public/assets/images/svg/svg-sprite-custom_material-symbol.svg rename to scripts/public/assets/images/svg/svg-sprite-custom_material-symbol.svg diff --git a/public/assets/images/svg/svg-sprite-device-symbol.svg b/scripts/public/assets/images/svg/svg-sprite-device-symbol.svg similarity index 100% rename from public/assets/images/svg/svg-sprite-device-symbol.svg rename to scripts/public/assets/images/svg/svg-sprite-device-symbol.svg diff --git a/public/assets/images/svg/svg-sprite-file-symbol.svg b/scripts/public/assets/images/svg/svg-sprite-file-symbol.svg similarity index 100% rename from public/assets/images/svg/svg-sprite-file-symbol.svg rename to scripts/public/assets/images/svg/svg-sprite-file-symbol.svg diff --git a/public/assets/images/svg/svg-sprite-hardware-symbol.svg b/scripts/public/assets/images/svg/svg-sprite-hardware-symbol.svg similarity index 100% rename from public/assets/images/svg/svg-sprite-hardware-symbol.svg rename to scripts/public/assets/images/svg/svg-sprite-hardware-symbol.svg diff --git a/public/assets/images/svg/svg-sprite-navigation-symbol.svg b/scripts/public/assets/images/svg/svg-sprite-navigation-symbol.svg similarity index 100% rename from public/assets/images/svg/svg-sprite-navigation-symbol.svg rename to scripts/public/assets/images/svg/svg-sprite-navigation-symbol.svg diff --git a/public/assets/images/svg/svg-sprite-notification-symbol.svg b/scripts/public/assets/images/svg/svg-sprite-notification-symbol.svg similarity index 100% rename from public/assets/images/svg/svg-sprite-notification-symbol.svg rename to scripts/public/assets/images/svg/svg-sprite-notification-symbol.svg diff --git a/public/assets/images/svg/svg-sprite-social-symbol.svg b/scripts/public/assets/images/svg/svg-sprite-social-symbol.svg similarity index 100% rename from public/assets/images/svg/svg-sprite-social-symbol.svg rename to scripts/public/assets/images/svg/svg-sprite-social-symbol.svg diff --git a/public/favicon.ico b/scripts/public/favicon.ico similarity index 100% rename from public/favicon.ico rename to scripts/public/favicon.ico diff --git a/public/javascripts/apitome/application.js b/scripts/public/javascripts/apitome/application.js similarity index 100% rename from public/javascripts/apitome/application.js rename to scripts/public/javascripts/apitome/application.js diff --git a/public/robots.txt b/scripts/public/robots.txt similarity index 100% rename from public/robots.txt rename to scripts/public/robots.txt diff --git a/public/sandbox/chai.js b/scripts/public/sandbox/chai.js similarity index 100% rename from public/sandbox/chai.js rename to scripts/public/sandbox/chai.js diff --git a/public/sandbox/challenge-worker.js b/scripts/public/sandbox/challenge-worker.js similarity index 100% rename from public/sandbox/challenge-worker.js rename to scripts/public/sandbox/challenge-worker.js diff --git a/public/sandbox/jasmine/boot.js b/scripts/public/sandbox/jasmine/boot.js similarity index 100% rename from public/sandbox/jasmine/boot.js rename to scripts/public/sandbox/jasmine/boot.js diff --git a/public/sandbox/jasmine/jasmine.js b/scripts/public/sandbox/jasmine/jasmine.js similarity index 100% rename from public/sandbox/jasmine/jasmine.js rename to scripts/public/sandbox/jasmine/jasmine.js diff --git a/public/sandbox/mocha/boot.js b/scripts/public/sandbox/mocha/boot.js similarity index 100% rename from public/sandbox/mocha/boot.js rename to scripts/public/sandbox/mocha/boot.js diff --git a/public/sandbox/mocha/mocha.js b/scripts/public/sandbox/mocha/mocha.js similarity index 100% rename from public/sandbox/mocha/mocha.js rename to scripts/public/sandbox/mocha/mocha.js diff --git a/public/sandbox/mocha/test.html b/scripts/public/sandbox/mocha/test.html similarity index 100% rename from public/sandbox/mocha/test.html rename to scripts/public/sandbox/mocha/test.html diff --git a/public/sandbox/sandbox.html b/scripts/public/sandbox/sandbox.html similarity index 100% rename from public/sandbox/sandbox.html rename to scripts/public/sandbox/sandbox.html diff --git a/public/sandbox/stacktrace.js b/scripts/public/sandbox/stacktrace.js similarity index 100% rename from public/sandbox/stacktrace.js rename to scripts/public/sandbox/stacktrace.js diff --git a/public/sandbox/worker.js b/scripts/public/sandbox/worker.js similarity index 100% rename from public/sandbox/worker.js rename to scripts/public/sandbox/worker.js diff --git a/public/stylesheets/apitome/application.css b/scripts/public/stylesheets/apitome/application.css similarity index 100% rename from public/stylesheets/apitome/application.css rename to scripts/public/stylesheets/apitome/application.css diff --git a/requirements.txt b/scripts/requirements.txt similarity index 100% rename from requirements.txt rename to scripts/requirements.txt diff --git a/scripts/sh/cohort_curriculum.sh b/scripts/scripts/sh/cohort_curriculum.sh similarity index 100% rename from scripts/sh/cohort_curriculum.sh rename to scripts/scripts/sh/cohort_curriculum.sh diff --git a/scripts/sh/content_file_mark_hidden.sh b/scripts/scripts/sh/content_file_mark_hidden.sh similarity index 100% rename from scripts/sh/content_file_mark_hidden.sh rename to scripts/scripts/sh/content_file_mark_hidden.sh diff --git a/scripts/sh/content_file_mark_visible.sh b/scripts/scripts/sh/content_file_mark_visible.sh similarity index 100% rename from scripts/sh/content_file_mark_visible.sh rename to scripts/scripts/sh/content_file_mark_visible.sh diff --git a/scripts/sh/unit_mark_hidden.sh b/scripts/scripts/sh/unit_mark_hidden.sh similarity index 100% rename from scripts/sh/unit_mark_hidden.sh rename to scripts/scripts/sh/unit_mark_hidden.sh diff --git a/scripts/sh/unit_mark_visible.sh b/scripts/scripts/sh/unit_mark_visible.sh similarity index 100% rename from scripts/sh/unit_mark_visible.sh rename to scripts/scripts/sh/unit_mark_visible.sh diff --git a/scripts/sql/checkpoint_answers.sql b/scripts/scripts/sql/checkpoint_answers.sql similarity index 100% rename from scripts/sql/checkpoint_answers.sql rename to scripts/scripts/sql/checkpoint_answers.sql diff --git a/scripts/sql/cohort_challenges_with_answers.sql b/scripts/scripts/sql/cohort_challenges_with_answers.sql similarity index 100% rename from scripts/sql/cohort_challenges_with_answers.sql rename to scripts/scripts/sql/cohort_challenges_with_answers.sql diff --git a/scripts/sql/cohort_prune_for_testing.sql b/scripts/scripts/sql/cohort_prune_for_testing.sql similarity index 100% rename from scripts/sql/cohort_prune_for_testing.sql rename to scripts/scripts/sql/cohort_prune_for_testing.sql diff --git a/scripts/sql/percent_metrics.sql b/scripts/scripts/sql/percent_metrics.sql similarity index 100% rename from scripts/sql/percent_metrics.sql rename to scripts/scripts/sql/percent_metrics.sql diff --git a/scripts/sql/scrub_cohort_data.sql b/scripts/scripts/sql/scrub_cohort_data.sql similarity index 100% rename from scripts/sql/scrub_cohort_data.sql rename to scripts/scripts/sql/scrub_cohort_data.sql diff --git a/scripts/serviceentry.yaml b/scripts/serviceentry.yaml new file mode 100644 index 0000000..9b4e97c --- /dev/null +++ b/scripts/serviceentry.yaml @@ -0,0 +1,15 @@ +apiVersion: networking.istio.io/v1beta1 +kind: ServiceEntry +metadata: + name: gitlab-external-se + namespace: galvanize-learn +spec: + hosts: + - code.il2.dsop.io + - google.com + location: MESH_EXTERNAL + ports: + - name: https + number: 443 + protocol: TLS + resolution: DNS diff --git a/spec/component_props/activity_feed_item_component_props_spec.rb b/scripts/spec/component_props/activity_feed_item_component_props_spec.rb similarity index 100% rename from spec/component_props/activity_feed_item_component_props_spec.rb rename to scripts/spec/component_props/activity_feed_item_component_props_spec.rb diff --git a/spec/component_props/notifications_component_props_spec.rb b/scripts/spec/component_props/notifications_component_props_spec.rb similarity index 100% rename from spec/component_props/notifications_component_props_spec.rb rename to scripts/spec/component_props/notifications_component_props_spec.rb diff --git a/spec/component_props/standard_card_component_props_spec.rb b/scripts/spec/component_props/standard_card_component_props_spec.rb similarity index 100% rename from spec/component_props/standard_card_component_props_spec.rb rename to scripts/spec/component_props/standard_card_component_props_spec.rb diff --git a/spec/controllers/api/v1/blocks/releases_controller_spec.rb b/scripts/spec/controllers/api/v1/blocks/releases_controller_spec.rb similarity index 100% rename from spec/controllers/api/v1/blocks/releases_controller_spec.rb rename to scripts/spec/controllers/api/v1/blocks/releases_controller_spec.rb diff --git a/spec/controllers/api/v1/blocks_controller_spec.rb b/scripts/spec/controllers/api/v1/blocks_controller_spec.rb similarity index 100% rename from spec/controllers/api/v1/blocks_controller_spec.rb rename to scripts/spec/controllers/api/v1/blocks_controller_spec.rb diff --git a/spec/controllers/api/v1/cohorts/blocks/content_files_controller_spec.rb b/scripts/spec/controllers/api/v1/cohorts/blocks/content_files_controller_spec.rb similarity index 100% rename from spec/controllers/api/v1/cohorts/blocks/content_files_controller_spec.rb rename to scripts/spec/controllers/api/v1/cohorts/blocks/content_files_controller_spec.rb diff --git a/spec/controllers/api/v1/cohorts/blocks/units_controller_spec.rb b/scripts/spec/controllers/api/v1/cohorts/blocks/units_controller_spec.rb similarity index 100% rename from spec/controllers/api/v1/cohorts/blocks/units_controller_spec.rb rename to scripts/spec/controllers/api/v1/cohorts/blocks/units_controller_spec.rb diff --git a/spec/controllers/api/v1/cohorts/cohorts_controller_spec.rb b/scripts/spec/controllers/api/v1/cohorts/cohorts_controller_spec.rb similarity index 100% rename from spec/controllers/api/v1/cohorts/cohorts_controller_spec.rb rename to scripts/spec/controllers/api/v1/cohorts/cohorts_controller_spec.rb diff --git a/spec/controllers/api/v1/cohorts/users_controller_spec.rb b/scripts/spec/controllers/api/v1/cohorts/users_controller_spec.rb similarity index 100% rename from spec/controllers/api/v1/cohorts/users_controller_spec.rb rename to scripts/spec/controllers/api/v1/cohorts/users_controller_spec.rb diff --git a/spec/controllers/api/v1/content_files_controller_spec.rb b/scripts/spec/controllers/api/v1/content_files_controller_spec.rb similarity index 100% rename from spec/controllers/api/v1/content_files_controller_spec.rb rename to scripts/spec/controllers/api/v1/content_files_controller_spec.rb diff --git a/spec/controllers/api/v1/users_controller_spec.rb b/scripts/spec/controllers/api/v1/users_controller_spec.rb similarity index 100% rename from spec/controllers/api/v1/users_controller_spec.rb rename to scripts/spec/controllers/api/v1/users_controller_spec.rb diff --git a/spec/controllers/application_controller_spec.rb b/scripts/spec/controllers/application_controller_spec.rb similarity index 100% rename from spec/controllers/application_controller_spec.rb rename to scripts/spec/controllers/application_controller_spec.rb diff --git a/spec/controllers/blocks/releases_controller_spec.rb b/scripts/spec/controllers/blocks/releases_controller_spec.rb similarity index 100% rename from spec/controllers/blocks/releases_controller_spec.rb rename to scripts/spec/controllers/blocks/releases_controller_spec.rb diff --git a/spec/controllers/blocks_controller_spec.rb b/scripts/spec/controllers/blocks_controller_spec.rb similarity index 100% rename from spec/controllers/blocks_controller_spec.rb rename to scripts/spec/controllers/blocks_controller_spec.rb diff --git a/spec/controllers/cohorts/blocks/content_files_controller_spec.rb b/scripts/spec/controllers/cohorts/blocks/content_files_controller_spec.rb similarity index 100% rename from spec/controllers/cohorts/blocks/content_files_controller_spec.rb rename to scripts/spec/controllers/cohorts/blocks/content_files_controller_spec.rb diff --git a/spec/controllers/cohorts/checkpoint_submissions/activities_controller_spec.rb b/scripts/spec/controllers/cohorts/checkpoint_submissions/activities_controller_spec.rb similarity index 100% rename from spec/controllers/cohorts/checkpoint_submissions/activities_controller_spec.rb rename to scripts/spec/controllers/cohorts/checkpoint_submissions/activities_controller_spec.rb diff --git a/spec/controllers/cohorts/cohort_releases_controller_spec.rb b/scripts/spec/controllers/cohorts/cohort_releases_controller_spec.rb similarity index 100% rename from spec/controllers/cohorts/cohort_releases_controller_spec.rb rename to scripts/spec/controllers/cohorts/cohort_releases_controller_spec.rb diff --git a/spec/controllers/cohorts/content_files/checkpoint_submissions_controller_spec.rb b/scripts/spec/controllers/cohorts/content_files/checkpoint_submissions_controller_spec.rb similarity index 100% rename from spec/controllers/cohorts/content_files/checkpoint_submissions_controller_spec.rb rename to scripts/spec/controllers/cohorts/content_files/checkpoint_submissions_controller_spec.rb diff --git a/spec/controllers/cohorts/content_files/submitted_challenge_answers_controller_spec.rb b/scripts/spec/controllers/cohorts/content_files/submitted_challenge_answers_controller_spec.rb similarity index 100% rename from spec/controllers/cohorts/content_files/submitted_challenge_answers_controller_spec.rb rename to scripts/spec/controllers/cohorts/content_files/submitted_challenge_answers_controller_spec.rb diff --git a/spec/controllers/cohorts/content_files_controller_spec.rb b/scripts/spec/controllers/cohorts/content_files_controller_spec.rb similarity index 100% rename from spec/controllers/cohorts/content_files_controller_spec.rb rename to scripts/spec/controllers/cohorts/content_files_controller_spec.rb diff --git a/spec/controllers/cohorts/pairings_controller_spec.rb b/scripts/spec/controllers/cohorts/pairings_controller_spec.rb similarity index 100% rename from spec/controllers/cohorts/pairings_controller_spec.rb rename to scripts/spec/controllers/cohorts/pairings_controller_spec.rb diff --git a/spec/controllers/cohorts/standards_controller_spec.rb b/scripts/spec/controllers/cohorts/standards_controller_spec.rb similarity index 100% rename from spec/controllers/cohorts/standards_controller_spec.rb rename to scripts/spec/controllers/cohorts/standards_controller_spec.rb diff --git a/spec/controllers/cohorts/submitted_challenge_answers/activities_controller_spec.rb b/scripts/spec/controllers/cohorts/submitted_challenge_answers/activities_controller_spec.rb similarity index 100% rename from spec/controllers/cohorts/submitted_challenge_answers/activities_controller_spec.rb rename to scripts/spec/controllers/cohorts/submitted_challenge_answers/activities_controller_spec.rb diff --git a/spec/controllers/cohorts/users/challenges_controller_spec.rb b/scripts/spec/controllers/cohorts/users/challenges_controller_spec.rb similarity index 100% rename from spec/controllers/cohorts/users/challenges_controller_spec.rb rename to scripts/spec/controllers/cohorts/users/challenges_controller_spec.rb diff --git a/spec/controllers/cohorts/users/performances_controller_spec.rb b/scripts/spec/controllers/cohorts/users/performances_controller_spec.rb similarity index 100% rename from spec/controllers/cohorts/users/performances_controller_spec.rb rename to scripts/spec/controllers/cohorts/users/performances_controller_spec.rb diff --git a/spec/controllers/cohorts/users_controller_spec.rb b/scripts/spec/controllers/cohorts/users_controller_spec.rb similarity index 100% rename from spec/controllers/cohorts/users_controller_spec.rb rename to scripts/spec/controllers/cohorts/users_controller_spec.rb diff --git a/spec/controllers/cohorts_controller_spec.rb b/scripts/spec/controllers/cohorts_controller_spec.rb similarity index 100% rename from spec/controllers/cohorts_controller_spec.rb rename to scripts/spec/controllers/cohorts_controller_spec.rb diff --git a/spec/controllers/home_controller_spec.rb b/scripts/spec/controllers/home_controller_spec.rb similarity index 100% rename from spec/controllers/home_controller_spec.rb rename to scripts/spec/controllers/home_controller_spec.rb diff --git a/spec/controllers/notifications_controller_spec.rb b/scripts/spec/controllers/notifications_controller_spec.rb similarity index 100% rename from spec/controllers/notifications_controller_spec.rb rename to scripts/spec/controllers/notifications_controller_spec.rb diff --git a/spec/controllers/permalinks_controller_spec.rb b/scripts/spec/controllers/permalinks_controller_spec.rb similarity index 100% rename from spec/controllers/permalinks_controller_spec.rb rename to scripts/spec/controllers/permalinks_controller_spec.rb diff --git a/spec/controllers/sessions_controller_spec.rb b/scripts/spec/controllers/sessions_controller_spec.rb similarity index 100% rename from spec/controllers/sessions_controller_spec.rb rename to scripts/spec/controllers/sessions_controller_spec.rb diff --git a/spec/controllers/users_controller_spec.rb b/scripts/spec/controllers/users_controller_spec.rb similarity index 100% rename from spec/controllers/users_controller_spec.rb rename to scripts/spec/controllers/users_controller_spec.rb diff --git a/spec/controllers/webhooks/assessments_service/submitted_challenge_answers_controller_spec.rb b/scripts/spec/controllers/webhooks/assessments_service/submitted_challenge_answers_controller_spec.rb similarity index 100% rename from spec/controllers/webhooks/assessments_service/submitted_challenge_answers_controller_spec.rb rename to scripts/spec/controllers/webhooks/assessments_service/submitted_challenge_answers_controller_spec.rb diff --git a/spec/exporters/performance_exporter_spec.rb b/scripts/spec/exporters/performance_exporter_spec.rb similarity index 100% rename from spec/exporters/performance_exporter_spec.rb rename to scripts/spec/exporters/performance_exporter_spec.rb diff --git a/spec/factories.rb b/scripts/spec/factories.rb similarity index 100% rename from spec/factories.rb rename to scripts/spec/factories.rb diff --git a/spec/features/blocks/management_feature_spec.rb b/scripts/spec/features/blocks/management_feature_spec.rb similarity index 100% rename from spec/features/blocks/management_feature_spec.rb rename to scripts/spec/features/blocks/management_feature_spec.rb diff --git a/spec/features/cohorts/activity_dashboard_spec.rb b/scripts/spec/features/cohorts/activity_dashboard_spec.rb similarity index 100% rename from spec/features/cohorts/activity_dashboard_spec.rb rename to scripts/spec/features/cohorts/activity_dashboard_spec.rb diff --git a/spec/features/cohorts/checkpoint_submissions_spec.rb b/scripts/spec/features/cohorts/checkpoint_submissions_spec.rb similarity index 100% rename from spec/features/cohorts/checkpoint_submissions_spec.rb rename to scripts/spec/features/cohorts/checkpoint_submissions_spec.rb diff --git a/spec/features/cohorts/curriculum_feature_spec.rb b/scripts/spec/features/cohorts/curriculum_feature_spec.rb similarity index 100% rename from spec/features/cohorts/curriculum_feature_spec.rb rename to scripts/spec/features/cohorts/curriculum_feature_spec.rb diff --git a/spec/features/cohorts/feed_feature_spec.rb b/scripts/spec/features/cohorts/feed_feature_spec.rb similarity index 100% rename from spec/features/cohorts/feed_feature_spec.rb rename to scripts/spec/features/cohorts/feed_feature_spec.rb diff --git a/spec/features/cohorts/management_feature_spec.rb b/scripts/spec/features/cohorts/management_feature_spec.rb similarity index 100% rename from spec/features/cohorts/management_feature_spec.rb rename to scripts/spec/features/cohorts/management_feature_spec.rb diff --git a/spec/features/cohorts/sandboxes_spec.rb b/scripts/spec/features/cohorts/sandboxes_spec.rb similarity index 100% rename from spec/features/cohorts/sandboxes_spec.rb rename to scripts/spec/features/cohorts/sandboxes_spec.rb diff --git a/spec/features/cohorts/student_progress_spec.rb b/scripts/spec/features/cohorts/student_progress_spec.rb similarity index 100% rename from spec/features/cohorts/student_progress_spec.rb rename to scripts/spec/features/cohorts/student_progress_spec.rb diff --git a/spec/features/cohorts/submissions_spec.rb b/scripts/spec/features/cohorts/submissions_spec.rb similarity index 100% rename from spec/features/cohorts/submissions_spec.rb rename to scripts/spec/features/cohorts/submissions_spec.rb diff --git a/spec/features/cohorts/users/challenges_feature_spec.rb b/scripts/spec/features/cohorts/users/challenges_feature_spec.rb similarity index 100% rename from spec/features/cohorts/users/challenges_feature_spec.rb rename to scripts/spec/features/cohorts/users/challenges_feature_spec.rb diff --git a/spec/features/cohorts/users/submissions_dashboard_feature_spec.rb b/scripts/spec/features/cohorts/users/submissions_dashboard_feature_spec.rb similarity index 100% rename from spec/features/cohorts/users/submissions_dashboard_feature_spec.rb rename to scripts/spec/features/cohorts/users/submissions_dashboard_feature_spec.rb diff --git a/spec/features/content_files/checkpoint_assessments_spec.rb b/scripts/spec/features/content_files/checkpoint_assessments_spec.rb similarity index 100% rename from spec/features/content_files/checkpoint_assessments_spec.rb rename to scripts/spec/features/content_files/checkpoint_assessments_spec.rb diff --git a/spec/features/content_files/checkpoint_submissions_spec.rb b/scripts/spec/features/content_files/checkpoint_submissions_spec.rb similarity index 100% rename from spec/features/content_files/checkpoint_submissions_spec.rb rename to scripts/spec/features/content_files/checkpoint_submissions_spec.rb diff --git a/spec/features/content_files/navigation_feature_spec.rb b/scripts/spec/features/content_files/navigation_feature_spec.rb similarity index 100% rename from spec/features/content_files/navigation_feature_spec.rb rename to scripts/spec/features/content_files/navigation_feature_spec.rb diff --git a/spec/features/content_files/permalinks_spec.rb b/scripts/spec/features/content_files/permalinks_spec.rb similarity index 100% rename from spec/features/content_files/permalinks_spec.rb rename to scripts/spec/features/content_files/permalinks_spec.rb diff --git a/spec/features/content_files/view_feature_spec.rb b/scripts/spec/features/content_files/view_feature_spec.rb similarity index 100% rename from spec/features/content_files/view_feature_spec.rb rename to scripts/spec/features/content_files/view_feature_spec.rb diff --git a/spec/features/home/header_feature_spec.rb b/scripts/spec/features/home/header_feature_spec.rb similarity index 100% rename from spec/features/home/header_feature_spec.rb rename to scripts/spec/features/home/header_feature_spec.rb diff --git a/spec/features_helper.rb b/scripts/spec/features_helper.rb similarity index 100% rename from spec/features_helper.rb rename to scripts/spec/features_helper.rb diff --git a/spec/finders/block_finder_spec.rb b/scripts/spec/finders/block_finder_spec.rb similarity index 100% rename from spec/finders/block_finder_spec.rb rename to scripts/spec/finders/block_finder_spec.rb diff --git a/spec/finders/checkpoint_submission_finder_spec.rb b/scripts/spec/finders/checkpoint_submission_finder_spec.rb similarity index 100% rename from spec/finders/checkpoint_submission_finder_spec.rb rename to scripts/spec/finders/checkpoint_submission_finder_spec.rb diff --git a/spec/finders/cohort_user_finder_spec.rb b/scripts/spec/finders/cohort_user_finder_spec.rb similarity index 100% rename from spec/finders/cohort_user_finder_spec.rb rename to scripts/spec/finders/cohort_user_finder_spec.rb diff --git a/spec/finders/content_file_finder_spec.rb b/scripts/spec/finders/content_file_finder_spec.rb similarity index 100% rename from spec/finders/content_file_finder_spec.rb rename to scripts/spec/finders/content_file_finder_spec.rb diff --git a/spec/finders/performance_finder_spec.rb b/scripts/spec/finders/performance_finder_spec.rb similarity index 100% rename from spec/finders/performance_finder_spec.rb rename to scripts/spec/finders/performance_finder_spec.rb diff --git a/spec/finders/release_finder_spec.rb b/scripts/spec/finders/release_finder_spec.rb similarity index 100% rename from spec/finders/release_finder_spec.rb rename to scripts/spec/finders/release_finder_spec.rb diff --git a/spec/finders/standard_finder_spec.rb b/scripts/spec/finders/standard_finder_spec.rb similarity index 100% rename from spec/finders/standard_finder_spec.rb rename to scripts/spec/finders/standard_finder_spec.rb diff --git a/spec/finders/submitted_challenge_answer_finder_spec.rb b/scripts/spec/finders/submitted_challenge_answer_finder_spec.rb similarity index 100% rename from spec/finders/submitted_challenge_answer_finder_spec.rb rename to scripts/spec/finders/submitted_challenge_answer_finder_spec.rb diff --git a/spec/finders/user_finder_spec.rb b/scripts/spec/finders/user_finder_spec.rb similarity index 100% rename from spec/finders/user_finder_spec.rb rename to scripts/spec/finders/user_finder_spec.rb diff --git a/spec/fixtures/preview-content-file/preview.md b/scripts/spec/fixtures/preview-content-file/preview.md similarity index 100% rename from spec/fixtures/preview-content-file/preview.md rename to scripts/spec/fixtures/preview-content-file/preview.md diff --git a/spec/fixtures/test-block-repo/._docker_directories_test-docker-folder.zip b/scripts/spec/fixtures/test-block-repo/._docker_directories_test-docker-folder.zip similarity index 100% rename from spec/fixtures/test-block-repo/._docker_directories_test-docker-folder.zip rename to scripts/spec/fixtures/test-block-repo/._docker_directories_test-docker-folder.zip diff --git a/spec/fixtures/test-block-repo/README.md b/scripts/spec/fixtures/test-block-repo/README.md similarity index 100% rename from spec/fixtures/test-block-repo/README.md rename to scripts/spec/fixtures/test-block-repo/README.md diff --git a/spec/fixtures/test-block-repo/challenges-smoketest.md b/scripts/spec/fixtures/test-block-repo/challenges-smoketest.md similarity index 100% rename from spec/fixtures/test-block-repo/challenges-smoketest.md rename to scripts/spec/fixtures/test-block-repo/challenges-smoketest.md diff --git a/spec/fixtures/test-block-repo/config.yaml b/scripts/spec/fixtures/test-block-repo/config.yaml similarity index 100% rename from spec/fixtures/test-block-repo/config.yaml rename to scripts/spec/fixtures/test-block-repo/config.yaml diff --git a/spec/fixtures/test-block-repo/docker_directories/test-docker-folder/Dockerfile b/scripts/spec/fixtures/test-block-repo/docker_directories/test-docker-folder/Dockerfile similarity index 100% rename from spec/fixtures/test-block-repo/docker_directories/test-docker-folder/Dockerfile rename to scripts/spec/fixtures/test-block-repo/docker_directories/test-docker-folder/Dockerfile diff --git a/spec/fixtures/test-block-repo/docker_directories/test-docker-folder/test.sh b/scripts/spec/fixtures/test-block-repo/docker_directories/test-docker-folder/test.sh similarity index 100% rename from spec/fixtures/test-block-repo/docker_directories/test-docker-folder/test.sh rename to scripts/spec/fixtures/test-block-repo/docker_directories/test-docker-folder/test.sh diff --git a/spec/fixtures/test-block-repo/folder/sibling.md b/scripts/spec/fixtures/test-block-repo/folder/sibling.md similarity index 100% rename from spec/fixtures/test-block-repo/folder/sibling.md rename to scripts/spec/fixtures/test-block-repo/folder/sibling.md diff --git a/spec/fixtures/test-block-repo/folder/target.md b/scripts/spec/fixtures/test-block-repo/folder/target.md similarity index 100% rename from spec/fixtures/test-block-repo/folder/target.md rename to scripts/spec/fixtures/test-block-repo/folder/target.md diff --git a/spec/fixtures/test-block-repo/images/galvanize-logo.png b/scripts/spec/fixtures/test-block-repo/images/galvanize-logo.png similarity index 100% rename from spec/fixtures/test-block-repo/images/galvanize-logo.png rename to scripts/spec/fixtures/test-block-repo/images/galvanize-logo.png diff --git a/spec/fixtures/test-block-repo/images/register_klass.gif b/scripts/spec/fixtures/test-block-repo/images/register_klass.gif similarity index 100% rename from spec/fixtures/test-block-repo/images/register_klass.gif rename to scripts/spec/fixtures/test-block-repo/images/register_klass.gif diff --git a/spec/fixtures/test-block-repo/markdown-smoketesT.md b/scripts/spec/fixtures/test-block-repo/markdown-smoketesT.md similarity index 100% rename from spec/fixtures/test-block-repo/markdown-smoketesT.md rename to scripts/spec/fixtures/test-block-repo/markdown-smoketesT.md diff --git a/spec/fixtures/test-block-repo/target.md b/scripts/spec/fixtures/test-block-repo/target.md similarity index 100% rename from spec/fixtures/test-block-repo/target.md rename to scripts/spec/fixtures/test-block-repo/target.md diff --git a/spec/fixtures/test-block-repo/test.sql b/scripts/spec/fixtures/test-block-repo/test.sql similarity index 100% rename from spec/fixtures/test-block-repo/test.sql rename to scripts/spec/fixtures/test-block-repo/test.sql diff --git a/spec/fixtures/vcr_cassettes/github-branch-success.yml b/scripts/spec/fixtures/vcr_cassettes/github-branch-success.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/github-branch-success.yml rename to scripts/spec/fixtures/vcr_cassettes/github-branch-success.yml diff --git a/spec/fixtures/vcr_cassettes/github-course-yaml-not-found.yml b/scripts/spec/fixtures/vcr_cassettes/github-course-yaml-not-found.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/github-course-yaml-not-found.yml rename to scripts/spec/fixtures/vcr_cassettes/github-course-yaml-not-found.yml diff --git a/spec/fixtures/vcr_cassettes/github-course-yaml-success-2.yml b/scripts/spec/fixtures/vcr_cassettes/github-course-yaml-success-2.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/github-course-yaml-success-2.yml rename to scripts/spec/fixtures/vcr_cassettes/github-course-yaml-success-2.yml diff --git a/spec/fixtures/vcr_cassettes/github-course-yaml-success.yml b/scripts/spec/fixtures/vcr_cassettes/github-course-yaml-success.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/github-course-yaml-success.yml rename to scripts/spec/fixtures/vcr_cassettes/github-course-yaml-success.yml diff --git a/spec/fixtures/vcr_cassettes/github-not-found.yml b/scripts/spec/fixtures/vcr_cassettes/github-not-found.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/github-not-found.yml rename to scripts/spec/fixtures/vcr_cassettes/github-not-found.yml diff --git a/spec/fixtures/vcr_cassettes/github-repo-success.yml b/scripts/spec/fixtures/vcr_cassettes/github-repo-success.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/github-repo-success.yml rename to scripts/spec/fixtures/vcr_cassettes/github-repo-success.yml diff --git a/spec/fixtures/vcr_cassettes/gitlab-course-yaml-branch-failure.yml b/scripts/spec/fixtures/vcr_cassettes/gitlab-course-yaml-branch-failure.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/gitlab-course-yaml-branch-failure.yml rename to scripts/spec/fixtures/vcr_cassettes/gitlab-course-yaml-branch-failure.yml diff --git a/spec/fixtures/vcr_cassettes/gitlab-course-yaml-success.yml b/scripts/spec/fixtures/vcr_cassettes/gitlab-course-yaml-success.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/gitlab-course-yaml-success.yml rename to scripts/spec/fixtures/vcr_cassettes/gitlab-course-yaml-success.yml diff --git a/spec/fixtures/vcr_cassettes/gitlab-not-found.yml b/scripts/spec/fixtures/vcr_cassettes/gitlab-not-found.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/gitlab-not-found.yml rename to scripts/spec/fixtures/vcr_cassettes/gitlab-not-found.yml diff --git a/spec/fixtures/vcr_cassettes/gitlab-success.yml b/scripts/spec/fixtures/vcr_cassettes/gitlab-success.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/gitlab-success.yml rename to scripts/spec/fixtures/vcr_cassettes/gitlab-success.yml diff --git a/spec/fixtures/vcr_cassettes/resync-course-job-success.yml b/scripts/spec/fixtures/vcr_cassettes/resync-course-job-success.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/resync-course-job-success.yml rename to scripts/spec/fixtures/vcr_cassettes/resync-course-job-success.yml diff --git a/spec/helpers/json_helper_spec.rb b/scripts/spec/helpers/json_helper_spec.rb similarity index 100% rename from spec/helpers/json_helper_spec.rb rename to scripts/spec/helpers/json_helper_spec.rb diff --git a/spec/helpers/mastery_mode_percent_helper_spec.rb b/scripts/spec/helpers/mastery_mode_percent_helper_spec.rb similarity index 100% rename from spec/helpers/mastery_mode_percent_helper_spec.rb rename to scripts/spec/helpers/mastery_mode_percent_helper_spec.rb diff --git a/spec/helpers/standard_navigation_helper_spec.rb b/scripts/spec/helpers/standard_navigation_helper_spec.rb similarity index 100% rename from spec/helpers/standard_navigation_helper_spec.rb rename to scripts/spec/helpers/standard_navigation_helper_spec.rb diff --git a/spec/integration_helper.rb b/scripts/spec/integration_helper.rb similarity index 100% rename from spec/integration_helper.rb rename to scripts/spec/integration_helper.rb diff --git a/spec/jobs/branch_release_notifier_job_spec.rb b/scripts/spec/jobs/branch_release_notifier_job_spec.rb similarity index 100% rename from spec/jobs/branch_release_notifier_job_spec.rb rename to scripts/spec/jobs/branch_release_notifier_job_spec.rb diff --git a/spec/jobs/checkpoint_paired_submission_job_spec.rb b/scripts/spec/jobs/checkpoint_paired_submission_job_spec.rb similarity index 100% rename from spec/jobs/checkpoint_paired_submission_job_spec.rb rename to scripts/spec/jobs/checkpoint_paired_submission_job_spec.rb diff --git a/spec/jobs/content_file_default_visibility_job_spec.rb b/scripts/spec/jobs/content_file_default_visibility_job_spec.rb similarity index 100% rename from spec/jobs/content_file_default_visibility_job_spec.rb rename to scripts/spec/jobs/content_file_default_visibility_job_spec.rb diff --git a/spec/jobs/content_file_visit_job_spec.rb b/scripts/spec/jobs/content_file_visit_job_spec.rb similarity index 100% rename from spec/jobs/content_file_visit_job_spec.rb rename to scripts/spec/jobs/content_file_visit_job_spec.rb diff --git a/spec/jobs/create_api_interaction_job_spec.rb b/scripts/spec/jobs/create_api_interaction_job_spec.rb similarity index 100% rename from spec/jobs/create_api_interaction_job_spec.rb rename to scripts/spec/jobs/create_api_interaction_job_spec.rb diff --git a/spec/jobs/create_release_job_spec.rb b/scripts/spec/jobs/create_release_job_spec.rb similarity index 100% rename from spec/jobs/create_release_job_spec.rb rename to scripts/spec/jobs/create_release_job_spec.rb diff --git a/spec/jobs/evaluate_code_snippet_job_spec.rb b/scripts/spec/jobs/evaluate_code_snippet_job_spec.rb similarity index 100% rename from spec/jobs/evaluate_code_snippet_job_spec.rb rename to scripts/spec/jobs/evaluate_code_snippet_job_spec.rb diff --git a/spec/jobs/evaluate_custom_snippet_job_spec.rb b/scripts/spec/jobs/evaluate_custom_snippet_job_spec.rb similarity index 100% rename from spec/jobs/evaluate_custom_snippet_job_spec.rb rename to scripts/spec/jobs/evaluate_custom_snippet_job_spec.rb diff --git a/spec/jobs/evaluate_project_job_spec.rb b/scripts/spec/jobs/evaluate_project_job_spec.rb similarity index 100% rename from spec/jobs/evaluate_project_job_spec.rb rename to scripts/spec/jobs/evaluate_project_job_spec.rb diff --git a/spec/jobs/grade_timed_checkpoint_job_spec.rb b/scripts/spec/jobs/grade_timed_checkpoint_job_spec.rb similarity index 100% rename from spec/jobs/grade_timed_checkpoint_job_spec.rb rename to scripts/spec/jobs/grade_timed_checkpoint_job_spec.rb diff --git a/spec/jobs/import_student_work_job_spec.rb b/scripts/spec/jobs/import_student_work_job_spec.rb similarity index 100% rename from spec/jobs/import_student_work_job_spec.rb rename to scripts/spec/jobs/import_student_work_job_spec.rb diff --git a/spec/jobs/release_notifier_job_spec.rb b/scripts/spec/jobs/release_notifier_job_spec.rb similarity index 100% rename from spec/jobs/release_notifier_job_spec.rb rename to scripts/spec/jobs/release_notifier_job_spec.rb diff --git a/spec/jobs/resync_course_job_spec.rb b/scripts/spec/jobs/resync_course_job_spec.rb similarity index 100% rename from spec/jobs/resync_course_job_spec.rb rename to scripts/spec/jobs/resync_course_job_spec.rb diff --git a/spec/jobs/set_block_caches_job_spec.rb b/scripts/spec/jobs/set_block_caches_job_spec.rb similarity index 100% rename from spec/jobs/set_block_caches_job_spec.rb rename to scripts/spec/jobs/set_block_caches_job_spec.rb diff --git a/spec/jobs/slack_ds_prep_job_spec.rb b/scripts/spec/jobs/slack_ds_prep_job_spec.rb similarity index 100% rename from spec/jobs/slack_ds_prep_job_spec.rb rename to scripts/spec/jobs/slack_ds_prep_job_spec.rb diff --git a/spec/jobs/slack_se_prep_job_spec.rb b/scripts/spec/jobs/slack_se_prep_job_spec.rb similarity index 100% rename from spec/jobs/slack_se_prep_job_spec.rb rename to scripts/spec/jobs/slack_se_prep_job_spec.rb diff --git a/spec/jobs/slack_student_job_spec.rb b/scripts/spec/jobs/slack_student_job_spec.rb similarity index 100% rename from spec/jobs/slack_student_job_spec.rb rename to scripts/spec/jobs/slack_student_job_spec.rb diff --git a/spec/jobs/switch_to_branch_job_spec.rb b/scripts/spec/jobs/switch_to_branch_job_spec.rb similarity index 100% rename from spec/jobs/switch_to_branch_job_spec.rb rename to scripts/spec/jobs/switch_to_branch_job_spec.rb diff --git a/spec/models/activity_spec.rb b/scripts/spec/models/activity_spec.rb similarity index 100% rename from spec/models/activity_spec.rb rename to scripts/spec/models/activity_spec.rb diff --git a/spec/models/api_interaction_spec.rb b/scripts/spec/models/api_interaction_spec.rb similarity index 100% rename from spec/models/api_interaction_spec.rb rename to scripts/spec/models/api_interaction_spec.rb diff --git a/spec/models/block_spec.rb b/scripts/spec/models/block_spec.rb similarity index 100% rename from spec/models/block_spec.rb rename to scripts/spec/models/block_spec.rb diff --git a/spec/models/challenge_spec.rb b/scripts/spec/models/challenge_spec.rb similarity index 100% rename from spec/models/challenge_spec.rb rename to scripts/spec/models/challenge_spec.rb diff --git a/spec/models/checkpoint_submission_spec.rb b/scripts/spec/models/checkpoint_submission_spec.rb similarity index 100% rename from spec/models/checkpoint_submission_spec.rb rename to scripts/spec/models/checkpoint_submission_spec.rb diff --git a/spec/models/cohort_release_spec.rb b/scripts/spec/models/cohort_release_spec.rb similarity index 100% rename from spec/models/cohort_release_spec.rb rename to scripts/spec/models/cohort_release_spec.rb diff --git a/spec/models/cohort_spec.rb b/scripts/spec/models/cohort_spec.rb similarity index 100% rename from spec/models/cohort_spec.rb rename to scripts/spec/models/cohort_spec.rb diff --git a/spec/models/cohort_user_spec.rb b/scripts/spec/models/cohort_user_spec.rb similarity index 100% rename from spec/models/cohort_user_spec.rb rename to scripts/spec/models/cohort_user_spec.rb diff --git a/spec/models/content_file_spec.rb b/scripts/spec/models/content_file_spec.rb similarity index 100% rename from spec/models/content_file_spec.rb rename to scripts/spec/models/content_file_spec.rb diff --git a/spec/models/content_visibility_spec.rb b/scripts/spec/models/content_visibility_spec.rb similarity index 100% rename from spec/models/content_visibility_spec.rb rename to scripts/spec/models/content_visibility_spec.rb diff --git a/spec/models/lesson_visit_spec.rb b/scripts/spec/models/lesson_visit_spec.rb similarity index 100% rename from spec/models/lesson_visit_spec.rb rename to scripts/spec/models/lesson_visit_spec.rb diff --git a/spec/models/notification_spec.rb b/scripts/spec/models/notification_spec.rb similarity index 100% rename from spec/models/notification_spec.rb rename to scripts/spec/models/notification_spec.rb diff --git a/spec/models/pairing_spec.rb b/scripts/spec/models/pairing_spec.rb similarity index 100% rename from spec/models/pairing_spec.rb rename to scripts/spec/models/pairing_spec.rb diff --git a/spec/models/performance_spec.rb b/scripts/spec/models/performance_spec.rb similarity index 100% rename from spec/models/performance_spec.rb rename to scripts/spec/models/performance_spec.rb diff --git a/spec/models/release_spec.rb b/scripts/spec/models/release_spec.rb similarity index 100% rename from spec/models/release_spec.rb rename to scripts/spec/models/release_spec.rb diff --git a/spec/models/resync_job_result_spec.rb b/scripts/spec/models/resync_job_result_spec.rb similarity index 100% rename from spec/models/resync_job_result_spec.rb rename to scripts/spec/models/resync_job_result_spec.rb diff --git a/spec/models/section_spec.rb b/scripts/spec/models/section_spec.rb similarity index 100% rename from spec/models/section_spec.rb rename to scripts/spec/models/section_spec.rb diff --git a/spec/models/standard_spec.rb b/scripts/spec/models/standard_spec.rb similarity index 100% rename from spec/models/standard_spec.rb rename to scripts/spec/models/standard_spec.rb diff --git a/spec/models/submitted_challenge_answer_spec.rb b/scripts/spec/models/submitted_challenge_answer_spec.rb similarity index 100% rename from spec/models/submitted_challenge_answer_spec.rb rename to scripts/spec/models/submitted_challenge_answer_spec.rb diff --git a/spec/models/user_last_viewed_standard_path_spec.rb b/scripts/spec/models/user_last_viewed_standard_path_spec.rb similarity index 100% rename from spec/models/user_last_viewed_standard_path_spec.rb rename to scripts/spec/models/user_last_viewed_standard_path_spec.rb diff --git a/spec/models/user_spec.rb b/scripts/spec/models/user_spec.rb similarity index 100% rename from spec/models/user_spec.rb rename to scripts/spec/models/user_spec.rb diff --git a/spec/policies/cohort_policy_spec.rb b/scripts/spec/policies/cohort_policy_spec.rb similarity index 100% rename from spec/policies/cohort_policy_spec.rb rename to scripts/spec/policies/cohort_policy_spec.rb diff --git a/spec/policies/content_file_policy_spec.rb b/scripts/spec/policies/content_file_policy_spec.rb similarity index 100% rename from spec/policies/content_file_policy_spec.rb rename to scripts/spec/policies/content_file_policy_spec.rb diff --git a/spec/policies/user_policy_spec.rb b/scripts/spec/policies/user_policy_spec.rb similarity index 100% rename from spec/policies/user_policy_spec.rb rename to scripts/spec/policies/user_policy_spec.rb diff --git a/spec/presenters/block_presenter/for_cohort_releases_new_spec.rb b/scripts/spec/presenters/block_presenter/for_cohort_releases_new_spec.rb similarity index 100% rename from spec/presenters/block_presenter/for_cohort_releases_new_spec.rb rename to scripts/spec/presenters/block_presenter/for_cohort_releases_new_spec.rb diff --git a/spec/presenters/block_presenter/for_cohort_releases_spec.rb b/scripts/spec/presenters/block_presenter/for_cohort_releases_spec.rb similarity index 100% rename from spec/presenters/block_presenter/for_cohort_releases_spec.rb rename to scripts/spec/presenters/block_presenter/for_cohort_releases_spec.rb diff --git a/spec/presenters/block_presenter/for_releases_spec.rb b/scripts/spec/presenters/block_presenter/for_releases_spec.rb similarity index 100% rename from spec/presenters/block_presenter/for_releases_spec.rb rename to scripts/spec/presenters/block_presenter/for_releases_spec.rb diff --git a/spec/presenters/challenge_with_submitted_challenge_answers_presenter_spec.rb b/scripts/spec/presenters/challenge_with_submitted_challenge_answers_presenter_spec.rb similarity index 100% rename from spec/presenters/challenge_with_submitted_challenge_answers_presenter_spec.rb rename to scripts/spec/presenters/challenge_with_submitted_challenge_answers_presenter_spec.rb diff --git a/spec/presenters/checkpoint_submission_presenter/for_index_spec.rb b/scripts/spec/presenters/checkpoint_submission_presenter/for_index_spec.rb similarity index 100% rename from spec/presenters/checkpoint_submission_presenter/for_index_spec.rb rename to scripts/spec/presenters/checkpoint_submission_presenter/for_index_spec.rb diff --git a/spec/presenters/checkpoint_submission_presenter_spec.rb b/scripts/spec/presenters/checkpoint_submission_presenter_spec.rb similarity index 100% rename from spec/presenters/checkpoint_submission_presenter_spec.rb rename to scripts/spec/presenters/checkpoint_submission_presenter_spec.rb diff --git a/spec/presenters/content_file_presenter/for_curriculum_last_viewed_spec.rb b/scripts/spec/presenters/content_file_presenter/for_curriculum_last_viewed_spec.rb similarity index 100% rename from spec/presenters/content_file_presenter/for_curriculum_last_viewed_spec.rb rename to scripts/spec/presenters/content_file_presenter/for_curriculum_last_viewed_spec.rb diff --git a/spec/presenters/content_file_presenter/for_show_spec.rb b/scripts/spec/presenters/content_file_presenter/for_show_spec.rb similarity index 100% rename from spec/presenters/content_file_presenter/for_show_spec.rb rename to scripts/spec/presenters/content_file_presenter/for_show_spec.rb diff --git a/spec/presenters/content_file_presenter/for_sidebar_spec.rb b/scripts/spec/presenters/content_file_presenter/for_sidebar_spec.rb similarity index 100% rename from spec/presenters/content_file_presenter/for_sidebar_spec.rb rename to scripts/spec/presenters/content_file_presenter/for_sidebar_spec.rb diff --git a/spec/presenters/standard_presenter/for_checkpoint_submission_spec.rb b/scripts/spec/presenters/standard_presenter/for_checkpoint_submission_spec.rb similarity index 100% rename from spec/presenters/standard_presenter/for_checkpoint_submission_spec.rb rename to scripts/spec/presenters/standard_presenter/for_checkpoint_submission_spec.rb diff --git a/spec/presenters/standard_presenter/for_standard_card_spec.rb b/scripts/spec/presenters/standard_presenter/for_standard_card_spec.rb similarity index 100% rename from spec/presenters/standard_presenter/for_standard_card_spec.rb rename to scripts/spec/presenters/standard_presenter/for_standard_card_spec.rb diff --git a/spec/presenters/student_progress_presenter_spec.rb b/scripts/spec/presenters/student_progress_presenter_spec.rb similarity index 100% rename from spec/presenters/student_progress_presenter_spec.rb rename to scripts/spec/presenters/student_progress_presenter_spec.rb diff --git a/spec/presenters/submissions_dashboard_presenter_spec.rb b/scripts/spec/presenters/submissions_dashboard_presenter_spec.rb similarity index 100% rename from spec/presenters/submissions_dashboard_presenter_spec.rb rename to scripts/spec/presenters/submissions_dashboard_presenter_spec.rb diff --git a/spec/presenters/submitted_challenge_answer_presenter_spec.rb b/scripts/spec/presenters/submitted_challenge_answer_presenter_spec.rb similarity index 100% rename from spec/presenters/submitted_challenge_answer_presenter_spec.rb rename to scripts/spec/presenters/submitted_challenge_answer_presenter_spec.rb diff --git a/spec/services/activity_aggregator_service_spec.rb b/scripts/spec/services/activity_aggregator_service_spec.rb similarity index 100% rename from spec/services/activity_aggregator_service_spec.rb rename to scripts/spec/services/activity_aggregator_service_spec.rb diff --git a/spec/services/assessment_service_spec.rb b/scripts/spec/services/assessment_service_spec.rb similarity index 100% rename from spec/services/assessment_service_spec.rb rename to scripts/spec/services/assessment_service_spec.rb diff --git a/spec/services/auto_assign_release_service_spec.rb b/scripts/spec/services/auto_assign_release_service_spec.rb similarity index 100% rename from spec/services/auto_assign_release_service_spec.rb rename to scripts/spec/services/auto_assign_release_service_spec.rb diff --git a/spec/services/checkpoint_submission_service_spec.rb b/scripts/spec/services/checkpoint_submission_service_spec.rb similarity index 100% rename from spec/services/checkpoint_submission_service_spec.rb rename to scripts/spec/services/checkpoint_submission_service_spec.rb diff --git a/spec/services/cohort_standard_progress_service_spec.rb b/scripts/spec/services/cohort_standard_progress_service_spec.rb similarity index 100% rename from spec/services/cohort_standard_progress_service_spec.rb rename to scripts/spec/services/cohort_standard_progress_service_spec.rb diff --git a/spec/services/course_validator_spec.rb b/scripts/spec/services/course_validator_spec.rb similarity index 100% rename from spec/services/course_validator_spec.rb rename to scripts/spec/services/course_validator_spec.rb diff --git a/spec/services/curriculum_progress_service_spec.rb b/scripts/spec/services/curriculum_progress_service_spec.rb similarity index 100% rename from spec/services/curriculum_progress_service_spec.rb rename to scripts/spec/services/curriculum_progress_service_spec.rb diff --git a/spec/services/download_repository_service_spec.rb b/scripts/spec/services/download_repository_service_spec.rb similarity index 100% rename from spec/services/download_repository_service_spec.rb rename to scripts/spec/services/download_repository_service_spec.rb diff --git a/spec/services/git_url_service_spec.rb b/scripts/spec/services/git_url_service_spec.rb similarity index 100% rename from spec/services/git_url_service_spec.rb rename to scripts/spec/services/git_url_service_spec.rb diff --git a/spec/services/mastery_average_service_spec.rb b/scripts/spec/services/mastery_average_service_spec.rb similarity index 100% rename from spec/services/mastery_average_service_spec.rb rename to scripts/spec/services/mastery_average_service_spec.rb diff --git a/spec/services/notification_service_spec.rb b/scripts/spec/services/notification_service_spec.rb similarity index 100% rename from spec/services/notification_service_spec.rb rename to scripts/spec/services/notification_service_spec.rb diff --git a/spec/services/platform_one_auth_resolver_service_spec.rb b/scripts/spec/services/platform_one_auth_resolver_service_spec.rb similarity index 100% rename from spec/services/platform_one_auth_resolver_service_spec.rb rename to scripts/spec/services/platform_one_auth_resolver_service_spec.rb diff --git a/spec/services/preview_content_file_service_spec.rb b/scripts/spec/services/preview_content_file_service_spec.rb similarity index 100% rename from spec/services/preview_content_file_service_spec.rb rename to scripts/spec/services/preview_content_file_service_spec.rb diff --git a/spec/services/release_destroyer_service_spec.rb b/scripts/spec/services/release_destroyer_service_spec.rb similarity index 100% rename from spec/services/release_destroyer_service_spec.rb rename to scripts/spec/services/release_destroyer_service_spec.rb diff --git a/spec/services/resync_course_service_spec.rb b/scripts/spec/services/resync_course_service_spec.rb similarity index 100% rename from spec/services/resync_course_service_spec.rb rename to scripts/spec/services/resync_course_service_spec.rb diff --git a/spec/services/s3_asset_uploader_service_spec.rb b/scripts/spec/services/s3_asset_uploader_service_spec.rb similarity index 100% rename from spec/services/s3_asset_uploader_service_spec.rb rename to scripts/spec/services/s3_asset_uploader_service_spec.rb diff --git a/spec/services/standard_submissions_service_spec.rb b/scripts/spec/services/standard_submissions_service_spec.rb similarity index 100% rename from spec/services/standard_submissions_service_spec.rb rename to scripts/spec/services/standard_submissions_service_spec.rb diff --git a/spec/spec_helper.rb b/scripts/spec/spec_helper.rb similarity index 100% rename from spec/spec_helper.rb rename to scripts/spec/spec_helper.rb diff --git a/spec/support/json_spec_matchers.rb b/scripts/spec/support/json_spec_matchers.rb similarity index 100% rename from spec/support/json_spec_matchers.rb rename to scripts/spec/support/json_spec_matchers.rb diff --git a/spec/support/mocktokit.rb b/scripts/spec/support/mocktokit.rb similarity index 100% rename from spec/support/mocktokit.rb rename to scripts/spec/support/mocktokit.rb diff --git a/spec/support/object_creation_methods.rb b/scripts/spec/support/object_creation_methods.rb similarity index 100% rename from spec/support/object_creation_methods.rb rename to scripts/spec/support/object_creation_methods.rb diff --git a/tsconfig.json b/scripts/tsconfig.json similarity index 100% rename from tsconfig.json rename to scripts/tsconfig.json diff --git a/vendor/assets/javascripts/bootstrap-datepicker.js b/scripts/vendor/assets/javascripts/bootstrap-datepicker.js similarity index 100% rename from vendor/assets/javascripts/bootstrap-datepicker.js rename to scripts/vendor/assets/javascripts/bootstrap-datepicker.js diff --git a/vendor/assets/javascripts/hopscotch.js b/scripts/vendor/assets/javascripts/hopscotch.js similarity index 100% rename from vendor/assets/javascripts/hopscotch.js rename to scripts/vendor/assets/javascripts/hopscotch.js diff --git a/vendor/assets/javascripts/react-tooltip.js b/scripts/vendor/assets/javascripts/react-tooltip.js similarity index 100% rename from vendor/assets/javascripts/react-tooltip.js rename to scripts/vendor/assets/javascripts/react-tooltip.js diff --git a/vendor/assets/stylesheets/bootstrap-datepicker.css b/scripts/vendor/assets/stylesheets/bootstrap-datepicker.css similarity index 100% rename from vendor/assets/stylesheets/bootstrap-datepicker.css rename to scripts/vendor/assets/stylesheets/bootstrap-datepicker.css diff --git a/vendor/assets/stylesheets/hopscotch.css b/scripts/vendor/assets/stylesheets/hopscotch.css similarity index 100% rename from vendor/assets/stylesheets/hopscotch.css rename to scripts/vendor/assets/stylesheets/hopscotch.css diff --git a/yarn.lock b/scripts/yarn.lock similarity index 100% rename from yarn.lock rename to scripts/yarn.lock -- GitLab From 10e5e9f6ad41f05893b0b6c71dfa924721f8795f Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Thu, 5 Nov 2020 16:48:46 -1000 Subject: [PATCH 188/283] Removed a byebug --- scripts/app/controllers/api/v1/users_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/app/controllers/api/v1/users_controller.rb b/scripts/app/controllers/api/v1/users_controller.rb index 1712099..245729e 100644 --- a/scripts/app/controllers/api/v1/users_controller.rb +++ b/scripts/app/controllers/api/v1/users_controller.rb @@ -32,7 +32,7 @@ class Api::V1::UsersController < Api::ApplicationController render_method_not_allowed_response and return unless request.post? authorize(current_user, :learn_cli_metadata?) - byebug + @api_interaction_metadata = { cli_benchmark: user_params.as_json } -- GitLab From 704e20528da1849182f1bb3042f9042de5829e1c Mon Sep 17 00:00:00 2001 From: Derrin Chong Date: Thu, 5 Nov 2020 20:00:13 -1000 Subject: [PATCH 189/283] Change entrypoint --- .Dockerfile.swp | Bin 20480 -> 0 bytes Dockerfile | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 .Dockerfile.swp diff --git a/.Dockerfile.swp b/.Dockerfile.swp deleted file mode 100644 index e38d85e67f1c1580477d7e6a7572442646f48eab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20480 zcmeI3du$v>9mhA#gHn<7!S8dPG?KKS^id$)h?bS`s<(kd)z||bf2)vL7iOh$t{wG^ z1s+r^o3GiEtdt5!1u`j6k1DxCJCt|l2gI%3xAzXV`_|b^UC72#0jYpgKq?>=kP1iz zqyka_slflY0+GL2L8`CZlw5|E{NB{@drMLtOMVY@e7-p;A4`5Ob$p%_=kP1iz{tF7|rlM?pgQ7eK=>311|Ns7tit;`1IdBe~1rLCO z;KiMaavl5(d9U?g0g`8*Bl8zC}@f1FnOo!MDK$ z@KNA^c`ykkKmok+dPVsY_%-+j_&T@%Y;X$9fp>xZ;CAr*&5H6(a2Bip6XZcZxDEXB zb&B#85P$;s*EaY8J`d)=JHXq(7Vykgj0G%k5d0mRFh2l~fJv|&+yY+4=F4U9F)#+U zfuCSQ=L_Hjm<30`Zg4Bu;HPh7a%zs{a+Sby4wvheZSsI=^)S%NmaA0_V}G-x^!2f^ zkr8&3``k6TYgjx~6=nS{Y^ywYP&*Ua(TL|()UX!!wW_*H7nW<-b(3pVznXZG*7Raz z1j~Mu-3|_N@;Y`m9Wbr!VPG^})1E53n8(7T<0O8^mAzO|?;S>cEOn)Q()u>+?~G&T z*P69vb(bz$B%^*-=}475n6DUEHrc0d1=pP2%3g8w4o6Yb#mjhN@UNqWUWe}M-c?Pb zTt2gny^`4kN_W`AOM+&l_a%|er|*SPHQ-^=Wm?@uq_l}&4Nu$c@`|dSOtTLMnf=o@ zXx8qf=&6gBjS2M^sx8YkuI|Y$^>afL`bPGv^E8T8jlFEE>N1*W7dzNu7+28O`cyKp zZEHf=_*()#cdkjXzE;{gQmLoX>;$u2mJ4GC!kQj%ZJEvll5_MwP0y$VJ+m8ik)SzX zrvoIw9F0G0xq2WTYTd4!+^t&aH!YRKgVBmI*gN_HZ(c5ysE=`~6;3P*$=3ZAp+S8; zGLi>sqbR0Q)Tg~D>-HgzZVK%KZdzf^u&vmmH9k=KScw|3k>kaNg9=N25GCY{0|#2m z?7>C}ON1UwIg>APyQ3c8LTlCgr&ra|clxSIv1pnjVNzQ9kM(JODkN_fje0=d(5f`u z3ak639&wgiW_R7iM2+Q!k#5^m^`Ii!1-^qw$#Q%zh*&L({IH;DrmZHcRW&?ELmSPn zmlyc5ijYN^iIH--5a(On2py2Vk>$DFx>&xqG&#=h{K)Xo^yqwPbgVc%Q<^)cB^AZ- zp|MfX!a$c^SU7|U+SuY;A+ets8aoGz=}50~mM^er9@Tvo)i^6Us6tG4|77XDqs0f6n7w=XCVG?x$9XWXLen0n8ZtNQ0-UWrM-urn(a z*7Bi>I<>lz+}5ieZQjaVCtu4emY+|m^?KyB z3`s?Ly5Q3_?+dz7+HQ+JR!r`arJ5eGCC&`pWs8CqDFS2C_lriU!aL>h~9 zps?O7W3djE#+bNKu&xj1)j|B1AILYW#qDy~Pv$H~htct6sGuO(h-Etrb~rHAI@k zR{Pmn8GG3nUaStWj)fcP znWp=`=6WWdcRaIh<9VtgIVs#pAJW6lG=+6*3lUeLM}$T-bVY$jx$c@a#yG6Mjqiq4WPm}DoFWGoF8k5A9j|M>wVG$>Pm zS*m+%#@$5<6hv6Mh?G??+Z45ncx#})e*gx;(`W3$&~6i~() zXrmiVbr+q$KyNhDaddv1<(dI{pf9P&E*HA*e! z&2*=;cL#6any}^P*^8Nd^kXM8+c}FoeeclwWzqg^=8>#0yYlIah~8Z@vk#)X8EvYW z*XlGZ2C^wOp4|j0IYx~e3)w~@v;WApdS=<+S@X46?`r__(|i||!L0G#D}xOld70I| zG53sl7mo_s$~Ci(cq8*$u4Es`^9?*5(w7#!>*)AdzJ(}Sp%dPyJNO;;2k0Gr z0BGMJ2i^>5uiz3m1?~nfLzBy38JqzI5IVia0)2ToQUR%eRG@bS)<54vkFRDdL?!Vi zbVMEzT3@sDKm;Dp@`w-)c99P9h*0anyEs6_zm7a2M5l(jM7inB)JT%jiXLnruskBv zao#gI!_>?%k_vIIL>>{6M}*`Nq5qvDLO8L8LoB|>&f;7OPLuJ-(3b0ts0&q79H|q9 I#zBmK1JXg1W&i*H diff --git a/Dockerfile b/Dockerfile index 26c4aa2..b80680a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -189,4 +189,4 @@ RUN bundle exec rake assets:clean ENV PATH /app/node_modules/.bin:$PATH # Set the entry point. -ENTRYPOINT ["./entrypoint-server.sh"] +ENTRYPOINT ["/app/entrypoint-server.sh"] -- GitLab From a158d37d85950cc2445eacc189798487367f9eac Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 6 Nov 2020 17:20:47 -1000 Subject: [PATCH 190/283] updating gitignore Former-commit-id: c32130ac1719b05890f935cd88aa3c14e133832f --- .gitignore | 30 ++++---- Dockerfile | 77 ++++++++++++------- scripts/bundles/bundle.tar.gz.REMOVED.git-id | 1 + .../node_modules.tar.gz.REMOVED.git-id | 1 + .../bundles/redis-cli.tar.gz.REMOVED.git-id | 1 + 5 files changed, 65 insertions(+), 45 deletions(-) create mode 100644 scripts/bundles/bundle.tar.gz.REMOVED.git-id create mode 100644 scripts/bundles/node_modules.tar.gz.REMOVED.git-id create mode 100644 scripts/bundles/redis-cli.tar.gz.REMOVED.git-id diff --git a/.gitignore b/.gitignore index 4f0f814..77aa186 100644 --- a/.gitignore +++ b/.gitignore @@ -5,26 +5,22 @@ # git config --global core.excludesfile '~/.gitignore_global' # Ignore bundler config. -/.bundle +/scripts/.bundle # Ignore all logfiles and tempfiles. -/log/* -/tmp/* - -/node_modules +/scripts/log/* +/scripts/tmp/* .byebug_history .DS_Store .env -.idea/* -/public/packs-test -/node_modules +.idea +/scripts/public/packs-test +node_modules .rspec_status -.idea/* -.vscode/* -/public/packs -/public/packs-test -/node_modules +.vscode +/scripts/public/packs +/scripts/public/packs-test yarn-debug.log* .yarn-integrity yarn-error.log @@ -33,8 +29,8 @@ tags .solargraph.yml .generators .rakeTasks -/coverage -/public/assets/ -!/public/assets/images +/scripts/coverage +/scritps/public/assets/ +!/scripts/public/assets/images log.txt -sidekiq.log \ No newline at end of file +sidekiq.log diff --git a/Dockerfile b/Dockerfile index b80680a..f5aaf35 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,35 +13,49 @@ FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} as builder USER 0 # Install what we can via dnf -RUN dnf update -y && dnf install -y \ - autoconf \ - automake \ - bzip2 \ - curl \ - diffutils \ - gcc-c++ \ - libedit \ - libffi-devel \ - libtool \ - make \ - openssl-devel \ - patch \ - readline \ - zlib \ - zlib-devel +#RUN dnf update -y && dnf install -y \ +# autoconf \ +# automake \ +# bzip2 \ +# curl \ +# diffutils \ +# gcc-c++ \ +# libedit \ +# libffi-devel \ +# libtool \ +# make \ +# openssl-devel \ +# patch \ +# readline \ +# zlib \ +# zlib-devel # Uncomment to test in Platform 1 -RUN curl -O https://download.redis.io/releases/redis-6.0.9.tar.gz +#RUN curl -O https://download.redis.io/releases/redis-6.0.9.tar.gz # Build redis from source #COPY redis-6.0.9.tar.gz . -RUN tar xzf redis-6.0.9.tar.gz -WORKDIR redis-6.0.9/deps -RUN make hiredis jemalloc linenoise lua -WORKDIR .. -RUN make -RUN make install -WORKDIR .. +#RUN tar xzf redis-6.0.9.tar.gz +#WORKDIR redis-6.0.9/deps +#RUN make hiredis jemalloc linenoise lua +#WORKDIR .. +#RUN make +#RUN make install + +# Switch to app directory. +WORKDIR /app + +# Redis. +COPY ./scripts/bundles/redis-cli.tar.gz . +RUN tar xzf redis-cli.tar.gz + +# Unzip the bundle directory. +COPY ./scripts/bundles/bundle.tar.gz . +RUN tar xzf bundle.tar.gz + +# Unzip the node_modules. +COPY ./scripts/bundles/node_modules.tar.gz . +RUN tar xzf node_modules.tar.gz # Stage 2: Setup the Image. FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} @@ -64,7 +78,13 @@ RUN dnf update -y && dnf install -y \ gcc-c++ # Redis CLI Binary. -COPY --from=builder /usr/local/bin/redis-cli /usr/local/bin/redis-cli +COPY --from=builder /app/redis-cli /usr/local/bin/redis-cli + +# copy the bundler fules. +COPY --from=builder /app/bundle /usr/local/bundle + +# Copy the node_modules +COPY --from=builder /app/node_modules /app/node_modules ## Patch Binary. #COPY --from=builder /usr/bin/patch /usr/bin/patch @@ -171,13 +191,13 @@ USER 1001 ENV RAILS_ENV production # Install Rails Dependecies. -RUN gem install bundler:2.1.4 +#RUN gem install bundler:2.1.4 # Run the bundle install -RUN bundle install +#RUN bundle install ## Run Yarn Install -RUN yarn install +#RUN yarn install # Precompile assets RUN bundle exec rake assets:precompile @@ -190,3 +210,4 @@ ENV PATH /app/node_modules/.bin:$PATH # Set the entry point. ENTRYPOINT ["/app/entrypoint-server.sh"] +#CMD tail -f /dev/null diff --git a/scripts/bundles/bundle.tar.gz.REMOVED.git-id b/scripts/bundles/bundle.tar.gz.REMOVED.git-id new file mode 100644 index 0000000..4b90411 --- /dev/null +++ b/scripts/bundles/bundle.tar.gz.REMOVED.git-id @@ -0,0 +1 @@ +e949587cc2c87f431a7d318d7b8e4853a8b1859d \ No newline at end of file diff --git a/scripts/bundles/node_modules.tar.gz.REMOVED.git-id b/scripts/bundles/node_modules.tar.gz.REMOVED.git-id new file mode 100644 index 0000000..d3c29b5 --- /dev/null +++ b/scripts/bundles/node_modules.tar.gz.REMOVED.git-id @@ -0,0 +1 @@ +67f211bd5a4a466daeead95c9d7accd1047c9492 \ No newline at end of file diff --git a/scripts/bundles/redis-cli.tar.gz.REMOVED.git-id b/scripts/bundles/redis-cli.tar.gz.REMOVED.git-id new file mode 100644 index 0000000..07b1028 --- /dev/null +++ b/scripts/bundles/redis-cli.tar.gz.REMOVED.git-id @@ -0,0 +1 @@ +e694dfedcbaeaf8927abdba4868d90eb0857e619 \ No newline at end of file -- GitLab From 21cdb1af06eae5b2eba2840b39abdf66d77e55cd Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 6 Nov 2020 19:53:54 -1000 Subject: [PATCH 191/283] adding node.js and yarn binaries Former-commit-id: 41845377c895e658f64b7cf504bb3a37eb868384 --- Dockerfile | 146 ++---------------- scripts/.nvmrc | 2 +- ...e-v14.15.0-linux-x64.tar.gz.REMOVED.git-id | 1 + .../yarn-v1.22.5.tar.gz.REMOVED.git-id | 1 + 4 files changed, 15 insertions(+), 135 deletions(-) create mode 100644 scripts/bundles/node-v14.15.0-linux-x64.tar.gz.REMOVED.git-id create mode 100644 scripts/bundles/yarn-v1.22.5.tar.gz.REMOVED.git-id diff --git a/Dockerfile b/Dockerfile index f5aaf35..779f350 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,36 +12,6 @@ ARG BASE_TAG=2.6.6.212 FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} as builder USER 0 -# Install what we can via dnf -#RUN dnf update -y && dnf install -y \ -# autoconf \ -# automake \ -# bzip2 \ -# curl \ -# diffutils \ -# gcc-c++ \ -# libedit \ -# libffi-devel \ -# libtool \ -# make \ -# openssl-devel \ -# patch \ -# readline \ -# zlib \ -# zlib-devel - -# Uncomment to test in Platform 1 -#RUN curl -O https://download.redis.io/releases/redis-6.0.9.tar.gz - -# Build redis from source -#COPY redis-6.0.9.tar.gz . -#RUN tar xzf redis-6.0.9.tar.gz -#WORKDIR redis-6.0.9/deps -#RUN make hiredis jemalloc linenoise lua -#WORKDIR .. -#RUN make -#RUN make install - # Switch to app directory. WORKDIR /app @@ -57,6 +27,11 @@ RUN tar xzf bundle.tar.gz COPY ./scripts/bundles/node_modules.tar.gz . RUN tar xzf node_modules.tar.gz +# Node.js +RUN echo node-v14.15.0-linux-x64.tar.gz +COPY ./scripts/bundles/node-v14.15.0-linux-x64.tar.gz . +RUN tar xzf node-v14.15.0-linux-x64.tar.gz + # Stage 2: Setup the Image. FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} USER 0 @@ -81,101 +56,13 @@ RUN dnf update -y && dnf install -y \ COPY --from=builder /app/redis-cli /usr/local/bin/redis-cli # copy the bundler fules. -COPY --from=builder /app/bundle /usr/local/bundle +COPY --from=builder /app/bundle /usr/local/bundle # Copy the node_modules COPY --from=builder /app/node_modules /app/node_modules -## Patch Binary. -#COPY --from=builder /usr/bin/patch /usr/bin/patch -# -## Make Binary. -#COPY --from=builder /usr/bin/make /usr/bin/make -# -## Git Binaries. -#COPY --from=builder /usr/bin/git* /usr/bin/ -# -## Yarn Binaries. -#COPY --from=builder /usr/share/yarn /usr/share/yarn -#RUN ln -s /usr/share/yarn/bin/yarn /usr/bin/yarn -#RUN ln -s /usr/share/yarn/bin/yarn /usr/bin/yarnpkg -# -## libz Dependencies. -#COPY --from=builder /usr/lib64/libz* /usr/lib64/ -# -## Postgres Dependencies -#COPY --from=builder /usr/bin/pkgconf /usr/bin/pkgconf -#COPY --from=builder /usr/bin/pg_config /usr/bin/pg_config -#COPY --from=builder /usr/lib64/libpq* /usr/lib64/ -#COPY --from=builder /usr/lib64/libpkgconf* /usr/lib64/ -#COPY --from=builder /usr/include/libpq /usr/include/libpq -#COPY --from=builder /usr/include/libpq* /usr/include/ -#COPY --from=builder /usr/include/pg* /usr/include/ -#COPY --from=builder /usr/include/pgsql /usr/include/pgsql -#COPY --from=builder /usr/include/postgres* /usr/include/ -# -## libxml2 Dependencies. -#COPY --from=builder /usr/lib64/libxml* /usr/lib64/ -#COPY --from=builder /usr/lib64/liblz* /usr/lib64/ -#COPY --from=builder /usr/lib64/libm-2* /usr/lib64/ -#COPY --from=builder /usr/lib64/libm.so* /usr/lib64/ -#COPY --from=builder /usr/include/lzma /usr/include/lzma -#COPY --from=builder /usr/include/zlib* /usr/include/ -#COPY --from=builder /usr/include/zconf* /usr/include/ -#COPY --from=builder /usr/include/libxml2 /usr/include/libxml2 -#COPY --from=builder /usr/lib64/xml2Conf.sh /usr/lib64/xml2Conf.sh -# -## libxslt Dependencies. -#COPY --from=builder /usr/lib64/libxslt* /usr/lib64/ -#COPY --from=builder /usr/lib64/libexslt* /usr/lib64/ -#COPY --from=builder /usr/include/libxslt /usr/include/libxslt -#COPY --from=builder /usr/include/libexslt /usr/include/libexslt -#COPY --from=builder /usr/include/gcrypt* /usr/include/ -#COPY --from=builder /usr/include/gpg* /usr/include/ -#COPY --from=builder /usr/lib64/xsltConf.sh /usr/lib64/xsltConf.sh - -## GCC Dependencies. -#COPY --from=builder /usr/bin/gcc* /usr/bin/ -#COPY --from=builder /usr/lib/gcc /usr/lib/gcc -#COPY --from=builder /usr/bin/as /usr/bin/as -#COPY --from=builder /usr/bin/ld /usr/bin/ld -#COPY --from=builder /usr/libexec/gcc /usr/libexec/gcc -#COPY --from=builder /usr/lib64/libmpc* /usr/lib64/ -#COPY --from=builder /usr/lib64/libopcodes* /usr/lib64/ -#COPY --from=builder /usr/lib64/libbfd* /usr/lib64/ -#COPY --from=builder /usr/lib64/libc.so* /usr/lib64/ -#COPY --from=builder /usr/lib64/libc_nonshared* /usr/lib64/ -#COPY --from=builder /usr/lib64/libcrypt* /usr/lib64/ -#COPY --from=builder /usr/lib64/libgomp* /usr/lib64/ -#COPY --from=builder /usr/lib64/libgpg* /usr/lib64/ -#COPY --from=builder /usr/lib64/libgcrypt* /usr/lib64/ -#COPY --from=builder /usr/lib64/libgcc* /usr/lib64/ -#COPY --from=builder /usr/lib64/crt* /usr/lib64/ -#COPY --from=builder /usr/lib64/libm-2* /usr/lib64/ -#COPY --from=builder /usr/lib64/libm.so* /usr/lib64/ -#COPY --from=builder /usr/lib64/libmcheck* /usr/lib64/ -#COPY --from=builder /usr/lib64/Mcrt1* /usr/lib64/ -#COPY --from=builder /usr/lib64/Scrt1* /usr/lib64/ -#COPY --from=builder /usr/lib64/gcrt* /usr/lib64/ -#COPY --from=builder /usr/lib64/libanl* /usr/lib64/ -#COPY --from=builder /usr/lib64/libdl* /usr/lib64/ -#COPY --from=builder /usr/lib64/libg* /usr/lib64/ -#COPY --from=builder /usr/lib64/libisl* /usr/lib64/ -#COPY --from=builder /usr/lib64/liblzma* /usr/lib64/ -#COPY --from=builder /usr/lib64/libmvec* /usr/lib64/ -#COPY --from=builder /usr/lib64/libpthread* /usr/lib64/ -#COPY --from=builder /usr/lib64/libresolv* /usr/lib64/ -#COPY --from=builder /usr/lib64/librt* /usr/lib64/ -#COPY --from=builder /usr/lib64/libthread_db* /usr/lib64/ -#COPY --from=builder /usr/lib64/libutil* /usr/lib64/ -#COPY --from=builder /usr/lib64/libz* /usr/lib64/ -#COPY --from=builder /usr/lib64/rcrt* /usr/lib64/ -#COPY --from=builder /usr/include /usr/include - -# Install Node -RUN curl -L -O https://raw.githubusercontent.com/tj/n/master/bin/n -COPY ./scripts/.nvmrc . -RUN bash n auto +# Copy node.js +COPY --from=builder /app/node-v14.15.0-linux-x64 /app/nodejs # Setup our environment WORKDIR /app @@ -187,17 +74,11 @@ RUN chown -R 1001 . # Become the ruby user USER 1001 -# Set the Rails environment variable. +# Set the Rails and node environment variable. ENV RAILS_ENV production - -# Install Rails Dependecies. -#RUN gem install bundler:2.1.4 - -# Run the bundle install -#RUN bundle install - -## Run Yarn Install -#RUN yarn install +ENV NODE_HOME /app/nodejs +ENV PATH /app/node_modules/.bin:$PATH +ENV PATH /app/nodejs/bin:$PATH # Precompile assets RUN bundle exec rake assets:precompile @@ -205,9 +86,6 @@ RUN bundle exec rake assets:precompile # Asset Clean RUN bundle exec rake assets:clean -# Add the node_modules to the path. -ENV PATH /app/node_modules/.bin:$PATH - # Set the entry point. ENTRYPOINT ["/app/entrypoint-server.sh"] #CMD tail -f /dev/null diff --git a/scripts/.nvmrc b/scripts/.nvmrc index 9306ff9..c107424 100644 --- a/scripts/.nvmrc +++ b/scripts/.nvmrc @@ -1 +1 @@ -14.8.0 +14.15.0 diff --git a/scripts/bundles/node-v14.15.0-linux-x64.tar.gz.REMOVED.git-id b/scripts/bundles/node-v14.15.0-linux-x64.tar.gz.REMOVED.git-id new file mode 100644 index 0000000..7152095 --- /dev/null +++ b/scripts/bundles/node-v14.15.0-linux-x64.tar.gz.REMOVED.git-id @@ -0,0 +1 @@ +f4d256209259d79fe547f7bbe8245e52e356d0a8 \ No newline at end of file diff --git a/scripts/bundles/yarn-v1.22.5.tar.gz.REMOVED.git-id b/scripts/bundles/yarn-v1.22.5.tar.gz.REMOVED.git-id new file mode 100644 index 0000000..89957a7 --- /dev/null +++ b/scripts/bundles/yarn-v1.22.5.tar.gz.REMOVED.git-id @@ -0,0 +1 @@ +2ffdf471020c0266a0c89ca2c125833d251e5181 \ No newline at end of file -- GitLab From 4d5f305c7f65247399ff19c25e098898dffb3df8 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 6 Nov 2020 19:59:26 -1000 Subject: [PATCH 192/283] changing node versions Former-commit-id: 420932defc348522db60b60c26b4621f1adcca9f --- Dockerfile | 8 ++++---- scripts/.nvmrc | 2 +- .../bundles/node-v14.15.0-linux-x64.tar.gz.REMOVED.git-id | 1 - .../bundles/node-v14.8.0-linux-x64.tar.gz.REMOVED.git-id | 1 + 4 files changed, 6 insertions(+), 6 deletions(-) delete mode 100644 scripts/bundles/node-v14.15.0-linux-x64.tar.gz.REMOVED.git-id create mode 100644 scripts/bundles/node-v14.8.0-linux-x64.tar.gz.REMOVED.git-id diff --git a/Dockerfile b/Dockerfile index 779f350..4c098f3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,9 +28,9 @@ COPY ./scripts/bundles/node_modules.tar.gz . RUN tar xzf node_modules.tar.gz # Node.js -RUN echo node-v14.15.0-linux-x64.tar.gz -COPY ./scripts/bundles/node-v14.15.0-linux-x64.tar.gz . -RUN tar xzf node-v14.15.0-linux-x64.tar.gz +RUN echo node-v14.8.0-linux-x64.tar.gz +COPY ./scripts/bundles/node-v14.8.0-linux-x64.tar.gz . +RUN tar xzf node-v14.8.0-linux-x64.tar.gz # Stage 2: Setup the Image. FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} @@ -62,7 +62,7 @@ COPY --from=builder /app/bundle /usr/local/bundle COPY --from=builder /app/node_modules /app/node_modules # Copy node.js -COPY --from=builder /app/node-v14.15.0-linux-x64 /app/nodejs +COPY --from=builder /app/node-v14.8.0-linux-x64 /app/nodejs # Setup our environment WORKDIR /app diff --git a/scripts/.nvmrc b/scripts/.nvmrc index c107424..a34fffa 100644 --- a/scripts/.nvmrc +++ b/scripts/.nvmrc @@ -1 +1 @@ -14.15.0 +14.8.0 \ No newline at end of file diff --git a/scripts/bundles/node-v14.15.0-linux-x64.tar.gz.REMOVED.git-id b/scripts/bundles/node-v14.15.0-linux-x64.tar.gz.REMOVED.git-id deleted file mode 100644 index 7152095..0000000 --- a/scripts/bundles/node-v14.15.0-linux-x64.tar.gz.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -f4d256209259d79fe547f7bbe8245e52e356d0a8 \ No newline at end of file diff --git a/scripts/bundles/node-v14.8.0-linux-x64.tar.gz.REMOVED.git-id b/scripts/bundles/node-v14.8.0-linux-x64.tar.gz.REMOVED.git-id new file mode 100644 index 0000000..937094b --- /dev/null +++ b/scripts/bundles/node-v14.8.0-linux-x64.tar.gz.REMOVED.git-id @@ -0,0 +1 @@ +eda96a7b40acb7ed21dabc8f89fb50627cea38b6 \ No newline at end of file -- GitLab From ba584ebdf0c629fd05071847d86e2c0e704818f0 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 6 Nov 2020 20:16:44 -1000 Subject: [PATCH 193/283] got nodejs install working Former-commit-id: 96ab458364230101f4346f00fde151f26d5cdcda --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 4c098f3..e7c650a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -79,6 +79,7 @@ ENV RAILS_ENV production ENV NODE_HOME /app/nodejs ENV PATH /app/node_modules/.bin:$PATH ENV PATH /app/nodejs/bin:$PATH +RUN ln -s /app/nodejs/bin/node /app/nodejs/bin/nodejs # Precompile assets RUN bundle exec rake assets:precompile -- GitLab From 0c46228ab1c6e363b87831ca04b95641a3c0bc92 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 6 Nov 2020 20:30:40 -1000 Subject: [PATCH 194/283] getting yarn to work. Former-commit-id: 9030c0dc6277bef23e78972b7989e6147bf96152 --- Dockerfile | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index e7c650a..9af19a7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,10 +28,13 @@ COPY ./scripts/bundles/node_modules.tar.gz . RUN tar xzf node_modules.tar.gz # Node.js -RUN echo node-v14.8.0-linux-x64.tar.gz COPY ./scripts/bundles/node-v14.8.0-linux-x64.tar.gz . RUN tar xzf node-v14.8.0-linux-x64.tar.gz +# Yarn +COPY ./scripts/bundles/yarn-v1.22.5.tar.gz . +RUN tar xzf yarn-v1.22.5.tar.gz + # Stage 2: Setup the Image. FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} USER 0 @@ -64,6 +67,9 @@ COPY --from=builder /app/node_modules /app/node_modules # Copy node.js COPY --from=builder /app/node-v14.8.0-linux-x64 /app/nodejs +# Copy yarn. +COPY --from=builder /app/yarn-v1.22.5 /app/yarn + # Setup our environment WORKDIR /app ADD ./scripts . @@ -78,6 +84,7 @@ USER 1001 ENV RAILS_ENV production ENV NODE_HOME /app/nodejs ENV PATH /app/node_modules/.bin:$PATH +ENV PATH /app/yarn/bin:$PATH ENV PATH /app/nodejs/bin:$PATH RUN ln -s /app/nodejs/bin/node /app/nodejs/bin/nodejs -- GitLab From a0fc05bc1652e848849058f926889b10b4852a2d Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 6 Nov 2020 20:48:30 -1000 Subject: [PATCH 195/283] got yarn working Former-commit-id: f07534b26304e8d538afa48661b7887166a9b566 --- Dockerfile | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 9af19a7..bdacc9a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -39,15 +39,11 @@ RUN tar xzf yarn-v1.22.5.tar.gz FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} USER 0 -RUN curl --silent --location https://dl.yarnpkg.com/rpm/yarn.repo | tee /etc/yum.repos.d/yarn.repo -RUN rpm --import https://dl.yarnpkg.com/rpm/pubkey.gpg - RUN dnf update -y && dnf install -y \ curl \ make \ patch \ git \ - yarn \ zlib-devel \ libpq-devel \ libxml2-devel \ @@ -58,7 +54,7 @@ RUN dnf update -y && dnf install -y \ # Redis CLI Binary. COPY --from=builder /app/redis-cli /usr/local/bin/redis-cli -# copy the bundler fules. +# Copy the bundler fules. COPY --from=builder /app/bundle /usr/local/bundle # Copy the node_modules -- GitLab From 84b0d186d1ee2395908dcb4051da1662efd4fe65 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 6 Nov 2020 20:49:00 -1000 Subject: [PATCH 196/283] cleanup Former-commit-id: 1f3350903ef6e501d4005f54503fdf21335cd72e --- Dockerfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index bdacc9a..1726227 100644 --- a/Dockerfile +++ b/Dockerfile @@ -92,4 +92,3 @@ RUN bundle exec rake assets:clean # Set the entry point. ENTRYPOINT ["/app/entrypoint-server.sh"] -#CMD tail -f /dev/null -- GitLab From 3dd86d3a4e63c21f0bb3a28a3d94ca57fd54bd5b Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 6 Nov 2020 21:20:45 -1000 Subject: [PATCH 197/283] converting to single stage docker build Former-commit-id: 73ef8c222a746e6bb6ce7d17728f756464d45b23 --- Dockerfile | 72 +++++++++++++++++++++++------------------------------- 1 file changed, 31 insertions(+), 41 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1726227..a77ed3f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,37 +8,11 @@ ARG BASE_REGISTRY=registry.il2.dsop.io ARG BASE_IMAGE=platform-one/devops/pipeline-templates/ironbank/ruby26 ARG BASE_TAG=2.6.6.212 -# Stage 1: Build redis from source. -FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} as builder -USER 0 - -# Switch to app directory. -WORKDIR /app - -# Redis. -COPY ./scripts/bundles/redis-cli.tar.gz . -RUN tar xzf redis-cli.tar.gz - -# Unzip the bundle directory. -COPY ./scripts/bundles/bundle.tar.gz . -RUN tar xzf bundle.tar.gz - -# Unzip the node_modules. -COPY ./scripts/bundles/node_modules.tar.gz . -RUN tar xzf node_modules.tar.gz - -# Node.js -COPY ./scripts/bundles/node-v14.8.0-linux-x64.tar.gz . -RUN tar xzf node-v14.8.0-linux-x64.tar.gz - -# Yarn -COPY ./scripts/bundles/yarn-v1.22.5.tar.gz . -RUN tar xzf yarn-v1.22.5.tar.gz - -# Stage 2: Setup the Image. +# Setup the Image. FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} USER 0 +# Install required libs. RUN dnf update -y && dnf install -y \ curl \ make \ @@ -51,24 +25,40 @@ RUN dnf update -y && dnf install -y \ gcc \ gcc-c++ -# Redis CLI Binary. -COPY --from=builder /app/redis-cli /usr/local/bin/redis-cli +# Setup our environment +WORKDIR /app +ADD ./scripts . + +# Switch to the binary directory. +WORKDIR /app/bundles -# Copy the bundler fules. -COPY --from=builder /app/bundle /usr/local/bundle +# Redis. +RUN tar xzf redis-cli.tar.gz +RUN rm redis-cli.tar.gz +RUN mv redis-cli /usr/local/bin/redis-cli + +# Unzip the bundle directory. +RUN tar xzf bundle.tar.gz +RUN rm bundle.tar.gz +RUN mv bundle /usr/local/bundle -# Copy the node_modules -COPY --from=builder /app/node_modules /app/node_modules +# Unzip the node_modules. +RUN tar xzf node_modules.tar.gz +RUN rm node_modules.tar.gz +RUN mv node_modules /app/node_modules -# Copy node.js -COPY --from=builder /app/node-v14.8.0-linux-x64 /app/nodejs +# Node.js +RUN tar xzf node-v14.8.0-linux-x64.tar.gz +RUN rm node-v14.8.0-linux-x64.tar.gz +RUN mv node-v14.8.0-linux-x64 /app/nodejs -# Copy yarn. -COPY --from=builder /app/yarn-v1.22.5 /app/yarn +# Yarn +RUN tar xzf yarn-v1.22.5.tar.gz +RUN rm yarn-v1.22.5.tar.gz +RUN mv yarn-v1.22.5 /app/yarn -# Setup our environment +# Switch back to app directory. WORKDIR /app -ADD ./scripts . # Add write permissions. RUN chown -R 1001 . @@ -91,4 +81,4 @@ RUN bundle exec rake assets:precompile RUN bundle exec rake assets:clean # Set the entry point. -ENTRYPOINT ["/app/entrypoint-server.sh"] +ENTRYPOINT ["/app/entrypoint-server.sh"] \ No newline at end of file -- GitLab From b70838940888572a4c1f24c4f36634dc92489dea Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 6 Nov 2020 21:43:15 -1000 Subject: [PATCH 198/283] fixing location of bundle directory Former-commit-id: 607763bdd3d00ef7defe312249bf1f53c0a4a7d4 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index a77ed3f..df342f1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -40,7 +40,7 @@ RUN mv redis-cli /usr/local/bin/redis-cli # Unzip the bundle directory. RUN tar xzf bundle.tar.gz RUN rm bundle.tar.gz -RUN mv bundle /usr/local/bundle +RUN mv bundle /usr/local/ # Unzip the node_modules. RUN tar xzf node_modules.tar.gz -- GitLab From ed6e4bf98034ff97e2b54cb28a1e5ca813ec8d6d Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 6 Nov 2020 22:03:34 -1000 Subject: [PATCH 199/283] changes for ironbank Former-commit-id: 9dfd0ad19fb257a80f22c0c29811c5e6a1cb946a --- Dockerfile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index df342f1..b6f6b78 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,12 @@ ### Iron Bank Settings -# ARG BASE_REGISTRY=registry1.dsop.io -# ARG BASE_IMAGE=ironbank/opensource/ruby/ruby26 -# ARG BASE_TAG=2.6.6 +ARG BASE_REGISTRY=registry1.dsop.io +ARG BASE_IMAGE=ironbank/opensource/ruby/ruby26 +ARG BASE_TAG=2.6.6 ### Platform 1 Pipeline Settings -ARG BASE_REGISTRY=registry.il2.dsop.io -ARG BASE_IMAGE=platform-one/devops/pipeline-templates/ironbank/ruby26 -ARG BASE_TAG=2.6.6.212 +#ARG BASE_REGISTRY=registry.il2.dsop.io +#ARG BASE_IMAGE=platform-one/devops/pipeline-templates/ironbank/ruby26 +#ARG BASE_TAG=2.6.6.212 # Setup the Image. FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} @@ -81,4 +81,4 @@ RUN bundle exec rake assets:precompile RUN bundle exec rake assets:clean # Set the entry point. -ENTRYPOINT ["/app/entrypoint-server.sh"] \ No newline at end of file +ENTRYPOINT ["/app/entrypoint-server.sh"] -- GitLab From 5a3271ac5e76ac278ffb3c9bbf0bea55c6093c23 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 6 Nov 2020 22:12:00 -1000 Subject: [PATCH 200/283] moving gitlab-ci file to scripts Former-commit-id: 451cb64de5930a2bb0ae2b88a42fbba8732da63a --- Dockerfile.old | 169 ----------------------- .gitlab-ci.yml => scripts/.gitlab-ci.yml | 0 2 files changed, 169 deletions(-) delete mode 100644 Dockerfile.old rename .gitlab-ci.yml => scripts/.gitlab-ci.yml (100%) diff --git a/Dockerfile.old b/Dockerfile.old deleted file mode 100644 index 613216e..0000000 --- a/Dockerfile.old +++ /dev/null @@ -1,169 +0,0 @@ -# Stage 1: Install libararies -FROM centos:8 as builder -USER 0 - -## Setup the yarn repo. -#RUN curl --silent --location https://dl.yarnpkg.com/rpm/yarn.repo | tee /etc/yum.repos.d/yarn.repo -#RUN rpm --import https://dl.yarnpkg.com/rpm/pubkey.gpg - -## Install the required packages. -RUN dnf update -y && \ - dnf install -y \ - redis -# make \ -# patch \ -# git \ -# yarn \ -# zlib-devel \ -# libpq-devel \ -# libxml2-devel \ -# libxslt-devel \ -# gcc - -# Stage 2: Setup the Image. -FROM registry.il2.dsop.io/platform-one/devops/pipeline-templates/ironbank/ruby26:2.6.6.212 -USER 0 - -RUN curl --silent --location https://dl.yarnpkg.com/rpm/yarn.repo | tee /etc/yum.repos.d/yarn.repo -RUN rpm --import https://dl.yarnpkg.com/rpm/pubkey.gpg - -RUN dnf update -y && \ - dnf install -y \ - make \ - patch \ - git \ - yarn \ - zlib-devel \ - libpq-devel \ - libxml2-devel \ - libxslt-devel \ - gcc \ - gcc-c++ - -# Redis CLI Binary. -COPY --from=builder /usr/bin/redis-cli /usr/bin/redis-cli - -## Patch Binary. -#COPY --from=builder /usr/bin/patch /usr/bin/patch -# -## Make Binary. -#COPY --from=builder /usr/bin/make /usr/bin/make -# -## Git Binaries. -#COPY --from=builder /usr/bin/git* /usr/bin/ -# -## Yarn Binaries. -#COPY --from=builder /usr/share/yarn /usr/share/yarn -#RUN ln -s /usr/share/yarn/bin/yarn /usr/bin/yarn -#RUN ln -s /usr/share/yarn/bin/yarn /usr/bin/yarnpkg -# -## libz Dependencies. -#COPY --from=builder /usr/lib64/libz* /usr/lib64/ -# -## Postgres Dependencies -#COPY --from=builder /usr/bin/pkgconf /usr/bin/pkgconf -#COPY --from=builder /usr/bin/pg_config /usr/bin/pg_config -#COPY --from=builder /usr/lib64/libpq* /usr/lib64/ -#COPY --from=builder /usr/lib64/libpkgconf* /usr/lib64/ -#COPY --from=builder /usr/include/libpq /usr/include/libpq -#COPY --from=builder /usr/include/libpq* /usr/include/ -#COPY --from=builder /usr/include/pg* /usr/include/ -#COPY --from=builder /usr/include/pgsql /usr/include/pgsql -#COPY --from=builder /usr/include/postgres* /usr/include/ -# -## libxml2 Dependencies. -#COPY --from=builder /usr/lib64/libxml* /usr/lib64/ -#COPY --from=builder /usr/lib64/liblz* /usr/lib64/ -#COPY --from=builder /usr/lib64/libm-2* /usr/lib64/ -#COPY --from=builder /usr/lib64/libm.so* /usr/lib64/ -#COPY --from=builder /usr/include/lzma /usr/include/lzma -#COPY --from=builder /usr/include/zlib* /usr/include/ -#COPY --from=builder /usr/include/zconf* /usr/include/ -#COPY --from=builder /usr/include/libxml2 /usr/include/libxml2 -#COPY --from=builder /usr/lib64/xml2Conf.sh /usr/lib64/xml2Conf.sh -# -## libxslt Dependencies. -#COPY --from=builder /usr/lib64/libxslt* /usr/lib64/ -#COPY --from=builder /usr/lib64/libexslt* /usr/lib64/ -#COPY --from=builder /usr/include/libxslt /usr/include/libxslt -#COPY --from=builder /usr/include/libexslt /usr/include/libexslt -#COPY --from=builder /usr/include/gcrypt* /usr/include/ -#COPY --from=builder /usr/include/gpg* /usr/include/ -#COPY --from=builder /usr/lib64/xsltConf.sh /usr/lib64/xsltConf.sh - -## GCC Dependencies. -#COPY --from=builder /usr/bin/gcc* /usr/bin/ -#COPY --from=builder /usr/lib/gcc /usr/lib/gcc -#COPY --from=builder /usr/bin/as /usr/bin/as -#COPY --from=builder /usr/bin/ld /usr/bin/ld -#COPY --from=builder /usr/libexec/gcc /usr/libexec/gcc -#COPY --from=builder /usr/lib64/libmpc* /usr/lib64/ -#COPY --from=builder /usr/lib64/libopcodes* /usr/lib64/ -#COPY --from=builder /usr/lib64/libbfd* /usr/lib64/ -#COPY --from=builder /usr/lib64/libc.so* /usr/lib64/ -#COPY --from=builder /usr/lib64/libc_nonshared* /usr/lib64/ -#COPY --from=builder /usr/lib64/libcrypt* /usr/lib64/ -#COPY --from=builder /usr/lib64/libgomp* /usr/lib64/ -#COPY --from=builder /usr/lib64/libgpg* /usr/lib64/ -#COPY --from=builder /usr/lib64/libgcrypt* /usr/lib64/ -#COPY --from=builder /usr/lib64/libgcc* /usr/lib64/ -#COPY --from=builder /usr/lib64/crt* /usr/lib64/ -#COPY --from=builder /usr/lib64/libm-2* /usr/lib64/ -#COPY --from=builder /usr/lib64/libm.so* /usr/lib64/ -#COPY --from=builder /usr/lib64/libmcheck* /usr/lib64/ -#COPY --from=builder /usr/lib64/Mcrt1* /usr/lib64/ -#COPY --from=builder /usr/lib64/Scrt1* /usr/lib64/ -#COPY --from=builder /usr/lib64/gcrt* /usr/lib64/ -#COPY --from=builder /usr/lib64/libanl* /usr/lib64/ -#COPY --from=builder /usr/lib64/libdl* /usr/lib64/ -#COPY --from=builder /usr/lib64/libg* /usr/lib64/ -#COPY --from=builder /usr/lib64/libisl* /usr/lib64/ -#COPY --from=builder /usr/lib64/liblzma* /usr/lib64/ -#COPY --from=builder /usr/lib64/libmvec* /usr/lib64/ -#COPY --from=builder /usr/lib64/libpthread* /usr/lib64/ -#COPY --from=builder /usr/lib64/libresolv* /usr/lib64/ -#COPY --from=builder /usr/lib64/librt* /usr/lib64/ -#COPY --from=builder /usr/lib64/libthread_db* /usr/lib64/ -#COPY --from=builder /usr/lib64/libutil* /usr/lib64/ -#COPY --from=builder /usr/lib64/libz* /usr/lib64/ -#COPY --from=builder /usr/lib64/rcrt* /usr/lib64/ -#COPY --from=builder /usr/include /usr/include - -# Install Node -ADD .nvmrc . -RUN curl -L https://raw.githubusercontent.com/tj/n/master/bin/n -o n -RUN bash n auto - -# Setup our environment -WORKDIR /usr/src/app -ADD . . - -# Add write permissions. -RUN chown -R 1001 . - -# Become the ruby user -USER 1001 - -# Set the Rails environment variable. -ENV RAILS_ENV production - -# Install Rails Dependecies. -RUN gem install bundler:2.1.4 - -# Run the bundle install -RUN bundle install - -## Run Yarn Install -RUN yarn install - -# Precompile assets -RUN bundle exec rake assets:precompile - -# Asset Clean -RUN bundle exec rake assets:clean - -# Add the node_modules to the path. -ENV PATH /usr/src/app/node_modules/.bin:$PATH - -# Set the entry point. -ENTRYPOINT ["./entrypoint-server.sh"] \ No newline at end of file diff --git a/.gitlab-ci.yml b/scripts/.gitlab-ci.yml similarity index 100% rename from .gitlab-ci.yml rename to scripts/.gitlab-ci.yml -- GitLab From 7597d09ddb31a30ebc9ca62d8ed5facb035b464d Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Thu, 19 Nov 2020 17:28:56 -1000 Subject: [PATCH 201/283] Add /api/v1/uploads path Former-commit-id: 3c4762a41ccba856afbcbc48c993c61333ebb6e7 --- scripts/app/assets/images/mobile-logo.png | Bin 0 -> 24976 bytes scripts/app/assets/images/p1-learn-lockup.png | Bin 0 -> 35627 bytes .../stylesheets/components/_footer.scss | 4 +- .../components/_primary-navigation.scss | 4 +- .../controllers/api/v1/uploads_controller.rb | 40 ++++++++++++++++++ scripts/config/routes.rb | 1 + 6 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 scripts/app/assets/images/mobile-logo.png create mode 100644 scripts/app/assets/images/p1-learn-lockup.png create mode 100644 scripts/app/controllers/api/v1/uploads_controller.rb diff --git a/scripts/app/assets/images/mobile-logo.png b/scripts/app/assets/images/mobile-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..af1f4aaeee4eff038288cda1873cc51995b3ca41 GIT binary patch literal 24976 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 footer { > .logo { background: none left center no-repeat; - background-image: image-url("svg/mobile-logo.svg"); + background-image: image-url("mobile-logo.png"); background-size: contain; height: 34px; margin: 0 1rem 0 0; min-width: 40px; @media screen and (min-width: $tablet-breakpoint) { - background-image: image-url("svg/g-learn-lockup.svg"); + background-image: image-url("p1-learn-lockup.png"); margin: 0 1.5rem 0 0; min-width: 150px; } diff --git a/scripts/app/assets/stylesheets/components/_primary-navigation.scss b/scripts/app/assets/stylesheets/components/_primary-navigation.scss index 42fc382..52e60f6 100644 --- a/scripts/app/assets/stylesheets/components/_primary-navigation.scss +++ b/scripts/app/assets/stylesheets/components/_primary-navigation.scss @@ -25,13 +25,13 @@ > .logo { background: none left center no-repeat; - background-image: image-url("svg/mobile-logo.svg"); + background-image: image-url("mobile-logo.png"); background-size: contain; height: 34px; margin: 0 1rem; min-width: 40px; @media screen and (min-width: $tablet-breakpoint) { - background-image: image-url("svg/g-learn-lockup.svg"); + background-image: image-url("p1-learn-lockup.png"); margin: 0 1.5rem; min-width: 236px; } diff --git a/scripts/app/controllers/api/v1/uploads_controller.rb b/scripts/app/controllers/api/v1/uploads_controller.rb new file mode 100644 index 0000000..f5e5fd3 --- /dev/null +++ b/scripts/app/controllers/api/v1/uploads_controller.rb @@ -0,0 +1,40 @@ +class Api::V1::UploadsController < Api::ApplicationController + def create + + render_method_not_allowed_response and return unless request.post? + + authorize(current_user, :regenerate_api_token?) + + @full_path = params[:full_path] + # @md5_name = data_path_md5 + @md5_name = SecureRandom.hex + @directory = params[:directory] || "content" + + if (@full_path.nil?) + json_response(error: "Parameter full_path not set") + return + end + + # Upload to s3 bucket + begin + file_content = request.body.read + aws_image_object = Rails.application.config.aws.object(content_key) + aws_image_object.put(body: file_content) + # aws_image_object.public_url + rescue StandardError => e + raise(Error, e) + end + + json_response(controller: "Uploaded file #{@full_path}") + end + + def content_key + @content_key ||= "#{@directory}/#{@md5_name}.#{@full_path}" + end + + # def data_path_md5 + # stdout, stderr, _status = Open3.capture3("openssl md5 '#{@full_path}'") + # stderr.blank? ? stdout.split("=").last.strip! : nil + # end + +end diff --git a/scripts/config/routes.rb b/scripts/config/routes.rb index b453d74..161d592 100644 --- a/scripts/config/routes.rb +++ b/scripts/config/routes.rb @@ -18,6 +18,7 @@ Rails.application.routes.draw do resources :releases, only: %i[create] do match "release_polling", via: :all, to: "release_polling" end + resources :uploads, only: %i[create] # resources :cohorts, only: %i[create] resources :cohorts, module: "cohorts", only: %i[create] do resources :users, only: %i[index create update destroy] -- GitLab From d04aea75e0541923e1a69fe1e80d71ba46490147 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Thu, 19 Nov 2020 21:50:20 -1000 Subject: [PATCH 202/283] Fixed api/v1/upload behavior Former-commit-id: 1a0d675f852407928d94a805ce845084359d4cd9 --- .../controllers/api/v1/uploads_controller.rb | 23 +++---------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/scripts/app/controllers/api/v1/uploads_controller.rb b/scripts/app/controllers/api/v1/uploads_controller.rb index f5e5fd3..10d31c7 100644 --- a/scripts/app/controllers/api/v1/uploads_controller.rb +++ b/scripts/app/controllers/api/v1/uploads_controller.rb @@ -6,9 +6,6 @@ class Api::V1::UploadsController < Api::ApplicationController authorize(current_user, :regenerate_api_token?) @full_path = params[:full_path] - # @md5_name = data_path_md5 - @md5_name = SecureRandom.hex - @directory = params[:directory] || "content" if (@full_path.nil?) json_response(error: "Parameter full_path not set") @@ -16,25 +13,11 @@ class Api::V1::UploadsController < Api::ApplicationController end # Upload to s3 bucket - begin - file_content = request.body.read - aws_image_object = Rails.application.config.aws.object(content_key) - aws_image_object.put(body: file_content) - # aws_image_object.public_url - rescue StandardError => e - raise(Error, e) - end + file_content = request.body.read + aws_image_object = Rails.application.config.aws.object(@full_path) + aws_image_object.put(body: file_content) json_response(controller: "Uploaded file #{@full_path}") end - def content_key - @content_key ||= "#{@directory}/#{@md5_name}.#{@full_path}" - end - - # def data_path_md5 - # stdout, stderr, _status = Open3.capture3("openssl md5 '#{@full_path}'") - # stderr.blank? ? stdout.split("=").last.strip! : nil - # end - end -- GitLab From d57307ed76e9c4a2547ed71e4ba764bfdfacffe7 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Thu, 19 Nov 2020 22:01:39 -1000 Subject: [PATCH 203/283] Revert icons Former-commit-id: 8db914ea1f780ffd7c68471cd3a350fb50c79076 --- scripts/app/assets/stylesheets/components/_footer.scss | 4 ++-- .../assets/stylesheets/components/_primary-navigation.scss | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/app/assets/stylesheets/components/_footer.scss b/scripts/app/assets/stylesheets/components/_footer.scss index 0e7e8d3..6ca2484 100644 --- a/scripts/app/assets/stylesheets/components/_footer.scss +++ b/scripts/app/assets/stylesheets/components/_footer.scss @@ -52,13 +52,13 @@ body > footer { > .logo { background: none left center no-repeat; - background-image: image-url("mobile-logo.png"); + background-image: image-url("svg/mobile-logo.svg"); background-size: contain; height: 34px; margin: 0 1rem 0 0; min-width: 40px; @media screen and (min-width: $tablet-breakpoint) { - background-image: image-url("p1-learn-lockup.png"); + background-image: image-url("svg/g-learn-lockup.svg"); margin: 0 1.5rem 0 0; min-width: 150px; } diff --git a/scripts/app/assets/stylesheets/components/_primary-navigation.scss b/scripts/app/assets/stylesheets/components/_primary-navigation.scss index 52e60f6..42fc382 100644 --- a/scripts/app/assets/stylesheets/components/_primary-navigation.scss +++ b/scripts/app/assets/stylesheets/components/_primary-navigation.scss @@ -25,13 +25,13 @@ > .logo { background: none left center no-repeat; - background-image: image-url("mobile-logo.png"); + background-image: image-url("svg/mobile-logo.svg"); background-size: contain; height: 34px; margin: 0 1rem; min-width: 40px; @media screen and (min-width: $tablet-breakpoint) { - background-image: image-url("p1-learn-lockup.png"); + background-image: image-url("svg/g-learn-lockup.svg"); margin: 0 1.5rem; min-width: 236px; } -- GitLab From 0a2c941e2feb1eed60c035c1fa2668d4e9327ed2 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Thu, 19 Nov 2020 22:45:10 -1000 Subject: [PATCH 204/283] Change to init preview block Former-commit-id: 9d134b4e319ddeb041c89461da38f5ba52ecdfc7 --- scripts/app/controllers/api/v1/users_controller.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/app/controllers/api/v1/users_controller.rb b/scripts/app/controllers/api/v1/users_controller.rb index 245729e..4cc51b9 100644 --- a/scripts/app/controllers/api/v1/users_controller.rb +++ b/scripts/app/controllers/api/v1/users_controller.rb @@ -12,6 +12,8 @@ class Api::V1::UsersController < Api::ApplicationController render_method_not_allowed_response and return unless request.get? authorize(current_user, :learn_cli_credentials?) + + Block.find_or_create_by(title: "preview", repo_name: "preview") render json: { user_id: current_user.id.to_s, -- GitLab From 6cc4de2ac5529e257a203af6bb1a5e5f57e82716 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 4 Dec 2020 10:09:18 -1000 Subject: [PATCH 205/283] adding logging Former-commit-id: 40f09dabcfd56bdf5c46d226e8921935d7aae681 --- scripts/config/environment.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/config/environment.rb b/scripts/config/environment.rb index 426333b..ff8d4c2 100644 --- a/scripts/config/environment.rb +++ b/scripts/config/environment.rb @@ -3,3 +3,9 @@ require_relative 'application' # Initialize the Rails application. Rails.application.initialize! + +puts "==========================================" +puts "Host: #{Rails.configuration.database_configuration[Rails.env]["host"]}" +puts "Database: #{Rails.configuration.database_configuration[Rails.env]["database"]}" +puts "User: #{Rails.configuration.database_configuration[Rails.env]["username"]}" +puts "==========================================" \ No newline at end of file -- GitLab From 1d30ca0cb25f96750c6b8e6221e965ca5ab5e1aa Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 7 Dec 2020 11:49:58 -1000 Subject: [PATCH 206/283] adding admin users to seed data Former-commit-id: 379dffeac1fc992b311ffe5986b3cf8898425a09 --- scripts/db/seeds.rb | 16 ++++++++++++++-- scripts/entrypoint-server.sh | 1 + 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/scripts/db/seeds.rb b/scripts/db/seeds.rb index ab31218..910d17b 100644 --- a/scripts/db/seeds.rb +++ b/scripts/db/seeds.rb @@ -12,8 +12,6 @@ # CreateReleaseJob.perform_now(pending_release_id: release.id) # end -Block.find_or_create_by(title: "preview", repo_name: "preview") - # # these values are specific to galvanize-auth-staging values # cohort = Cohort.create(uid: "9871fef341f9ef250b", # name: "Story Testing", @@ -117,3 +115,17 @@ Block.find_or_create_by(title: "preview", repo_name: "preview") # }) # end # end + +Block.find_or_create_by(title: "preview", repo_name: "preview") + +admin_users = [ + "muranaka@revacomm.com", + "csakamaki@revacomm.com", + "dcong@revacomm.com" +] +roles = ["forge.admin", "forge.blocks_manager"] + +admin_users.each do |email| + user = User.find_or_create_by(email: email) + user.update(roles: roles) +end \ No newline at end of file diff --git a/scripts/entrypoint-server.sh b/scripts/entrypoint-server.sh index 3df1bbc..4c83c42 100755 --- a/scripts/entrypoint-server.sh +++ b/scripts/entrypoint-server.sh @@ -2,4 +2,5 @@ rm -f tmp/pids/server.pid bundle exec rails db:migrate +bundle exec rails db:seed RAILS_ENV=production rails server -b 0.0.0.0 -p 3000 -- GitLab From 390563ff4e73a067020171d31eaf6dfb0edc6bb6 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 7 Dec 2020 12:16:24 -1000 Subject: [PATCH 207/283] fixing derrins name Former-commit-id: e9215b8408d1c98dc7d5b3273ff6438a2b49299a --- scripts/db/seeds.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/db/seeds.rb b/scripts/db/seeds.rb index 910d17b..cdada57 100644 --- a/scripts/db/seeds.rb +++ b/scripts/db/seeds.rb @@ -121,7 +121,7 @@ Block.find_or_create_by(title: "preview", repo_name: "preview") admin_users = [ "muranaka@revacomm.com", "csakamaki@revacomm.com", - "dcong@revacomm.com" + "dchong@revacomm.com" ] roles = ["forge.admin", "forge.blocks_manager"] -- GitLab From 9d60de7b015f901d45fe4c6b08dc78886a6a4e0f Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 7 Dec 2020 12:18:24 -1000 Subject: [PATCH 208/283] adding third role. Former-commit-id: eb79ec03cce2f36b0e1a1fce3cc5124a6747a174 --- scripts/db/seeds.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/db/seeds.rb b/scripts/db/seeds.rb index cdada57..702cef8 100644 --- a/scripts/db/seeds.rb +++ b/scripts/db/seeds.rb @@ -123,7 +123,11 @@ admin_users = [ "csakamaki@revacomm.com", "dchong@revacomm.com" ] -roles = ["forge.admin", "forge.blocks_manager"] +roles = [ + "forge.admin", + "forge.blocks_manager", + "auth.product_admin" +] admin_users.each do |email| user = User.find_or_create_by(email: email) -- GitLab From 9d1f6c471713ba942c2fbacbe9b2711598e5d842 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 7 Dec 2020 12:24:47 -1000 Subject: [PATCH 209/283] fixing Former-commit-id: 0741431ec1145952db86c79e92d37fbe19b5bcbc --- scripts/db/seeds.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/db/seeds.rb b/scripts/db/seeds.rb index 702cef8..b006a85 100644 --- a/scripts/db/seeds.rb +++ b/scripts/db/seeds.rb @@ -132,4 +132,6 @@ roles = [ admin_users.each do |email| user = User.find_or_create_by(email: email) user.update(roles: roles) -end \ No newline at end of file +end + +User.delete_by(email: "dcong@revacomm.com") \ No newline at end of file -- GitLab From 14aaf8a81f6c69b036b49f2e98f1371b0f22d104 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 7 Dec 2020 12:48:45 -1000 Subject: [PATCH 210/283] removing cleanup Former-commit-id: 0093f0d77b8d40d85a32fc973f4a014fdc3eded9 --- scripts/db/seeds.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/db/seeds.rb b/scripts/db/seeds.rb index b006a85..702cef8 100644 --- a/scripts/db/seeds.rb +++ b/scripts/db/seeds.rb @@ -132,6 +132,4 @@ roles = [ admin_users.each do |email| user = User.find_or_create_by(email: email) user.update(roles: roles) -end - -User.delete_by(email: "dcong@revacomm.com") \ No newline at end of file +end \ No newline at end of file -- GitLab From 73f0890934b408fd84307d660e6c3a18208159f4 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 8 Dec 2020 11:32:47 -1000 Subject: [PATCH 211/283] adding sleep to entrypoint script Former-commit-id: f91ff9dcdca4f9e63def2f8c07cbaac4239b9cdf --- scripts/entrypoint-server.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/entrypoint-server.sh b/scripts/entrypoint-server.sh index 4c83c42..5938f0e 100755 --- a/scripts/entrypoint-server.sh +++ b/scripts/entrypoint-server.sh @@ -1,5 +1,7 @@ #!/bin/sh +sleep 5 + rm -f tmp/pids/server.pid bundle exec rails db:migrate bundle exec rails db:seed -- GitLab From 0251913080e52deb44d8246a704646bd4e10045a Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 8 Dec 2020 15:57:05 -1000 Subject: [PATCH 212/283] debugging Former-commit-id: b464e8d9371ea4cbd82450f772f53e8ca6fc6806 --- scripts/app/services/platform_one_auth_resolver_service.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/app/services/platform_one_auth_resolver_service.rb b/scripts/app/services/platform_one_auth_resolver_service.rb index f6bde0d..aac063b 100644 --- a/scripts/app/services/platform_one_auth_resolver_service.rb +++ b/scripts/app/services/platform_one_auth_resolver_service.rb @@ -7,6 +7,7 @@ class PlatformOneAuthResolverService def initialize(jwt_token) @payload = JWT.decode(jwt_token, nil, false)[0] + puts @payload @uid = @payload["sub"] @email = @payload["email"] @first_name = @payload["given_name"] -- GitLab From d836ecfad988b29cf1e87f110a776b6fcec5c89a Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 8 Dec 2020 16:16:40 -1000 Subject: [PATCH 213/283] removing debug printing Former-commit-id: 8bd479da815da16bd7ba9f4eabe3ab7fbf8c1d70 --- .../app/services/platform_one_auth_resolver_service.rb | 1 - scripts/config/environment.rb | 10 +++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/scripts/app/services/platform_one_auth_resolver_service.rb b/scripts/app/services/platform_one_auth_resolver_service.rb index aac063b..f6bde0d 100644 --- a/scripts/app/services/platform_one_auth_resolver_service.rb +++ b/scripts/app/services/platform_one_auth_resolver_service.rb @@ -7,7 +7,6 @@ class PlatformOneAuthResolverService def initialize(jwt_token) @payload = JWT.decode(jwt_token, nil, false)[0] - puts @payload @uid = @payload["sub"] @email = @payload["email"] @first_name = @payload["given_name"] diff --git a/scripts/config/environment.rb b/scripts/config/environment.rb index ff8d4c2..45506d9 100644 --- a/scripts/config/environment.rb +++ b/scripts/config/environment.rb @@ -4,8 +4,8 @@ require_relative 'application' # Initialize the Rails application. Rails.application.initialize! -puts "==========================================" -puts "Host: #{Rails.configuration.database_configuration[Rails.env]["host"]}" -puts "Database: #{Rails.configuration.database_configuration[Rails.env]["database"]}" -puts "User: #{Rails.configuration.database_configuration[Rails.env]["username"]}" -puts "==========================================" \ No newline at end of file +# puts "==========================================" +# puts "Host: #{Rails.configuration.database_configuration[Rails.env]["host"]}" +# puts "Database: #{Rails.configuration.database_configuration[Rails.env]["database"]}" +# puts "User: #{Rails.configuration.database_configuration[Rails.env]["username"]}" +# puts "==========================================" \ No newline at end of file -- GitLab From 781a9be88877aad19877e5affa91945bce620ad9 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 8 Dec 2020 16:40:39 -1000 Subject: [PATCH 214/283] increasing timeout Former-commit-id: b84362d7b57c3df6edbbe82e77541cbc721c8deb --- scripts/entrypoint-server.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/entrypoint-server.sh b/scripts/entrypoint-server.sh index 5938f0e..b64943d 100755 --- a/scripts/entrypoint-server.sh +++ b/scripts/entrypoint-server.sh @@ -1,6 +1,6 @@ #!/bin/sh -sleep 5 +sleep 10 rm -f tmp/pids/server.pid bundle exec rails db:migrate -- GitLab From 618ed8d5a6b88ee55c41afef93dd34e6eafb0800 Mon Sep 17 00:00:00 2001 From: Joshua Eason Date: Thu, 10 Dec 2020 16:40:43 -0700 Subject: [PATCH 215/283] Converting to hardening manifest Former-commit-id: 97a456d61cb4d7e97378d5d25dcae8cd4c4bdaa4 --- Dockerfile | 10 -------- Jenkinsfile | 14 ----------- LICENSE | 1 + README.md | 2 +- download.json | 13 ---------- hardening_manifest.yaml | 54 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 56 insertions(+), 38 deletions(-) delete mode 100644 Jenkinsfile create mode 100644 LICENSE delete mode 100644 download.json create mode 100644 hardening_manifest.yaml diff --git a/Dockerfile b/Dockerfile index b6f6b78..b56cce9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,3 @@ -### Iron Bank Settings -ARG BASE_REGISTRY=registry1.dsop.io -ARG BASE_IMAGE=ironbank/opensource/ruby/ruby26 -ARG BASE_TAG=2.6.6 - -### Platform 1 Pipeline Settings -#ARG BASE_REGISTRY=registry.il2.dsop.io -#ARG BASE_IMAGE=platform-one/devops/pipeline-templates/ironbank/ruby26 -#ARG BASE_TAG=2.6.6.212 - # Setup the Image. FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} USER 0 diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index ec2a93f..0000000 --- a/Jenkinsfile +++ /dev/null @@ -1,14 +0,0 @@ -@Library('DCCSCR@master') _ -dccscrPipeline(version: "0.1.0") - -/* The above format is required for all production submissions. -* The version will be the image tag associated with this container for this branch. -* -* You may limit the job to the build stage or the scanning stage only: -* dccscrPipeline(version: "1.4.2", scan: false) -* dccscrPipeline(version: "1.0.0", build: false) -* -* You may also use a different branch of the jenkins-shared-library. -* Only do this if you know what you are doing: -* @Library('DCCSCR@feature1_branch') _ */ - diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e9db0f7 --- /dev/null +++ b/LICENSE @@ -0,0 +1 @@ +Please add a license \ No newline at end of file diff --git a/README.md b/README.md index 288603e..a901b4b 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ # forge -forge \ No newline at end of file +Please provide a detailed README \ No newline at end of file diff --git a/download.json b/download.json deleted file mode 100644 index 39b3156..0000000 --- a/download.json +++ /dev/null @@ -1,13 +0,0 @@ -{ "resources": - [ - { - "url" : "https://download.redis.io/releases/redis-6.0.9.tar.gz", - "filename": "redis-6.0.9.tar.gz", - "validation": - { - "type": "sha256", - "value": "dc2bdcf81c620e9f09cfd12e85d3bc631c897b2db7a55218fd8a65eaa37f86dd" - } - } - ] -} diff --git a/hardening_manifest.yaml b/hardening_manifest.yaml new file mode 100644 index 0000000..953d282 --- /dev/null +++ b/hardening_manifest.yaml @@ -0,0 +1,54 @@ +--- +apiVersion: v1 + +# The repository name in registry1, excluding /ironbank/ +name: "forge" + +# List of tags to push for the repository in registry1 +# The most specific version should be the first tag and will be shown +# on ironbank.dsop.io +tags: +- "0.1.0" +- "latest" + +# Build args passed to Dockerfile ARGs +args: + BASE_IMAGE: "ironbank/opensource/ruby/ruby26" + BASE_TAG: "2.6.6.212" + +# Docker image labels +labels: + org.opencontainers.image.title: "forge" + ## Human-readable description of the software packaged in the image + # org.opencontainers.image.description: "FIXME" + ## License(s) under which contained software is distributed + # org.opencontainers.image.licenses: "FIXME" + ## URL to find more information on the image + # org.opencontainers.image.url: "FIXME" + ## Name of the distributing entity, organization or individual + # org.opencontainers.image.vendor: "FIXME" + org.opencontainers.image.version: "0.1.0" + ## Keywords to help with search (ex. "cicd,gitops,golang") + # mil.dso.ironbank.image.keywords: "FIXME" + ## This value can be "opensource" or "commercial" + # mil.dso.ironbank.image.type: "FIXME" + ## Product the image belongs to for grouping multiple images + # mil.dso.ironbank.product.name: "FIXME" + +# List of resources to make available to the offline build context +resources: +- url: https://download.redis.io/releases/redis-6.0.9.tar.gz + filename: redis-6.0.9.tar.gz + validation: + type: sha256 + value: dc2bdcf81c620e9f09cfd12e85d3bc631c897b2db7a55218fd8a65eaa37f86dd + +# List of project maintainers +maintainers: +- email: "dchong@revacomm.com" + # The name of the current container owner + name: "Derrin Chong" + username: "dchong" +- name: "Joshua Eason" + username: "jeason" + cht_member: true -- GitLab From 2fd64a45e51383e0adb49787ffc7d4a766b09def Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 15 Dec 2020 10:22:52 -1000 Subject: [PATCH 216/283] Updating from ironbank Former-commit-id: 4ba070e3ee01f782b7c0704124a709d0ace7b2b4 --- Dockerfile | 6 ++- README.md | 110 +++++++++++++++++++++++++++++++++++++++- hardening_manifest.yaml | 25 ++++----- 3 files changed, 124 insertions(+), 17 deletions(-) diff --git a/Dockerfile b/Dockerfile index b56cce9..8c04504 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,8 @@ -# Setup the Image. +# Platform 1 Pipeline Settings +ARG BASE_REGISTRY=registry.il2.dsop.io +ARG BASE_IMAGE=platform-one/devops/pipeline-templates/ironbank/ruby26 +ARG BASE_TAG=2.6.6.212 + FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} USER 0 diff --git a/README.md b/README.md index a901b4b..9098182 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,109 @@ -# forge +Forge +===== -Please provide a detailed README \ No newline at end of file +## Standards +See the [software-team-standards](https://www.github.com/Galvanize-IT/software-team-standards) for git aliases. + +## Dependency Setup + +[install Homebrew](http://brew.sh/) if you don't already have it. + +Install rbenv and get the right version of ruby (the version here may change, so check the Gemfile for the correct +version. ) + +- `brew install rbenv` +- `rbenv install 2.6.6` + +Install our data stores: + +- `brew install postgresql` +- `brew install redis` +- `brew services start redis` + +To simplify your postgres installation, once you've installed it with homebrew, it's recommended that you use the +[Postgres.app](http://postgresapp.com/), which is an easy download and install. This allows you to not need to specify a +username/password in your `database.yml`. + + +## Installation + +You will need a [Github access token](https://github.com/settings/tokens). Replace the `YOUR_GENERATED_PERSONAL_ACCESS_TOKEN` with your token. + +The token will need **Full control of private repositories** + +- `git clone git@github.com:Galvanize-IT/forge.git && cd forge` +- `rbenv local 2.6.6` +- `gem install bundler` +- `bundle config --local GITHUB__COM YOUR_GENERATED_PERSONAL_ACCESS_TOKEN:x-oauth-basic` +- `bundle` +- `yarn install` + +## Data + +- `rake db:create` +- `rake db:migrate` + +## Auth + +Set up [Auth](https://github.com/Galvanize-IT/auth) before running Forge. + +## Configuration + +Ask a co-developer for their .env example. + +### Sidekiq + +As an admin, you can view Sidekiq jobs at `/admin/sidekiq`. + +## Starting the server + +`heroku local -p 3003` + +or: +`rails s -p 3003` +`sidekiq` +`bin/webpack-dev-server` + +## Deployment + +PRs are automatically deployed to their own one-off environments. To test webhook-related Auth features, be sure to update the webhooks for Forge at `auth-staging.herokuapp.com` to point to your review enviroment. + +Sign in to your review environment using your credentials for `auth-staging.herokuapp.com`, or `dev+auth@galvanize.com:password`. + +`master` is automatically deployed to `staging` once CI passes. + +Migrations are run as part of the deployment release phase. + +Note: `galvanize-forge` will need to have access to any repos used for project challenges. + +## Mailer previews + +To preview our mailers, go to `http://localhost:3003/rails/mailers`. + +## End-to-end Tests (e2e) + +The [Forge e2e suite](https://github.com/Galvanize-IT/forge-e2e) is run on every deploy to staging, and the results are posted to `#forge_devops`. + +## Code Generators + +The `ts_routes` gem generates typesafe routes for use in TypeScript. To update them: + +`rake ts:routes` + +### API Documentation + +The specs for the API use a specific DSL that allows the tests to generate our API documentation. You can then run the +integration specs and generate the documentation. The documentation can be committed if you’ve made changes to the API, +otherwise they can be disregard. + +Run `rails spec:api:docs` to generate the documentation files and then browse to `/api/docs` to see what the +documentation looks like. + +## Linters + +We use `rubocop` and `eslint`. + +You can use overcommit to automatically run our linters in a pre-commit hook: (`gem install overcommit; overcommit --install`). +Note: If you want to disable it inline (i.e. for a WIP commit), use `OVERCOMMIT_DISABLE=1 git commit -m "wip"`. + +You can also run the linters manually with auto-correction, along with the test suite, by running `bash lintspec.sh`. diff --git a/hardening_manifest.yaml b/hardening_manifest.yaml index 953d282..beb8cd9 100644 --- a/hardening_manifest.yaml +++ b/hardening_manifest.yaml @@ -20,35 +20,32 @@ args: labels: org.opencontainers.image.title: "forge" ## Human-readable description of the software packaged in the image - # org.opencontainers.image.description: "FIXME" + #org.opencontainers.image.description: "FIXME" ## License(s) under which contained software is distributed # org.opencontainers.image.licenses: "FIXME" ## URL to find more information on the image # org.opencontainers.image.url: "FIXME" ## Name of the distributing entity, organization or individual - # org.opencontainers.image.vendor: "FIXME" + org.opencontainers.image.vendor: "Galvanize" org.opencontainers.image.version: "0.1.0" ## Keywords to help with search (ex. "cicd,gitops,golang") - # mil.dso.ironbank.image.keywords: "FIXME" + mil.dso.ironbank.image.keywords: "learn,lms,galvanize" ## This value can be "opensource" or "commercial" - # mil.dso.ironbank.image.type: "FIXME" + mil.dso.ironbank.image.type: "commercial" ## Product the image belongs to for grouping multiple images - # mil.dso.ironbank.product.name: "FIXME" - -# List of resources to make available to the offline build context -resources: -- url: https://download.redis.io/releases/redis-6.0.9.tar.gz - filename: redis-6.0.9.tar.gz - validation: - type: sha256 - value: dc2bdcf81c620e9f09cfd12e85d3bc631c897b2db7a55218fd8a65eaa37f86dd + mil.dso.ironbank.product.name: "Learn" # List of project maintainers maintainers: - email: "dchong@revacomm.com" - # The name of the current container owner name: "Derrin Chong" username: "dchong" +- email: "muranaka@revacomm.com" + name: "Michael Uranaka" + username: "muranaka" +- email: "csakamaki@revacomm.com" + name: "Charlie Sakamaki" + username: "csakamaki" - name: "Joshua Eason" username: "jeason" cht_member: true -- GitLab From 766472c36b444ce03dce76dcc0e57a359725cfd9 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Sun, 20 Dec 2020 22:41:40 -1000 Subject: [PATCH 217/283] updating registry Former-commit-id: 333fde25ce43213479f4f3c63f6bdd2c69761861 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 8c04504..1489bcb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Platform 1 Pipeline Settings -ARG BASE_REGISTRY=registry.il2.dsop.io +ARG BASE_REGISTRY=registry.il2.dso.mil ARG BASE_IMAGE=platform-one/devops/pipeline-templates/ironbank/ruby26 ARG BASE_TAG=2.6.6.212 -- GitLab From 666fdba6c8fbb6d5038996c8e8486630089439b1 Mon Sep 17 00:00:00 2001 From: Derrin Chong Date: Tue, 22 Dec 2020 02:12:58 +0000 Subject: [PATCH 218/283] Fill in the blanks Former-commit-id: 044ef843741cb456c03fd4ee1fe76c7fcf33ef3c --- hardening_manifest.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hardening_manifest.yaml b/hardening_manifest.yaml index beb8cd9..5286f6d 100644 --- a/hardening_manifest.yaml +++ b/hardening_manifest.yaml @@ -20,7 +20,7 @@ args: labels: org.opencontainers.image.title: "forge" ## Human-readable description of the software packaged in the image - #org.opencontainers.image.description: "FIXME" + org.opencontainers.image.description: "Galvanize is a technology ecosystem for learners, entrepreneurs, startups, and established companies that meets the needs of the rapidly changing digital world. Our goal is to transform individuals and teams through effective education and community programs Delivering exceptional outcomes Coalescing and nurturing a community of innovators anchored by our campuses" ## License(s) under which contained software is distributed # org.opencontainers.image.licenses: "FIXME" ## URL to find more information on the image @@ -29,7 +29,7 @@ labels: org.opencontainers.image.vendor: "Galvanize" org.opencontainers.image.version: "0.1.0" ## Keywords to help with search (ex. "cicd,gitops,golang") - mil.dso.ironbank.image.keywords: "learn,lms,galvanize" + mil.dso.ironbank.image.keywords: "learn,lms,galvanize,online,remote,school,learning" ## This value can be "opensource" or "commercial" mil.dso.ironbank.image.type: "commercial" ## Product the image belongs to for grouping multiple images -- GitLab From 1064264c93c84eba36c269c640d24071edf3441f Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Wed, 23 Dec 2020 15:13:30 -1000 Subject: [PATCH 219/283] Fix domain for test Former-commit-id: 30204853ef50caccc9515a5f51a481360d80b2b0 --- scripts/spec/services/download_repository_service_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/spec/services/download_repository_service_spec.rb b/scripts/spec/services/download_repository_service_spec.rb index d08a6bc..2ef54a8 100644 --- a/scripts/spec/services/download_repository_service_spec.rb +++ b/scripts/spec/services/download_repository_service_spec.rb @@ -44,7 +44,7 @@ describe DownloadRepositoryService do end context "when downloading from gitlab" do - let(:block) { create(:block, org: "csakamaki", origin: "code.il2.dsop.io", repo_name: "test-20200917")} + let(:block) { create(:block, org: "csakamaki", origin: "code.il2.dso.mil", repo_name: "test-20200917")} let(:release) { create(:release, block: block)} subject { DownloadGitlabRepositoryService.new(release: release, tmp_path: Rails.root.join("tmp", block.repo_name)).execute } -- GitLab From ee470c10a5a1bc96325bc7ac0f26cc1a54b94b14 Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Wed, 23 Dec 2020 18:18:43 -1000 Subject: [PATCH 220/283] Updates for new dso.mil domain Former-commit-id: fb677beff2add260a03630bbc9f19bfbd19ef0c0 --- scripts/Gemfile | 2 +- scripts/config/secrets.yml | 2 +- scripts/doc/api.md | 2 +- scripts/serviceentry.yaml | 2 +- .../controllers/sessions_controller_spec.rb | 2 +- .../gitlab-course-yaml-branch-failure.yml | 18 +-- .../gitlab-course-yaml-success.yml | 104 +++++++++--------- .../vcr_cassettes/gitlab-not-found.yml | 12 +- .../fixtures/vcr_cassettes/gitlab-success.yml | 24 ++-- .../spec/services/course_validator_spec.rb | 8 +- .../download_repository_service_spec.rb | 2 +- scripts/spec/services/git_url_service_spec.rb | 6 +- ...platform_one_auth_resolver_service_spec.rb | 4 +- 13 files changed, 93 insertions(+), 95 deletions(-) diff --git a/scripts/Gemfile b/scripts/Gemfile index d937d75..1a86e24 100644 --- a/scripts/Gemfile +++ b/scripts/Gemfile @@ -53,7 +53,7 @@ gem "solid_use_case" # file processing ### We need to pass git credentials into the docker build command so we can clone the block-parser -# gem "block_parser", :git => "https://code.il2.dsop.io/tron/products/learn-lms/ruby-gems/block-parser.git" +# gem "block_parser", :git => "https://code.il2.dso.mil/tron/products/learn-lms/ruby-gems/block-parser.git" gem "block_parser", path: "./gems/block-parser" # Reduces boot times through caching; required in config/boot.rb diff --git a/scripts/config/secrets.yml b/scripts/config/secrets.yml index a3a095e..c989a87 100644 --- a/scripts/config/secrets.yml +++ b/scripts/config/secrets.yml @@ -32,7 +32,7 @@ shared: github_com: type: github token: <%= ENV['GITHUB_COM_TOKEN'] %> - code_il2_dsop_io: + code_il2_dso_mil: type: gitlab token: <%= ENV['GITLAB_DSOP_IL2_TOKEN'] %> gitlab_com: diff --git a/scripts/doc/api.md b/scripts/doc/api.md index 7631cd6..8f251a2 100644 --- a/scripts/doc/api.md +++ b/scripts/doc/api.md @@ -8,7 +8,7 @@ Future work might add the ability to publish curriculum and manage cohort creati Authentication ============== -Each Learn admin and instructor account will have a token that can be used to access the API. The token can be found in the UI under the account dropdown, or by going directly to https://learn.apps.il2.dsop.io/api_token. The token must be passed in the header of API requests as `X-LEARN-API-TOKEN: Bearer {token}` +Each Learn admin and instructor account will have a token that can be used to access the API. The token can be found in the UI under the account dropdown, or by going directly to https://learn.dso.mil/api_token. The token must be passed in the header of API requests as `X-LEARN-API-TOKEN: Bearer {token}` The authorization scope for each token will match the user’s permissions. For example, if a user is allowed to update a cohort’s visibility in the UI, that user’s token will be allowed to make API requests to do the same. diff --git a/scripts/serviceentry.yaml b/scripts/serviceentry.yaml index 9b4e97c..3cb48be 100644 --- a/scripts/serviceentry.yaml +++ b/scripts/serviceentry.yaml @@ -5,7 +5,7 @@ metadata: namespace: galvanize-learn spec: hosts: - - code.il2.dsop.io + - code.il2.dso.mil - google.com location: MESH_EXTERNAL ports: diff --git a/scripts/spec/controllers/sessions_controller_spec.rb b/scripts/spec/controllers/sessions_controller_spec.rb index 4dab6eb..91eeb73 100644 --- a/scripts/spec/controllers/sessions_controller_spec.rb +++ b/scripts/spec/controllers/sessions_controller_spec.rb @@ -32,7 +32,7 @@ describe SessionsController do iat: Time.now.to_i, auth_time: Time.now.to_i, jti: "e4600f88-1b42-4e01-ac01-8646d3cc4df6", - iss: "https://login.dsop.io/auth/realms/baby-yoda", + iss: "https://login.dso.mil/auth/realms/baby-yoda", aud: "il4_191f836b-ec50-4819-ba10-1afaa5b99600_mission-widow", sub: "2cba6ea8-8451-4952-80d6-c7de379d5b7e", typ: "ID", diff --git a/scripts/spec/fixtures/vcr_cassettes/gitlab-course-yaml-branch-failure.yml b/scripts/spec/fixtures/vcr_cassettes/gitlab-course-yaml-branch-failure.yml index bc1ecf6..8787042 100644 --- a/scripts/spec/fixtures/vcr_cassettes/gitlab-course-yaml-branch-failure.yml +++ b/scripts/spec/fixtures/vcr_cassettes/gitlab-course-yaml-branch-failure.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: get - uri: https://code.il2.dsop.io/api/v4/projects?search=p1-test + uri: https://code.il2.dso.mil/api/v4/projects?search=p1-test body: encoding: US-ASCII string: '' @@ -29,8 +29,8 @@ http_interactions: Etag: - W/"905a13fb3b949a706442a5f1b4b540d6" Link: - - ; - rel="first", ; + - ; + rel="first", ; rel="last" Vary: - Origin @@ -63,14 +63,14 @@ http_interactions: body: encoding: UTF-8 string: '[{"id":702,"description":"","name":"p1-test","name_with_namespace":"Charlie - Sakamaki / p1-test","path":"p1-test","path_with_namespace":"csakamaki/p1-test","created_at":"2020-09-23T19:53:49.310Z","default_branch":"master","tag_list":[],"ssh_url_to_repo":"git@code.il2.dsop.io:csakamaki/p1-test.git","http_url_to_repo":"https://code.il2.dsop.io/csakamaki/p1-test.git","web_url":"https://code.il2.dsop.io/csakamaki/p1-test","readme_url":null,"avatar_url":null,"star_count":0,"forks_count":0,"last_activity_at":"2020-09-24T00:07:57.336Z","namespace":{"id":288,"name":"Charlie - Sakamaki","path":"csakamaki","kind":"user","full_path":"csakamaki","parent_id":null,"avatar_url":"https://secure.gravatar.com/avatar/ed30ad3597897901ccbd315e731bf100?s=80\u0026d=identicon","web_url":"https://code.il2.dsop.io/csakamaki"},"_links":{"self":"https://code.il2.dsop.io/api/v4/projects/702","issues":"https://code.il2.dsop.io/api/v4/projects/702/issues","merge_requests":"https://code.il2.dsop.io/api/v4/projects/702/merge_requests","repo_branches":"https://code.il2.dsop.io/api/v4/projects/702/repository/branches","labels":"https://code.il2.dsop.io/api/v4/projects/702/labels","events":"https://code.il2.dsop.io/api/v4/projects/702/events","members":"https://code.il2.dsop.io/api/v4/projects/702/members"},"empty_repo":false,"archived":false,"visibility":"private","owner":{"id":238,"name":"Charlie - Sakamaki","username":"csakamaki","state":"active","avatar_url":"https://secure.gravatar.com/avatar/ed30ad3597897901ccbd315e731bf100?s=80\u0026d=identicon","web_url":"https://code.il2.dsop.io/csakamaki"},"resolve_outdated_diff_discussions":false,"container_registry_enabled":true,"container_expiration_policy":{"cadence":"7d","enabled":true,"keep_n":null,"older_than":null,"name_regex":null,"name_regex_keep":null,"next_run_at":"2020-10-07T20:50:13.933Z"},"issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"jobs_enabled":true,"snippets_enabled":true,"can_create_merge_request_in":true,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"enabled","wiki_access_level":"enabled","builds_access_level":"enabled","snippets_access_level":"enabled","pages_access_level":"private","emails_disabled":null,"shared_runners_enabled":true,"lfs_enabled":true,"creator_id":238,"import_status":"none","open_issues_count":0,"ci_default_git_depth":50,"public_jobs":true,"build_timeout":3600,"auto_cancel_pending_pipelines":"enabled","build_coverage_regex":null,"ci_config_path":"","shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"request_access_enabled":true,"only_allow_merge_if_all_discussions_are_resolved":false,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"merge","suggestion_commit_message":null,"auto_devops_enabled":false,"auto_devops_deploy_strategy":"continuous","autoclose_referenced_issues":true,"approvals_before_merge":0,"mirror":false,"external_authorization_classification_label":null,"packages_enabled":true,"service_desk_enabled":false,"service_desk_address":null,"marked_for_deletion_at":null,"marked_for_deletion_on":null,"permissions":{"project_access":{"access_level":40,"notification_level":3},"group_access":null}}]' - http_version: + Sakamaki / p1-test","path":"p1-test","path_with_namespace":"csakamaki/p1-test","created_at":"2020-09-23T19:53:49.310Z","default_branch":"master","tag_list":[],"ssh_url_to_repo":"git@code.il2.dso.mil:csakamaki/p1-test.git","http_url_to_repo":"https://code.il2.dso.mil/csakamaki/p1-test.git","web_url":"https://code.il2.dso.mil/csakamaki/p1-test","readme_url":null,"avatar_url":null,"star_count":0,"forks_count":0,"last_activity_at":"2020-09-24T00:07:57.336Z","namespace":{"id":288,"name":"Charlie + Sakamaki","path":"csakamaki","kind":"user","full_path":"csakamaki","parent_id":null,"avatar_url":"https://secure.gravatar.com/avatar/ed30ad3597897901ccbd315e731bf100?s=80\u0026d=identicon","web_url":"https://code.il2.dso.mil/csakamaki"},"_links":{"self":"https://code.il2.dso.mil/api/v4/projects/702","issues":"https://code.il2.dso.mil/api/v4/projects/702/issues","merge_requests":"https://code.il2.dso.mil/api/v4/projects/702/merge_requests","repo_branches":"https://code.il2.dso.mil/api/v4/projects/702/repository/branches","labels":"https://code.il2.dso.mil/api/v4/projects/702/labels","events":"https://code.il2.dso.mil/api/v4/projects/702/events","members":"https://code.il2.dso.mil/api/v4/projects/702/members"},"empty_repo":false,"archived":false,"visibility":"private","owner":{"id":238,"name":"Charlie + Sakamaki","username":"csakamaki","state":"active","avatar_url":"https://secure.gravatar.com/avatar/ed30ad3597897901ccbd315e731bf100?s=80\u0026d=identicon","web_url":"https://code.il2.dso.mil/csakamaki"},"resolve_outdated_diff_discussions":false,"container_registry_enabled":true,"container_expiration_policy":{"cadence":"7d","enabled":true,"keep_n":null,"older_than":null,"name_regex":null,"name_regex_keep":null,"next_run_at":"2020-10-07T20:50:13.933Z"},"issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"jobs_enabled":true,"snippets_enabled":true,"can_create_merge_request_in":true,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"enabled","wiki_access_level":"enabled","builds_access_level":"enabled","snippets_access_level":"enabled","pages_access_level":"private","emails_disabled":null,"shared_runners_enabled":true,"lfs_enabled":true,"creator_id":238,"import_status":"none","open_issues_count":0,"ci_default_git_depth":50,"public_jobs":true,"build_timeout":3600,"auto_cancel_pending_pipelines":"enabled","build_coverage_regex":null,"ci_config_path":"","shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"request_access_enabled":true,"only_allow_merge_if_all_discussions_are_resolved":false,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"merge","suggestion_commit_message":null,"auto_devops_enabled":false,"auto_devops_deploy_strategy":"continuous","autoclose_referenced_issues":true,"approvals_before_merge":0,"mirror":false,"external_authorization_classification_label":null,"packages_enabled":true,"service_desk_enabled":false,"service_desk_address":null,"marked_for_deletion_at":null,"marked_for_deletion_on":null,"permissions":{"project_access":{"access_level":40,"notification_level":3},"group_access":null}}]' + http_version: recorded_at: Tue, 06 Oct 2020 07:44:25 GMT - request: method: get - uri: https://code.il2.dsop.io/api/v4/projects/702/repository/files/course.yaml?ref=missingfile + uri: https://code.il2.dso.mil/api/v4/projects/702/repository/files/course.yaml?ref=missingfile body: encoding: US-ASCII string: '' @@ -113,6 +113,6 @@ http_interactions: body: encoding: UTF-8 string: '{"message":"404 Commit Not Found"}' - http_version: + http_version: recorded_at: Tue, 06 Oct 2020 07:44:25 GMT recorded_with: VCR 4.0.0 diff --git a/scripts/spec/fixtures/vcr_cassettes/gitlab-course-yaml-success.yml b/scripts/spec/fixtures/vcr_cassettes/gitlab-course-yaml-success.yml index 549e280..a84944c 100644 --- a/scripts/spec/fixtures/vcr_cassettes/gitlab-course-yaml-success.yml +++ b/scripts/spec/fixtures/vcr_cassettes/gitlab-course-yaml-success.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: get - uri: https://code.il2.dsop.io/api/v4/projects?search=p1-test + uri: https://code.il2.dso.mil/api/v4/projects?search=p1-test body: encoding: US-ASCII string: '' @@ -22,15 +22,13 @@ http_interactions: headers: Cache-Control: - max-age=0, private, must-revalidate - Content-Length: - - '3280' Content-Type: - application/json Etag: - - W/"905a13fb3b949a706442a5f1b4b540d6" + - W/"81be7f29b8b3092ab074fadd48e9b3f2" Link: - - ; - rel="first", ; + - ; + rel="first", ; rel="last" Vary: - Origin @@ -47,30 +45,31 @@ http_interactions: X-Prev-Page: - '' X-Request-Id: - - O1E5nWd8Oa5 + - 8Xlos2Tb412 X-Runtime: - - '0.103785' + - '0.072129' X-Total: - '1' X-Total-Pages: - '1' Date: - - Tue, 06 Oct 2020 07:37:19 GMT + - Thu, 24 Dec 2020 04:03:11 GMT X-Envoy-Upstream-Service-Time: - - '108' + - '74' Server: - istio-envoy + Transfer-Encoding: + - chunked body: encoding: UTF-8 string: '[{"id":702,"description":"","name":"p1-test","name_with_namespace":"Charlie - Sakamaki / p1-test","path":"p1-test","path_with_namespace":"csakamaki/p1-test","created_at":"2020-09-23T19:53:49.310Z","default_branch":"master","tag_list":[],"ssh_url_to_repo":"git@code.il2.dsop.io:csakamaki/p1-test.git","http_url_to_repo":"https://code.il2.dsop.io/csakamaki/p1-test.git","web_url":"https://code.il2.dsop.io/csakamaki/p1-test","readme_url":null,"avatar_url":null,"star_count":0,"forks_count":0,"last_activity_at":"2020-09-24T00:07:57.336Z","namespace":{"id":288,"name":"Charlie - Sakamaki","path":"csakamaki","kind":"user","full_path":"csakamaki","parent_id":null,"avatar_url":"https://secure.gravatar.com/avatar/ed30ad3597897901ccbd315e731bf100?s=80\u0026d=identicon","web_url":"https://code.il2.dsop.io/csakamaki"},"_links":{"self":"https://code.il2.dsop.io/api/v4/projects/702","issues":"https://code.il2.dsop.io/api/v4/projects/702/issues","merge_requests":"https://code.il2.dsop.io/api/v4/projects/702/merge_requests","repo_branches":"https://code.il2.dsop.io/api/v4/projects/702/repository/branches","labels":"https://code.il2.dsop.io/api/v4/projects/702/labels","events":"https://code.il2.dsop.io/api/v4/projects/702/events","members":"https://code.il2.dsop.io/api/v4/projects/702/members"},"empty_repo":false,"archived":false,"visibility":"private","owner":{"id":238,"name":"Charlie - Sakamaki","username":"csakamaki","state":"active","avatar_url":"https://secure.gravatar.com/avatar/ed30ad3597897901ccbd315e731bf100?s=80\u0026d=identicon","web_url":"https://code.il2.dsop.io/csakamaki"},"resolve_outdated_diff_discussions":false,"container_registry_enabled":true,"container_expiration_policy":{"cadence":"7d","enabled":true,"keep_n":null,"older_than":null,"name_regex":null,"name_regex_keep":null,"next_run_at":"2020-10-07T20:50:13.933Z"},"issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"jobs_enabled":true,"snippets_enabled":true,"can_create_merge_request_in":true,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"enabled","wiki_access_level":"enabled","builds_access_level":"enabled","snippets_access_level":"enabled","pages_access_level":"private","emails_disabled":null,"shared_runners_enabled":true,"lfs_enabled":true,"creator_id":238,"import_status":"none","open_issues_count":0,"ci_default_git_depth":50,"public_jobs":true,"build_timeout":3600,"auto_cancel_pending_pipelines":"enabled","build_coverage_regex":null,"ci_config_path":"","shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"request_access_enabled":true,"only_allow_merge_if_all_discussions_are_resolved":false,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"merge","suggestion_commit_message":null,"auto_devops_enabled":false,"auto_devops_deploy_strategy":"continuous","autoclose_referenced_issues":true,"approvals_before_merge":0,"mirror":false,"external_authorization_classification_label":null,"packages_enabled":true,"service_desk_enabled":false,"service_desk_address":null,"marked_for_deletion_at":null,"marked_for_deletion_on":null,"permissions":{"project_access":{"access_level":40,"notification_level":3},"group_access":null}}]' - http_version: - recorded_at: Tue, 06 Oct 2020 07:37:19 GMT + Sakamaki / p1-test","path":"p1-test","path_with_namespace":"csakamaki/p1-test","created_at":"2020-09-23T19:53:49.310Z","default_branch":"master","tag_list":[],"ssh_url_to_repo":"git@code.il2.dso.mil:csakamaki/p1-test.git","http_url_to_repo":"https://code.il2.dso.mil/csakamaki/p1-test.git","web_url":"https://code.il2.dso.mil/csakamaki/p1-test","readme_url":null,"avatar_url":null,"forks_count":0,"star_count":0,"last_activity_at":"2020-12-24T02:53:59.799Z","namespace":{"id":288,"name":"Charlie + Sakamaki","path":"csakamaki","kind":"user","full_path":"csakamaki","parent_id":null,"avatar_url":"https://secure.gravatar.com/avatar/ed30ad3597897901ccbd315e731bf100?s=80\u0026d=identicon","web_url":"https://code.il2.dso.mil/csakamaki"},"_links":{"self":"https://code.il2.dso.mil/api/v4/projects/702","issues":"https://code.il2.dso.mil/api/v4/projects/702/issues","merge_requests":"https://code.il2.dso.mil/api/v4/projects/702/merge_requests","repo_branches":"https://code.il2.dso.mil/api/v4/projects/702/repository/branches","labels":"https://code.il2.dso.mil/api/v4/projects/702/labels","events":"https://code.il2.dso.mil/api/v4/projects/702/events","members":"https://code.il2.dso.mil/api/v4/projects/702/members"},"packages_enabled":true,"empty_repo":false,"archived":false,"visibility":"private","owner":{"id":238,"name":"Charlie + Sakamaki","username":"csakamaki","state":"active","avatar_url":"https://secure.gravatar.com/avatar/ed30ad3597897901ccbd315e731bf100?s=80\u0026d=identicon","web_url":"https://code.il2.dso.mil/csakamaki"},"resolve_outdated_diff_discussions":false,"container_registry_enabled":true,"container_expiration_policy":{"cadence":"7d","enabled":true,"keep_n":null,"older_than":null,"name_regex":null,"name_regex_keep":null,"next_run_at":"2020-11-19T00:50:12.208Z"},"issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"jobs_enabled":true,"snippets_enabled":true,"service_desk_enabled":false,"service_desk_address":null,"can_create_merge_request_in":true,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"enabled","wiki_access_level":"enabled","builds_access_level":"enabled","snippets_access_level":"enabled","pages_access_level":"private","emails_disabled":null,"shared_runners_enabled":true,"lfs_enabled":true,"creator_id":238,"import_status":"none","open_issues_count":0,"ci_default_git_depth":50,"ci_forward_deployment_enabled":true,"public_jobs":true,"build_timeout":3600,"auto_cancel_pending_pipelines":"enabled","build_coverage_regex":null,"ci_config_path":"","shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"allow_merge_on_skipped_pipeline":null,"request_access_enabled":true,"only_allow_merge_if_all_discussions_are_resolved":false,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"merge","suggestion_commit_message":null,"auto_devops_enabled":false,"auto_devops_deploy_strategy":"continuous","autoclose_referenced_issues":true,"permissions":{"project_access":{"access_level":40,"notification_level":3},"group_access":null}}]' + recorded_at: Thu, 24 Dec 2020 04:03:11 GMT - request: method: get - uri: https://code.il2.dsop.io/api/v4/projects/702/repository/files/course.yaml?ref=master + uri: https://code.il2.dso.mil/api/v4/projects/702/repository/files/course.yaml?ref=master body: encoding: US-ASCII string: '' @@ -90,12 +89,10 @@ http_interactions: headers: Cache-Control: - max-age=0, private, must-revalidate - Content-Length: - - '648' Content-Type: - application/json Etag: - - W/"58ce3aa47e9466c129ffaf1a1f8ab1fe" + - W/"46686ce61776a9ce9a5cbf67a8f117c6" Vary: - Origin X-Content-Type-Options: @@ -103,11 +100,11 @@ http_interactions: X-Frame-Options: - SAMEORIGIN X-Gitlab-Blob-Id: - - 696c1f44c7233b2fd1c27c43c2b1106cc06f0eb3 + - 48654c43a0644a1f46d9cb7772317cc9408ffb25 X-Gitlab-Commit-Id: - - c114c7afbf65344d93f697f34060ca901b3035df + - 55ce2e91da39472f9ae9faf77c4025a872c55c74 X-Gitlab-Content-Sha256: - - d537f06b2b5bc5e1e1980872aac58766d2a57578d2f565e53b007debf05feb9f + - 365879dd4054b10e3c12e2e2d30b3ec988f01017896d7a46bfe9dc24c5832ec3 X-Gitlab-Encoding: - base64 X-Gitlab-File-Name: @@ -115,29 +112,30 @@ http_interactions: X-Gitlab-File-Path: - course.yaml X-Gitlab-Last-Commit-Id: - - ac0da165cce031bf056866c3629dc7f221748c8f + - 55ce2e91da39472f9ae9faf77c4025a872c55c74 X-Gitlab-Ref: - master X-Gitlab-Size: - '211' X-Request-Id: - - UlX7wrEymh2 + - eAMVwDv2Qw1 X-Runtime: - - '0.052112' + - '0.036504' Date: - - Tue, 06 Oct 2020 07:37:19 GMT + - Thu, 24 Dec 2020 04:03:12 GMT + Content-Length: + - '648' X-Envoy-Upstream-Service-Time: - - '54' + - '38' Server: - istio-envoy body: encoding: UTF-8 - string: '{"file_name":"course.yaml","file_path":"course.yaml","size":211,"encoding":"base64","content_sha256":"d537f06b2b5bc5e1e1980872aac58766d2a57578d2f565e53b007debf05feb9f","ref":"master","blob_id":"696c1f44c7233b2fd1c27c43c2b1106cc06f0eb3","commit_id":"c114c7afbf65344d93f697f34060ca901b3035df","last_commit_id":"ac0da165cce031bf056866c3629dc7f221748c8f","content":"LS0tCiAgQ291cnNlOgogICAgLSBTZWN0aW9uOiBEU09QIEdpdExhYgogICAgICBSZXBvczoKICAgICAgICAtIFVSTDogaHR0cHM6Ly9jb2RlLmlsMi5kc29wLmlvL2NzYWthbWFraS9wMS10ZXN0CiAgICAtIFNlY3Rpb246IGdTY2hvb2wgR2l0SHViCiAgICAgIFJlcG9zOgogICAgICAgIC0gVVJMOiBodHRwczovL2dpdGh1Yi5jb20vZ1NjaG9vbC9yZXZhY29tbS10ZXN0Cg=="}' - http_version: - recorded_at: Tue, 06 Oct 2020 07:37:19 GMT + string: '{"file_name":"course.yaml","file_path":"course.yaml","size":211,"encoding":"base64","content_sha256":"365879dd4054b10e3c12e2e2d30b3ec988f01017896d7a46bfe9dc24c5832ec3","ref":"master","blob_id":"48654c43a0644a1f46d9cb7772317cc9408ffb25","commit_id":"55ce2e91da39472f9ae9faf77c4025a872c55c74","last_commit_id":"55ce2e91da39472f9ae9faf77c4025a872c55c74","content":"LS0tCiAgQ291cnNlOgogICAgLSBTZWN0aW9uOiBEU09QIEdpdExhYgogICAgICBSZXBvczoKICAgICAgICAtIFVSTDogaHR0cHM6Ly9jb2RlLmlsMi5kc28ubWlsL2NzYWthbWFraS9wMS10ZXN0CiAgICAtIFNlY3Rpb246IGdTY2hvb2wgR2l0SHViCiAgICAgIFJlcG9zOgogICAgICAgIC0gVVJMOiBodHRwczovL2dpdGh1Yi5jb20vZ1NjaG9vbC9yZXZhY29tbS10ZXN0Cg=="}' + recorded_at: Thu, 24 Dec 2020 04:03:12 GMT - request: method: get - uri: https://code.il2.dsop.io/api/v4/projects?search=p1-test + uri: https://code.il2.dso.mil/api/v4/projects?search=p1-test body: encoding: US-ASCII string: '' @@ -157,15 +155,13 @@ http_interactions: headers: Cache-Control: - max-age=0, private, must-revalidate - Content-Length: - - '3280' Content-Type: - application/json Etag: - - W/"905a13fb3b949a706442a5f1b4b540d6" + - W/"81be7f29b8b3092ab074fadd48e9b3f2" Link: - - ; - rel="first", ; + - ; + rel="first", ; rel="last" Vary: - Origin @@ -182,27 +178,28 @@ http_interactions: X-Prev-Page: - '' X-Request-Id: - - kFr194XN4I8 + - ybXkfLYyKN1 X-Runtime: - - '0.065975' + - '0.067555' X-Total: - '1' X-Total-Pages: - '1' Date: - - Tue, 06 Oct 2020 07:37:19 GMT + - Thu, 24 Dec 2020 04:03:12 GMT X-Envoy-Upstream-Service-Time: - - '68' + - '69' Server: - istio-envoy + Transfer-Encoding: + - chunked body: encoding: UTF-8 string: '[{"id":702,"description":"","name":"p1-test","name_with_namespace":"Charlie - Sakamaki / p1-test","path":"p1-test","path_with_namespace":"csakamaki/p1-test","created_at":"2020-09-23T19:53:49.310Z","default_branch":"master","tag_list":[],"ssh_url_to_repo":"git@code.il2.dsop.io:csakamaki/p1-test.git","http_url_to_repo":"https://code.il2.dsop.io/csakamaki/p1-test.git","web_url":"https://code.il2.dsop.io/csakamaki/p1-test","readme_url":null,"avatar_url":null,"star_count":0,"forks_count":0,"last_activity_at":"2020-09-24T00:07:57.336Z","namespace":{"id":288,"name":"Charlie - Sakamaki","path":"csakamaki","kind":"user","full_path":"csakamaki","parent_id":null,"avatar_url":"https://secure.gravatar.com/avatar/ed30ad3597897901ccbd315e731bf100?s=80\u0026d=identicon","web_url":"https://code.il2.dsop.io/csakamaki"},"_links":{"self":"https://code.il2.dsop.io/api/v4/projects/702","issues":"https://code.il2.dsop.io/api/v4/projects/702/issues","merge_requests":"https://code.il2.dsop.io/api/v4/projects/702/merge_requests","repo_branches":"https://code.il2.dsop.io/api/v4/projects/702/repository/branches","labels":"https://code.il2.dsop.io/api/v4/projects/702/labels","events":"https://code.il2.dsop.io/api/v4/projects/702/events","members":"https://code.il2.dsop.io/api/v4/projects/702/members"},"empty_repo":false,"archived":false,"visibility":"private","owner":{"id":238,"name":"Charlie - Sakamaki","username":"csakamaki","state":"active","avatar_url":"https://secure.gravatar.com/avatar/ed30ad3597897901ccbd315e731bf100?s=80\u0026d=identicon","web_url":"https://code.il2.dsop.io/csakamaki"},"resolve_outdated_diff_discussions":false,"container_registry_enabled":true,"container_expiration_policy":{"cadence":"7d","enabled":true,"keep_n":null,"older_than":null,"name_regex":null,"name_regex_keep":null,"next_run_at":"2020-10-07T20:50:13.933Z"},"issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"jobs_enabled":true,"snippets_enabled":true,"can_create_merge_request_in":true,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"enabled","wiki_access_level":"enabled","builds_access_level":"enabled","snippets_access_level":"enabled","pages_access_level":"private","emails_disabled":null,"shared_runners_enabled":true,"lfs_enabled":true,"creator_id":238,"import_status":"none","open_issues_count":0,"ci_default_git_depth":50,"public_jobs":true,"build_timeout":3600,"auto_cancel_pending_pipelines":"enabled","build_coverage_regex":null,"ci_config_path":"","shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"request_access_enabled":true,"only_allow_merge_if_all_discussions_are_resolved":false,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"merge","suggestion_commit_message":null,"auto_devops_enabled":false,"auto_devops_deploy_strategy":"continuous","autoclose_referenced_issues":true,"approvals_before_merge":0,"mirror":false,"external_authorization_classification_label":null,"packages_enabled":true,"service_desk_enabled":false,"service_desk_address":null,"marked_for_deletion_at":null,"marked_for_deletion_on":null,"permissions":{"project_access":{"access_level":40,"notification_level":3},"group_access":null}}]' - http_version: - recorded_at: Tue, 06 Oct 2020 07:37:20 GMT + Sakamaki / p1-test","path":"p1-test","path_with_namespace":"csakamaki/p1-test","created_at":"2020-09-23T19:53:49.310Z","default_branch":"master","tag_list":[],"ssh_url_to_repo":"git@code.il2.dso.mil:csakamaki/p1-test.git","http_url_to_repo":"https://code.il2.dso.mil/csakamaki/p1-test.git","web_url":"https://code.il2.dso.mil/csakamaki/p1-test","readme_url":null,"avatar_url":null,"forks_count":0,"star_count":0,"last_activity_at":"2020-12-24T02:53:59.799Z","namespace":{"id":288,"name":"Charlie + Sakamaki","path":"csakamaki","kind":"user","full_path":"csakamaki","parent_id":null,"avatar_url":"https://secure.gravatar.com/avatar/ed30ad3597897901ccbd315e731bf100?s=80\u0026d=identicon","web_url":"https://code.il2.dso.mil/csakamaki"},"_links":{"self":"https://code.il2.dso.mil/api/v4/projects/702","issues":"https://code.il2.dso.mil/api/v4/projects/702/issues","merge_requests":"https://code.il2.dso.mil/api/v4/projects/702/merge_requests","repo_branches":"https://code.il2.dso.mil/api/v4/projects/702/repository/branches","labels":"https://code.il2.dso.mil/api/v4/projects/702/labels","events":"https://code.il2.dso.mil/api/v4/projects/702/events","members":"https://code.il2.dso.mil/api/v4/projects/702/members"},"packages_enabled":true,"empty_repo":false,"archived":false,"visibility":"private","owner":{"id":238,"name":"Charlie + Sakamaki","username":"csakamaki","state":"active","avatar_url":"https://secure.gravatar.com/avatar/ed30ad3597897901ccbd315e731bf100?s=80\u0026d=identicon","web_url":"https://code.il2.dso.mil/csakamaki"},"resolve_outdated_diff_discussions":false,"container_registry_enabled":true,"container_expiration_policy":{"cadence":"7d","enabled":true,"keep_n":null,"older_than":null,"name_regex":null,"name_regex_keep":null,"next_run_at":"2020-11-19T00:50:12.208Z"},"issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"jobs_enabled":true,"snippets_enabled":true,"service_desk_enabled":false,"service_desk_address":null,"can_create_merge_request_in":true,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"enabled","wiki_access_level":"enabled","builds_access_level":"enabled","snippets_access_level":"enabled","pages_access_level":"private","emails_disabled":null,"shared_runners_enabled":true,"lfs_enabled":true,"creator_id":238,"import_status":"none","open_issues_count":0,"ci_default_git_depth":50,"ci_forward_deployment_enabled":true,"public_jobs":true,"build_timeout":3600,"auto_cancel_pending_pipelines":"enabled","build_coverage_regex":null,"ci_config_path":"","shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"allow_merge_on_skipped_pipeline":null,"request_access_enabled":true,"only_allow_merge_if_all_discussions_are_resolved":false,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"merge","suggestion_commit_message":null,"auto_devops_enabled":false,"auto_devops_deploy_strategy":"continuous","autoclose_referenced_issues":true,"permissions":{"project_access":{"access_level":40,"notification_level":3},"group_access":null}}]' + recorded_at: Thu, 24 Dec 2020 04:03:12 GMT - request: method: head uri: https://api.github.com/repos/gSchool/revacomm-test @@ -214,13 +211,15 @@ http_interactions: - token 86f4c1b3eb7417dc81fe87466c5179106a6d213c User-Agent: - Galvanize Forge + Accept: + - "*/*" response: status: code: 200 message: OK headers: Date: - - Tue, 06 Oct 2020 07:37:21 GMT + - Thu, 24 Dec 2020 04:03:13 GMT Content-Type: - application/json; charset=utf-8 Content-Length: @@ -236,11 +235,11 @@ http_interactions: - Accept-Encoding - Accept-Encoding, Accept, X-Requested-With Etag: - - '"2575197bdf1788abeea33fa22b34b5e4e00fe10bb9a22582fbd0a22e3ae43d14"' + - '"8be52508cc022f98cb8fae642ff9da872b8bbe22765f95db5fe31d62d2fc1286"' Last-Modified: - Wed, 23 Sep 2020 20:21:08 GMT X-Oauth-Scopes: - - repo + - repo, workflow X-Accepted-Oauth-Scopes: - repo X-Github-Media-Type: @@ -250,7 +249,7 @@ http_interactions: X-Ratelimit-Remaining: - '4999' X-Ratelimit-Reset: - - '1601973441' + - '1608786193' X-Ratelimit-Used: - '1' Access-Control-Expose-Headers: @@ -272,10 +271,9 @@ http_interactions: Content-Security-Policy: - default-src 'none' X-Github-Request-Id: - - D9CF:6749:3F7741:4BD406:5F7C1EB0 + - CBEA:439C:161B825:1ABDF59:5FE41301 body: encoding: UTF-8 string: '' - http_version: - recorded_at: Tue, 06 Oct 2020 07:37:21 GMT -recorded_with: VCR 4.0.0 + recorded_at: Thu, 24 Dec 2020 04:03:13 GMT +recorded_with: VCR 6.0.0 diff --git a/scripts/spec/fixtures/vcr_cassettes/gitlab-not-found.yml b/scripts/spec/fixtures/vcr_cassettes/gitlab-not-found.yml index 7d3fbbb..01d3667 100644 --- a/scripts/spec/fixtures/vcr_cassettes/gitlab-not-found.yml +++ b/scripts/spec/fixtures/vcr_cassettes/gitlab-not-found.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: get - uri: https://code.il2.dsop.io/api/v4/projects?membership=true&search=does-not-exist + uri: https://code.il2.dso.mil/api/v4/projects?membership=true&search=does-not-exist body: encoding: US-ASCII string: '' @@ -29,8 +29,8 @@ http_interactions: Etag: - W/"4f53cda18c2baa0c0354bb5f9a3ecbe5" Link: - - ; - rel="first", ; + - ; + rel="first", ; rel="last" Vary: - Origin @@ -63,11 +63,11 @@ http_interactions: body: encoding: UTF-8 string: "[]" - http_version: + http_version: recorded_at: Tue, 06 Oct 2020 07:49:47 GMT - request: method: get - uri: https://code.il2.dsop.io/api/v4/projects//repository/branches/master + uri: https://code.il2.dso.mil/api/v4/projects//repository/branches/master body: encoding: US-ASCII string: '' @@ -106,6 +106,6 @@ http_interactions: body: encoding: UTF-8 string: '{"error":"404 Not Found"}' - http_version: + http_version: recorded_at: Tue, 06 Oct 2020 07:49:47 GMT recorded_with: VCR 4.0.0 diff --git a/scripts/spec/fixtures/vcr_cassettes/gitlab-success.yml b/scripts/spec/fixtures/vcr_cassettes/gitlab-success.yml index c701ecf..1b66453 100644 --- a/scripts/spec/fixtures/vcr_cassettes/gitlab-success.yml +++ b/scripts/spec/fixtures/vcr_cassettes/gitlab-success.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: get - uri: https://code.il2.dsop.io/api/v4/projects?membership=true&search=test-20200917 + uri: https://code.il2.dso.mil/api/v4/projects?membership=true&search=test-20200917 body: encoding: US-ASCII string: '' @@ -29,8 +29,8 @@ http_interactions: Etag: - W/"94af059ec19294995f506264a0cbc893" Link: - - ; - rel="first", ; + - ; + rel="first", ; rel="last" Vary: - Origin @@ -63,14 +63,14 @@ http_interactions: body: encoding: UTF-8 string: '[{"id":599,"description":"","name":"test-20200917","name_with_namespace":"Charlie - Sakamaki / test-20200917","path":"test-20200917","path_with_namespace":"csakamaki/test-20200917","created_at":"2020-09-18T20:08:10.651Z","default_branch":"master","tag_list":[],"ssh_url_to_repo":"git@code.il2.dsop.io:csakamaki/test-20200917.git","http_url_to_repo":"https://code.il2.dsop.io/csakamaki/test-20200917.git","web_url":"https://code.il2.dsop.io/csakamaki/test-20200917","readme_url":"https://code.il2.dsop.io/csakamaki/test-20200917/-/blob/master/README.md","avatar_url":null,"star_count":0,"forks_count":0,"last_activity_at":"2020-09-30T19:14:19.395Z","namespace":{"id":288,"name":"Charlie - Sakamaki","path":"csakamaki","kind":"user","full_path":"csakamaki","parent_id":null,"avatar_url":"https://secure.gravatar.com/avatar/ed30ad3597897901ccbd315e731bf100?s=80\u0026d=identicon","web_url":"https://code.il2.dsop.io/csakamaki"},"_links":{"self":"https://code.il2.dsop.io/api/v4/projects/599","issues":"https://code.il2.dsop.io/api/v4/projects/599/issues","merge_requests":"https://code.il2.dsop.io/api/v4/projects/599/merge_requests","repo_branches":"https://code.il2.dsop.io/api/v4/projects/599/repository/branches","labels":"https://code.il2.dsop.io/api/v4/projects/599/labels","events":"https://code.il2.dsop.io/api/v4/projects/599/events","members":"https://code.il2.dsop.io/api/v4/projects/599/members"},"empty_repo":false,"archived":false,"visibility":"public","owner":{"id":238,"name":"Charlie - Sakamaki","username":"csakamaki","state":"active","avatar_url":"https://secure.gravatar.com/avatar/ed30ad3597897901ccbd315e731bf100?s=80\u0026d=identicon","web_url":"https://code.il2.dsop.io/csakamaki"},"resolve_outdated_diff_discussions":false,"container_registry_enabled":true,"container_expiration_policy":{"cadence":"7d","enabled":true,"keep_n":null,"older_than":null,"name_regex":null,"name_regex_keep":null,"next_run_at":"2020-10-09T20:50:21.090Z"},"issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"jobs_enabled":true,"snippets_enabled":true,"can_create_merge_request_in":true,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"enabled","wiki_access_level":"enabled","builds_access_level":"enabled","snippets_access_level":"enabled","pages_access_level":"enabled","emails_disabled":null,"shared_runners_enabled":true,"lfs_enabled":true,"creator_id":238,"import_status":"none","open_issues_count":0,"ci_default_git_depth":50,"public_jobs":true,"build_timeout":3600,"auto_cancel_pending_pipelines":"enabled","build_coverage_regex":null,"ci_config_path":"","shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"request_access_enabled":true,"only_allow_merge_if_all_discussions_are_resolved":false,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"merge","suggestion_commit_message":null,"auto_devops_enabled":false,"auto_devops_deploy_strategy":"continuous","autoclose_referenced_issues":true,"approvals_before_merge":0,"mirror":false,"external_authorization_classification_label":null,"packages_enabled":true,"service_desk_enabled":false,"service_desk_address":null,"marked_for_deletion_at":null,"marked_for_deletion_on":null,"permissions":{"project_access":{"access_level":40,"notification_level":3},"group_access":null}}]' - http_version: + Sakamaki / test-20200917","path":"test-20200917","path_with_namespace":"csakamaki/test-20200917","created_at":"2020-09-18T20:08:10.651Z","default_branch":"master","tag_list":[],"ssh_url_to_repo":"git@code.il2.dso.mil:csakamaki/test-20200917.git","http_url_to_repo":"https://code.il2.dso.mil/csakamaki/test-20200917.git","web_url":"https://code.il2.dso.mil/csakamaki/test-20200917","readme_url":"https://code.il2.dso.mil/csakamaki/test-20200917/-/blob/master/README.md","avatar_url":null,"star_count":0,"forks_count":0,"last_activity_at":"2020-09-30T19:14:19.395Z","namespace":{"id":288,"name":"Charlie + Sakamaki","path":"csakamaki","kind":"user","full_path":"csakamaki","parent_id":null,"avatar_url":"https://secure.gravatar.com/avatar/ed30ad3597897901ccbd315e731bf100?s=80\u0026d=identicon","web_url":"https://code.il2.dso.mil/csakamaki"},"_links":{"self":"https://code.il2.dso.mil/api/v4/projects/599","issues":"https://code.il2.dso.mil/api/v4/projects/599/issues","merge_requests":"https://code.il2.dso.mil/api/v4/projects/599/merge_requests","repo_branches":"https://code.il2.dso.mil/api/v4/projects/599/repository/branches","labels":"https://code.il2.dso.mil/api/v4/projects/599/labels","events":"https://code.il2.dso.mil/api/v4/projects/599/events","members":"https://code.il2.dso.mil/api/v4/projects/599/members"},"empty_repo":false,"archived":false,"visibility":"public","owner":{"id":238,"name":"Charlie + Sakamaki","username":"csakamaki","state":"active","avatar_url":"https://secure.gravatar.com/avatar/ed30ad3597897901ccbd315e731bf100?s=80\u0026d=identicon","web_url":"https://code.il2.dso.mil/csakamaki"},"resolve_outdated_diff_discussions":false,"container_registry_enabled":true,"container_expiration_policy":{"cadence":"7d","enabled":true,"keep_n":null,"older_than":null,"name_regex":null,"name_regex_keep":null,"next_run_at":"2020-10-09T20:50:21.090Z"},"issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"jobs_enabled":true,"snippets_enabled":true,"can_create_merge_request_in":true,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"enabled","wiki_access_level":"enabled","builds_access_level":"enabled","snippets_access_level":"enabled","pages_access_level":"enabled","emails_disabled":null,"shared_runners_enabled":true,"lfs_enabled":true,"creator_id":238,"import_status":"none","open_issues_count":0,"ci_default_git_depth":50,"public_jobs":true,"build_timeout":3600,"auto_cancel_pending_pipelines":"enabled","build_coverage_regex":null,"ci_config_path":"","shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"request_access_enabled":true,"only_allow_merge_if_all_discussions_are_resolved":false,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"merge","suggestion_commit_message":null,"auto_devops_enabled":false,"auto_devops_deploy_strategy":"continuous","autoclose_referenced_issues":true,"approvals_before_merge":0,"mirror":false,"external_authorization_classification_label":null,"packages_enabled":true,"service_desk_enabled":false,"service_desk_address":null,"marked_for_deletion_at":null,"marked_for_deletion_on":null,"permissions":{"project_access":{"access_level":40,"notification_level":3},"group_access":null}}]' + http_version: recorded_at: Tue, 06 Oct 2020 07:55:51 GMT - request: method: get - uri: https://code.il2.dsop.io/api/v4/projects/599/repository/branches/master + uri: https://code.il2.dso.mil/api/v4/projects/599/repository/branches/master body: encoding: US-ASCII string: '' @@ -116,12 +116,12 @@ http_interactions: encoding: UTF-8 string: '{"name":"master","commit":{"id":"0d3ccb796757d84e99dcf43ef913821483a248a0","short_id":"0d3ccb79","created_at":"2020-09-30T09:12:44.000-10:00","parent_ids":["1ff934599cfdc0f21efe3d524609aec8c73b0632"],"title":"add python-simple","message":"add python-simple\n","author_name":"Charlie Sakamaki","author_email":"csakamaki@revacomm.com","authored_date":"2020-09-30T09:12:44.000-10:00","committer_name":"Charlie - Sakamaki","committer_email":"csakamaki@revacomm.com","committed_date":"2020-09-30T09:12:44.000-10:00","web_url":"https://code.il2.dsop.io/csakamaki/test-20200917/-/commit/0d3ccb796757d84e99dcf43ef913821483a248a0"},"merged":false,"protected":true,"developers_can_push":false,"developers_can_merge":false,"can_push":true,"default":true,"web_url":"https://code.il2.dsop.io/csakamaki/test-20200917/-/tree/master"}' - http_version: + Sakamaki","committer_email":"csakamaki@revacomm.com","committed_date":"2020-09-30T09:12:44.000-10:00","web_url":"https://code.il2.dso.mil/csakamaki/test-20200917/-/commit/0d3ccb796757d84e99dcf43ef913821483a248a0"},"merged":false,"protected":true,"developers_can_push":false,"developers_can_merge":false,"can_push":true,"default":true,"web_url":"https://code.il2.dso.mil/csakamaki/test-20200917/-/tree/master"}' + http_version: recorded_at: Tue, 06 Oct 2020 07:55:52 GMT - request: method: get - uri: https://code.il2.dsop.io/api/v4/projects/599/repository/archive.zip + uri: https://code.il2.dso.mil/api/v4/projects/599/repository/archive.zip body: encoding: US-ASCII string: '' @@ -173,6 +173,6 @@ http_interactions: encoding: ASCII-8BIT string: !binary |- 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Y291cnNlZmlsZXMvVVQFAAGs2HRfUEsDBAoAAAAAAJaZPlEAAAAAAAAAAAAAAABRAAkAdGVzdC0yMDIwMDkxNy1tYXN0ZXItMGQzY2NiNzk2NzU3ZDg0ZTk5ZGNmNDNlZjkxMzgyMTQ4M2EyNDhhMC9jb3Vyc2VmaWxlcy9naXRodWIvVVQFAAGs2HRfUEsDBAoAAAAIAJaZPlHw+naYXQAAAHUAAABcAAkAdGVzdC0yMDIwMDkxNy1tYXN0ZXItMGQzY2NiNzk2NzU3ZDg0ZTk5ZGNmNDNlZjkxMzgyMTQ4M2EyNDhhMC9jb3Vyc2VmaWxlcy9naXRodWIvY291cnNlLnlhbWxVVAUAAazYdF81ijsOgCAQRHtOMRdYie22tlYYD6BmIyQiBFbP7ydazZs3Y4jIAF06ShW+CSAMsmhIO/+A9h0AJzlV/srzHF3P8Kq5srVrUH/MzZKidXJOd8bOT2ULYlWqUvmkuQBQSwMECgAAAAAAlpk+UQAAAAAAAAAAAAAAAFEACQB0ZXN0LTIwMjAwOTE3LW1hc3Rlci0wZDNjY2I3OTY3NTdkODRlOTlkY2Y0M2VmOTEzODIxNDgzYTI0OGEwL2NvdXJzZWZpbGVzL2dpdGxhYi9VVAUAAazYdF9QSwMECgAAAAgAlpk+Uc9Kmm1jAAAAdQAAAFwACQB0ZXN0LTIwMjAwOTE3LW1hc3Rlci0wZDNjY2I3OTY3NTdkODRlOTlkY2Y0M2VmOTEzODIxNDgzYTI0OGEwL2NvdXJzZWZpbGVzL2dpdGxhYi9jb3Vyc2UueWFtbFVUBQABrNh0XzWKOw4CMQwF+5ziXcBJNg3CLS3VIg4QZS0RLeAIe+/PR2w3o5lARAE46fYy4Q8BhIs07/rkHTD9AjDLUOO/fM/rfGbc3IdxSk0Xif1e4mI6YtfUrK71UdeeXMyp5JLzcTqEN1BLAwQKAAAACACWmT5RoKr04p4BAAAfAwAATgAJAHRlc3QtMjAyMDA5MTctbWFzdGVyLTBkM2NjYjc5Njc1N2Q4NGU5OWRjZjQzZWY5MTM4MjE0ODNhMjQ4YTAvcHl0aG9uLXNpbXBsZS5tZFVUBQABrNh0X2VTTXObMBC961dsh+kMzgCTxDZ2fE2bX5BLT0aGxWgqJKKPafn33Q3Y2KkuSG/fvt23QkmSwLe6k1qjOaMQDxDGAQ9Q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c3QtMjAyMDA5MTctbWFzdGVyLTBkM2NjYjc5Njc1N2Q4NGU5OWRjZjQzZWY5MTM4MjE0ODNhMjQ4YTAvY2hlY2twb2ludC5tZFVUBQABrNh0X1BLAQIAAAoAAAAIAJaZPlE+YPWdeAEAANwCAABJAAkAAAAAAAEAAAAAAEgIAAB0ZXN0LTIwMjAwOTE3LW1hc3Rlci0wZDNjY2I3OTY3NTdkODRlOTlkY2Y0M2VmOTEzODIxNDgzYTI0OGEwL2NvbmZpZy55YW1sVVQFAAGs2HRfUEsBAgAACgAAAAAAlpk+UQAAAAAAAAAAAAAAAEoACQAAAAAAAAAQAAAAMAoAAHRlc3QtMjAyMDA5MTctbWFzdGVyLTBkM2NjYjc5Njc1N2Q4NGU5OWRjZjQzZWY5MTM4MjE0ODNhMjQ4YTAvY291cnNlZmlsZXMvVVQFAAGs2HRfUEsBAgAACgAAAAAAlpk+UQAAAAAAAAAAAAAAAFEACQAAAAAAAAAQAAAAoQoAAHRlc3QtMjAyMDA5MTctbWFzdGVyLTBkM2NjYjc5Njc1N2Q4NGU5OWRjZjQzZWY5MTM4MjE0ODNhMjQ4YTAvY291cnNlZmlsZXMvZ2l0aHViL1VUBQABrNh0X1BLAQIAAAoAAAAIAJaZPlHw+naYXQAAAHUAAABcAAkAAAAAAAEAAAAAABkLAAB0ZXN0LTIwMjAwOTE3LW1hc3Rlci0wZDNjY2I3OTY3NTdkODRlOTlkY2Y0M2VmOTEzODIxNDgzYTI0OGEwL2NvdXJzZWZpbGVzL2dpdGh1Yi9jb3Vyc2UueWFtbFVUBQABrNh0X1BLAQIAAAoAAAAAAJaZPlEAAAAAAAAAAAAAAABRAAkAAAAAAAAAEAAAAPkLAAB0ZXN0LTIwMjAwOTE3LW1hc3Rlci0wZDNjY2I3OTY3NTdkODRlOTlkY2Y0M2VmOTEzODIxNDgzYTI0OGEwL2NvdXJzZWZpbGVzL2dpdGxhYi9VVAUAAazYdF9QSwECAAAKAAAACACWmT5Rz0qabWMAAAB1AAAAXAAJAAAAAAABAAAAAABxDAAAdGVzdC0yMDIwMDkxNy1tYXN0ZXItMGQzY2NiNzk2NzU3ZDg0ZTk5ZGNmNDNlZjkxMzgyMTQ4M2EyNDhhMC9jb3Vyc2VmaWxlcy9naXRsYWIvY291cnNlLnlhbWxVVAUAAazYdF9QSwECAAAKAAAACACWmT5RoKr04p4BAAAfAwAATgAJAAAAAAABAAAAAABXDQAAdGVzdC0yMDIwMDkxNy1tYXN0ZXItMGQzY2NiNzk2NzU3ZDg0ZTk5ZGNmNDNlZjkxMzgyMTQ4M2EyNDhhMC9weXRob24tc2ltcGxlLm1kVVQFAAGs2HRfUEsBAgAACgAAAAgAlpk+URN/NXSBAwAAIwgAAE4ACQAAAAAAAQAAAAAAag8AAHRlc3QtMjAyMDA5MTctbWFzdGVyLTBkM2NjYjc5Njc1N2Q4NGU5OWRjZjQzZWY5MTM4MjE0ODNhMjQ4YTAvcmV2YWNvbW0tcXVpei5tZFVUBQABrNh0X1BLBQYAAAAADAAMAEsGAABgEwAAKAAwZDNjY2I3OTY3NTdkODRlOTlkY2Y0M2VmOTEzODIxNDgzYTI0OGEw - http_version: + http_version: recorded_at: Tue, 06 Oct 2020 07:55:52 GMT recorded_with: VCR 4.0.0 diff --git a/scripts/spec/services/course_validator_spec.rb b/scripts/spec/services/course_validator_spec.rb index f873719..3abaad2 100644 --- a/scripts/spec/services/course_validator_spec.rb +++ b/scripts/spec/services/course_validator_spec.rb @@ -28,8 +28,8 @@ describe CourseValidator do end it "works when the course yaml file comes from gitlab sources" do - VCR.use_cassette("gitlab-course-yaml-success") do - result = described_class.run(url: "https://code.il2.dsop.io/csakamaki/p1-test/-/blob/master/course.yaml") + VCR.use_cassette("gitlab-course-yaml-success" ) do + result = described_class.run(url: "https://code.il2.dso.mil/csakamaki/p1-test/-/blob/master/course.yaml") expect(result).to be_a_success expect(result.value[:course]).to eq({ default_unit_visibility: false, @@ -37,7 +37,7 @@ describe CourseValidator do { title: "DSOP GitLab", repos: [ - { url: "https://code.il2.dsop.io/csakamaki/p1-test" } + { url: "https://code.il2.dso.mil/csakamaki/p1-test" } ] }, { @@ -54,7 +54,7 @@ describe CourseValidator do it "fetches from branches and fails when repos are missing in the yaml" do VCR.use_cassette("gitlab-course-yaml-branch-failure") do - result = described_class.run(url: "https://code.il2.dsop.io/csakamaki/p1-test/-/blob/missingfile/course.yaml") + result = described_class.run(url: "https://code.il2.dso.mil/csakamaki/p1-test/-/blob/missingfile/course.yaml") expect(result).to be_a_failure expect(result.value.type).to eq :top_course_http_fetch_error end diff --git a/scripts/spec/services/download_repository_service_spec.rb b/scripts/spec/services/download_repository_service_spec.rb index 2ef54a8..95f0558 100644 --- a/scripts/spec/services/download_repository_service_spec.rb +++ b/scripts/spec/services/download_repository_service_spec.rb @@ -51,7 +51,7 @@ describe DownloadRepositoryService do describe ".execute" do context "when provided an invalid gitlab url" do - let(:block) { create(:block, org: "not-found", origin: "code.il2.dsop.io", repo_name: "does-not-exist")} + let(:block) { create(:block, org: "not-found", origin: "code.il2.dso.mil", repo_name: "does-not-exist")} it "returns an error" do VCR.use_cassette("gitlab-not-found") do diff --git a/scripts/spec/services/git_url_service_spec.rb b/scripts/spec/services/git_url_service_spec.rb index 8ec13b3..f886208 100644 --- a/scripts/spec/services/git_url_service_spec.rb +++ b/scripts/spec/services/git_url_service_spec.rb @@ -157,7 +157,7 @@ describe GitUrlService do describe "subgroup gitlab url" do context "for a project with a branch" do - let(:url) { "https://code.il2.dsop.io/tron/products/learn-lms/microservices/forge/-/tree/keycloak-auth" } + let(:url) { "https://code.il2.dso.mil/tron/products/learn-lms/microservices/forge/-/tree/keycloak-auth" } it "gets the correct repo" do expect(subject.repository).to eq("forge") @@ -181,7 +181,7 @@ describe GitUrlService do end context "for a project with a file specified" do - let(:url) { "https://code.il2.dsop.io/tron/products/learn-lms/microservices/forge/-/blob/master/config/environment.rb" } + let(:url) { "https://code.il2.dso.mil/tron/products/learn-lms/microservices/forge/-/blob/master/config/environment.rb" } it "returns a full path without file information" do expect(subject.full_path).to eq("tron/products/learn-lms/microservices/forge") @@ -193,7 +193,7 @@ describe GitUrlService do end context "for a project with just a repository" do - let(:url) { "https://code.il2.dsop.io/tron/products/learn-lms/microservices/forge" } + let(:url) { "https://code.il2.dso.mil/tron/products/learn-lms/microservices/forge" } it "returns a full path without file information" do expect(subject.full_path).to eq("tron/products/learn-lms/microservices/forge") diff --git a/scripts/spec/services/platform_one_auth_resolver_service_spec.rb b/scripts/spec/services/platform_one_auth_resolver_service_spec.rb index cf0f3f2..d84b723 100644 --- a/scripts/spec/services/platform_one_auth_resolver_service_spec.rb +++ b/scripts/spec/services/platform_one_auth_resolver_service_spec.rb @@ -8,7 +8,7 @@ describe PlatformOneAuthResolverService do iat: Time.now.to_i, auth_time: Time.now.to_i, jti: "e4600f88-1b42-4e01-ac01-8646d3cc4df6", - iss: "https://login.dsop.io/auth/realms/baby-yoda", + iss: "https://login.dso.mil/auth/realms/baby-yoda", aud: "il4_191f836b-ec50-4819-ba10-1afaa5b99600_mission-widow", sub: "2cba6ea8-8451-4952-80d6-c7de379d5b7e", typ: "ID", @@ -55,7 +55,7 @@ describe PlatformOneAuthResolverService do iat: Time.now.to_i, auth_time: Time.now.to_i, jti: "e4600f88-1b42-4e01-ac01-8646d3cc4df6", - iss: "https://login.dsop.io/auth/realms/baby-yoda", + iss: "https://login.dso.mil/auth/realms/baby-yoda", aud: "il4_191f836b-ec50-4819-ba10-1afaa5b99600_mission-widow", sub: "2cba6ea8-8451-4952-80d6-c7de379d5b7e", typ: "ID", -- GitLab From 24af98b00b43fb027e17fc6a14dcf23f793556e0 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Wed, 30 Dec 2020 10:40:43 -1000 Subject: [PATCH 221/283] updating secrets to match minio credentials Former-commit-id: e774b49cd8bb743d4aca0407dbcf4c1c1ff0b0e5 --- scripts/.env.example | 6 +++++- scripts/app.json | 2 +- scripts/config/secrets.yml | 9 +++++---- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/scripts/.env.example b/scripts/.env.example index 2ad408f..7759360 100644 --- a/scripts/.env.example +++ b/scripts/.env.example @@ -10,4 +10,8 @@ STANDARD_EVENT_UIDS="40f3bb48-1d23-4105-a22a-7f07b90bd1e6,cc22ef7e-d9c9-4e3d-ae9 S3_REGION=us-gov-west-1 accesskey= secretkey= -appS3BucketUUID= \ No newline at end of file +appS3BucketUUID= +S3_BUCKET= +host= +port= +protocol= \ No newline at end of file diff --git a/scripts/app.json b/scripts/app.json index 8384ccf..d825267 100644 --- a/scripts/app.json +++ b/scripts/app.json @@ -79,7 +79,7 @@ "MIXPANEL_PROJECT_TOKEN": { "required": true }, - "PROTOCOL": { + "FORGE_PROTOCOL": { "required": true }, "RACK_ENV": { diff --git a/scripts/config/secrets.yml b/scripts/config/secrets.yml index c989a87..1743ee0 100644 --- a/scripts/config/secrets.yml +++ b/scripts/config/secrets.yml @@ -10,8 +10,9 @@ shared: auth_webhook_token: <%= ENV["AUTH_WEBHOOK_TOKEN"] %> github_token: <%= ENV["GITHUB_COM_TOKEN"] %> mixpanel_project_token: <%= ENV["MIXPANEL_PROJECT_TOKEN"] %> - protocol: <%= ENV['PROTOCOL'] || "http://" %> - s3_bucket_name: <%= ENV["APP_S3_BUCKET"] || "temp" %> + protocol: <%= ENV['FORGE_PROTOCOL'] || "http://" %> + s3_bucket_name: <%= ENV["S3_BUCKET"] ? (ENV["appS3BucketUUID"] ? "#{ENV["S3_BUCKET"]}-#{ENV["appS3BucketUUID"]}" : ENV["S3_BUCKET"]) : "temp" %> + s3_bucket_uuid: <% ENV["appS3BucketUUID"] %>> secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> sendgrid_password: <%= ENV['SENDGRID_PASSWORD'] %> sendgrid_username: <%= ENV['SENDGRID_USERNAME'] %> @@ -24,10 +25,10 @@ shared: glearn_access_key_id: <%= ENV['accesskey'] || "temp" %> glearn_secret_access_key: <%= ENV['secretkey'] || "temp" %> glearn_key_prefix: <%= ENV['GLEARN_KEY_PREFIX'] || "forge" %> - glearn_bucket_name: <%= ENV["APP_S3_BUCKET"] || "temp" %> + glearn_bucket_name: <%= ENV["S3_BUCKET"] ? (ENV["appS3BucketUUID"] ? "#{ENV["S3_BUCKET"]}-#{ENV["appS3BucketUUID"]}" : ENV["S3_BUCKET"]) : "temp" %> s3_region: <%= ENV["S3_REGION"] || "us-gov-west-1" %> dev_notify_slack_url: <%= ENV['DEV_NOTIFY_SLACK_URL'] %> - minio_endpoint_url: <%= ENV["MINIO_ENDPOINT_URL"] %> + minio_endpoint_url: <%= (ENV["protocol"] && ENV["host"] && ENV["port"]) ? "#{ENV["protocol"]}://#{ENV["host"]}:#{ENV["port"]}" : nil %> git_download_tokens: github_com: type: github -- GitLab From 1ac1b36b236a12fb42cd1afbc0bb6ece929ddd9e Mon Sep 17 00:00:00 2001 From: Charlie Sakamaki Date: Wed, 30 Dec 2020 10:55:46 -1000 Subject: [PATCH 222/283] Add delay for intermittent failing tests Former-commit-id: 3d936bb779763ec07c957ea9302a274c9bc370b4 --- scripts/spec/features/cohorts/users/challenges_feature_spec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/spec/features/cohorts/users/challenges_feature_spec.rb b/scripts/spec/features/cohorts/users/challenges_feature_spec.rb index 8db44db..5a0c787 100644 --- a/scripts/spec/features/cohorts/users/challenges_feature_spec.rb +++ b/scripts/spec/features/cohorts/users/challenges_feature_spec.rb @@ -126,6 +126,7 @@ describe "Challenges" do within("#challenge_#{challenge_2.id}") do within(".challenge-grading-buttons") do find(".incorrect-status").click + sleep 1 within(".status-section") do find(".incorrect-check") end @@ -140,7 +141,7 @@ describe "Challenges" do within("#challenge_#{challenge_2.id}") do within(".challenge-grading-buttons") do find(".correct-status").click - + sleep 1 within(".status-section") do find(".correct-check") end -- GitLab From 520db999abb7ecb38b24819190f1fa03a17d1795 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Wed, 20 Jan 2021 20:06:58 -1000 Subject: [PATCH 223/283] adding license Former-commit-id: 6579d2a4b2b6582cf5455b99ef4f0172d12cdd88 --- LICENSE | 1 - 1 file changed, 1 deletion(-) diff --git a/LICENSE b/LICENSE index e9db0f7..e69de29 100644 --- a/LICENSE +++ b/LICENSE @@ -1 +0,0 @@ -Please add a license \ No newline at end of file -- GitLab From 6e86df85c9620c318568501390d5bb9e1c5f9b92 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Wed, 20 Jan 2021 20:18:30 -1000 Subject: [PATCH 224/283] adding license Former-commit-id: 0007f2f5395208e3cfa0aeed6fcf423c9aaff88f --- LICENSE | 27 +++++++++++++++++++++++++++ hardening_manifest.yaml | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index e69de29..6b1e578 100644 --- a/LICENSE +++ b/LICENSE @@ -0,0 +1,27 @@ +Copyright 2021. Galvanize Inc. Galvanize Inc. proprietary and confidential. Do not distribute. + +A commercial license will be required to run an instance (or any copy or derivative thereof) of this software and the +learning management system (the "Software"). Purchase of a license will be facilitated by contacting +legal@galvanize.com. Use of the Software is prohibited without a commercial license. By way of example, but not +limitation, without a commercial license, you may not use the Software in any way or at any time, either directly or +indirectly, including but not limited to, you may not at any time, attempt, directly or indirectly, or allow any third +party to attempt to (i) copy, modify, or create derivative works of the Software, in whole or in part; (ii) use, rent, +lease, lend, sell, license, sublicense, assign, distribute, publish, transfer, or otherwise make available the Software; +(iii) reverse engineer, disassemble, decompile, decode, adapt, or otherwise attempt to derive or gain access to any +software component of the Software, in whole or in part; (iv) remove any proprietary notices from the Software; +or (v) use the Software in any manner or for any purpose that infringes, misappropriates, or otherwise violates any +intellectual property right or other right of any person, or that violates any applicable law. THE SOFTWARE IS PROVIDED +"AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL GALVANIZE, THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +FURTHER, IN NO EVENT WILL GALVANIZE, THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE UNDER OR IN CONNECTION WITH THIS +AGREEMENT UNDER ANY LEGAL OR EQUITABLE THEORY, INCLUDING BREACH OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT +LIABILITY, AND OTHERWISE, FOR ANY: (a) CONSEQUENTIAL, INCIDENTAL, INDIRECT, EXEMPLARY, SPECIAL, ENHANCED, OR PUNITIVE +DAMAGES; (b) INCREASED COSTS, DIMINUTION IN VALUE OR LOST BUSINESS, PRODUCTION, REVENUES, OR PROFITS; (c) LOSS OF +GOODWILL OR REPUTATION; (d) USE, INABILITY TO USE, LOSS, INTERRUPTION, DELAY OR RECOVERY OF ANY DATA, OR BREACH OF +DATA OR SYSTEM SECURITY; (e) COST OF REPLACEMENT GOODS OR SERVICES; OR (f) ANY DIRECT DAMAGES, INCLUDING ANY LIABILITY +ARISING OUT OF OR RELATED TO THIS AGREEMENT UNDER ANY LEGAL OR EQUITABLE THEORY, INCLUDING BREACH OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), OR STRICT LIABILITY, IN EACH CASE REGARDLESS OF WHETHER GALVANIZE, THE AUTHORS OR +COPYRIGHT HOLDERS WAS ADVISED OF THE POSSIBILITY OF SUCH LOSSES OR DAMAGES OR SUCH LOSSES OR DAMAGES WERE OTHERWISE +FORESEEABLE. \ No newline at end of file diff --git a/hardening_manifest.yaml b/hardening_manifest.yaml index 5286f6d..a3c8ba9 100644 --- a/hardening_manifest.yaml +++ b/hardening_manifest.yaml @@ -22,7 +22,7 @@ labels: ## Human-readable description of the software packaged in the image org.opencontainers.image.description: "Galvanize is a technology ecosystem for learners, entrepreneurs, startups, and established companies that meets the needs of the rapidly changing digital world. Our goal is to transform individuals and teams through effective education and community programs Delivering exceptional outcomes Coalescing and nurturing a community of innovators anchored by our campuses" ## License(s) under which contained software is distributed - # org.opencontainers.image.licenses: "FIXME" + org.opencontainers.image.licenses: "proprietary" ## URL to find more information on the image # org.opencontainers.image.url: "FIXME" ## Name of the distributing entity, organization or individual -- GitLab From d2392bfd3820be4d3c0c4502f5b893a3f8b1e520 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Wed, 20 Jan 2021 20:25:47 -1000 Subject: [PATCH 225/283] filling in rest of params. Former-commit-id: c931b9523e771f4a62131ee6bfc5cfd0ec106c8c --- hardening_manifest.yaml | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/hardening_manifest.yaml b/hardening_manifest.yaml index a3c8ba9..62189ba 100644 --- a/hardening_manifest.yaml +++ b/hardening_manifest.yaml @@ -19,20 +19,13 @@ args: # Docker image labels labels: org.opencontainers.image.title: "forge" - ## Human-readable description of the software packaged in the image org.opencontainers.image.description: "Galvanize is a technology ecosystem for learners, entrepreneurs, startups, and established companies that meets the needs of the rapidly changing digital world. Our goal is to transform individuals and teams through effective education and community programs Delivering exceptional outcomes Coalescing and nurturing a community of innovators anchored by our campuses" - ## License(s) under which contained software is distributed - org.opencontainers.image.licenses: "proprietary" - ## URL to find more information on the image - # org.opencontainers.image.url: "FIXME" - ## Name of the distributing entity, organization or individual + org.opencontainers.image.licenses: "proprietary" + org.opencontainers.image.url: "https://www.galvanize.com" org.opencontainers.image.vendor: "Galvanize" org.opencontainers.image.version: "0.1.0" - ## Keywords to help with search (ex. "cicd,gitops,golang") mil.dso.ironbank.image.keywords: "learn,lms,galvanize,online,remote,school,learning" - ## This value can be "opensource" or "commercial" mil.dso.ironbank.image.type: "commercial" - ## Product the image belongs to for grouping multiple images mil.dso.ironbank.product.name: "Learn" # List of project maintainers -- GitLab From 1bc0015332ec7aa37c440bdb29f5092fb7fb0a44 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Wed, 20 Jan 2021 20:29:42 -1000 Subject: [PATCH 226/283] fixing spacing Former-commit-id: a44c631272ffd9b0f6dc95cdd8ac797f04436568 --- hardening_manifest.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hardening_manifest.yaml b/hardening_manifest.yaml index 62189ba..c7a2652 100644 --- a/hardening_manifest.yaml +++ b/hardening_manifest.yaml @@ -21,7 +21,7 @@ labels: org.opencontainers.image.title: "forge" org.opencontainers.image.description: "Galvanize is a technology ecosystem for learners, entrepreneurs, startups, and established companies that meets the needs of the rapidly changing digital world. Our goal is to transform individuals and teams through effective education and community programs Delivering exceptional outcomes Coalescing and nurturing a community of innovators anchored by our campuses" org.opencontainers.image.licenses: "proprietary" - org.opencontainers.image.url: "https://www.galvanize.com" + org.opencontainers.image.url: "https://www.galvanize.com" org.opencontainers.image.vendor: "Galvanize" org.opencontainers.image.version: "0.1.0" mil.dso.ironbank.image.keywords: "learn,lms,galvanize,online,remote,school,learning" -- GitLab From a1ae76f22b80ff6d7e4eb6b7c738292f81d9f7cf Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Thu, 21 Jan 2021 10:18:50 -1000 Subject: [PATCH 227/283] fixing for ironbank Former-commit-id: cbd2592cfe7db19cc20c7f86ce3e4bba9a27e5fd --- Dockerfile | 5 ----- hardening_manifest.yaml | 6 +++--- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1489bcb..98565aa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,3 @@ -# Platform 1 Pipeline Settings -ARG BASE_REGISTRY=registry.il2.dso.mil -ARG BASE_IMAGE=platform-one/devops/pipeline-templates/ironbank/ruby26 -ARG BASE_TAG=2.6.6.212 - FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} USER 0 diff --git a/hardening_manifest.yaml b/hardening_manifest.yaml index c7a2652..87f83e3 100644 --- a/hardening_manifest.yaml +++ b/hardening_manifest.yaml @@ -2,7 +2,7 @@ apiVersion: v1 # The repository name in registry1, excluding /ironbank/ -name: "forge" +name: "galvanize/galvanize/forge" # List of tags to push for the repository in registry1 # The most specific version should be the first tag and will be shown @@ -13,8 +13,8 @@ tags: # Build args passed to Dockerfile ARGs args: - BASE_IMAGE: "ironbank/opensource/ruby/ruby26" - BASE_TAG: "2.6.6.212" + BASE_IMAGE: "opensource/ruby/ruby26" + BASE_TAG: "2.6.6" # Docker image labels labels: -- GitLab From 212760cb1d008f62a4108f1c5d5dbf90640dd8c6 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Thu, 21 Jan 2021 16:50:35 -1000 Subject: [PATCH 228/283] updating node modules and node version Former-commit-id: c4c081c6e5521e3869c54b9a3671097f381fc60f --- Dockerfile | 6 +- scripts/.nvmrc | 2 +- ...e-v14.15.4-linux-x64.tar.gz.REMOVED.git-id | 1 + ...de-v14.8.0-linux-x64.tar.gz.REMOVED.git-id | 1 - scripts/package.json | 68 +- scripts/yarn.lock | 620 +++++++++++------- 6 files changed, 405 insertions(+), 293 deletions(-) create mode 100644 scripts/bundles/node-v14.15.4-linux-x64.tar.gz.REMOVED.git-id delete mode 100644 scripts/bundles/node-v14.8.0-linux-x64.tar.gz.REMOVED.git-id diff --git a/Dockerfile b/Dockerfile index 98565aa..817917c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,9 +37,9 @@ RUN rm node_modules.tar.gz RUN mv node_modules /app/node_modules # Node.js -RUN tar xzf node-v14.8.0-linux-x64.tar.gz -RUN rm node-v14.8.0-linux-x64.tar.gz -RUN mv node-v14.8.0-linux-x64 /app/nodejs +RUN tar xzf node-v14.15.4-linux-x64.tar.gz +RUN rm node-v14.15.4-linux-x64.tar.gz +RUN mv node-v14.15.4-linux-x64 /app/nodejs # Yarn RUN tar xzf yarn-v1.22.5.tar.gz diff --git a/scripts/.nvmrc b/scripts/.nvmrc index a34fffa..47266f8 100644 --- a/scripts/.nvmrc +++ b/scripts/.nvmrc @@ -1 +1 @@ -14.8.0 \ No newline at end of file +14.15.4 \ No newline at end of file diff --git a/scripts/bundles/node-v14.15.4-linux-x64.tar.gz.REMOVED.git-id b/scripts/bundles/node-v14.15.4-linux-x64.tar.gz.REMOVED.git-id new file mode 100644 index 0000000..e1ab22e --- /dev/null +++ b/scripts/bundles/node-v14.15.4-linux-x64.tar.gz.REMOVED.git-id @@ -0,0 +1 @@ +95016bc120595a9214116f158624cf9ea07e7cb8 \ No newline at end of file diff --git a/scripts/bundles/node-v14.8.0-linux-x64.tar.gz.REMOVED.git-id b/scripts/bundles/node-v14.8.0-linux-x64.tar.gz.REMOVED.git-id deleted file mode 100644 index 937094b..0000000 --- a/scripts/bundles/node-v14.8.0-linux-x64.tar.gz.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -eda96a7b40acb7ed21dabc8f89fb50627cea38b6 \ No newline at end of file diff --git a/scripts/package.json b/scripts/package.json index 099c822..b6d54dd 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -16,11 +16,14 @@ "url": "https://github.com/Galvanize-IT/forge/issues" }, "homepage": "https://github.com/Galvanize-IT/forge#readme", + "engines": { + "node": "14.15.4" + }, "dependencies": { "@rails/webpacker": "5.2.1", "@types/react-paginate": "^6.2.1", - "@types/react-pdf": "^4.0.6", - "@vimeo/player": "^2.14.0", + "@types/react-pdf": "^5.0.1", + "@vimeo/player": "^2.15.0", "babel-preset-react": "^6.24.1", "brace": "^0.11.1", "browserify": "^16.5.2", @@ -28,59 +31,56 @@ "dropzone": "^5.7.2", "highlightjs": "^9.16.2", "immutability-helper": "^3.1.1", - "lodash-es": "^4.17.15", - "marked": "^1.2.0", - "moment": "2.29.1", - "moment-timezone": "0.5.31", + "lodash-es": "^4.17.20", + "marked": "^1.2.7", + "moment": "^2.29.1", + "moment-timezone": "^0.5.32", "objectify-array": "^2.1.0", "popper.js": "^1.16.1", "prop-types": "^15.7.2", "rc-slider": "Galvanize-IT/slider#c569ca3b11979aced8306e6c02f37466cb7cd365", - "react": "^16.13.1", + "react": "^17.0.1", "react-addons-css-transition-group": "^15.6.2", "react-addons-test-utils": "^15.6.2", "react-beautiful-dnd": "^13.0.0", - "react-copy-to-clipboard": "^5.0.2", - "react-datepicker": "^3.2.2", - "react-dom": "^16.13.1", + "react-copy-to-clipboard": "^5.0.3", + "react-datepicker": "^3.4.1", + "react-dom": "^17.0.1", "react-json-pretty": "^2.2.0", - "react-paginate": "^6.5.0", + "react-paginate": "^7.0.0", "react-pdf": "^4.2.0", "react-scroll-sync": "^0.8.0", "react-sizeme": "^2.6.12", - "react-textarea-autosize": "^8.2.0", - "react-tooltip": "^4.2.10", + "react-textarea-autosize": "^8.3.0", + "react-tooltip": "^4.2.13", "react_ujs": "^2.6.1", "reactify": "^1.1.1", - "ts-loader": "8.0.4", - "typescript": "^4.0.3", + "ts-loader": "^8.0.14", + "typescript": "^4.1.3", "unfetch": "^4.2.0" }, "devDependencies": { "@types/lodash-es": "^4.17.3", - "@types/node-fetch": "^2.5.7", + "@types/node-fetch": "^2.5.8", "@types/rc-slider": "^8.6.6", - "@types/react": "^16.9.51", + "@types/react": "^17.0.0", "@types/react-addons-css-transition-group": "^15.0.5", "@types/react-beautiful-dnd": "^13.0.0", - "@types/react-copy-to-clipboard": "^4.3.0", - "@types/react-datepicker": "^3.1.1", - "@types/react-dom": "^16.9.8", + "@types/react-copy-to-clipboard": "^5.0.0", + "@types/react-datepicker": "^3.1.3", + "@types/react-dom": "^17.0.0", "@types/react-textarea-autosize": "^4.3.5", - "@types/vimeo__player": "^2.9.1", - "eslint": "7.10.0", - "eslint-config-airbnb": "18.2.0", - "eslint-plugin-import": "2.22.1", - "eslint-plugin-jsx-a11y": "6.3.1", - "eslint-plugin-promise": "4.2.1", - "eslint-plugin-react": "7.21.3", - "eslint-plugin-standard": "4.0.1", - "postcss-flexbugs-fixes": "^4.2.1", - "postcss-import": "^12.0.1", + "@types/vimeo__player": "^2.10.0", + "eslint": "^7.18.0", + "eslint-config-airbnb": "^18.2.1", + "eslint-plugin-import": "^2.22.1", + "eslint-plugin-jsx-a11y": "^6.4.1", + "eslint-plugin-promise": "^4.2.1", + "eslint-plugin-react": "^7.22.0", + "eslint-plugin-standard": "^5.0.0", + "postcss-flexbugs-fixes": "^5.0.2", + "postcss-import": "^14.0.0", "postcss-preset-env": "^6.7.0", - "webpack-dev-server": "^3.11.0" - }, - "engines": { - "node": "14.8.0" + "webpack-dev-server": "^3.11.2" } } diff --git a/scripts/yarn.lock b/scripts/yarn.lock index f8fc261..0d818ba 100644 --- a/scripts/yarn.lock +++ b/scripts/yarn.lock @@ -863,10 +863,10 @@ resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7" integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw== -"@eslint/eslintrc@^0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.1.3.tgz#7d1a2b2358552cc04834c0979bd4275362e37085" - integrity sha512-4YVwPkANLeNtRjMekzux1ci8hIaH5eGKktGqR0d3LWsKNn5B2X/1Z6Trxy7jQXl9EBGE6Yj02O+t09FMeRllaA== +"@eslint/eslintrc@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.3.0.tgz#d736d6963d7003b6514e6324bec9c602ac340318" + integrity sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg== dependencies: ajv "^6.12.4" debug "^4.1.1" @@ -875,7 +875,7 @@ ignore "^4.0.6" import-fresh "^3.2.1" js-yaml "^3.13.1" - lodash "^4.17.19" + lodash "^4.17.20" minimatch "^3.0.4" strip-json-comments "^3.1.1" @@ -964,10 +964,10 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== -"@types/node-fetch@^2.5.7": - version "2.5.7" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.7.tgz#20a2afffa882ab04d44ca786449a276f9f6bbf3c" - integrity sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw== +"@types/node-fetch@^2.5.8": + version "2.5.8" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.8.tgz#e199c835d234c7eb0846f6618012e558544ee2fb" + integrity sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw== dependencies: "@types/node" "*" form-data "^3.0.0" @@ -1027,26 +1027,26 @@ dependencies: "@types/react" "*" -"@types/react-copy-to-clipboard@^4.3.0": - version "4.3.0" - resolved "https://registry.yarnpkg.com/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-4.3.0.tgz#8e07becb4f11cfced4bd36038cb5bdf5c2658be5" - integrity sha512-iideNPRyroENqsOFh1i2Dv3zkviYS9r/9qD9Uh3Z9NNoAAqqa2x53i7iGndGNnJFIo20wIu7Hgh77tx1io8bgw== +"@types/react-copy-to-clipboard@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.0.tgz#38b035ca0c28334d3e0efaf3f319b81eea9690cd" + integrity sha512-faUg6Kx3Dfv0MBIcs+xzIptlRtjEVSaNjqyC14YAp4UwSiTHghnKtBOt9ERRTZZJfoJgnw10tomVaqG86GzdAw== dependencies: "@types/react" "*" -"@types/react-datepicker@^3.1.1": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@types/react-datepicker/-/react-datepicker-3.1.1.tgz#bbb5e4561f657ca8e3d6829dd99b91a98c0bb74c" - integrity sha512-vwNrgaIMJThvvwmtnA8jSVVJZ0FNgljQrq1jDA4MtYJIDmVmd9NNrFaXf9u2JqR2nS+8Kvi8OVs/tnAbUqZhHw== +"@types/react-datepicker@^3.1.3": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@types/react-datepicker/-/react-datepicker-3.1.3.tgz#4525475c451091477de27ed52c029a9043ec6b11" + integrity sha512-Gca56Pa8hpy3eO2naRLdC63iflER7JXxgdHTGJ6yF5DjvhQoirRPqCJerWLq6TOWd+sEsZWwMm17Q17YRVLFtw== dependencies: "@types/react" "*" date-fns "^2.0.1" popper.js "^1.14.1" -"@types/react-dom@^16.9.8": - version "16.9.8" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.8.tgz#fe4c1e11dfc67155733dfa6aa65108b4971cb423" - integrity sha512-ykkPQ+5nFknnlU6lDd947WbQ6TE3NNzbQAkInC2EKY1qeYdTKp7onFusmYZb+ityzx2YviqT6BXSu+LyWWJwcA== +"@types/react-dom@^17.0.0": + version "17.0.0" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.0.tgz#b3b691eb956c4b3401777ee67b900cb28415d95a" + integrity sha512-lUqY7OlkF/RbNtD5nIq7ot8NquXrdFrjSOR6+w9a9RFQevGi1oZO1dcJbXMeONAPKtZ2UrZOEJ5UOCVsxbLk/g== dependencies: "@types/react" "*" @@ -1057,10 +1057,10 @@ dependencies: "@types/react" "*" -"@types/react-pdf@^4.0.6": - version "4.0.6" - resolved "https://registry.yarnpkg.com/@types/react-pdf/-/react-pdf-4.0.6.tgz#cc96357d87ca72e21d8d4caec5956c62a3990abc" - integrity sha512-ZmtUA31L5AaF9PilB8cJ3PuGOHIiyWcHnCir7KOux1cDjfVH6VxiN/j7CcyX98U9hwlyN81bkqxeNWNuEc0a4w== +"@types/react-pdf@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@types/react-pdf/-/react-pdf-5.0.1.tgz#bfa1a2e052dabe76c2fcc30162e1d3e33a4c2abe" + integrity sha512-iDpGh45UAyLx4udkzJy0lxMeCLBrAfO08fEL4FKfeSXXvBTnax60ueTTysJ4XY0XqEJn5gYDuMH93nlJhAjFoQ== dependencies: "@types/pdfjs-dist" "*" "@types/react" "*" @@ -1079,23 +1079,23 @@ "@types/prop-types" "*" csstype "^2.2.0" -"@types/react@^16.9.51": - version "16.9.51" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.51.tgz#f8aa51ffa9996f1387f63686696d9b59713d2b60" - integrity sha512-lQa12IyO+DMlnSZ3+AGHRUiUcpK47aakMMoBG8f7HGxJT8Yfe+WE128HIXaHOHVPReAW0oDS3KAI0JI2DDe1PQ== +"@types/react@^17.0.0": + version "17.0.0" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.0.tgz#5af3eb7fad2807092f0046a1302b7823e27919b8" + integrity sha512-aj/L7RIMsRlWML3YB6KZiXB3fV2t41+5RBGYF8z+tAKU43Px8C3cYUZsDvf1/+Bm4FK21QWBrDutu8ZJ/70qOw== dependencies: "@types/prop-types" "*" csstype "^3.0.2" -"@types/vimeo__player@^2.9.1": - version "2.9.1" - resolved "https://registry.yarnpkg.com/@types/vimeo__player/-/vimeo__player-2.9.1.tgz#4de8583753a1480a1b5dbc6dcf5ec21c55c67e1a" - integrity sha512-L6XHWenPkN+WHFWmo/fhA70kTQnNUxOs3bQS3nF/FK3kv+UzEVRqPEkxJNUZWExwrhOKaTKzplZHmxYwmr0SJA== +"@types/vimeo__player@^2.10.0": + version "2.10.0" + resolved "https://registry.yarnpkg.com/@types/vimeo__player/-/vimeo__player-2.10.0.tgz#dee8934c59d0a01a4252e6fb143c8807d3235502" + integrity sha512-uhKJDgEfQiEhKHw9bP7+wZSvXTyN4iw4Yb+7Omo76jCJZp1NZkWfZYaaobXrkiuFT6k2ld2eqaXKSpvqfmDUPQ== -"@vimeo/player@^2.14.0": - version "2.14.0" - resolved "https://registry.yarnpkg.com/@vimeo/player/-/player-2.14.0.tgz#0d7826162ab072505e2eadb221ab9c8f79507a0d" - integrity sha512-hTeROVnkcyboRjetPi9tasryrjDPVsmr/73clwbYsBpSk8k5q1ygFyvkWXQShv9Rc+hvXM5RJXPd7i7Wh7dqcA== +"@vimeo/player@^2.15.0": + version "2.15.0" + resolved "https://registry.yarnpkg.com/@vimeo/player/-/player-2.15.0.tgz#c1037706f0a95abf87f6aa960d058e11efe6510e" + integrity sha512-PH+H7G7pIUbrw8AHeigOc13cUoe8E78y4XCVqSP7pLFj/kQm0EvHQGBO3224Qq7a0XMEmNR6kH+n+8o0GslWCg== dependencies: native-promise-only "0.8.1" weakmap-polyfill "2.0.1" @@ -1280,7 +1280,7 @@ accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: mime-types "~2.1.24" negotiator "0.6.2" -acorn-jsx@^5.2.0: +acorn-jsx@^5.2.0, acorn-jsx@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== @@ -1362,6 +1362,16 @@ ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-7.0.3.tgz#13ae747eff125cafb230ac504b2406cf371eece2" + integrity sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + alphanum-sort@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" @@ -1412,7 +1422,7 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.1.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== @@ -1492,6 +1502,17 @@ array-includes@^3.1.1: es-abstract "^1.17.0" is-string "^1.0.5" +array-includes@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.2.tgz#a8db03e0b88c8c6aeddc49cb132f9bcab4ebf9c8" + integrity sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + get-intrinsic "^1.0.1" + is-string "^1.0.5" + array-union@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" @@ -1561,10 +1582,10 @@ ast-types@0.9.6: version "0.9.6" resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9" -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== async-each@^1.0.1: version "1.0.3" @@ -1618,12 +1639,12 @@ aws4@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" -axe-core@^3.5.4: - version "3.5.5" - resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-3.5.5.tgz#84315073b53fa3c0c51676c588d59da09a192227" - integrity sha512-5P0QZ6J5xGikH780pghEdbEKijCTrruK9KxtPZCFWUpef0f6GipO+xEZ5GKCb020mmqgbiNO6TcA55CriL784Q== +axe-core@^4.0.2: + version "4.1.1" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.1.1.tgz#70a7855888e287f7add66002211a423937063eaf" + integrity sha512-5Kgy8Cz6LPC9DJcNb3yjAXTu3XihQgEdnIg50c//zOC/MyLP0Clg+Y8Sh9ZjjnvBrDZU4DgXS9C3T9r4/scGZQ== -axobject-query@^2.1.2: +axobject-query@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA== @@ -2136,6 +2157,14 @@ cached-path-relative@^1.0.0, cached-path-relative@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.0.2.tgz#a13df4196d26776220cc3356eb147a52dba2c6db" +call-bind@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + caller-callsite@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" @@ -2214,7 +2243,7 @@ chalk@^1.1.1: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0, chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.0, chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" dependencies: @@ -2222,7 +2251,7 @@ chalk@^2.0, chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0: +chalk@^4.0.0, chalk@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== @@ -2481,10 +2510,10 @@ concat-stream@^1.5.0, concat-stream@^1.6.0, concat-stream@^1.6.1, concat-stream@ readable-stream "^2.2.2" typedarray "^0.0.6" -confusing-browser-globals@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz#72bc13b483c0276801681871d4898516f8f54fdd" - integrity sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw== +confusing-browser-globals@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz#30d1e7f3d1b882b25ec4933d1d1adac353d20a59" + integrity sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA== connect-history-api-fallback@^1.6.0: version "1.6.0" @@ -2915,7 +2944,7 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: dependencies: ms "2.0.0" -debug@^3.1.1, debug@^3.2.5, debug@^3.2.6: +debug@^3.1.1, debug@^3.2.6: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" dependencies: @@ -3229,6 +3258,11 @@ emoji-regex@^7.0.1: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + emoji-regex@^9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.0.0.tgz#48a2309cc8a1d2e9d23bc6a67c39b63032e76ea4" @@ -3361,22 +3395,22 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" -eslint-config-airbnb-base@^14.2.0: - version "14.2.0" - resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.0.tgz#fe89c24b3f9dc8008c9c0d0d88c28f95ed65e9c4" - integrity sha512-Snswd5oC6nJaevs3nZoLSTvGJBvzTfnBqOIArkf3cbyTyq9UD79wOk8s+RiL6bhca0p/eRO6veczhf6A/7Jy8Q== +eslint-config-airbnb-base@^14.2.1: + version "14.2.1" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.1.tgz#8a2eb38455dc5a312550193b319cdaeef042cd1e" + integrity sha512-GOrQyDtVEc1Xy20U7vsB2yAoB4nBlfH5HZJeatRXHleO+OS5Ot+MWij4Dpltw4/DyIkqUfqz1epfhVR5XWWQPA== dependencies: - confusing-browser-globals "^1.0.9" - object.assign "^4.1.0" + confusing-browser-globals "^1.0.10" + object.assign "^4.1.2" object.entries "^1.1.2" -eslint-config-airbnb@18.2.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-18.2.0.tgz#8a82168713effce8fc08e10896a63f1235499dcd" - integrity sha512-Fz4JIUKkrhO0du2cg5opdyPKQXOI2MvF8KUvN2710nJMT6jaRUpRE2swrJftAjVGL7T1otLM5ieo5RqS1v9Udg== +eslint-config-airbnb@^18.2.1: + version "18.2.1" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-18.2.1.tgz#b7fe2b42f9f8173e825b73c8014b592e449c98d9" + integrity sha512-glZNDEZ36VdlZWoxn/bUR1r/sdFKPd1mHPbqUtkctgNG4yT2DLLtJ3D+yCV+jzZCc2V1nBVkmdknOJBZ5Hc0fg== dependencies: - eslint-config-airbnb-base "^14.2.0" - object.assign "^4.1.0" + eslint-config-airbnb-base "^14.2.1" + object.assign "^4.1.2" object.entries "^1.1.2" eslint-import-resolver-node@^0.3.4: @@ -3395,7 +3429,7 @@ eslint-module-utils@^2.6.0: debug "^2.6.9" pkg-dir "^2.0.0" -eslint-plugin-import@2.22.1: +eslint-plugin-import@^2.22.1: version "2.22.1" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz#0896c7e6a0cf44109a2d97b95903c2bb689d7702" integrity sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw== @@ -3414,49 +3448,49 @@ eslint-plugin-import@2.22.1: resolve "^1.17.0" tsconfig-paths "^3.9.0" -eslint-plugin-jsx-a11y@6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.3.1.tgz#99ef7e97f567cc6a5b8dd5ab95a94a67058a2660" - integrity sha512-i1S+P+c3HOlBJzMFORRbC58tHa65Kbo8b52/TwCwSKLohwvpfT5rm2GjGWzOHTEuq4xxf2aRlHHTtmExDQOP+g== +eslint-plugin-jsx-a11y@^6.4.1: + version "6.4.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.4.1.tgz#a2d84caa49756942f42f1ffab9002436391718fd" + integrity sha512-0rGPJBbwHoGNPU73/QCLP/vveMlM1b1Z9PponxO87jfr6tuH5ligXbDT6nHSSzBC8ovX2Z+BQu7Bk5D/Xgq9zg== dependencies: - "@babel/runtime" "^7.10.2" + "@babel/runtime" "^7.11.2" aria-query "^4.2.2" array-includes "^3.1.1" ast-types-flow "^0.0.7" - axe-core "^3.5.4" - axobject-query "^2.1.2" + axe-core "^4.0.2" + axobject-query "^2.2.0" damerau-levenshtein "^1.0.6" emoji-regex "^9.0.0" has "^1.0.3" - jsx-ast-utils "^2.4.1" + jsx-ast-utils "^3.1.0" language-tags "^1.0.5" -eslint-plugin-promise@4.2.1: +eslint-plugin-promise@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz#845fd8b2260ad8f82564c1222fce44ad71d9418a" integrity sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw== -eslint-plugin-react@7.21.3: - version "7.21.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.21.3.tgz#71655d2af5155b19285ec929dd2cdc67a4470b52" - integrity sha512-OI4GwTCqyIb4ipaOEGLWdaOHCXZZydStAsBEPB2e1ZfNM37bojpgO1BoOQbFb0eLVz3QLDx7b+6kYcrxCuJfhw== +eslint-plugin-react@^7.22.0: + version "7.22.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.22.0.tgz#3d1c542d1d3169c45421c1215d9470e341707269" + integrity sha512-p30tuX3VS+NWv9nQot9xIGAHBXR0+xJVaZriEsHoJrASGCJZDJ8JLNM0YqKqI0AKm6Uxaa1VUHoNEibxRCMQHA== dependencies: array-includes "^3.1.1" array.prototype.flatmap "^1.2.3" doctrine "^2.1.0" has "^1.0.3" - jsx-ast-utils "^2.4.1" + jsx-ast-utils "^2.4.1 || ^3.0.0" object.entries "^1.1.2" object.fromentries "^2.0.2" object.values "^1.1.1" prop-types "^15.7.2" - resolve "^1.17.0" + resolve "^1.18.1" string.prototype.matchall "^4.0.2" -eslint-plugin-standard@4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.0.1.tgz#ff0519f7ffaff114f76d1bd7c3996eef0f6e20b4" - integrity sha512-v/KBnfyaOMPmZc/dmc6ozOdWqekGp7bBGq4jLAecEfPGmfKiWS4sA8sC0LqiV9w5qmXAtXVn4M3p1jSyhY85SQ== +eslint-plugin-standard@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-5.0.0.tgz#c43f6925d669f177db46f095ea30be95476b1ee4" + integrity sha512-eSIXPc9wBM4BrniMzJRBm2uoVuXz2EPa+NXPk2+itrVt+r5SbKFERx/IgrK/HmfjddyKVz2f+j+7gBRvu19xLg== eslint-scope@^4.0.3: version "4.0.3" @@ -3486,13 +3520,18 @@ eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== -eslint@7.10.0: - version "7.10.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.10.0.tgz#494edb3e4750fb791133ca379e786a8f648c72b9" - integrity sha512-BDVffmqWl7JJXqCjAK6lWtcQThZB/aP1HXSH1JKwGwv0LQEdvpR7qzNrUT487RM39B5goWuboFad5ovMBmD8yA== +eslint-visitor-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" + integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== + +eslint@^7.18.0: + version "7.18.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.18.0.tgz#7fdcd2f3715a41fe6295a16234bd69aed2c75e67" + integrity sha512-fbgTiE8BfUJZuBeq2Yi7J3RB3WGUQ9PNuNbmgi6jt9Iv8qrkxfy19Ds3OpL1Pm7zg3BtTVhvcUZbIRQ0wmSjAQ== dependencies: "@babel/code-frame" "^7.0.0" - "@eslint/eslintrc" "^0.1.3" + "@eslint/eslintrc" "^0.3.0" ajv "^6.10.0" chalk "^4.0.0" cross-spawn "^7.0.2" @@ -3501,11 +3540,11 @@ eslint@7.10.0: enquirer "^2.3.5" eslint-scope "^5.1.1" eslint-utils "^2.1.0" - eslint-visitor-keys "^1.3.0" - espree "^7.3.0" + eslint-visitor-keys "^2.0.0" + espree "^7.3.1" esquery "^1.2.0" esutils "^2.0.2" - file-entry-cache "^5.0.1" + file-entry-cache "^6.0.0" functional-red-black-tree "^1.0.1" glob-parent "^5.0.0" globals "^12.1.0" @@ -3516,7 +3555,7 @@ eslint@7.10.0: js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" - lodash "^4.17.19" + lodash "^4.17.20" minimatch "^3.0.4" natural-compare "^1.4.0" optionator "^0.9.1" @@ -3525,7 +3564,7 @@ eslint@7.10.0: semver "^7.2.1" strip-ansi "^6.0.0" strip-json-comments "^3.1.0" - table "^5.2.3" + table "^6.0.4" text-table "^0.2.0" v8-compile-cache "^2.0.3" @@ -3538,6 +3577,15 @@ espree@^7.3.0: acorn-jsx "^5.2.0" eslint-visitor-keys "^1.3.0" +espree@^7.3.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" + integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== + dependencies: + acorn "^7.4.0" + acorn-jsx "^5.3.1" + eslint-visitor-keys "^1.3.0" + esprima-fb@13001.1001.0-dev-harmony-fb: version "13001.1001.0-dev-harmony-fb" resolved "https://registry.yarnpkg.com/esprima-fb/-/esprima-fb-13001.1001.0-dev-harmony-fb.tgz#633acdb40d9bd4db8a1c1d68c06a942959fad2b0" @@ -3739,13 +3787,7 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= -faye-websocket@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4" - dependencies: - websocket-driver ">=0.5.1" - -faye-websocket@~0.11.1: +faye-websocket@^0.11.3: version "0.11.3" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e" integrity sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA== @@ -3757,12 +3799,12 @@ figgy-pudding@^3.5.1: resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== -file-entry-cache@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== +file-entry-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.0.tgz#7921a89c391c6d93efec2169ac6bf300c527ea0a" + integrity sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA== dependencies: - flat-cache "^2.0.1" + flat-cache "^3.0.4" file-loader@^6.0.0: version "6.1.0" @@ -3875,25 +3917,24 @@ findup-sync@^3.0.0: micromatch "^3.0.4" resolve-dir "^1.0.1" -flat-cache@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== dependencies: - flatted "^2.0.0" - rimraf "2.6.3" - write "1.0.3" - -flatted@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" - integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== + flatted "^3.1.0" + rimraf "^3.0.2" flatted@^3.0.4: version "3.1.0" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.0.tgz#a5d06b4a8b01e3a63771daa5cb7a1903e2e57067" integrity sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA== +flatted@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" + integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== + flatten@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" @@ -4054,6 +4095,15 @@ get-caller-file@^2.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-intrinsic@^1.0.1, get-intrinsic@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.2.tgz#6820da226e50b24894e08859469dc68361545d49" + integrity sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + get-stdin@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" @@ -4407,6 +4457,11 @@ http-errors@~1.7.2: version "0.4.10" resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4" +http-parser-js@>=0.5.1: + version "0.5.3" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9" + integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg== + http-proxy-middleware@0.19.1: version "0.19.1" resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a" @@ -4706,6 +4761,13 @@ is-color-stop@^1.0.0: rgb-regex "^1.0.1" rgba-regex "^1.0.0" +is-core-module@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a" + integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ== + dependencies: + has "^1.0.3" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -4772,6 +4834,11 @@ is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" @@ -4967,6 +5034,11 @@ json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" @@ -4986,9 +5058,10 @@ json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" -json3@^3.3.2: +json3@^3.3.3: version "3.3.3" resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81" + integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA== json5@^1.0.1: version "1.0.1" @@ -5038,13 +5111,13 @@ jstransform@^10.1.0: esprima-fb "13001.1001.0-dev-harmony-fb" source-map "0.1.31" -jsx-ast-utils@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz#1114a4c1209481db06c690c2b4f488cc665f657e" - integrity sha512-z1xSldJ6imESSzOjd3NNkieVJKRlKYSOtMG8SFyCj2FIrvSaSuli/WjpBkEzCBoR9bYYYFgqJw61Xhu7Lcgk+w== +"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz#41108d2cec408c3453c1bbe8a4aae9e1e2bd8f82" + integrity sha512-EIsmt3O3ljsU6sot/J4E1zDRxfBNrhjyf/OKjlydwgEimQuznlM4Wv7U+ueONJMyEn1WRE0K8dhi3dVAXYT24Q== dependencies: - array-includes "^3.1.1" - object.assign "^4.1.0" + array-includes "^3.1.2" + object.assign "^4.1.2" killable@^1.0.1: version "1.0.1" @@ -5156,7 +5229,7 @@ loader-utils@^1.0.0, loader-utils@^1.2.3, loader-utils@^1.4.0: emojis-list "^3.0.0" json5 "^1.0.1" -loader-utils@^1.0.2, loader-utils@^1.1.0: +loader-utils@^1.1.0: version "1.2.3" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" dependencies: @@ -5195,10 +5268,10 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" -lodash-es@^4.17.15: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78" - integrity sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ== +lodash-es@^4.17.20: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.20.tgz#29f6332eefc60e849f869c264bc71126ad61e8f7" + integrity sha512-JD1COMZsq8maT6mnuz1UMV0jvYD0E0aUsSOdrr1/nAG3dhqQXwRRgeW0cSqH1U43INKcqxaiVIQNOUDld7gRDA== lodash._getnative@^3.0.0: version "3.9.1" @@ -5264,7 +5337,7 @@ lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.4, lodash@~4.17.10 version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" -lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.5: +lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.5: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== @@ -5346,10 +5419,10 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" -marked@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/marked/-/marked-1.2.0.tgz#7221ce2395fa6cf6d722e6f2871a32d3513c85ca" - integrity sha512-tiRxakgbNPBr301ihe/785NntvYyhxlqcL3YaC8CaxJQh7kiaEtrN9B/eK2I2943Yjkh5gw25chYFDQhOMCwMA== +marked@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/marked/-/marked-1.2.7.tgz#6e14b595581d2319cdcf033a24caaf41455a01fb" + integrity sha512-No11hFYcXr/zkBvL6qFmAp1z6BKY3zqLMHny/JN/ey+al7qwCM2+CMBL9BOgqMxZU36fz4cCWfn2poWIf7QRXA== md5.js@^1.3.4: version "1.3.5" @@ -5629,22 +5702,22 @@ module-deps@^6.2.3: through2 "^2.0.0" xtend "^4.0.0" -moment-timezone@0.5.31: - version "0.5.31" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.31.tgz#9c40d8c5026f0c7ab46eda3d63e49c155148de05" - integrity sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA== +moment-timezone@^0.5.32: + version "0.5.32" + resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.32.tgz#db7677cc3cc680fd30303ebd90b0da1ca0dfecc2" + integrity sha512-Z8QNyuQHQAmWucp8Knmgei8YNo28aLjJq6Ma+jy1ZSpSk5nyfRT8xgUbSQvD2+2UajISfenndwvFuH3NGS+nvA== dependencies: moment ">= 2.9.0" -moment@2.29.1: - version "2.29.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" - integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== - "moment@>= 2.9.0": version "2.24.0" resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" +moment@^2.29.1: + version "2.29.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" + integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== + move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" @@ -5978,6 +6051,16 @@ object.assign@^4.1.0, object.assign@^4.1.1: has-symbols "^1.0.1" object-keys "^1.1.1" +object.assign@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" + object.entries@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.2.tgz#bc73f00acb6b6bb16c203434b10f9a7e797d3add" @@ -6576,6 +6659,11 @@ postcss-flexbugs-fixes@^4.2.1: dependencies: postcss "^7.0.26" +postcss-flexbugs-fixes@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz#2028e145313074fc9abe276cb7ca14e5401eb49d" + integrity sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ== + postcss-focus-visible@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz#477d107113ade6024b14128317ade2bd1e17046e" @@ -6622,6 +6710,15 @@ postcss-import@^12.0.1: read-cache "^1.0.0" resolve "^1.1.7" +postcss-import@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-14.0.0.tgz#3ed1dadac5a16650bde3f4cdea6633b9c3c78296" + integrity sha512-gFDDzXhqr9ELmnLHgCC3TbGfA6Dm/YMb/UN8/f7Uuq4fL7VTk2vOIj6hwINEwbokEmp123bLD7a5m+E+KIetRg== + dependencies: + postcss-value-parser "^4.0.0" + read-cache "^1.0.0" + resolve "^1.1.7" + postcss-initial@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-3.0.2.tgz#f018563694b3c16ae8eaabe3c585ac6319637b2d" @@ -7014,7 +7111,7 @@ postcss-value-parser@^3.0.0, postcss-value-parser@^3.2.3, postcss-value-parser@^ version "3.3.1" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" -postcss-value-parser@^4.1.0: +postcss-value-parser@^4.0.0, postcss-value-parser@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== @@ -7313,18 +7410,18 @@ react-beautiful-dnd@^13.0.0: redux "^4.0.4" use-memo-one "^1.1.1" -react-copy-to-clipboard@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.2.tgz#d82a437e081e68dfca3761fbd57dbf2abdda1316" - integrity sha512-/2t5mLMMPuN5GmdXo6TebFa8IoFxZ+KTDDqYhcDm0PhkgEzSxVvIX26G20s1EB02A4h2UZgwtfymZ3lGJm0OLg== +react-copy-to-clipboard@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.3.tgz#2a0623b1115a1d8c84144e9434d3342b5af41ab4" + integrity sha512-9S3j+m+UxDZOM0Qb8mhnT/rMR0NGSrj9A/073yz2DSxPMYhmYFBMYIdI2X4o8AjOjyFsSNxDRnCX6s/gRxpriw== dependencies: copy-to-clipboard "^3" prop-types "^15.5.8" -react-datepicker@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/react-datepicker/-/react-datepicker-3.2.2.tgz#cd5351ab1bba0b34412dd11db3169801f8f8b2ef" - integrity sha512-/3D6hfhXcCNCbO8LICuQeoNDItWFyitGo+aLcsi0tAyJLtCInamYRwPIXhsEF+N6/qWim1yNyr71mqjj4YEBmg== +react-datepicker@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/react-datepicker/-/react-datepicker-3.4.1.tgz#3c8e8989f1ab31a767c17170a2d1318aa3c3b9ef" + integrity sha512-ASyVb7UmVx1vzeITidD7Cr/EXRXhKyjjbSkBndPc1MipYq4rqQ3eMFgvRQzpsXc3JmIMFgICm7nmN6Otc1GE/Q== dependencies: classnames "^2.2.6" date-fns "^2.0.1" @@ -7332,15 +7429,14 @@ react-datepicker@^3.2.2: react-onclickoutside "^6.9.0" react-popper "^1.3.4" -react-dom@^16.13.1: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f" - integrity sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag== +react-dom@^17.0.1: + version "17.0.1" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.1.tgz#1de2560474ec9f0e334285662ede52dbc5426fc6" + integrity sha512-6eV150oJZ9U2t9svnsspTMrWNyHc6chX0KzDeAOXftRa8bNeOKTTfCJ7KorIwenkHd2xqVTBTCZd79yk/lx/Ug== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" - prop-types "^15.6.2" - scheduler "^0.19.1" + scheduler "^0.20.1" react-is@^16.7.0, react-is@^16.8.1: version "16.9.0" @@ -7367,10 +7463,10 @@ react-onclickoutside@^6.9.0: resolved "https://registry.yarnpkg.com/react-onclickoutside/-/react-onclickoutside-6.9.0.tgz#a54bc317ae8cf6131a5d78acea55a11067f37a1f" integrity sha512-8ltIY3bC7oGhj2nPAvWOGi+xGFybPNhJM0V1H8hY/whNcXgmDeaeoCMPPd8VatrpTsUWjb/vGzrmu6SrXVty3A== -react-paginate@^6.5.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/react-paginate/-/react-paginate-6.5.0.tgz#b9baf53627b115cfd688afa048776aa45bffda19" - integrity sha512-H7xSi9jyiJzgfaj+2nNhQcjZfwzJ/Mxb64V2RiyDctjZyCWojwsaGwMqhLBpQ58iAuMVtBMRQ7ECqMcUKG9QSQ== +react-paginate@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/react-paginate/-/react-paginate-7.0.0.tgz#af206ef92a2b6ef87646855eb1612157254ad0c0" + integrity sha512-mzPwHGJfSs79JBGX2V0v/FfQp3yWdz0XRrB9JvsUbJdsxqCt4osk1O669+K8VPQ0Lh9v0lJsnLLoJwnsgdJFng== dependencies: prop-types "^15.6.1" @@ -7425,10 +7521,10 @@ react-sizeme@^2.6.12: shallowequal "^1.1.0" throttle-debounce "^2.1.0" -react-textarea-autosize@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.2.0.tgz#fae38653f5ec172a855fd5fffb39e466d56aebdb" - integrity sha512-grajUlVbkx6VdtSxCgzloUIphIZF5bKr21OYMceWPKkniy7H0mRAT/AXPrRtObAe+zUePnNlBwUc4ivVjUGIjw== +react-textarea-autosize@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.3.0.tgz#e6e2fd186d9f61bb80ac6e2dcb4c55504f93c2fa" + integrity sha512-3GLWFAan2pbwBeoeNDoqGmSbrShORtgWfaWX0RJDivsUrpShh01saRM5RU/i4Zmf+whpBVEY5cA90Eq8Ub1N3w== dependencies: "@babel/runtime" "^7.10.2" use-composed-ref "^1.0.0" @@ -7441,10 +7537,10 @@ react-tools@~0.13.0: commoner "^0.10.0" jstransform "^10.1.0" -react-tooltip@^4.2.10: - version "4.2.10" - resolved "https://registry.yarnpkg.com/react-tooltip/-/react-tooltip-4.2.10.tgz#ed1a1acd388940c96f4b6309f4fd4dcce5e01bdc" - integrity sha512-D7ZLx6/QwpUl0SZRek3IZy/HWpsEEp0v3562tcT8IwZgu8IgV7hY5ZzniTkHyRcuL+IQnljpjj7A7zCgl2+T3w== +react-tooltip@^4.2.13: + version "4.2.13" + resolved "https://registry.yarnpkg.com/react-tooltip/-/react-tooltip-4.2.13.tgz#908db8a41dc10ae2ae9cc1864746cde939aaab0f" + integrity sha512-iAZ02wSxChLWb7Vnu0zeQMyAo/jiGHrwFNILWaR3pCKaFVRjKcv/B6TBI4+Xd66xLXVzLngwJ91Tf5D+mqAqVA== dependencies: prop-types "^15.7.2" uuid "^7.0.3" @@ -7459,14 +7555,13 @@ react-transition-group@^1.2.0: prop-types "^15.5.6" warning "^3.0.0" -react@^16.13.1: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e" - integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w== +react@^17.0.1: + version "17.0.1" + resolved "https://registry.yarnpkg.com/react/-/react-17.0.1.tgz#6e0600416bd57574e3f86d92edba3d9008726127" + integrity sha512-lG9c9UuMHdcAexXtigOZLX8exLWkW0Ku29qPRU8uhF2R9BN96dLCt0psvzPLlHc5OWkgymP3qwTRgbnw5BKx3w== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" - prop-types "^15.6.2" react_ujs@^2.6.0: version "2.6.0" @@ -7713,6 +7808,11 @@ require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + require-main-filename@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" @@ -7762,6 +7862,14 @@ resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.3.2, resolve@^1.4. dependencies: path-parse "^1.0.6" +resolve@^1.18.1: + version "1.19.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" + integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== + dependencies: + is-core-module "^2.1.0" + path-parse "^1.0.6" + ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" @@ -7785,13 +7893,6 @@ rimraf@2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3: dependencies: glob "^7.1.3" -rimraf@2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -7855,10 +7956,10 @@ sax@^1.2.4, sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" -scheduler@^0.19.1: - version "0.19.1" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196" - integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA== +scheduler@^0.20.1: + version "0.20.1" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.1.tgz#da0b907e24026b01181ecbc75efdc7f27b5a000c" + integrity sha512-LKTe+2xNJBNxu/QhHvDR14wUXHRQbVY5ZOYpOGWRzhydZUqrLb2JBvLPY7cAqFmqrWuDED0Mjk7013SZiOz6Bw== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -7900,7 +8001,7 @@ select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" -selfsigned@^1.10.7: +selfsigned@^1.10.8: version "1.10.8" resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.8.tgz#0d17208b7d12c33f8eac85c41835f27fc3d81a30" integrity sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w== @@ -7926,6 +8027,13 @@ semver@^7.2.1: resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== +semver@^7.3.4: + version "7.3.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" + integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== + dependencies: + lru-cache "^6.0.0" + semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" @@ -8088,14 +8196,14 @@ simple-swizzle@^0.2.2: dependencies: is-arrayish "^0.3.1" -slice-ansi@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" snapdragon-node@^2.0.1: version "2.1.1" @@ -8124,26 +8232,26 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" -sockjs-client@1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.4.0.tgz#c9f2568e19c8fd8173b4997ea3420e0bb306c7d5" - integrity sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g== +sockjs-client@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.5.0.tgz#2f8ff5d4b659e0d092f7aba0b7c386bd2aa20add" + integrity sha512-8Dt3BDi4FYNrCFGTL/HtwVzkARrENdwOUf1ZoW/9p3M8lZdFT35jVdrHza+qgxuG9H3/shR4cuX/X9umUrjP8Q== dependencies: - debug "^3.2.5" + debug "^3.2.6" eventsource "^1.0.7" - faye-websocket "~0.11.1" - inherits "^2.0.3" - json3 "^3.3.2" - url-parse "^1.4.3" + faye-websocket "^0.11.3" + inherits "^2.0.4" + json3 "^3.3.3" + url-parse "^1.4.7" -sockjs@0.3.20: - version "0.3.20" - resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.20.tgz#b26a283ec562ef8b2687b44033a4eeceac75d855" - integrity sha512-SpmVOVpdq0DJc0qArhF3E5xsxvaiqGNb73XfgBpK1y3UD5gs8DSo8aCTsuT5pX8rssdc2NDIzANwP9eCAiSdTA== +sockjs@^0.3.21: + version "0.3.21" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.21.tgz#b34ffb98e796930b60a0cfa11904d6a339a7d417" + integrity sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw== dependencies: - faye-websocket "^0.10.0" + faye-websocket "^0.11.3" uuid "^3.4.0" - websocket-driver "0.6.5" + websocket-driver "^0.7.4" sort-keys@^1.0.0: version "1.1.2" @@ -8386,6 +8494,15 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" +string-width@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + string.prototype.matchall@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz#48bb510326fb9fdeb6a33ceaa81a6ea04ef7648e" @@ -8564,15 +8681,15 @@ syntax-error@^1.1.1: dependencies: acorn-node "^1.2.0" -table@^5.2.3: - version "5.4.6" - resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" - integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== +table@^6.0.4: + version "6.0.7" + resolved "https://registry.yarnpkg.com/table/-/table-6.0.7.tgz#e45897ffbcc1bcf9e8a87bf420f2c9e5a7a52a34" + integrity sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g== dependencies: - ajv "^6.10.2" - lodash "^4.17.14" - slice-ansi "^2.1.0" - string-width "^3.0.0" + ajv "^7.0.2" + lodash "^4.17.20" + slice-ansi "^4.0.0" + string-width "^4.2.0" tapable@^1.0.0, tapable@^1.1.3: version "1.1.3" @@ -8782,16 +8899,16 @@ ts-essentials@^2.0.3: resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-2.0.12.tgz#c9303f3d74f75fa7528c3d49b80e089ab09d8745" integrity sha512-3IVX4nI6B5cc31/GFFE+i8ey/N2eA0CZDbo6n0yrz0zDX8ZJ8djmU1p+XRz7G3is0F3bB3pu2pAroFdAWQKU3w== -ts-loader@8.0.4: - version "8.0.4" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.0.4.tgz#02b9c91fbcfdb3114d8b1e98a3829265270eee7a" - integrity sha512-5u8KF1SW8eCUb/Ff7At81e3wznPmT/27fvaGRO9CziVy+6NlPVRvrzSox4OwU0/e6OflOUB32Err4VquysCSAQ== +ts-loader@^8.0.14: + version "8.0.14" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.0.14.tgz#e46ac1f8dcb88808d0b1335d2eae65b74bd78fe8" + integrity sha512-Jt/hHlUnApOZjnSjTmZ+AbD5BGlQFx3f1D0nYuNKwz0JJnuDGHJas6az+FlWKwwRTu+26GXpv249A8UAnYUpqA== dependencies: - chalk "^2.3.0" + chalk "^4.1.0" enhanced-resolve "^4.0.0" - loader-utils "^1.0.2" + loader-utils "^2.0.0" micromatch "^4.0.0" - semver "^6.0.0" + semver "^7.3.4" ts-pnp@^1.1.6: version "1.2.0" @@ -8859,10 +8976,10 @@ typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" -typescript@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.3.tgz#153bbd468ef07725c1df9c77e8b453f8d36abba5" - integrity sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg== +typescript@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7" + integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg== umd@^3.0.0: version "3.0.3" @@ -8969,7 +9086,7 @@ urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" -url-parse@^1.4.3: +url-parse@^1.4.3, url-parse@^1.4.7: version "1.4.7" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278" dependencies: @@ -9177,10 +9294,10 @@ webpack-dev-middleware@^3.7.2: range-parser "^1.2.1" webpack-log "^2.0.0" -webpack-dev-server@^3.11.0: - version "3.11.0" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.0.tgz#8f154a3bce1bcfd1cc618ef4e703278855e7ff8c" - integrity sha512-PUxZ+oSTxogFQgkTtFndEtJIPNmml7ExwufBZ9L2/Xyyd5PnOL5UreWe5ZT7IU25DSdykL9p1MLQzmLh2ljSeg== +webpack-dev-server@^3.11.2: + version "3.11.2" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.2.tgz#695ebced76a4929f0d5de7fd73fafe185fe33708" + integrity sha512-A80BkuHRQfCiNtGBS1EMf2ChTUs0x+B3wGDFmOeT4rmJOHhHTCH2naNxIHhmkr0/UillP4U3yeIyv1pNp+QDLQ== dependencies: ansi-html "0.0.7" bonjour "^3.5.0" @@ -9202,11 +9319,11 @@ webpack-dev-server@^3.11.0: p-retry "^3.0.1" portfinder "^1.0.26" schema-utils "^1.0.0" - selfsigned "^1.10.7" + selfsigned "^1.10.8" semver "^6.3.0" serve-index "^1.9.1" - sockjs "0.3.20" - sockjs-client "1.4.0" + sockjs "^0.3.21" + sockjs-client "^1.5.0" spdy "^4.0.2" strip-ansi "^3.0.1" supports-color "^6.1.0" @@ -9260,13 +9377,6 @@ webpack@^4.44.1: watchpack "^1.7.4" webpack-sources "^1.4.1" -websocket-driver@0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.6.5.tgz#5cb2556ceb85f4373c6d8238aa691c8454e13a36" - integrity sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY= - dependencies: - websocket-extensions ">=0.1.1" - websocket-driver@>=0.5.1: version "0.7.3" resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.3.tgz#a2d4e0d4f4f116f1e6297eba58b05d430100e9f9" @@ -9275,6 +9385,15 @@ websocket-driver@>=0.5.1: safe-buffer ">=5.1.0" websocket-extensions ">=0.1.1" +websocket-driver@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== + dependencies: + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + websocket-extensions@>=0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" @@ -9335,13 +9454,6 @@ wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" -write@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== - dependencies: - mkdirp "^0.5.1" - ws@^6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" -- GitLab From 84d7a907e8dbbdde37e35f2b040f4c3896e4d58a Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Thu, 21 Jan 2021 17:57:50 -1000 Subject: [PATCH 229/283] updating node modules Former-commit-id: 32c502be26c2a8389e1a171a1779b9fdaecb606c --- .gitignore | 1 + scripts/bundles/node_modules.tar.gz.REMOVED.git-id | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 77aa186..13fbbd3 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,4 @@ tags !/scripts/public/assets/images log.txt sidekiq.log +Dockerfile.packages diff --git a/scripts/bundles/node_modules.tar.gz.REMOVED.git-id b/scripts/bundles/node_modules.tar.gz.REMOVED.git-id index d3c29b5..f31166f 100644 --- a/scripts/bundles/node_modules.tar.gz.REMOVED.git-id +++ b/scripts/bundles/node_modules.tar.gz.REMOVED.git-id @@ -1 +1 @@ -67f211bd5a4a466daeead95c9d7accd1047c9492 \ No newline at end of file +0e7ff92b037bcac0e65982b90a202c51c7d1703f \ No newline at end of file -- GitLab From 914388e999397079de54087b15e7fc82e9a5f379 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Thu, 21 Jan 2021 19:41:29 -1000 Subject: [PATCH 230/283] downgrading some modules that break the build Former-commit-id: 5fbbef71ec0228721b8d57fdab22d03036e79933 --- .../bundles/node_modules.tar.gz.REMOVED.git-id | 2 +- scripts/package.json | 12 ++++++------ scripts/yarn.lock | 16 +--------------- 3 files changed, 8 insertions(+), 22 deletions(-) diff --git a/scripts/bundles/node_modules.tar.gz.REMOVED.git-id b/scripts/bundles/node_modules.tar.gz.REMOVED.git-id index f31166f..4e9c14f 100644 --- a/scripts/bundles/node_modules.tar.gz.REMOVED.git-id +++ b/scripts/bundles/node_modules.tar.gz.REMOVED.git-id @@ -1 +1 @@ -0e7ff92b037bcac0e65982b90a202c51c7d1703f \ No newline at end of file +3766c04acbeedd18f840987086baad4f7ac75904 \ No newline at end of file diff --git a/scripts/package.json b/scripts/package.json index b6d54dd..0057077 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -39,13 +39,13 @@ "popper.js": "^1.16.1", "prop-types": "^15.7.2", "rc-slider": "Galvanize-IT/slider#c569ca3b11979aced8306e6c02f37466cb7cd365", - "react": "^17.0.1", + "react": "^16.14.0", "react-addons-css-transition-group": "^15.6.2", "react-addons-test-utils": "^15.6.2", "react-beautiful-dnd": "^13.0.0", "react-copy-to-clipboard": "^5.0.3", "react-datepicker": "^3.4.1", - "react-dom": "^17.0.1", + "react-dom": "^16.14.0", "react-json-pretty": "^2.2.0", "react-paginate": "^7.0.0", "react-pdf": "^4.2.0", @@ -63,12 +63,12 @@ "@types/lodash-es": "^4.17.3", "@types/node-fetch": "^2.5.8", "@types/rc-slider": "^8.6.6", - "@types/react": "^17.0.0", + "@types/react": "^16.9.56", "@types/react-addons-css-transition-group": "^15.0.5", "@types/react-beautiful-dnd": "^13.0.0", "@types/react-copy-to-clipboard": "^5.0.0", "@types/react-datepicker": "^3.1.3", - "@types/react-dom": "^17.0.0", + "@types/react-dom": "^16.9.9", "@types/react-textarea-autosize": "^4.3.5", "@types/vimeo__player": "^2.10.0", "eslint": "^7.18.0", @@ -78,8 +78,8 @@ "eslint-plugin-promise": "^4.2.1", "eslint-plugin-react": "^7.22.0", "eslint-plugin-standard": "^5.0.0", - "postcss-flexbugs-fixes": "^5.0.2", - "postcss-import": "^14.0.0", + "postcss-flexbugs-fixes": "^4.2.1", + "postcss-import": "^12.0.1", "postcss-preset-env": "^6.7.0", "webpack-dev-server": "^3.11.2" } diff --git a/scripts/yarn.lock b/scripts/yarn.lock index 0d818ba..c271a6d 100644 --- a/scripts/yarn.lock +++ b/scripts/yarn.lock @@ -6659,11 +6659,6 @@ postcss-flexbugs-fixes@^4.2.1: dependencies: postcss "^7.0.26" -postcss-flexbugs-fixes@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz#2028e145313074fc9abe276cb7ca14e5401eb49d" - integrity sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ== - postcss-focus-visible@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz#477d107113ade6024b14128317ade2bd1e17046e" @@ -6710,15 +6705,6 @@ postcss-import@^12.0.1: read-cache "^1.0.0" resolve "^1.1.7" -postcss-import@^14.0.0: - version "14.0.0" - resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-14.0.0.tgz#3ed1dadac5a16650bde3f4cdea6633b9c3c78296" - integrity sha512-gFDDzXhqr9ELmnLHgCC3TbGfA6Dm/YMb/UN8/f7Uuq4fL7VTk2vOIj6hwINEwbokEmp123bLD7a5m+E+KIetRg== - dependencies: - postcss-value-parser "^4.0.0" - read-cache "^1.0.0" - resolve "^1.1.7" - postcss-initial@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-3.0.2.tgz#f018563694b3c16ae8eaabe3c585ac6319637b2d" @@ -7111,7 +7097,7 @@ postcss-value-parser@^3.0.0, postcss-value-parser@^3.2.3, postcss-value-parser@^ version "3.3.1" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" -postcss-value-parser@^4.0.0, postcss-value-parser@^4.1.0: +postcss-value-parser@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== -- GitLab From 509769d18b39d467b490912fd1c47dadd28eb1a9 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 22 Jan 2021 15:46:11 -1000 Subject: [PATCH 231/283] updaing dependencies Former-commit-id: d153fdc4bbd87691ac7f835b0a8c7a8e6943cf66 --- .gitignore | 1 + scripts/Gemfile.lock | 650 ++++++++++-------- scripts/bundles/bundle.tar.gz.REMOVED.git-id | 2 +- .../node_modules.tar.gz.REMOVED.git-id | 2 +- scripts/gems/block-parser/Gemfile.lock | 101 +-- scripts/package.json | 8 +- 6 files changed, 440 insertions(+), 324 deletions(-) diff --git a/.gitignore b/.gitignore index 13fbbd3..d313f3c 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ tags log.txt sidekiq.log Dockerfile.packages +repackage.sh diff --git a/scripts/Gemfile.lock b/scripts/Gemfile.lock index 12b55c6..1fc26f0 100644 --- a/scripts/Gemfile.lock +++ b/scripts/Gemfile.lock @@ -16,61 +16,65 @@ PATH GEM remote: https://rubygems.org/ specs: - actioncable (6.0.3.4) - actionpack (= 6.0.3.4) + actioncable (6.1.1) + actionpack (= 6.1.1) + activesupport (= 6.1.1) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.0.3.4) - actionpack (= 6.0.3.4) - activejob (= 6.0.3.4) - activerecord (= 6.0.3.4) - activestorage (= 6.0.3.4) - activesupport (= 6.0.3.4) + actionmailbox (6.1.1) + actionpack (= 6.1.1) + activejob (= 6.1.1) + activerecord (= 6.1.1) + activestorage (= 6.1.1) + activesupport (= 6.1.1) mail (>= 2.7.1) - actionmailer (6.0.3.4) - actionpack (= 6.0.3.4) - actionview (= 6.0.3.4) - activejob (= 6.0.3.4) + actionmailer (6.1.1) + actionpack (= 6.1.1) + actionview (= 6.1.1) + activejob (= 6.1.1) + activesupport (= 6.1.1) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.0.3.4) - actionview (= 6.0.3.4) - activesupport (= 6.0.3.4) - rack (~> 2.0, >= 2.0.8) + actionpack (6.1.1) + actionview (= 6.1.1) + activesupport (= 6.1.1) + rack (~> 2.0, >= 2.0.9) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.0.3.4) - actionpack (= 6.0.3.4) - activerecord (= 6.0.3.4) - activestorage (= 6.0.3.4) - activesupport (= 6.0.3.4) + actiontext (6.1.1) + actionpack (= 6.1.1) + activerecord (= 6.1.1) + activestorage (= 6.1.1) + activesupport (= 6.1.1) nokogiri (>= 1.8.5) - actionview (6.0.3.4) - activesupport (= 6.0.3.4) + actionview (6.1.1) + activesupport (= 6.1.1) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.0.3.4) - activesupport (= 6.0.3.4) + activejob (6.1.1) + activesupport (= 6.1.1) globalid (>= 0.3.6) - activemodel (6.0.3.4) - activesupport (= 6.0.3.4) - activerecord (6.0.3.4) - activemodel (= 6.0.3.4) - activesupport (= 6.0.3.4) - activestorage (6.0.3.4) - actionpack (= 6.0.3.4) - activejob (= 6.0.3.4) - activerecord (= 6.0.3.4) + activemodel (6.1.1) + activesupport (= 6.1.1) + activerecord (6.1.1) + activemodel (= 6.1.1) + activesupport (= 6.1.1) + activestorage (6.1.1) + actionpack (= 6.1.1) + activejob (= 6.1.1) + activerecord (= 6.1.1) + activesupport (= 6.1.1) marcel (~> 0.3.1) - activesupport (6.0.3.4) + mimemagic (~> 0.3.2) + activesupport (6.1.1) concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - zeitwerk (~> 2.2, >= 2.2.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + zeitwerk (~> 2.3) addressable (2.7.0) public_suffix (>= 2.0.2, < 5.0) analytics-ruby (2.2.8) @@ -78,85 +82,97 @@ GEM kramdown railties ast (2.4.1) - autoprefixer-rails (10.0.1.0) + autoprefixer-rails (10.2.0.0) execjs aws-eventstream (1.1.0) - aws-partitions (1.382.0) + aws-partitions (1.418.0) aws-sdk (3.0.1) aws-sdk-resources (~> 3) - aws-sdk-accessanalyzer (1.13.0) + aws-sdk-accessanalyzer (1.14.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-acm (1.38.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-acmpca (1.30.0) + aws-sdk-acmpca (1.32.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-alexaforbusiness (1.43.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-amplify (1.26.0) + aws-sdk-amplify (1.27.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-amplifybackend (1.1.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-apigateway (1.55.0) + aws-sdk-apigateway (1.58.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-apigatewaymanagementapi (1.19.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-apigatewayv2 (1.29.0) + aws-sdk-apigatewayv2 (1.30.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-appconfig (1.12.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-appflow (1.2.0) + aws-sdk-appflow (1.4.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-applicationautoscaling (1.48.0) + aws-sdk-appintegrationsservice (1.0.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-applicationautoscaling (1.49.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-applicationdiscoveryservice (1.33.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-applicationinsights (1.15.0) + aws-sdk-applicationinsights (1.16.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-appmesh (1.33.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-appmesh (1.31.0) + aws-sdk-appregistry (1.3.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-appstream (1.48.0) + aws-sdk-appstream (1.49.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-appsync (1.36.0) + aws-sdk-appsync (1.37.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-athena (1.33.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) + aws-sdk-auditmanager (1.1.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) aws-sdk-augmentedairuntime (1.10.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-autoscaling (1.47.0) + aws-sdk-autoscaling (1.53.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-autoscalingplans (1.28.0) + aws-sdk-autoscalingplans (1.29.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-backup (1.23.0) + aws-sdk-backup (1.25.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-batch (1.39.0) + aws-sdk-batch (1.43.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-braket (1.4.0) + aws-sdk-braket (1.5.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-budgets (1.36.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-chime (1.37.0) + aws-sdk-chime (1.40.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-cloud9 (1.29.0) @@ -165,40 +181,40 @@ GEM aws-sdk-clouddirectory (1.29.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-cloudformation (1.44.0) + aws-sdk-cloudformation (1.46.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-cloudfront (1.43.0) + aws-sdk-cloudfront (1.47.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-cloudhsm (1.27.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-cloudhsmv2 (1.30.0) + aws-sdk-cloudhsmv2 (1.31.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-cloudsearch (1.26.0) + aws-sdk-cloudsearch (1.27.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-cloudsearchdomain (1.22.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-cloudtrail (1.29.0) + aws-sdk-cloudtrail (1.31.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-cloudwatch (1.45.0) + aws-sdk-cloudwatch (1.47.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-cloudwatchevents (1.38.0) + aws-sdk-cloudwatchevents (1.40.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-cloudwatchlogs (1.38.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-codeartifact (1.4.0) + aws-sdk-codeartifact (1.6.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-codebuild (1.63.0) + aws-sdk-codebuild (1.65.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-codecommit (1.40.0) @@ -210,49 +226,52 @@ GEM aws-sdk-codeguruprofiler (1.12.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-codegurureviewer (1.13.0) + aws-sdk-codegurureviewer (1.14.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-codepipeline (1.37.0) + aws-sdk-codepipeline (1.39.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-codestar (1.27.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-codestarconnections (1.11.0) + aws-sdk-codestarconnections (1.12.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-codestarnotifications (1.8.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-cognitoidentity (1.27.0) + aws-sdk-cognitoidentity (1.29.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-cognitoidentityprovider (1.47.0) + aws-sdk-cognitoidentityprovider (1.48.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-cognitosync (1.24.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-comprehend (1.41.0) + aws-sdk-comprehend (1.42.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-comprehendmedical (1.23.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-computeoptimizer (1.9.0) + aws-sdk-computeoptimizer (1.11.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-configservice (1.55.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-configservice (1.53.0) + aws-sdk-connect (1.38.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-connect (1.34.0) + aws-sdk-connectcontactlens (1.0.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-connectparticipant (1.8.0) + aws-sdk-connectparticipant (1.9.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-core (3.109.1) + aws-sdk-core (3.111.2) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.239.0) aws-sigv4 (~> 1.1) @@ -260,10 +279,13 @@ GEM aws-sdk-costandusagereportservice (1.28.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-costexplorer (1.52.0) + aws-sdk-costexplorer (1.56.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-databasemigrationservice (1.45.0) + aws-sdk-customerprofiles (1.1.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-databasemigrationservice (1.50.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-dataexchange (1.10.0) @@ -272,7 +294,7 @@ GEM aws-sdk-datapipeline (1.24.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-datasync (1.27.0) + aws-sdk-datasync (1.28.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-dax (1.27.0) @@ -284,49 +306,55 @@ GEM aws-sdk-devicefarm (1.39.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) + aws-sdk-devopsguru (1.2.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) aws-sdk-directconnect (1.37.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-directoryservice (1.34.0) + aws-sdk-directoryservice (1.37.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-dlm (1.35.0) + aws-sdk-dlm (1.37.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-docdb (1.25.0) + aws-sdk-docdb (1.27.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-dynamodb (1.55.0) + aws-sdk-dynamodb (1.58.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-dynamodbstreams (1.26.0) + aws-sdk-dynamodbstreams (1.27.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-ebs (1.11.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-ec2 (1.200.0) + aws-sdk-ec2 (1.221.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-ec2instanceconnect (1.11.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-ecr (1.39.0) + aws-sdk-ecr (1.40.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-ecrpublic (1.0.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-ecs (1.70.0) + aws-sdk-ecs (1.73.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-efs (1.36.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-eks (1.45.0) + aws-sdk-eks (1.46.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-elasticache (1.44.0) + aws-sdk-elasticache (1.50.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-elasticbeanstalk (1.38.0) + aws-sdk-elasticbeanstalk (1.40.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-elasticinference (1.10.0) @@ -335,64 +363,76 @@ GEM aws-sdk-elasticloadbalancing (1.29.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-elasticloadbalancingv2 (1.53.0) + aws-sdk-elasticloadbalancingv2 (1.56.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-elasticsearchservice (1.43.0) + aws-sdk-elasticsearchservice (1.46.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-elastictranscoder (1.27.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-emr (1.39.0) + aws-sdk-emr (1.40.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-eventbridge (1.16.0) + aws-sdk-emrcontainers (1.0.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-eventbridge (1.18.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-firehose (1.35.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-fms (1.32.0) + aws-sdk-fms (1.33.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-forecastqueryservice (1.10.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-forecastservice (1.11.0) + aws-sdk-forecastservice (1.14.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-frauddetector (1.13.0) + aws-sdk-frauddetector (1.15.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-fsx (1.31.0) + aws-sdk-fsx (1.33.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-gamelift (1.38.0) + aws-sdk-gamelift (1.39.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-glacier (1.35.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-globalaccelerator (1.23.0) + aws-sdk-globalaccelerator (1.27.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-glue (1.82.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-glue (1.75.0) + aws-sdk-gluedatabrew (1.0.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-greengrass (1.37.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) + aws-sdk-greengrassv2 (1.1.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) aws-sdk-groundstation (1.15.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-guardduty (1.42.0) + aws-sdk-guardduty (1.43.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-health (1.31.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-honeycode (1.3.0) + aws-sdk-healthlake (1.1.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-honeycode (1.4.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-iam (1.46.0) @@ -401,7 +441,7 @@ GEM aws-sdk-identitystore (1.3.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-imagebuilder (1.15.0) + aws-sdk-imagebuilder (1.17.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-importexport (1.24.0) @@ -410,7 +450,7 @@ GEM aws-sdk-inspector (1.32.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-iot (1.59.0) + aws-sdk-iot (1.64.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-iot1clickdevicesservice (1.26.0) @@ -419,37 +459,46 @@ GEM aws-sdk-iot1clickprojects (1.26.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-iotanalytics (1.34.0) + aws-sdk-iotanalytics (1.36.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-iotdataplane (1.26.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) + aws-sdk-iotdeviceadvisor (1.0.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) aws-sdk-iotevents (1.20.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-ioteventsdata (1.13.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) + aws-sdk-iotfleethub (1.0.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) aws-sdk-iotjobsdataplane (1.25.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-iotsecuretunneling (1.8.0) + aws-sdk-iotsecuretunneling (1.9.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-iotsitewise (1.12.0) + aws-sdk-iotsitewise (1.16.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-iotthingsgraph (1.12.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) + aws-sdk-iotwireless (1.1.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) aws-sdk-ivs (1.5.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-kafka (1.29.0) + aws-sdk-kafka (1.33.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-kendra (1.14.0) + aws-sdk-kendra (1.20.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-kinesis (1.30.0) @@ -458,7 +507,7 @@ GEM aws-sdk-kinesisanalytics (1.29.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-kinesisanalyticsv2 (1.23.0) + aws-sdk-kinesisanalyticsv2 (1.24.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-kinesisvideo (1.30.0) @@ -473,28 +522,40 @@ GEM aws-sdk-kinesisvideosignalingchannels (1.8.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-kms (1.39.0) + aws-sdk-kms (1.41.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-lakeformation (1.11.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-lambda (1.51.0) + aws-sdk-lambda (1.57.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-lambdapreview (1.24.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-lex (1.32.0) + aws-sdk-lex (1.33.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-lexmodelbuildingservice (1.42.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-lexmodelsv2 (1.0.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-lexmodelbuildingservice (1.39.0) + aws-sdk-lexruntimev2 (1.0.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-licensemanager (1.20.0) + aws-sdk-licensemanager (1.23.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-lightsail (1.39.0) + aws-sdk-lightsail (1.41.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-locationservice (1.0.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-lookoutforvision (1.0.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-machinelearning (1.25.0) @@ -503,31 +564,31 @@ GEM aws-sdk-macie (1.25.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-macie2 (1.13.0) + aws-sdk-macie2 (1.19.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-managedblockchain (1.17.0) + aws-sdk-managedblockchain (1.18.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-marketplacecatalog (1.9.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-marketplacecommerceanalytics (1.29.0) + aws-sdk-marketplacecommerceanalytics (1.30.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-marketplaceentitlementservice (1.24.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-marketplacemetering (1.31.0) + aws-sdk-marketplacemetering (1.32.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-mediaconnect (1.28.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-mediaconvert (1.58.0) + aws-sdk-mediaconvert (1.61.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-medialive (1.56.0) + aws-sdk-medialive (1.61.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-mediapackage (1.36.0) @@ -542,7 +603,7 @@ GEM aws-sdk-mediastoredata (1.27.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-mediatailor (1.32.0) + aws-sdk-mediatailor (1.33.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-migrationhub (1.29.0) @@ -554,16 +615,22 @@ GEM aws-sdk-mobile (1.24.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-mq (1.33.0) + aws-sdk-mq (1.34.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-mturk (1.27.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-neptune (1.30.0) + aws-sdk-mwaa (1.0.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-networkmanager (1.8.0) + aws-sdk-neptune (1.32.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-networkfirewall (1.0.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-networkmanager (1.9.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-opsworks (1.30.0) @@ -572,25 +639,25 @@ GEM aws-sdk-opsworkscm (1.40.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-organizations (1.52.0) + aws-sdk-organizations (1.55.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-outposts (1.10.0) + aws-sdk-outposts (1.13.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-personalize (1.19.0) + aws-sdk-personalize (1.20.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-personalizeevents (1.14.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-personalizeruntime (1.18.0) + aws-sdk-personalizeruntime (1.20.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-pi (1.24.0) + aws-sdk-pi (1.25.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-pinpoint (1.47.0) + aws-sdk-pinpoint (1.48.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-pinpointemail (1.24.0) @@ -599,31 +666,34 @@ GEM aws-sdk-pinpointsmsvoice (1.21.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-polly (1.37.0) + aws-sdk-polly (1.38.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-pricing (1.24.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) + aws-sdk-prometheusservice (1.1.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) aws-sdk-qldb (1.11.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-qldbsession (1.9.0) + aws-sdk-qldbsession (1.10.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-quicksight (1.33.0) + aws-sdk-quicksight (1.39.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-ram (1.22.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-rds (1.104.0) + aws-sdk-rds (1.111.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-rdsdataservice (1.23.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-redshift (1.50.0) + aws-sdk-redshift (1.53.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-redshiftdataapiservice (1.2.0) @@ -632,30 +702,34 @@ GEM aws-sdk-rekognition (1.47.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-resourcegroups (1.32.0) + aws-sdk-resourcegroups (1.33.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-resourcegroupstaggingapi (1.34.0) + aws-sdk-resourcegroupstaggingapi (1.35.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-resources (3.84.0) + aws-sdk-resources (3.94.0) aws-sdk-accessanalyzer (~> 1) aws-sdk-acm (~> 1) aws-sdk-acmpca (~> 1) aws-sdk-alexaforbusiness (~> 1) aws-sdk-amplify (~> 1) + aws-sdk-amplifybackend (~> 1) aws-sdk-apigateway (~> 1) aws-sdk-apigatewaymanagementapi (~> 1) aws-sdk-apigatewayv2 (~> 1) aws-sdk-appconfig (~> 1) aws-sdk-appflow (~> 1) + aws-sdk-appintegrationsservice (~> 1) aws-sdk-applicationautoscaling (~> 1) aws-sdk-applicationdiscoveryservice (~> 1) aws-sdk-applicationinsights (~> 1) aws-sdk-appmesh (~> 1) + aws-sdk-appregistry (~> 1) aws-sdk-appstream (~> 1) aws-sdk-appsync (~> 1) aws-sdk-athena (~> 1) + aws-sdk-auditmanager (~> 1) aws-sdk-augmentedairuntime (~> 1) aws-sdk-autoscaling (~> 1) aws-sdk-autoscalingplans (~> 1) @@ -694,9 +768,11 @@ GEM aws-sdk-computeoptimizer (~> 1) aws-sdk-configservice (~> 1) aws-sdk-connect (~> 1) + aws-sdk-connectcontactlens (~> 1) aws-sdk-connectparticipant (~> 1) aws-sdk-costandusagereportservice (~> 1) aws-sdk-costexplorer (~> 1) + aws-sdk-customerprofiles (~> 1) aws-sdk-databasemigrationservice (~> 1) aws-sdk-dataexchange (~> 1) aws-sdk-datapipeline (~> 1) @@ -704,6 +780,7 @@ GEM aws-sdk-dax (~> 1) aws-sdk-detective (~> 1) aws-sdk-devicefarm (~> 1) + aws-sdk-devopsguru (~> 1) aws-sdk-directconnect (~> 1) aws-sdk-directoryservice (~> 1) aws-sdk-dlm (~> 1) @@ -714,6 +791,7 @@ GEM aws-sdk-ec2 (~> 1) aws-sdk-ec2instanceconnect (~> 1) aws-sdk-ecr (~> 1) + aws-sdk-ecrpublic (~> 1) aws-sdk-ecs (~> 1) aws-sdk-efs (~> 1) aws-sdk-eks (~> 1) @@ -725,6 +803,7 @@ GEM aws-sdk-elasticsearchservice (~> 1) aws-sdk-elastictranscoder (~> 1) aws-sdk-emr (~> 1) + aws-sdk-emrcontainers (~> 1) aws-sdk-eventbridge (~> 1) aws-sdk-firehose (~> 1) aws-sdk-fms (~> 1) @@ -736,10 +815,13 @@ GEM aws-sdk-glacier (~> 1) aws-sdk-globalaccelerator (~> 1) aws-sdk-glue (~> 1) + aws-sdk-gluedatabrew (~> 1) aws-sdk-greengrass (~> 1) + aws-sdk-greengrassv2 (~> 1) aws-sdk-groundstation (~> 1) aws-sdk-guardduty (~> 1) aws-sdk-health (~> 1) + aws-sdk-healthlake (~> 1) aws-sdk-honeycode (~> 1) aws-sdk-iam (~> 1) aws-sdk-identitystore (~> 1) @@ -751,12 +833,15 @@ GEM aws-sdk-iot1clickprojects (~> 1) aws-sdk-iotanalytics (~> 1) aws-sdk-iotdataplane (~> 1) + aws-sdk-iotdeviceadvisor (~> 1) aws-sdk-iotevents (~> 1) aws-sdk-ioteventsdata (~> 1) + aws-sdk-iotfleethub (~> 1) aws-sdk-iotjobsdataplane (~> 1) aws-sdk-iotsecuretunneling (~> 1) aws-sdk-iotsitewise (~> 1) aws-sdk-iotthingsgraph (~> 1) + aws-sdk-iotwireless (~> 1) aws-sdk-ivs (~> 1) aws-sdk-kafka (~> 1) aws-sdk-kendra (~> 1) @@ -773,8 +858,12 @@ GEM aws-sdk-lambdapreview (~> 1) aws-sdk-lex (~> 1) aws-sdk-lexmodelbuildingservice (~> 1) + aws-sdk-lexmodelsv2 (~> 1) + aws-sdk-lexruntimev2 (~> 1) aws-sdk-licensemanager (~> 1) aws-sdk-lightsail (~> 1) + aws-sdk-locationservice (~> 1) + aws-sdk-lookoutforvision (~> 1) aws-sdk-machinelearning (~> 1) aws-sdk-macie (~> 1) aws-sdk-macie2 (~> 1) @@ -796,7 +885,9 @@ GEM aws-sdk-mobile (~> 1) aws-sdk-mq (~> 1) aws-sdk-mturk (~> 1) + aws-sdk-mwaa (~> 1) aws-sdk-neptune (~> 1) + aws-sdk-networkfirewall (~> 1) aws-sdk-networkmanager (~> 1) aws-sdk-opsworks (~> 1) aws-sdk-opsworkscm (~> 1) @@ -811,6 +902,7 @@ GEM aws-sdk-pinpointsmsvoice (~> 1) aws-sdk-polly (~> 1) aws-sdk-pricing (~> 1) + aws-sdk-prometheusservice (~> 1) aws-sdk-qldb (~> 1) aws-sdk-qldbsession (~> 1) aws-sdk-quicksight (~> 1) @@ -830,6 +922,8 @@ GEM aws-sdk-s3control (~> 1) aws-sdk-s3outposts (~> 1) aws-sdk-sagemaker (~> 1) + aws-sdk-sagemakeredgemanager (~> 1) + aws-sdk-sagemakerfeaturestoreruntime (~> 1) aws-sdk-sagemakerruntime (~> 1) aws-sdk-savingsplans (~> 1) aws-sdk-schemas (~> 1) @@ -866,38 +960,45 @@ GEM aws-sdk-waf (~> 1) aws-sdk-wafregional (~> 1) aws-sdk-wafv2 (~> 1) + aws-sdk-wellarchitected (~> 1) aws-sdk-workdocs (~> 1) aws-sdk-worklink (~> 1) aws-sdk-workmail (~> 1) aws-sdk-workmailmessageflow (~> 1) aws-sdk-workspaces (~> 1) aws-sdk-xray (~> 1) - aws-sdk-robomaker (1.30.0) + aws-sdk-robomaker (1.31.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-route53 (1.44.0) + aws-sdk-route53 (1.45.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-route53domains (1.28.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-route53resolver (1.21.0) + aws-sdk-route53resolver (1.22.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.83.0) + aws-sdk-s3 (1.87.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.1) - aws-sdk-s3control (1.24.0) + aws-sdk-s3control (1.26.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-s3outposts (1.0.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-sagemaker (1.70.0) + aws-sdk-sagemaker (1.75.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-sagemakeredgemanager (1.0.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-sagemakerfeaturestoreruntime (1.0.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-sagemakerruntime (1.27.0) + aws-sdk-sagemakerruntime (1.28.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-savingsplans (1.12.0) @@ -909,31 +1010,31 @@ GEM aws-sdk-secretsmanager (1.43.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-securityhub (1.35.0) + aws-sdk-securityhub (1.38.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-serverlessapplicationrepository (1.32.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-servicecatalog (1.50.0) + aws-sdk-servicecatalog (1.57.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-servicediscovery (1.31.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-servicequotas (1.11.0) + aws-sdk-servicequotas (1.12.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-ses (1.36.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-sesv2 (1.13.0) + aws-sdk-sesv2 (1.14.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-shield (1.32.0) + aws-sdk-shield (1.33.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-signer (1.26.0) + aws-sdk-signer (1.27.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-simpledb (1.24.0) @@ -945,25 +1046,25 @@ GEM aws-sdk-snowball (1.35.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-sns (1.33.0) + aws-sdk-sns (1.37.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-sqs (1.34.0) + aws-sdk-sqs (1.35.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-ssm (1.94.0) + aws-sdk-ssm (1.103.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-ssoadmin (1.3.0) + aws-sdk-ssoadmin (1.4.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-ssooidc (1.8.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-states (1.36.0) + aws-sdk-states (1.37.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-storagegateway (1.50.0) + aws-sdk-storagegateway (1.52.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-support (1.28.0) @@ -972,28 +1073,28 @@ GEM aws-sdk-swf (1.25.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-synthetics (1.9.0) + aws-sdk-synthetics (1.10.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-textract (1.21.0) + aws-sdk-textract (1.22.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-timestreamquery (1.1.0) + aws-sdk-timestreamquery (1.2.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-timestreamwrite (1.1.0) + aws-sdk-timestreamwrite (1.2.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-transcribeservice (1.50.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-transcribestreamingservice (1.22.0) + aws-sdk-transcribestreamingservice (1.24.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-transfer (1.28.0) + aws-sdk-transfer (1.29.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-translate (1.28.0) + aws-sdk-translate (1.29.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-waf (1.36.0) @@ -1005,22 +1106,25 @@ GEM aws-sdk-wafv2 (1.14.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) + aws-sdk-wellarchitected (1.0.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) aws-sdk-workdocs (1.28.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-worklink (1.21.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-workmail (1.32.0) + aws-sdk-workmail (1.33.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sdk-workmailmessageflow (1.9.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-workspaces (1.48.0) + aws-sdk-workspaces (1.49.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-xray (1.34.0) + aws-sdk-xray (1.35.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) aws-sigv2 (1.0.1) @@ -1033,22 +1137,22 @@ GEM barnes (0.0.8) multi_json (~> 1) statsd-ruby (~> 1.1) - better_errors (2.8.3) + better_errors (2.9.1) coderay (>= 1.0.0) erubi (>= 1.0.0) rack (>= 0.9.0) - binding_of_caller (0.8.0) + binding_of_caller (1.0.0) debug_inspector (>= 0.0.1) - bootsnap (1.4.8) + bootsnap (1.5.1) msgpack (~> 1.0) - bootstrap (4.5.2) + bootstrap (4.5.3) autoprefixer-rails (>= 9.1.0) popper_js (>= 1.14.3, < 2) sassc-rails (>= 2.0.0) - browser (5.1.0) + browser (5.3.0) builder (3.2.4) byebug (11.1.3) - capybara (3.33.0) + capybara (3.34.0) addressable mini_mime (>= 0.1.3) nokogiri (~> 1.8) @@ -1058,43 +1162,47 @@ GEM xpath (~> 3.2) childprocess (3.0.0) coderay (1.1.3) - commonmarker (0.21.0) + commonmarker (0.21.1) ruby-enum (~> 0.5) - concurrent-ruby (1.1.7) + concurrent-ruby (1.1.8) connection_pool (2.2.3) - crack (0.4.4) + crack (0.4.5) + rexml crass (1.0.6) database_cleaner (1.8.5) - debug_inspector (0.0.3) + debug_inspector (1.0.0) deterministic (0.6.0) diff-lcs (1.4.4) - docile (1.3.2) + docile (1.3.5) dotenv (2.7.6) dotenv-rails (2.7.6) dotenv (= 2.7.6) railties (>= 3.2) - erubi (1.9.0) + erubi (1.10.0) execjs (2.7.0) factory_bot (6.1.0) activesupport (>= 5.0.0) factory_bot_rails (6.1.0) factory_bot (~> 6.1.0) railties (>= 5.0.0) - faraday (1.0.1) + faraday (1.3.0) + faraday-net_http (~> 1.0) multipart-post (>= 1.2, < 3) - ffi (1.13.1) + ruby2_keywords + faraday-net_http (1.0.1) + ffi (1.14.2) flamegraph (0.9.5) - font-awesome-rails (4.7.0.5) - railties (>= 3.2, < 6.1) + font-awesome-rails (4.7.0.6) + railties (>= 3.2, < 6.2) foreman (0.87.2) - github-markup (3.0.4) + github-markup (3.0.5) github_url (0.2.1) - gitlab (4.16.1) - httparty (~> 0.14, >= 0.14.0) + gitlab (4.17.0) + httparty (~> 0.18) terminal-table (~> 1.5, >= 1.5.1) globalid (0.4.2) activesupport (>= 4.2.0) - haml (5.2.0) + haml (5.2.1) temple (>= 0.8.0) tilt hashdiff (1.0.1) @@ -1102,7 +1210,7 @@ GEM httparty (0.18.1) mime-types (~> 3.0) multi_xml (>= 0.5.2) - i18n (1.8.5) + i18n (1.8.7) concurrent-ruby (~> 1.0) iniparse (1.5.0) jmespath (1.4.0) @@ -1110,9 +1218,8 @@ GEM rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) - js-routes (1.4.9) + js-routes (1.4.14) railties (>= 4) - sprockets-rails json_spec (1.1.5) multi_json (~> 1.0) rspec (>= 2.0, < 4.0) @@ -1123,10 +1230,10 @@ GEM addressable (~> 2.7) letter_opener (1.7.0) launchy (~> 2.2) - listen (3.2.1) + listen (3.4.1) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) - loofah (2.7.0) + loofah (2.9.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) @@ -1135,64 +1242,66 @@ GEM mimemagic (~> 0.3.2) mathjax-rails (2.6.1) railties (>= 3.0) - memory_profiler (0.9.14) + memory_profiler (1.0.0) method_source (1.0.0) mime-types (3.3.1) mime-types-data (~> 3.2015) - mime-types-data (3.2020.0512) + mime-types-data (3.2020.1104) mimemagic (0.3.5) mini_mime (1.0.2) - mini_portile2 (2.4.0) - minitest (5.14.2) + mini_portile2 (2.5.0) + minitest (5.14.3) msgpack (1.3.3) multi_json (1.15.0) multi_xml (0.6.0) multipart-post (2.1.1) mustache (1.1.1) nio4r (2.5.4) - nokogiri (1.10.10) - mini_portile2 (~> 2.4.0) - octokit (4.18.0) + nokogiri (1.11.1) + mini_portile2 (~> 2.5.0) + racc (~> 1.4) + octokit (4.20.0) faraday (>= 0.9) sawyer (~> 0.8.0, >= 0.5.3) overcommit (0.57.0) childprocess (>= 0.6.3, < 5) iniparse (~> 1.4) - pagy (3.8.3) - parallel (1.19.2) - parser (2.7.2.0) + pagy (3.10.0) + parallel (1.20.1) + parser (3.0.0.0) ast (~> 2.4.1) pg (1.2.3) popper_js (1.16.0) - psych (3.2.0) + psych (3.3.0) public_suffix (4.0.6) - puma (5.0.2) + puma (5.1.1) nio4r (~> 2.0) pundit (2.1.0) activesupport (>= 3.0.0) + racc (1.5.2) rack (2.2.3) rack-attack (6.3.1) rack (>= 1.0, < 3) - rack-mini-profiler (2.1.0) + rack-mini-profiler (2.3.0) rack (>= 1.2.0) rack-proxy (0.6.5) rack rack-test (1.1.0) rack (>= 1.0, < 3) - rails (6.0.3.4) - actioncable (= 6.0.3.4) - actionmailbox (= 6.0.3.4) - actionmailer (= 6.0.3.4) - actionpack (= 6.0.3.4) - actiontext (= 6.0.3.4) - actionview (= 6.0.3.4) - activejob (= 6.0.3.4) - activemodel (= 6.0.3.4) - activerecord (= 6.0.3.4) - activestorage (= 6.0.3.4) - activesupport (= 6.0.3.4) - bundler (>= 1.3.0) - railties (= 6.0.3.4) + rails (6.1.1) + actioncable (= 6.1.1) + actionmailbox (= 6.1.1) + actionmailer (= 6.1.1) + actionpack (= 6.1.1) + actiontext (= 6.1.1) + actionview (= 6.1.1) + activejob (= 6.1.1) + activemodel (= 6.1.1) + activerecord (= 6.1.1) + activestorage (= 6.1.1) + activesupport (= 6.1.1) + bundler (>= 1.15.0) + railties (= 6.1.1) sprockets-rails (>= 2.0.0) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) @@ -1203,14 +1312,14 @@ GEM nokogiri (>= 1.6) rails-html-sanitizer (1.3.0) loofah (~> 2.3) - railties (6.0.3.4) - actionpack (= 6.0.3.4) - activesupport (= 6.0.3.4) + railties (6.1.1) + actionpack (= 6.1.1) + activesupport (= 6.1.1) method_source rake (>= 0.8.7) - thor (>= 0.20.3, < 2.0) + thor (~> 1.0) rainbow (3.0.0) - rake (13.0.1) + rake (13.0.3) rb-fsevent (0.10.4) rb-inotify (0.10.1) ffi (~> 1.0) @@ -1220,51 +1329,52 @@ GEM execjs railties (>= 3.2) tilt - redcarpet (3.5.0) - redis (4.2.2) + redcarpet (3.5.1) + redis (4.2.5) regexp_parser (1.8.2) rexml (3.2.4) - rspec (3.9.0) - rspec-core (~> 3.9.0) - rspec-expectations (~> 3.9.0) - rspec-mocks (~> 3.9.0) - rspec-core (3.9.3) - rspec-support (~> 3.9.3) - rspec-expectations (3.9.2) + rspec (3.10.0) + rspec-core (~> 3.10.0) + rspec-expectations (~> 3.10.0) + rspec-mocks (~> 3.10.0) + rspec-core (3.10.1) + rspec-support (~> 3.10.0) + rspec-expectations (3.10.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.9.0) - rspec-mocks (3.9.1) + rspec-support (~> 3.10.0) + rspec-mocks (3.10.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.9.0) - rspec-rails (4.0.1) + rspec-support (~> 3.10.0) + rspec-rails (4.0.2) actionpack (>= 4.2) activesupport (>= 4.2) railties (>= 4.2) - rspec-core (~> 3.9) - rspec-expectations (~> 3.9) - rspec-mocks (~> 3.9) - rspec-support (~> 3.9) - rspec-support (3.9.3) + rspec-core (~> 3.10) + rspec-expectations (~> 3.10) + rspec-mocks (~> 3.10) + rspec-support (~> 3.10) + rspec-support (3.10.1) rspec_api_documentation (6.1.0) activesupport (>= 3.0.0) mustache (~> 1.0, >= 0.99.4) rspec (~> 3.0) rspec_junit_formatter (0.4.1) rspec-core (>= 2, < 4, != 2.12.0) - rubocop (0.93.1) + rubocop (1.8.1) parallel (~> 1.10) - parser (>= 2.7.1.5) + parser (>= 3.0.0.0) rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.8) + regexp_parser (>= 1.8, < 3.0) rexml - rubocop-ast (>= 0.6.0) + rubocop-ast (>= 1.2.0, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 2.0) - rubocop-ast (0.8.0) + unicode-display_width (>= 1.4.0, < 3.0) + rubocop-ast (1.4.0) parser (>= 2.7.1.5) ruby-enum (0.8.0) i18n - ruby-progressbar (1.10.1) + ruby-progressbar (1.11.0) + ruby2_keywords (0.0.4) rubyzip (2.3.0) sass-rails (6.0.0) sassc-rails (~> 2.1, >= 2.1.1) @@ -1279,22 +1389,24 @@ GEM sawyer (0.8.2) addressable (>= 2.3.5) faraday (> 0.8, < 2.0) - scout_apm (2.6.9) + scout_apm (4.0.3) parser selenium-webdriver (3.142.7) childprocess (>= 0.5, < 4.0) rubyzip (>= 1.2.2) - semantic_range (2.3.0) - shoulda-matchers (4.4.1) + semantic_range (2.3.1) + shoulda-matchers (4.5.1) activesupport (>= 4.2.0) - sidekiq (6.1.2) + sidekiq (6.1.3) connection_pool (>= 2.2.2) rack (~> 2.0) redis (>= 4.2.0) - simplecov (0.19.0) + simplecov (0.21.2) docile (~> 1.1) simplecov-html (~> 0.11) + simplecov_json_formatter (~> 0.1) simplecov-html (0.12.3) + simplecov_json_formatter (0.1.2) solid_use_case (2.2.0) deterministic (~> 0.6.0) sprockets (4.0.2) @@ -1304,25 +1416,23 @@ GEM actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) - stackprof (0.2.15) - statsd-ruby (1.4.0) + stackprof (0.2.16) + statsd-ruby (1.5.0) temple (0.8.2) - terminal-table (1.8.0) - unicode-display_width (~> 1.1, >= 1.1.1) - thor (1.0.1) - thread_safe (0.3.6) + terminal-table (1.6.0) + thor (1.1.0) tilt (2.0.10) timecop (0.9.2) ts_routes (1.0.3) railties (>= 4.0) - tzinfo (1.2.7) - thread_safe (~> 0.1) + tzinfo (2.0.4) + concurrent-ruby (~> 1.0) uglifier (4.2.0) execjs (>= 0.3.0, < 3) underscore-rails (1.8.3) - unicode-display_width (1.7.0) + unicode-display_width (2.0.0) vcr (6.0.0) - webmock (3.9.2) + webmock (3.11.1) addressable (>= 2.3.6) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) @@ -1336,7 +1446,7 @@ GEM websocket-extensions (0.1.5) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.4.0) + zeitwerk (2.4.2) zip-zip (0.3) rubyzip (>= 1.0.0) diff --git a/scripts/bundles/bundle.tar.gz.REMOVED.git-id b/scripts/bundles/bundle.tar.gz.REMOVED.git-id index 4b90411..4d2c500 100644 --- a/scripts/bundles/bundle.tar.gz.REMOVED.git-id +++ b/scripts/bundles/bundle.tar.gz.REMOVED.git-id @@ -1 +1 @@ -e949587cc2c87f431a7d318d7b8e4853a8b1859d \ No newline at end of file +200756010d7b37199ed54c0795a6c377cb33f8aa \ No newline at end of file diff --git a/scripts/bundles/node_modules.tar.gz.REMOVED.git-id b/scripts/bundles/node_modules.tar.gz.REMOVED.git-id index 4e9c14f..f47e9e9 100644 --- a/scripts/bundles/node_modules.tar.gz.REMOVED.git-id +++ b/scripts/bundles/node_modules.tar.gz.REMOVED.git-id @@ -1 +1 @@ -3766c04acbeedd18f840987086baad4f7ac75904 \ No newline at end of file +9d9fcd20003a816854393a6e7ac24b19b3a0b904 \ No newline at end of file diff --git a/scripts/gems/block-parser/Gemfile.lock b/scripts/gems/block-parser/Gemfile.lock index 3d84f82..aaece8f 100644 --- a/scripts/gems/block-parser/Gemfile.lock +++ b/scripts/gems/block-parser/Gemfile.lock @@ -16,95 +16,100 @@ PATH GEM remote: https://rubygems.org/ specs: - activemodel (6.0.3.4) - activesupport (= 6.0.3.4) - activesupport (6.0.3.4) + activemodel (6.1.1) + activesupport (= 6.1.1) + activesupport (6.1.1) concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - zeitwerk (~> 2.2, >= 2.2.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + zeitwerk (~> 2.3) addressable (2.7.0) public_suffix (>= 2.0.2, < 5.0) ast (2.4.1) byebug (11.1.3) - commonmarker (0.21.0) + commonmarker (0.21.1) ruby-enum (~> 0.5) - concurrent-ruby (1.1.7) + concurrent-ruby (1.1.8) diff-lcs (1.4.4) - faraday (1.0.1) + faraday (1.3.0) + faraday-net_http (~> 1.0) multipart-post (>= 1.2, < 3) - github-markup (3.0.4) + ruby2_keywords + faraday-net_http (1.0.1) + github-markup (3.0.5) github_url (0.2.1) - gitlab (4.16.1) - httparty (~> 0.14, >= 0.14.0) + gitlab (4.17.0) + httparty (~> 0.18) terminal-table (~> 1.5, >= 1.5.1) httparty (0.18.1) mime-types (~> 3.0) multi_xml (>= 0.5.2) - i18n (1.8.5) + i18n (1.8.7) concurrent-ruby (~> 1.0) mime-types (3.3.1) mime-types-data (~> 3.2015) - mime-types-data (3.2020.0512) - mini_portile2 (2.4.0) - minitest (5.14.2) + mime-types-data (3.2020.1104) + mini_portile2 (2.5.0) + minitest (5.14.3) multi_xml (0.6.0) multipart-post (2.1.1) - nokogiri (1.10.10) - mini_portile2 (~> 2.4.0) - octokit (4.18.0) + nokogiri (1.11.1) + mini_portile2 (~> 2.5.0) + racc (~> 1.4) + octokit (4.20.0) faraday (>= 0.9) sawyer (~> 0.8.0, >= 0.5.3) - parallel (1.19.2) - parser (2.7.2.0) + parallel (1.20.1) + parser (3.0.0.0) ast (~> 2.4.1) - psych (3.2.0) + psych (3.3.0) public_suffix (4.0.6) + racc (1.5.2) rainbow (3.0.0) - rake (13.0.1) - redcarpet (3.5.0) - regexp_parser (1.8.2) + rake (13.0.3) + redcarpet (3.5.1) + regexp_parser (2.0.3) rexml (3.2.4) - rspec (3.9.0) - rspec-core (~> 3.9.0) - rspec-expectations (~> 3.9.0) - rspec-mocks (~> 3.9.0) - rspec-core (3.9.3) - rspec-support (~> 3.9.3) - rspec-expectations (3.9.2) + rspec (3.10.0) + rspec-core (~> 3.10.0) + rspec-expectations (~> 3.10.0) + rspec-mocks (~> 3.10.0) + rspec-core (3.10.1) + rspec-support (~> 3.10.0) + rspec-expectations (3.10.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.9.0) - rspec-mocks (3.9.1) + rspec-support (~> 3.10.0) + rspec-mocks (3.10.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.9.0) - rspec-support (3.9.3) + rspec-support (~> 3.10.0) + rspec-support (3.10.1) rspec_junit_formatter (0.4.1) rspec-core (>= 2, < 4, != 2.12.0) - rubocop (0.93.1) + rubocop (1.8.1) parallel (~> 1.10) - parser (>= 2.7.1.5) + parser (>= 3.0.0.0) rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.8) + regexp_parser (>= 1.8, < 3.0) rexml - rubocop-ast (>= 0.6.0) + rubocop-ast (>= 1.2.0, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 2.0) - rubocop-ast (0.8.0) + unicode-display_width (>= 1.4.0, < 3.0) + rubocop-ast (1.4.0) parser (>= 2.7.1.5) ruby-enum (0.8.0) i18n - ruby-progressbar (1.10.1) + ruby-progressbar (1.11.0) + ruby2_keywords (0.0.4) sawyer (0.8.2) addressable (>= 2.3.5) faraday (> 0.8, < 2.0) terminal-table (1.8.0) unicode-display_width (~> 1.1, >= 1.1.1) - thread_safe (0.3.6) - tzinfo (1.2.7) - thread_safe (~> 0.1) + tzinfo (2.0.4) + concurrent-ruby (~> 1.0) unicode-display_width (1.7.0) - zeitwerk (2.4.0) + zeitwerk (2.4.2) PLATFORMS ruby diff --git a/scripts/package.json b/scripts/package.json index 0057077..75fdb56 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -39,13 +39,13 @@ "popper.js": "^1.16.1", "prop-types": "^15.7.2", "rc-slider": "Galvanize-IT/slider#c569ca3b11979aced8306e6c02f37466cb7cd365", - "react": "^16.14.0", + "react": "^17.0.1", "react-addons-css-transition-group": "^15.6.2", "react-addons-test-utils": "^15.6.2", "react-beautiful-dnd": "^13.0.0", "react-copy-to-clipboard": "^5.0.3", "react-datepicker": "^3.4.1", - "react-dom": "^16.14.0", + "react-dom": "^17.0.1", "react-json-pretty": "^2.2.0", "react-paginate": "^7.0.0", "react-pdf": "^4.2.0", @@ -63,12 +63,12 @@ "@types/lodash-es": "^4.17.3", "@types/node-fetch": "^2.5.8", "@types/rc-slider": "^8.6.6", - "@types/react": "^16.9.56", + "@types/react": "^17.0.0", "@types/react-addons-css-transition-group": "^15.0.5", "@types/react-beautiful-dnd": "^13.0.0", "@types/react-copy-to-clipboard": "^5.0.0", "@types/react-datepicker": "^3.1.3", - "@types/react-dom": "^16.9.9", + "@types/react-dom": "^17.0.0", "@types/react-textarea-autosize": "^4.3.5", "@types/vimeo__player": "^2.10.0", "eslint": "^7.18.0", -- GitLab From e3dff03572f213c965e3f3d1763c11d17209ee52 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 22 Jan 2021 19:38:03 -1000 Subject: [PATCH 232/283] upgrading lodash Former-commit-id: 64cdeba5fa1575f4b8df26c575ebeef86790aac6 --- scripts/bundles/bundle.tar.gz.REMOVED.git-id | 2 +- scripts/bundles/node_modules.tar.gz.REMOVED.git-id | 2 +- scripts/package.json | 3 +++ scripts/yarn.lock | 6 +----- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/scripts/bundles/bundle.tar.gz.REMOVED.git-id b/scripts/bundles/bundle.tar.gz.REMOVED.git-id index 4d2c500..89036ce 100644 --- a/scripts/bundles/bundle.tar.gz.REMOVED.git-id +++ b/scripts/bundles/bundle.tar.gz.REMOVED.git-id @@ -1 +1 @@ -200756010d7b37199ed54c0795a6c377cb33f8aa \ No newline at end of file +10ac483f32e0fca9d2c80d9d452ebe0909cc8565 \ No newline at end of file diff --git a/scripts/bundles/node_modules.tar.gz.REMOVED.git-id b/scripts/bundles/node_modules.tar.gz.REMOVED.git-id index f47e9e9..c8dd64b 100644 --- a/scripts/bundles/node_modules.tar.gz.REMOVED.git-id +++ b/scripts/bundles/node_modules.tar.gz.REMOVED.git-id @@ -1 +1 @@ -9d9fcd20003a816854393a6e7ac24b19b3a0b904 \ No newline at end of file +496063f7686db1ceb7714693ad3608674591c583 \ No newline at end of file diff --git a/scripts/package.json b/scripts/package.json index 75fdb56..14e26cb 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -82,5 +82,8 @@ "postcss-import": "^12.0.1", "postcss-preset-env": "^6.7.0", "webpack-dev-server": "^3.11.2" + }, + "resolutions": { + "lodash": "^4.17.20" } } diff --git a/scripts/yarn.lock b/scripts/yarn.lock index c271a6d..cfb8198 100644 --- a/scripts/yarn.lock +++ b/scripts/yarn.lock @@ -5333,11 +5333,7 @@ lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" -lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.4, lodash@~4.17.10: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - -lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.5: +lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4, lodash@^4.17.5, lodash@~4.17.10: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== -- GitLab From 7f4aa0591140b161973dd9082117d094d09c7659 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 22 Jan 2021 22:58:26 -1000 Subject: [PATCH 233/283] fixing docker file. updating modules Former-commit-id: d84029603e55753a29056d94132159677628783b --- Dockerfile | 8 +- scripts/bundles/bundle.tar.gz.REMOVED.git-id | 2 +- .../node_modules.tar.gz.REMOVED.git-id | 2 +- scripts/package.json | 10 ++- scripts/yarn.lock | 83 +++++++------------ 5 files changed, 46 insertions(+), 59 deletions(-) diff --git a/Dockerfile b/Dockerfile index 817917c..4b7920f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ RUN dnf update -y && dnf install -y \ # Setup our environment WORKDIR /app -ADD ./scripts . +COPY ./scripts . # Switch to the binary directory. WORKDIR /app/bundles @@ -49,6 +49,9 @@ RUN mv yarn-v1.22.5 /app/yarn # Switch back to app directory. WORKDIR /app +# Remove the bundles directory. +RUN rm -rf bundles + # Add write permissions. RUN chown -R 1001 . @@ -69,5 +72,8 @@ RUN bundle exec rake assets:precompile # Asset Clean RUN bundle exec rake assets:clean +# Health check. +HEALTHCHECK none + # Set the entry point. ENTRYPOINT ["/app/entrypoint-server.sh"] diff --git a/scripts/bundles/bundle.tar.gz.REMOVED.git-id b/scripts/bundles/bundle.tar.gz.REMOVED.git-id index 89036ce..33f3ce2 100644 --- a/scripts/bundles/bundle.tar.gz.REMOVED.git-id +++ b/scripts/bundles/bundle.tar.gz.REMOVED.git-id @@ -1 +1 @@ -10ac483f32e0fca9d2c80d9d452ebe0909cc8565 \ No newline at end of file +1e00d7dfa42b51862181fa5607c250fc41de3d22 \ No newline at end of file diff --git a/scripts/bundles/node_modules.tar.gz.REMOVED.git-id b/scripts/bundles/node_modules.tar.gz.REMOVED.git-id index c8dd64b..aee6e2e 100644 --- a/scripts/bundles/node_modules.tar.gz.REMOVED.git-id +++ b/scripts/bundles/node_modules.tar.gz.REMOVED.git-id @@ -1 +1 @@ -496063f7686db1ceb7714693ad3608674591c583 \ No newline at end of file +2c1e25ca234f1529cfb072af94c49b6ff0fb3f69 \ No newline at end of file diff --git a/scripts/package.json b/scripts/package.json index 14e26cb..0d87798 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -84,6 +84,14 @@ "webpack-dev-server": "^3.11.2" }, "resolutions": { - "lodash": "^4.17.20" + "acorn": "^7.1.1", + "dot-prop": "^4.2.1", + "elliptic": "^6.5.3", + "ini": "^1.3.6", + "kind-of": "^6.0.3", + "lodash": "^4.17.20", + "mathjax": "^2.7.4", + "minimist": "^1.2.3", + "websocket-extensions": "^0.1.4" } } diff --git a/scripts/yarn.lock b/scripts/yarn.lock index cfb8198..669aa41 100644 --- a/scripts/yarn.lock +++ b/scripts/yarn.lock @@ -1297,20 +1297,7 @@ acorn-walk@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.0.0.tgz#c8ba6f0f1aac4b0a9e32d1f0af12be769528f36b" -acorn@^5.2.1: - version "5.7.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" - -acorn@^6.4.1: - version "6.4.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" - integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== - -acorn@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.0.0.tgz#26b8d1cd9a9b700350b71c0905546f64d1284e7a" - -acorn@^7.4.0: +acorn@^5.2.1, acorn@^6.4.1, acorn@^7.0.0, acorn@^7.1.1, acorn@^7.4.0: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== @@ -3184,9 +3171,10 @@ domutils@^1.7.0: dom-serializer "0" domelementtype "1" -dot-prop@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" +dot-prop@^4.1.1, dot-prop@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.1.tgz#45884194a71fc2cda71cbb4bceb3a4dd2f433ba4" + integrity sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ== dependencies: is-obj "^1.0.0" @@ -3237,9 +3225,10 @@ element-resize-detector@^1.2.1: dependencies: batch-processor "1.0.0" -elliptic@^6.0.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.0.tgz#2b8ed4c891b7de3200e14412a5b8248c7af505ca" +elliptic@^6.0.0, elliptic@^6.5.3: + version "6.5.3" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6" + integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw== dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -4619,9 +4608,10 @@ inherits@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" -ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" +ini@^1.3.4, ini@^1.3.5, ini@^1.3.6, ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== inline-source-map@~0.6.0: version "0.6.2" @@ -4737,7 +4727,7 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-buffer@^1.1.0, is-buffer@^1.1.5: +is-buffer@^1.1.0: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" @@ -5124,25 +5114,10 @@ killable@^1.0.1: resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" integrity sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg== -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0, kind-of@^4.0.0, kind-of@^5.0.0, kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== labeled-stream-splicer@^2.0.0: version "2.0.2" @@ -5420,6 +5395,11 @@ marked@^1.2.7: resolved "https://registry.yarnpkg.com/marked/-/marked-1.2.7.tgz#6e14b595581d2319cdcf033a24caaf41455a01fb" integrity sha512-No11hFYcXr/zkBvL6qFmAp1z6BKY3zqLMHny/JN/ey+al7qwCM2+CMBL9BOgqMxZU36fz4cCWfn2poWIf7QRXA== +mathjax@^2.7.4: + version "2.7.9" + resolved "https://registry.yarnpkg.com/mathjax/-/mathjax-2.7.9.tgz#d6b67955c173e7d719fcb2fc0288662884eb7d3d" + integrity sha512-NOGEDTIM9+MrsqnjPEjVGNx4q0GQxqm61yQwSK+/5S59i26wId5IC5gNu9/bu8+CCVl5p9G2IHcAl/wJa+5+BQ== + md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -5569,15 +5549,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: dependencies: brace-expansion "^1.1.7" -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - -minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - -minimist@^1.1.1, minimist@^1.2.5: +minimist@0.0.8, minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -9376,9 +9348,10 @@ websocket-driver@^0.7.4: safe-buffer ">=5.1.0" websocket-extensions ">=0.1.1" -websocket-extensions@>=0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" +websocket-extensions@>=0.1.1, websocket-extensions@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== which-module@^2.0.0: version "2.0.0" -- GitLab From 4fb54336de6a66402ac0bfcb53b21ccac7572282 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Sat, 23 Jan 2021 11:40:21 -1000 Subject: [PATCH 234/283] testing remove of node and yarn after build Former-commit-id: ffc64689a435283aad60303d44b9f13cf04cad3b --- Dockerfile | 5 +++++ scripts/bundles/node_modules.tar.gz.REMOVED.git-id | 2 +- scripts/package.json | 4 ++-- scripts/yarn.lock | 4 ++-- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 4b7920f..12e46f3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -72,6 +72,11 @@ RUN bundle exec rake assets:precompile # Asset Clean RUN bundle exec rake assets:clean +# Remove node and yarn. +RUN rm -rf nodejs +RUN rm -rf yarn +RUN rm -rf node_modules + # Health check. HEALTHCHECK none diff --git a/scripts/bundles/node_modules.tar.gz.REMOVED.git-id b/scripts/bundles/node_modules.tar.gz.REMOVED.git-id index aee6e2e..a170676 100644 --- a/scripts/bundles/node_modules.tar.gz.REMOVED.git-id +++ b/scripts/bundles/node_modules.tar.gz.REMOVED.git-id @@ -1 +1 @@ -2c1e25ca234f1529cfb072af94c49b6ff0fb3f69 \ No newline at end of file +ef4893c7feaf37f2c0a10e210a0875477edb57ef \ No newline at end of file diff --git a/scripts/package.json b/scripts/package.json index 0d87798..d730cd5 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -87,10 +87,10 @@ "acorn": "^7.1.1", "dot-prop": "^4.2.1", "elliptic": "^6.5.3", - "ini": "^1.3.6", + "ini": "^1.3.8", "kind-of": "^6.0.3", "lodash": "^4.17.20", - "mathjax": "^2.7.4", + "mathjax": "^2.7.9", "minimist": "^1.2.3", "websocket-extensions": "^0.1.4" } diff --git a/scripts/yarn.lock b/scripts/yarn.lock index 669aa41..df7585c 100644 --- a/scripts/yarn.lock +++ b/scripts/yarn.lock @@ -4608,7 +4608,7 @@ inherits@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" -ini@^1.3.4, ini@^1.3.5, ini@^1.3.6, ini@~1.3.0: +ini@^1.3.4, ini@^1.3.5, ini@^1.3.8, ini@~1.3.0: version "1.3.8" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== @@ -5395,7 +5395,7 @@ marked@^1.2.7: resolved "https://registry.yarnpkg.com/marked/-/marked-1.2.7.tgz#6e14b595581d2319cdcf033a24caaf41455a01fb" integrity sha512-No11hFYcXr/zkBvL6qFmAp1z6BKY3zqLMHny/JN/ey+al7qwCM2+CMBL9BOgqMxZU36fz4cCWfn2poWIf7QRXA== -mathjax@^2.7.4: +mathjax@^2.7.9: version "2.7.9" resolved "https://registry.yarnpkg.com/mathjax/-/mathjax-2.7.9.tgz#d6b67955c173e7d719fcb2fc0288662884eb7d3d" integrity sha512-NOGEDTIM9+MrsqnjPEjVGNx4q0GQxqm61yQwSK+/5S59i26wId5IC5gNu9/bu8+CCVl5p9G2IHcAl/wJa+5+BQ== -- GitLab From 4bd5fb3f6bf9baa01222e5d5a223ff2df68d9985 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Sat, 23 Jan 2021 12:04:26 -1000 Subject: [PATCH 235/283] adding node bank in Former-commit-id: 81142bccd1363e875274b78657e421d52d0c3415 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 12e46f3..c19aaa7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -73,7 +73,7 @@ RUN bundle exec rake assets:precompile RUN bundle exec rake assets:clean # Remove node and yarn. -RUN rm -rf nodejs +#RUN rm -rf nodejs RUN rm -rf yarn RUN rm -rf node_modules -- GitLab From cf267a764cc6212d6c2a41cc88fb0b54c7718040 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Sat, 23 Jan 2021 12:42:03 -1000 Subject: [PATCH 236/283] updating npm version Former-commit-id: 0783c5d7559a1febb49a124ae64be1d2a759ea4f --- Dockerfile | 3 +-- scripts/bundles/node-v14.15.4-linux-x64.tar.gz.REMOVED.git-id | 2 +- scripts/bundles/node_modules.tar.gz.REMOVED.git-id | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index c19aaa7..be21cc7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -72,8 +72,7 @@ RUN bundle exec rake assets:precompile # Asset Clean RUN bundle exec rake assets:clean -# Remove node and yarn. -#RUN rm -rf nodejs +# Remove yarn and node modules after compile. RUN rm -rf yarn RUN rm -rf node_modules diff --git a/scripts/bundles/node-v14.15.4-linux-x64.tar.gz.REMOVED.git-id b/scripts/bundles/node-v14.15.4-linux-x64.tar.gz.REMOVED.git-id index e1ab22e..5b59680 100644 --- a/scripts/bundles/node-v14.15.4-linux-x64.tar.gz.REMOVED.git-id +++ b/scripts/bundles/node-v14.15.4-linux-x64.tar.gz.REMOVED.git-id @@ -1 +1 @@ -95016bc120595a9214116f158624cf9ea07e7cb8 \ No newline at end of file +47adb6c4a299fbd9ecc10f90ca0dcd5dd1e6d4d1 \ No newline at end of file diff --git a/scripts/bundles/node_modules.tar.gz.REMOVED.git-id b/scripts/bundles/node_modules.tar.gz.REMOVED.git-id index a170676..e925b2c 100644 --- a/scripts/bundles/node_modules.tar.gz.REMOVED.git-id +++ b/scripts/bundles/node_modules.tar.gz.REMOVED.git-id @@ -1 +1 @@ -ef4893c7feaf37f2c0a10e210a0875477edb57ef \ No newline at end of file +20baab03056513e3e89c5d262b91b38004897dc8 \ No newline at end of file -- GitLab From 00b09ffae89770be8415e9db0ec15d685c6b482c Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Sat, 23 Jan 2021 14:09:10 -1000 Subject: [PATCH 237/283] fixing bug in dockerfile Former-commit-id: 4e3ae887bad8533ab69ea492e2cd14713ca32a95 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index be21cc7..a895894 100644 --- a/Dockerfile +++ b/Dockerfile @@ -39,7 +39,7 @@ RUN mv node_modules /app/node_modules # Node.js RUN tar xzf node-v14.15.4-linux-x64.tar.gz RUN rm node-v14.15.4-linux-x64.tar.gz -RUN mv node-v14.15.4-linux-x64 /app/nodejs +RUN mv nodejs /app/nodejs # Yarn RUN tar xzf yarn-v1.22.5.tar.gz -- GitLab From 1e7f73ca738bf631cbac6d1ae0492b342009a079 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Sat, 23 Jan 2021 14:19:04 -1000 Subject: [PATCH 238/283] removing symbolic link Former-commit-id: 72f243bcf0526d27c2a1fb1c6922aa7f2240c8a2 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index a895894..e368355 100644 --- a/Dockerfile +++ b/Dockerfile @@ -64,7 +64,7 @@ ENV NODE_HOME /app/nodejs ENV PATH /app/node_modules/.bin:$PATH ENV PATH /app/yarn/bin:$PATH ENV PATH /app/nodejs/bin:$PATH -RUN ln -s /app/nodejs/bin/node /app/nodejs/bin/nodejs +#RUN ln -s /app/nodejs/bin/node /app/nodejs/bin/nodejs # Precompile assets RUN bundle exec rake assets:precompile -- GitLab From 1a68535219093b3be5bbabf0ed89596cc1682e28 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Sun, 24 Jan 2021 02:21:26 +0000 Subject: [PATCH 239/283] Changing the way yarn and nodejs are loaded. Former-commit-id: 242003b11948c8232935d540037bba17c4ab21ed --- Dockerfile | 12 +++--------- .../node-v14.15.4-linux-x64.tar.gz.REMOVED.git-id | 1 - scripts/bundles/nodejs.tar.gz.REMOVED.git-id | 1 + scripts/bundles/yarn-v1.22.5.tar.gz.REMOVED.git-id | 1 - scripts/bundles/yarn.tar.gz.REMOVED.git-id | 1 + 5 files changed, 5 insertions(+), 11 deletions(-) delete mode 100644 scripts/bundles/node-v14.15.4-linux-x64.tar.gz.REMOVED.git-id create mode 100644 scripts/bundles/nodejs.tar.gz.REMOVED.git-id delete mode 100644 scripts/bundles/yarn-v1.22.5.tar.gz.REMOVED.git-id create mode 100644 scripts/bundles/yarn.tar.gz.REMOVED.git-id diff --git a/Dockerfile b/Dockerfile index e368355..3a3ea20 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,28 +23,23 @@ WORKDIR /app/bundles # Redis. RUN tar xzf redis-cli.tar.gz -RUN rm redis-cli.tar.gz RUN mv redis-cli /usr/local/bin/redis-cli # Unzip the bundle directory. RUN tar xzf bundle.tar.gz -RUN rm bundle.tar.gz RUN mv bundle /usr/local/ # Unzip the node_modules. RUN tar xzf node_modules.tar.gz -RUN rm node_modules.tar.gz RUN mv node_modules /app/node_modules # Node.js -RUN tar xzf node-v14.15.4-linux-x64.tar.gz -RUN rm node-v14.15.4-linux-x64.tar.gz +RUN tar xzf nodejs.tar.gz RUN mv nodejs /app/nodejs # Yarn -RUN tar xzf yarn-v1.22.5.tar.gz -RUN rm yarn-v1.22.5.tar.gz -RUN mv yarn-v1.22.5 /app/yarn +RUN tar xzf yarn.tar.gz +RUN mv yarn /app/yarn # Switch back to app directory. WORKDIR /app @@ -64,7 +59,6 @@ ENV NODE_HOME /app/nodejs ENV PATH /app/node_modules/.bin:$PATH ENV PATH /app/yarn/bin:$PATH ENV PATH /app/nodejs/bin:$PATH -#RUN ln -s /app/nodejs/bin/node /app/nodejs/bin/nodejs # Precompile assets RUN bundle exec rake assets:precompile diff --git a/scripts/bundles/node-v14.15.4-linux-x64.tar.gz.REMOVED.git-id b/scripts/bundles/node-v14.15.4-linux-x64.tar.gz.REMOVED.git-id deleted file mode 100644 index 5b59680..0000000 --- a/scripts/bundles/node-v14.15.4-linux-x64.tar.gz.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -47adb6c4a299fbd9ecc10f90ca0dcd5dd1e6d4d1 \ No newline at end of file diff --git a/scripts/bundles/nodejs.tar.gz.REMOVED.git-id b/scripts/bundles/nodejs.tar.gz.REMOVED.git-id new file mode 100644 index 0000000..eceaef7 --- /dev/null +++ b/scripts/bundles/nodejs.tar.gz.REMOVED.git-id @@ -0,0 +1 @@ +3e9b0070e0d29a9b3cba05c6b53c8c608529e5d9 \ No newline at end of file diff --git a/scripts/bundles/yarn-v1.22.5.tar.gz.REMOVED.git-id b/scripts/bundles/yarn-v1.22.5.tar.gz.REMOVED.git-id deleted file mode 100644 index 89957a7..0000000 --- a/scripts/bundles/yarn-v1.22.5.tar.gz.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -2ffdf471020c0266a0c89ca2c125833d251e5181 \ No newline at end of file diff --git a/scripts/bundles/yarn.tar.gz.REMOVED.git-id b/scripts/bundles/yarn.tar.gz.REMOVED.git-id new file mode 100644 index 0000000..98061eb --- /dev/null +++ b/scripts/bundles/yarn.tar.gz.REMOVED.git-id @@ -0,0 +1 @@ +18cf0892e6d57bc9876394d4d7f952dca3e6ca09 \ No newline at end of file -- GitLab From 0d57111578366dc90f91224b7c572a0f2df71a47 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Sat, 23 Jan 2021 16:27:36 -1000 Subject: [PATCH 240/283] adding scripts to rebuild the bundles. Former-commit-id: 0c15fddf37fe2e531d0bd50c57576440a2716e00 --- .gitignore | 4 +- scripts/Dockerfile.packages | 84 +++++++++++++++++++++++++++++++++++++ scripts/repackage.sh | 38 +++++++++++++++++ 3 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 scripts/Dockerfile.packages create mode 100755 scripts/repackage.sh diff --git a/.gitignore b/.gitignore index d313f3c..651d0b2 100644 --- a/.gitignore +++ b/.gitignore @@ -34,5 +34,5 @@ tags !/scripts/public/assets/images log.txt sidekiq.log -Dockerfile.packages -repackage.sh +#Dockerfile.packages +#repackage.sh diff --git a/scripts/Dockerfile.packages b/scripts/Dockerfile.packages new file mode 100644 index 0000000..68f7093 --- /dev/null +++ b/scripts/Dockerfile.packages @@ -0,0 +1,84 @@ +ARG BASE_REGISTRY +ARG BASE_IMAGE +ARG BASE_TAG + +FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} +USER 0 + +ARG NODE_VERSION +ARG YARN_VERSION + +# Install required libs. +RUN dnf update -y && dnf install -y \ + curl \ + make \ + patch \ + git \ + zlib-devel \ + libpq-devel \ + libxml2-devel \ + libxslt-devel \ + gcc \ + gcc-c++ + +# Setup our environment +WORKDIR /app +ADD . . + +# Switch to the binary directory. +WORKDIR /app/bundles + +# Node.js +RUN curl -L https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz -o node-v$NODE_VERSION-linux-x64.tar.gz +RUN tar xzf node-v$NODE_VERSION-linux-x64.tar.gz +RUN mv node-v$NODE_VERSION-linux-x64 /app/nodejs + +# Yarn +RUN curl -L https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz -o yarn-v$YARN_VERSION.tar.gz +RUN ls -la +RUN tar xzf yarn-v$YARN_VERSION.tar.gz +RUN mv yarn-v$YARN_VERSION /app/yarn + +# Switch back to app dir. +WORKDIR /app + +# Add write permissions. +RUN chown -R 1001 . + +# Become the ruby user +USER 1001 + +# Set Environment Variables +ENV NODE_HOME /app/nodejs +ENV PATH /app/node_modules/.bin:$PATH +ENV PATH /app/yarn/bin:$PATH +ENV PATH /app/nodejs/bin:$PATH +RUN ln -s /app/nodejs/bin/node /app/nodejs/bin/nodejs + +# Upgrade npm and repackage node. +RUN npm i -g npm +RUN tar czf nodejs.tar.gz nodejs + +# Repackage yarn. +RUN tar czf yarn.tar.gz yarn + +# Precompile assets +RUN yarn install +RUN tar czf node_modules.tar.gz node_modules + +# Run bundle install. +RUN gem install bundler +RUN bundle install + +# Go to bundle dir. +WORKDIR /usr/local +USER 0 +RUN tar czf bundle.tar.gz bundle +RUN cp bundle.tar.gz /app/ +USER 1001 + +# Change back to app dir. +WORKDIR /app + +# Set the entry point. +CMD tail -f /dev/null diff --git a/scripts/repackage.sh b/scripts/repackage.sh new file mode 100755 index 0000000..2fff3c7 --- /dev/null +++ b/scripts/repackage.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +BASE_REGISTRY=registry.il2.dso.mil +BASE_IMAGE=platform-one/devops/pipeline-templates/ironbank/ruby26 +BASE_TAG=2.6.6.212 +NODE_VERSION=14.15.4 +YARN_VERSION=1.22.5 + +echo "Clearing node_modules." +rm -rf node_modules + +#echo "Switch to correct node version." +#source ~/.zprofile +#nvm use +# +#echo "Update yarn lock file." +#yarn install +# +#echo "Remove node_modules directory." +#rm -rf node_modules + +echo "Building docker image." +IMAGE_ID=$(docker build --file Dockerfile.packages . -q --build-arg BASE_REGISTRY=$BASE_REGISTRY --build-arg BASE_IMAGE=$BASE_IMAGE --build-arg BASE_TAG=$BASE_TAG --build-arg NODE_VERSION=$NODE_VERSION --build-arg YARN_VERSION=$YARN_VERSION) +echo "Image ID: ${IMAGE_ID}" + +echo "Starting docker container." +CONTAINER_ID=$(docker run -d $IMAGE_ID) +echo "Container ID: ${CONTAINER_ID}" + +echo "Copying node modules and gems to the bundles directory." +docker cp $CONTAINER_ID:/app/node_modules.tar.gz bundles +docker cp $CONTAINER_ID:/app/nodejs.tar.gz bundles +docker cp $CONTAINER_ID:/app/bundle.tar.gz bundles +docker cp $CONTAINER_ID:/app/yarn.tar.gz bundles + +echo "Stopping the docker container." +docker stop $CONTAINER_ID +echo "Success" \ No newline at end of file -- GitLab From 53355476ed6a8fdcbdb638dbf994be9a392a1ce0 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 25 Jan 2021 16:14:26 -1000 Subject: [PATCH 241/283] Updating repackage script Former-commit-id: 3a768baa3ba9f2c46f559b4273f8655e49b89f90 --- scripts/Dockerfile.packages | 10 ++++++++++ scripts/repackage.sh | 15 +++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/scripts/Dockerfile.packages b/scripts/Dockerfile.packages index 68f7093..d65779c 100644 --- a/scripts/Dockerfile.packages +++ b/scripts/Dockerfile.packages @@ -28,6 +28,16 @@ ADD . . # Switch to the binary directory. WORKDIR /app/bundles +# Redis +RUN curl -L http://download.redis.io/redis-stable.tar.gz -o redis-stable.tar.gz +RUN tar xzf redis-stable.tar.gz +WORKDIR /app/bundles/redis-stable +RUN make redis-cli +WORKDIR /app/bundles/redis-stable/src +RUN tar czf redis-cli.tar.gz redis-cli +RUN mv redis-cli.tar.gz /app/ +WORKDIR /app/bundles + # Node.js RUN curl -L https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz -o node-v$NODE_VERSION-linux-x64.tar.gz RUN tar xzf node-v$NODE_VERSION-linux-x64.tar.gz diff --git a/scripts/repackage.sh b/scripts/repackage.sh index 2fff3c7..06991ca 100755 --- a/scripts/repackage.sh +++ b/scripts/repackage.sh @@ -6,6 +6,12 @@ BASE_TAG=2.6.6.212 NODE_VERSION=14.15.4 YARN_VERSION=1.22.5 +COPY_NODE_MODULES=false +COPY_NODEJS=false +COPY_YARN=false +COPY_REDIS_CLI=false +COPY_BUNDLE=false + echo "Clearing node_modules." rm -rf node_modules @@ -28,10 +34,11 @@ CONTAINER_ID=$(docker run -d $IMAGE_ID) echo "Container ID: ${CONTAINER_ID}" echo "Copying node modules and gems to the bundles directory." -docker cp $CONTAINER_ID:/app/node_modules.tar.gz bundles -docker cp $CONTAINER_ID:/app/nodejs.tar.gz bundles -docker cp $CONTAINER_ID:/app/bundle.tar.gz bundles -docker cp $CONTAINER_ID:/app/yarn.tar.gz bundles +if [ $COPY_NODE_MODULES == "true" ] ; then docker cp $CONTAINER_ID:/app/node_modules.tar.gz bundles ; fi +if [ $COPY_NODEJS == "true" ] ; then docker cp $CONTAINER_ID:/app/nodejs.tar.gz bundles ; fi +if [ $COPY_YARN == "true" ] ; then docker cp $CONTAINER_ID:/app/yarn.tar.gz bundles ; fi +if [ $COPY_REDIS_CLI == "true" ] ; then docker cp $CONTAINER_ID:/app/redis-cli.tar.gz bundles ; fi +if [ $COPY_BUNDLE == "true" ] ; then docker cp $CONTAINER_ID:/app/bundle.tar.gz bundles ; fi echo "Stopping the docker container." docker stop $CONTAINER_ID -- GitLab From 1a3e722b77201467341f6548e818fe3bd590dc08 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 25 Jan 2021 16:23:00 -1000 Subject: [PATCH 242/283] testing which packages are required Former-commit-id: e92cdb7ed3760079873490096d5c1479ed3125f9 --- Dockerfile | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3a3ea20..405e31a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,17 +2,19 @@ FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} USER 0 # Install required libs. -RUN dnf update -y && dnf install -y \ - curl \ - make \ - patch \ - git \ - zlib-devel \ - libpq-devel \ - libxml2-devel \ - libxslt-devel \ - gcc \ - gcc-c++ +#RUN dnf update -y && dnf install -y \ +# curl \ +# make \ +# patch \ +# git \ +# zlib-devel \ +# libpq-devel \ +# libxml2-devel \ +# libxslt-devel \ +# gcc \ +# gcc-c++ + +RUN dnf update && dnf clean # Setup our environment WORKDIR /app -- GitLab From 9327226bc4d8565ff4467bb111dc7289c7cc92bc Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 25 Jan 2021 16:35:42 -1000 Subject: [PATCH 243/283] fixing prompt Former-commit-id: ac82c7d20f802af28abb6ab2286542fa21064c79 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 405e31a..bb3b764 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,7 +14,7 @@ USER 0 # gcc \ # gcc-c++ -RUN dnf update && dnf clean +RUN dnf update -y && dnf clean -y # Setup our environment WORKDIR /app -- GitLab From cdcf35adb8c6cfa36301413626f20d4a2d11db5b Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 25 Jan 2021 16:41:47 -1000 Subject: [PATCH 244/283] fixing prompt Former-commit-id: 413da45d0fb6fb16e7431abf6b322de170c74a4f --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index bb3b764..eeefa5e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,7 +14,7 @@ USER 0 # gcc \ # gcc-c++ -RUN dnf update -y && dnf clean -y +RUN dnf update -y && dnf clean all # Setup our environment WORKDIR /app -- GitLab From e498ba6ded846387b8601370d2d0849b2b6648ba Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 25 Jan 2021 17:05:51 -1000 Subject: [PATCH 245/283] changing back Former-commit-id: c4ecd0b180d24f403f4e17cdcbd197d84bb9dd2d --- Dockerfile | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/Dockerfile b/Dockerfile index eeefa5e..b56b557 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,19 +2,17 @@ FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} USER 0 # Install required libs. -#RUN dnf update -y && dnf install -y \ -# curl \ -# make \ -# patch \ -# git \ -# zlib-devel \ -# libpq-devel \ -# libxml2-devel \ -# libxslt-devel \ -# gcc \ -# gcc-c++ - -RUN dnf update -y && dnf clean all +RUN dnf update -y && dnf install -y \ + curl \ + make \ + patch \ + git \ + zlib-devel \ + libpq-devel \ + libxml2-devel \ + libxslt-devel \ + gcc \ + gcc-c++ # Setup our environment WORKDIR /app -- GitLab From ccfe4c73b2636ff420a668c20efa1de41914d2e0 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 25 Jan 2021 17:20:10 -1000 Subject: [PATCH 246/283] adding libqp back in Former-commit-id: fca206a95e5d97a25bd857b3adbdf6f7de37f656 --- Dockerfile | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Dockerfile b/Dockerfile index b56b557..28ba5e3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,16 +3,16 @@ USER 0 # Install required libs. RUN dnf update -y && dnf install -y \ - curl \ - make \ - patch \ - git \ - zlib-devel \ - libpq-devel \ - libxml2-devel \ - libxslt-devel \ - gcc \ - gcc-c++ +# curl \ +# make \ +# patch \ +# git \ +# zlib-devel \ + libpq-devel +# libxml2-devel \ +# libxslt-devel \ +# gcc \ +# gcc-c++ # Setup our environment WORKDIR /app -- GitLab From e12ac1af3815b1a19f145f10d5c49d1f79553406 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 25 Jan 2021 18:43:48 -1000 Subject: [PATCH 247/283] testing Former-commit-id: 1be329efca37ef0a26c88c8fdc0e06f332f92404 --- Dockerfile | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Dockerfile b/Dockerfile index 28ba5e3..bc245a0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,16 +3,17 @@ USER 0 # Install required libs. RUN dnf update -y && dnf install -y \ -# curl \ -# make \ -# patch \ -# git \ -# zlib-devel \ - libpq-devel -# libxml2-devel \ -# libxslt-devel \ -# gcc \ -# gcc-c++ + curl \ + make \ + patch \ + git \ + zlib-devel \ + libpq-devel \ + libxml2-devel \ + libxslt-devel \ + gcc \ + gcc-c++ \ + && dnf clean all # Setup our environment WORKDIR /app -- GitLab From 7e9a1524960ff9611efe3af981841d6135b3ba60 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 26 Jan 2021 09:23:06 -1000 Subject: [PATCH 248/283] logging Former-commit-id: e3de9641bb064446451317fb247400ef2edd0855 --- scripts/config/application.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/config/application.rb b/scripts/config/application.rb index ef9d3f5..c3d5db7 100644 --- a/scripts/config/application.rb +++ b/scripts/config/application.rb @@ -36,6 +36,8 @@ module Forge port: Rails.application.secrets.actionmailer_port } + puts config.action_mailer.default_url_options + config.react.jsx_transform_options = { blacklist: ["spec.functionName", "validation.react", "strict"], # default options optional: ["es7.classProperties"] # pass extra babel options -- GitLab From aaf9df246d26381495dd674e625ec8abee4dcff4 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 26 Jan 2021 12:58:31 -1000 Subject: [PATCH 249/283] testing Former-commit-id: 342fc23bcf789549c22e313b9a0fb9955cbc13b8 --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index bc245a0..606150a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -68,8 +68,8 @@ RUN bundle exec rake assets:precompile RUN bundle exec rake assets:clean # Remove yarn and node modules after compile. -RUN rm -rf yarn -RUN rm -rf node_modules +#RUN rm -rf yarn +#RUN rm -rf node_modules # Health check. HEALTHCHECK none -- GitLab From 8fd8e16c07f58c22135072c867c71cb07ee5f0e9 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Tue, 26 Jan 2021 14:51:09 -1000 Subject: [PATCH 250/283] testing Former-commit-id: 4cc7359560eff08eeb4986f1c74344c130d1719e --- Dockerfile | 22 +++++++++++----------- scripts/config/application.rb | 2 -- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/Dockerfile b/Dockerfile index 606150a..f52494b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,16 +3,16 @@ USER 0 # Install required libs. RUN dnf update -y && dnf install -y \ - curl \ - make \ - patch \ - git \ - zlib-devel \ +# curl \ +# make \ +# patch \ +# git \ +# zlib-devel \ libpq-devel \ - libxml2-devel \ - libxslt-devel \ - gcc \ - gcc-c++ \ +# libxml2-devel \ +# libxslt-devel \ +# gcc \ +# gcc-c++ \ && dnf clean all # Setup our environment @@ -68,8 +68,8 @@ RUN bundle exec rake assets:precompile RUN bundle exec rake assets:clean # Remove yarn and node modules after compile. -#RUN rm -rf yarn -#RUN rm -rf node_modules +RUN rm -rf yarn +RUN rm -rf node_modules # Health check. HEALTHCHECK none diff --git a/scripts/config/application.rb b/scripts/config/application.rb index c3d5db7..ef9d3f5 100644 --- a/scripts/config/application.rb +++ b/scripts/config/application.rb @@ -36,8 +36,6 @@ module Forge port: Rails.application.secrets.actionmailer_port } - puts config.action_mailer.default_url_options - config.react.jsx_transform_options = { blacklist: ["spec.functionName", "validation.react", "strict"], # default options optional: ["es7.classProperties"] # pass extra babel options -- GitLab From d74e518b87febff1823ef7ca2f34dbb4edaf209a Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Wed, 27 Jan 2021 15:40:01 -1000 Subject: [PATCH 251/283] removing npm, removining jquery 1 and 2. switching to jquery 3 Former-commit-id: 8723cc416172e8cae344b1f3b12c0b31eb96a9a7 --- scripts/Dockerfile.packages | 7 +++++-- scripts/app/assets/javascripts/application.js | 2 +- scripts/bundles/bundle.tar.gz.REMOVED.git-id | 2 +- scripts/bundles/nodejs.tar.gz.REMOVED.git-id | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/scripts/Dockerfile.packages b/scripts/Dockerfile.packages index d65779c..ae6d933 100644 --- a/scripts/Dockerfile.packages +++ b/scripts/Dockerfile.packages @@ -65,8 +65,8 @@ ENV PATH /app/yarn/bin:$PATH ENV PATH /app/nodejs/bin:$PATH RUN ln -s /app/nodejs/bin/node /app/nodejs/bin/nodejs -# Upgrade npm and repackage node. -RUN npm i -g npm +# Remove NPM and repackage node. +RUN rm -rf /app/nodejs/bin/nodejs/lib/node_modules/npm RUN tar czf nodejs.tar.gz nodejs # Repackage yarn. @@ -80,6 +80,9 @@ RUN tar czf node_modules.tar.gz node_modules RUN gem install bundler RUN bundle install +# Remove extra JS files from jquery gem. + + # Go to bundle dir. WORKDIR /usr/local USER 0 diff --git a/scripts/app/assets/javascripts/application.js b/scripts/app/assets/javascripts/application.js index fb0297b..0878c57 100644 --- a/scripts/app/assets/javascripts/application.js +++ b/scripts/app/assets/javascripts/application.js @@ -1,4 +1,4 @@ -//= require jquery +//= require jquery3 //= require rails-ujs //= require popper //= require bootstrap-sprockets diff --git a/scripts/bundles/bundle.tar.gz.REMOVED.git-id b/scripts/bundles/bundle.tar.gz.REMOVED.git-id index 33f3ce2..04f748c 100644 --- a/scripts/bundles/bundle.tar.gz.REMOVED.git-id +++ b/scripts/bundles/bundle.tar.gz.REMOVED.git-id @@ -1 +1 @@ -1e00d7dfa42b51862181fa5607c250fc41de3d22 \ No newline at end of file +e642701e6e136d20901a5e81ff06b259fbb6691d \ No newline at end of file diff --git a/scripts/bundles/nodejs.tar.gz.REMOVED.git-id b/scripts/bundles/nodejs.tar.gz.REMOVED.git-id index eceaef7..60c726e 100644 --- a/scripts/bundles/nodejs.tar.gz.REMOVED.git-id +++ b/scripts/bundles/nodejs.tar.gz.REMOVED.git-id @@ -1 +1 @@ -3e9b0070e0d29a9b3cba05c6b53c8c608529e5d9 \ No newline at end of file +a10b8c2e56c335960e156f7c4ed6b8f433d0a2bd \ No newline at end of file -- GitLab From 16bafe1737c076c9703b0393b040d9503b656df3 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Wed, 27 Jan 2021 16:29:32 -1000 Subject: [PATCH 252/283] added setting action mailer variables on sidekiq Former-commit-id: 0c7f5228779abb390414e0a3f7458fa15ca9a7c1 --- scripts/config/initializers/sidekiq.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/scripts/config/initializers/sidekiq.rb b/scripts/config/initializers/sidekiq.rb index 1668b85..6a70575 100644 --- a/scripts/config/initializers/sidekiq.rb +++ b/scripts/config/initializers/sidekiq.rb @@ -2,3 +2,12 @@ if ENV["INLINE_SIDEKIQ"] == "true" require "sidekiq/testing/inline" Sidekiq::Testing.inline! end + +Rails.application.configure do + config.action_mailer.default_url_options = { + host: Rails.application.secrets.actionmailer_host, + port: Rails.application.secrets.actionmailer_port + } + + puts config.action_mailer.default_url_options +end \ No newline at end of file -- GitLab From 3b68ecb2bb6ac46dbf12bb872404a082bf7ee3b7 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Thu, 28 Jan 2021 09:36:44 -1000 Subject: [PATCH 253/283] Fixing node package Former-commit-id: eb5278a85782336bb3a69b19c1a81d1611a62770 --- scripts/Dockerfile.packages | 2 +- scripts/bundles/nodejs.tar.gz.REMOVED.git-id | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/Dockerfile.packages b/scripts/Dockerfile.packages index ae6d933..51c6cca 100644 --- a/scripts/Dockerfile.packages +++ b/scripts/Dockerfile.packages @@ -66,7 +66,7 @@ ENV PATH /app/nodejs/bin:$PATH RUN ln -s /app/nodejs/bin/node /app/nodejs/bin/nodejs # Remove NPM and repackage node. -RUN rm -rf /app/nodejs/bin/nodejs/lib/node_modules/npm +RUN rm -rf /app/nodejs/lib/node_modules/npm RUN tar czf nodejs.tar.gz nodejs # Repackage yarn. diff --git a/scripts/bundles/nodejs.tar.gz.REMOVED.git-id b/scripts/bundles/nodejs.tar.gz.REMOVED.git-id index 60c726e..6370c52 100644 --- a/scripts/bundles/nodejs.tar.gz.REMOVED.git-id +++ b/scripts/bundles/nodejs.tar.gz.REMOVED.git-id @@ -1 +1 @@ -a10b8c2e56c335960e156f7c4ed6b8f433d0a2bd \ No newline at end of file +57e2f57eab29bd0c17dd1fbf1fee4bfed7d14d8c \ No newline at end of file -- GitLab From f69ede87fec63ed36d0a0585af0182e31f9bbf8b Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Thu, 28 Jan 2021 21:11:54 -1000 Subject: [PATCH 254/283] updating package scripts Former-commit-id: 8beb675aed0b4b9d8c3000989f7c0197c0c06506 --- scripts/Dockerfile.packages | 13 +++++++++---- scripts/repackage.sh | 3 ++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/scripts/Dockerfile.packages b/scripts/Dockerfile.packages index 51c6cca..922aec7 100644 --- a/scripts/Dockerfile.packages +++ b/scripts/Dockerfile.packages @@ -7,6 +7,7 @@ USER 0 ARG NODE_VERSION ARG YARN_VERSION +ARG JQUERY_RAILS_VERSION # Install required libs. RUN dnf update -y && dnf install -y \ @@ -78,17 +79,21 @@ RUN tar czf node_modules.tar.gz node_modules # Run bundle install. RUN gem install bundler +RUN bundle config set --local without 'development:test' RUN bundle install -# Remove extra JS files from jquery gem. +# Switch back to root user. +USER 0 +# Go to jquery-rails directory +WORKDIR /usr/local/bundle/gems/jquery-rails-$JQUERY_RAILS_VERSION/vendor/assets/javascripts +RUN ls -la +RUN rm jquery_ujs.js jquery.js jquery.min.js jquery.min.map jquery2.js jquery2.min.js jquery2.min.map -# Go to bundle dir. +# Package Rails Gems. WORKDIR /usr/local -USER 0 RUN tar czf bundle.tar.gz bundle RUN cp bundle.tar.gz /app/ -USER 1001 # Change back to app dir. WORKDIR /app diff --git a/scripts/repackage.sh b/scripts/repackage.sh index 06991ca..700cef8 100755 --- a/scripts/repackage.sh +++ b/scripts/repackage.sh @@ -5,6 +5,7 @@ BASE_IMAGE=platform-one/devops/pipeline-templates/ironbank/ruby26 BASE_TAG=2.6.6.212 NODE_VERSION=14.15.4 YARN_VERSION=1.22.5 +JQUERY_RAILS_VERSION=4.4.0 COPY_NODE_MODULES=false COPY_NODEJS=false @@ -26,7 +27,7 @@ rm -rf node_modules #rm -rf node_modules echo "Building docker image." -IMAGE_ID=$(docker build --file Dockerfile.packages . -q --build-arg BASE_REGISTRY=$BASE_REGISTRY --build-arg BASE_IMAGE=$BASE_IMAGE --build-arg BASE_TAG=$BASE_TAG --build-arg NODE_VERSION=$NODE_VERSION --build-arg YARN_VERSION=$YARN_VERSION) +IMAGE_ID=$(docker build --file Dockerfile.packages . -q --build-arg BASE_REGISTRY=$BASE_REGISTRY --build-arg BASE_IMAGE=$BASE_IMAGE --build-arg BASE_TAG=$BASE_TAG --build-arg NODE_VERSION=$NODE_VERSION --build-arg YARN_VERSION=$YARN_VERSION --build-arg JQUERY_RAILS_VERSION=$JQUERY_RAILS_VERSION) echo "Image ID: ${IMAGE_ID}" echo "Starting docker container." -- GitLab From 7bb14dcbf570598813d8e80f7d4bd9abd5b5ec3a Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 29 Jan 2021 17:18:39 -1000 Subject: [PATCH 255/283] updating package shell script to upload dependencies to s3 Former-commit-id: d4b386c5a727be408a2660ddea2bda23b5d140f9 --- .gitignore | 3 +-- scripts/repackage.sh | 54 ++++++++++++++++++++++++++------------------ 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/.gitignore b/.gitignore index 651d0b2..510b35a 100644 --- a/.gitignore +++ b/.gitignore @@ -34,5 +34,4 @@ tags !/scripts/public/assets/images log.txt sidekiq.log -#Dockerfile.packages -#repackage.sh +build_dependencies diff --git a/scripts/repackage.sh b/scripts/repackage.sh index 700cef8..60f7f0c 100755 --- a/scripts/repackage.sh +++ b/scripts/repackage.sh @@ -1,33 +1,36 @@ #!/bin/bash +# Image Params. BASE_REGISTRY=registry.il2.dso.mil BASE_IMAGE=platform-one/devops/pipeline-templates/ironbank/ruby26 BASE_TAG=2.6.6.212 + +# Package Versions. NODE_VERSION=14.15.4 YARN_VERSION=1.22.5 JQUERY_RAILS_VERSION=4.4.0 -COPY_NODE_MODULES=false -COPY_NODEJS=false -COPY_YARN=false -COPY_REDIS_CLI=false -COPY_BUNDLE=false +# This is the profile name in your aws credentials file. +DEPENDENCY_FOLDER=build_dependencies +AWS_PROFILE_NAME=revacomm +AWS_BUCKET_NAME=learn-dependencies/forge +AWS_REGION=us-gov-west-1 + +echo "Clearing dependency folder." +rm -rf $DEPENDENCY_FOLDER +mkdir $DEPENDENCY_FOLDER echo "Clearing node_modules." rm -rf node_modules -#echo "Switch to correct node version." -#source ~/.zprofile -#nvm use -# -#echo "Update yarn lock file." -#yarn install -# -#echo "Remove node_modules directory." -#rm -rf node_modules - echo "Building docker image." -IMAGE_ID=$(docker build --file Dockerfile.packages . -q --build-arg BASE_REGISTRY=$BASE_REGISTRY --build-arg BASE_IMAGE=$BASE_IMAGE --build-arg BASE_TAG=$BASE_TAG --build-arg NODE_VERSION=$NODE_VERSION --build-arg YARN_VERSION=$YARN_VERSION --build-arg JQUERY_RAILS_VERSION=$JQUERY_RAILS_VERSION) +IMAGE_ID=$(docker build --file Dockerfile.packages . -q \ + --build-arg BASE_REGISTRY=$BASE_REGISTRY \ + --build-arg BASE_IMAGE=$BASE_IMAGE \ + --build-arg BASE_TAG=$BASE_TAG \ + --build-arg NODE_VERSION=$NODE_VERSION \ + --build-arg YARN_VERSION=$YARN_VERSION \ + --build-arg JQUERY_RAILS_VERSION=$JQUERY_RAILS_VERSION) echo "Image ID: ${IMAGE_ID}" echo "Starting docker container." @@ -35,12 +38,19 @@ CONTAINER_ID=$(docker run -d $IMAGE_ID) echo "Container ID: ${CONTAINER_ID}" echo "Copying node modules and gems to the bundles directory." -if [ $COPY_NODE_MODULES == "true" ] ; then docker cp $CONTAINER_ID:/app/node_modules.tar.gz bundles ; fi -if [ $COPY_NODEJS == "true" ] ; then docker cp $CONTAINER_ID:/app/nodejs.tar.gz bundles ; fi -if [ $COPY_YARN == "true" ] ; then docker cp $CONTAINER_ID:/app/yarn.tar.gz bundles ; fi -if [ $COPY_REDIS_CLI == "true" ] ; then docker cp $CONTAINER_ID:/app/redis-cli.tar.gz bundles ; fi -if [ $COPY_BUNDLE == "true" ] ; then docker cp $CONTAINER_ID:/app/bundle.tar.gz bundles ; fi +docker cp $CONTAINER_ID:/app/node_modules.tar.gz $DEPENDENCY_FOLDER +docker cp $CONTAINER_ID:/app/nodejs.tar.gz $DEPENDENCY_FOLDER +docker cp $CONTAINER_ID:/app/yarn.tar.gz $DEPENDENCY_FOLDER +docker cp $CONTAINER_ID:/app/redis-cli.tar.gz $DEPENDENCY_FOLDER +docker cp $CONTAINER_ID:/app/bundle.tar.gz $DEPENDENCY_FOLDER echo "Stopping the docker container." docker stop $CONTAINER_ID -echo "Success" \ No newline at end of file + +echo "Uploading all the build dependencies to AWS." +aws s3 sync $DEPENDENCY_FOLDER s3://$AWS_BUCKET_NAME --delete --profile $AWS_PROFILE_NAME --region $AWS_REGION + +echo "Removing dependency folder." +rm -rf $DEPENDENCY_FOLDER + +echo "Done!" \ No newline at end of file -- GitLab From bd2dce66d17a8ad27533ba66beb5cd7a7e453bac Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 29 Jan 2021 20:24:01 -1000 Subject: [PATCH 256/283] removing binaries and updating docker file Former-commit-id: a2877e3b84cbb919a596c5839702de6ec923a649 --- Dockerfile | 36 +++++++------------ scripts/bundles/bundle.tar.gz.REMOVED.git-id | 1 - .../node_modules.tar.gz.REMOVED.git-id | 1 - scripts/bundles/nodejs.tar.gz.REMOVED.git-id | 1 - .../bundles/redis-cli.tar.gz.REMOVED.git-id | 1 - scripts/bundles/yarn.tar.gz.REMOVED.git-id | 1 - 6 files changed, 13 insertions(+), 28 deletions(-) delete mode 100644 scripts/bundles/bundle.tar.gz.REMOVED.git-id delete mode 100644 scripts/bundles/node_modules.tar.gz.REMOVED.git-id delete mode 100644 scripts/bundles/nodejs.tar.gz.REMOVED.git-id delete mode 100644 scripts/bundles/redis-cli.tar.gz.REMOVED.git-id delete mode 100644 scripts/bundles/yarn.tar.gz.REMOVED.git-id diff --git a/Dockerfile b/Dockerfile index f52494b..1191233 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,47 +3,34 @@ USER 0 # Install required libs. RUN dnf update -y && dnf install -y \ -# curl \ -# make \ -# patch \ -# git \ -# zlib-devel \ libpq-devel \ -# libxml2-devel \ -# libxslt-devel \ -# gcc \ -# gcc-c++ \ && dnf clean all # Setup our environment WORKDIR /app COPY ./scripts . - -# Switch to the binary directory. -WORKDIR /app/bundles +COPY bundle.tar.gz . +COPY node_modules.tar.gz . +COPY nodejs.tar.gz . +COPY redis-cli.tar.gz . +COPY yarn.tar.gz . # Redis. -RUN tar xzf redis-cli.tar.gz +RUN tar xzf redis-cli.tar.gz && rm redis-cli.tar.gz RUN mv redis-cli /usr/local/bin/redis-cli # Unzip the bundle directory. -RUN tar xzf bundle.tar.gz +RUN tar xzf bundle.tar.gz && rm bundle.tar.gz RUN mv bundle /usr/local/ # Unzip the node_modules. -RUN tar xzf node_modules.tar.gz -RUN mv node_modules /app/node_modules +RUN tar xzf node_modules.tar.gz && rm node_modules.tar.gz # Node.js -RUN tar xzf nodejs.tar.gz -RUN mv nodejs /app/nodejs +RUN tar xzf nodejs.tar.gz && rm nodejs.tar.gz # Yarn -RUN tar xzf yarn.tar.gz -RUN mv yarn /app/yarn - -# Switch back to app directory. -WORKDIR /app +RUN tar xzf yarn.tar.gz && rm yarn.tar.gz # Remove the bundles directory. RUN rm -rf bundles @@ -51,6 +38,9 @@ RUN rm -rf bundles # Add write permissions. RUN chown -R 1001 . +# Test +RUN ls -la + # Become the ruby user USER 1001 diff --git a/scripts/bundles/bundle.tar.gz.REMOVED.git-id b/scripts/bundles/bundle.tar.gz.REMOVED.git-id deleted file mode 100644 index 04f748c..0000000 --- a/scripts/bundles/bundle.tar.gz.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -e642701e6e136d20901a5e81ff06b259fbb6691d \ No newline at end of file diff --git a/scripts/bundles/node_modules.tar.gz.REMOVED.git-id b/scripts/bundles/node_modules.tar.gz.REMOVED.git-id deleted file mode 100644 index e925b2c..0000000 --- a/scripts/bundles/node_modules.tar.gz.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -20baab03056513e3e89c5d262b91b38004897dc8 \ No newline at end of file diff --git a/scripts/bundles/nodejs.tar.gz.REMOVED.git-id b/scripts/bundles/nodejs.tar.gz.REMOVED.git-id deleted file mode 100644 index 6370c52..0000000 --- a/scripts/bundles/nodejs.tar.gz.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -57e2f57eab29bd0c17dd1fbf1fee4bfed7d14d8c \ No newline at end of file diff --git a/scripts/bundles/redis-cli.tar.gz.REMOVED.git-id b/scripts/bundles/redis-cli.tar.gz.REMOVED.git-id deleted file mode 100644 index 07b1028..0000000 --- a/scripts/bundles/redis-cli.tar.gz.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -e694dfedcbaeaf8927abdba4868d90eb0857e619 \ No newline at end of file diff --git a/scripts/bundles/yarn.tar.gz.REMOVED.git-id b/scripts/bundles/yarn.tar.gz.REMOVED.git-id deleted file mode 100644 index 98061eb..0000000 --- a/scripts/bundles/yarn.tar.gz.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -18cf0892e6d57bc9876394d4d7f952dca3e6ca09 \ No newline at end of file -- GitLab From 01b03fcf21e3bada5da32e731265f747ef4b3c58 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Thu, 4 Feb 2021 11:07:53 -1000 Subject: [PATCH 257/283] removing gitlab ci file --- scripts/.gitlab-ci.yml | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 scripts/.gitlab-ci.yml diff --git a/scripts/.gitlab-ci.yml b/scripts/.gitlab-ci.yml deleted file mode 100644 index dcfae11..0000000 --- a/scripts/.gitlab-ci.yml +++ /dev/null @@ -1,4 +0,0 @@ -include: - - project: 'platform-one/devops/pipeline-products' - ref: 'learn-ci' - file: 'products/tron/galvanize/learn/forge-ci.yml' -- GitLab From 1803a8911527059540effed2df9554bf19be4883 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 12 Feb 2021 11:55:09 -1000 Subject: [PATCH 258/283] Updating readme and adding args back into docker file --- Dockerfile | 4 ++++ README.md | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/Dockerfile b/Dockerfile index 1191233..f4b61a2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,7 @@ +ARG BASE_REGISTRY=registry1.dso.mil +ARG BASE_IMAGE=opensource/ruby/ruby26 +ARG BASE_TAG=2.6.6 + FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} USER 0 diff --git a/README.md b/README.md index 9098182..6b2b5c2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,29 @@ Forge ===== +## Container Usage: + +### Container info: + +- workdir: /app +- user id: 1001 +- container port: 3000 + +### Recommended Resources: + +- Min/Max CPU: 0.25/0.5 +- Min/Max Memory: 256Mi/1Gi + +### Required Environment Variables: + +- ```REDIS_URL``` - The redis server host address. +- ```S3_REGION``` - TheS3 bucket region. +- ```LEARN_BASE_URL``` - The applications base url. +- ```S3_BUCKET``` - The S3 bucket name. +- ```ACTIONMAILER_HOST``` - The containers host name. +- ```ACTIONMAILER_PORT``` - The the containers external port. +- ```FORGE_PROTOCOL``` - The services host protocol. Ex: ```http://``` + ## Standards See the [software-team-standards](https://www.github.com/Galvanize-IT/software-team-standards) for git aliases. -- GitLab From 5f44faa619671a8f03af9c2db12bcc865f209979 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 12 Feb 2021 16:35:29 -1000 Subject: [PATCH 259/283] adding resources section --- hardening_manifest.yaml | 48 +++++++++++++++++++++++++++++++++++++++++ scripts/repackage.sh | 9 ++++++++ 2 files changed, 57 insertions(+) diff --git a/hardening_manifest.yaml b/hardening_manifest.yaml index 87f83e3..6911341 100644 --- a/hardening_manifest.yaml +++ b/hardening_manifest.yaml @@ -28,6 +28,54 @@ labels: mil.dso.ironbank.image.type: "commercial" mil.dso.ironbank.product.name: "Learn" +# List of resources to make available to the offline build context +resources: + - auth: + type: s3 + id: galvanize + region: us-gov-west-1 + url: s3://learn-dependencies/forge/redis-cli.tar.gz + filename: redis-cli.tar.gz + validation: + type: sha256 + value: a35f87996aaf065f059141881e82a6f203276219bed2fa0231ab7c0cc93ec51e + - auth: + type: s3 + id: galvanize + region: us-gov-west-1 + url: s3://learn-dependencies/forge/node_modules.tar.gz + filename: node_modules.tar.gz + validation: + type: sha256 + value: 0a2e412b98e4861732c1486a9c8a1aa1f9589fe3658be4636ea91c8153f1a03e + - auth: + type: s3 + id: galvanize + region: us-gov-west-1 + url: s3://learn-dependencies/forge/nodejs.tar.gz + filename: nodejs.tar.gz + validation: + type: sha256 + value: 585d55c930d94984d3615486fd4ed1c7bcb84c2180703d1c13a580086c959d6b + - auth: + type: s3 + id: galvanize + region: us-gov-west-1 + url: s3://learn-dependencies/forge/yarn.tar.gz + filename: yarn.tar.gz + validation: + type: sha256 + value: 37ebe0a0b4f7265d1c385e5e31746b76865d45fb36d6bc9a4ed80ad04c81bf54 + - auth: + type: s3 + id: galvanize + region: us-gov-west-1 + url: s3://learn-dependencies/forge/bundle.tar.gz + filename: bundle.tar.gz + validation: + type: sha256 + value: 8e047082e85e8ba9bfac282c5ed57d5a5f5d6023c1a11a61b54626d8895af2c9 + # List of project maintainers maintainers: - email: "dchong@revacomm.com" diff --git a/scripts/repackage.sh b/scripts/repackage.sh index 60f7f0c..abc0f23 100755 --- a/scripts/repackage.sh +++ b/scripts/repackage.sh @@ -50,6 +50,15 @@ docker stop $CONTAINER_ID echo "Uploading all the build dependencies to AWS." aws s3 sync $DEPENDENCY_FOLDER s3://$AWS_BUCKET_NAME --delete --profile $AWS_PROFILE_NAME --region $AWS_REGION +echo "Checksums:" +cd $DEPENDENCY_FOLDER +sha256sum node_modules.tar.gz +sha256sum nodejs.tar.gz +sha256sum yarn.tar.gz +sha256sum redis-cli.tar.gz +sha256sum bundle.tar.gz +cd .. + echo "Removing dependency folder." rm -rf $DEPENDENCY_FOLDER -- GitLab From 422ccea6334b60ff15c1ad5d7830d8ed6ef20fdd Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Thu, 18 Feb 2021 17:43:14 -1000 Subject: [PATCH 260/283] upgrading to node 14.15.5 and ruby 2.7.2 --- Dockerfile | 4 ++-- README.md | 4 ++-- hardening_manifest.yaml | 14 +++++++------- scripts/.nvmrc | 2 +- scripts/.ruby-version | 2 +- scripts/Gemfile | 2 +- scripts/Gemfile.lock | 2 +- scripts/README.md | 4 ++-- scripts/package.json | 2 +- scripts/repackage.sh | 6 +++--- 10 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Dockerfile b/Dockerfile index f4b61a2..3d9cfe2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ ARG BASE_REGISTRY=registry1.dso.mil -ARG BASE_IMAGE=opensource/ruby/ruby26 -ARG BASE_TAG=2.6.6 +ARG BASE_IMAGE=opensource/ruby/ruby27 +ARG BASE_TAG=2.7.2 FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} USER 0 diff --git a/README.md b/README.md index 6b2b5c2..8957ab9 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Install rbenv and get the right version of ruby (the version here may change, so version. ) - `brew install rbenv` -- `rbenv install 2.6.6` +- `rbenv install 2.7.2` Install our data stores: @@ -55,7 +55,7 @@ You will need a [Github access token](https://github.com/settings/tokens). Repla The token will need **Full control of private repositories** - `git clone git@github.com:Galvanize-IT/forge.git && cd forge` -- `rbenv local 2.6.6` +- `rbenv local 2.7.2` - `gem install bundler` - `bundle config --local GITHUB__COM YOUR_GENERATED_PERSONAL_ACCESS_TOKEN:x-oauth-basic` - `bundle` diff --git a/hardening_manifest.yaml b/hardening_manifest.yaml index 6911341..f606c32 100644 --- a/hardening_manifest.yaml +++ b/hardening_manifest.yaml @@ -13,8 +13,8 @@ tags: # Build args passed to Dockerfile ARGs args: - BASE_IMAGE: "opensource/ruby/ruby26" - BASE_TAG: "2.6.6" + BASE_IMAGE: "opensource/ruby/ruby27" + BASE_TAG: "2.7.2" # Docker image labels labels: @@ -38,7 +38,7 @@ resources: filename: redis-cli.tar.gz validation: type: sha256 - value: a35f87996aaf065f059141881e82a6f203276219bed2fa0231ab7c0cc93ec51e + value: 003cdc4277d0d021f6c54249ce277293a06fb63bf7d8fd1444ef42f595218f86 - auth: type: s3 id: galvanize @@ -47,7 +47,7 @@ resources: filename: node_modules.tar.gz validation: type: sha256 - value: 0a2e412b98e4861732c1486a9c8a1aa1f9589fe3658be4636ea91c8153f1a03e + value: 830b0824cc9d7b2c037dd5e3de5176e7908fbbe104be9f12c67fedd5e75aac37 - auth: type: s3 id: galvanize @@ -56,7 +56,7 @@ resources: filename: nodejs.tar.gz validation: type: sha256 - value: 585d55c930d94984d3615486fd4ed1c7bcb84c2180703d1c13a580086c959d6b + value: 2194da489ad24a6261607433e79d6bc4c8e8d28d8265c53249282f960339b6e0 - auth: type: s3 id: galvanize @@ -65,7 +65,7 @@ resources: filename: yarn.tar.gz validation: type: sha256 - value: 37ebe0a0b4f7265d1c385e5e31746b76865d45fb36d6bc9a4ed80ad04c81bf54 + value: 9cdc059965f8c46a49fbf8105addec82ace7a2a2486554c060e4be408a73837e - auth: type: s3 id: galvanize @@ -74,7 +74,7 @@ resources: filename: bundle.tar.gz validation: type: sha256 - value: 8e047082e85e8ba9bfac282c5ed57d5a5f5d6023c1a11a61b54626d8895af2c9 + value: b439f3b9c3becb568a061fbf3615914a6b9546cf71e266c6caa7a316ef8a751d # List of project maintainers maintainers: diff --git a/scripts/.nvmrc b/scripts/.nvmrc index 47266f8..d4cf210 100644 --- a/scripts/.nvmrc +++ b/scripts/.nvmrc @@ -1 +1 @@ -14.15.4 \ No newline at end of file +14.15.5 \ No newline at end of file diff --git a/scripts/.ruby-version b/scripts/.ruby-version index 338a5b5..37c2961 100644 --- a/scripts/.ruby-version +++ b/scripts/.ruby-version @@ -1 +1 @@ -2.6.6 +2.7.2 diff --git a/scripts/Gemfile b/scripts/Gemfile index 1a86e24..cd6da3c 100644 --- a/scripts/Gemfile +++ b/scripts/Gemfile @@ -1,5 +1,5 @@ source "https://rubygems.org" -ruby "2.6.6" +ruby "2.7.2" git_source(:github) do |repo_name| repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/") diff --git a/scripts/Gemfile.lock b/scripts/Gemfile.lock index 1fc26f0..e5d5378 100644 --- a/scripts/Gemfile.lock +++ b/scripts/Gemfile.lock @@ -1521,7 +1521,7 @@ DEPENDENCIES zip-zip RUBY VERSION - ruby 2.6.6p146 + ruby 2.7.2p137 BUNDLED WITH 2.1.4 diff --git a/scripts/README.md b/scripts/README.md index b7fc7d5..82d0ef2 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -12,7 +12,7 @@ Install rbenv and get the right version of ruby (the version here may change, so version. ) - `brew install rbenv` -- `rbenv install 2.6.6` +- `rbenv install 2.7.2` Install our data stores: @@ -32,7 +32,7 @@ You will need a [Github access token](https://github.com/settings/tokens). Repla The token will need **Full control of private repositories** - `git clone git@github.com:Galvanize-IT/forge.git && cd forge` -- `rbenv local 2.6.6` +- `rbenv local 2.7.2` - `gem install bundler` - `bundle config --local GITHUB__COM YOUR_GENERATED_PERSONAL_ACCESS_TOKEN:x-oauth-basic` - `bundle` diff --git a/scripts/package.json b/scripts/package.json index d730cd5..21a89b3 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -17,7 +17,7 @@ }, "homepage": "https://github.com/Galvanize-IT/forge#readme", "engines": { - "node": "14.15.4" + "node": "14" }, "dependencies": { "@rails/webpacker": "5.2.1", diff --git a/scripts/repackage.sh b/scripts/repackage.sh index abc0f23..b4e3efc 100755 --- a/scripts/repackage.sh +++ b/scripts/repackage.sh @@ -2,11 +2,11 @@ # Image Params. BASE_REGISTRY=registry.il2.dso.mil -BASE_IMAGE=platform-one/devops/pipeline-templates/ironbank/ruby26 -BASE_TAG=2.6.6.212 +BASE_IMAGE=platform-one/devops/pipeline-templates/ironbank/ruby27 +BASE_TAG=2.7.2 # Package Versions. -NODE_VERSION=14.15.4 +NODE_VERSION=14.15.5 YARN_VERSION=1.22.5 JQUERY_RAILS_VERSION=4.4.0 -- GitLab From 37023d09b46d366237a0f6a4257099312240f339 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 19 Feb 2021 14:15:23 -1000 Subject: [PATCH 261/283] upgrading ruby gems and node modules --- Dockerfile | 3 - hardening_manifest.yaml | 10 +- scripts/Gemfile.lock | 1203 ++++++++++++------------ scripts/gems/block-parser/Gemfile.lock | 29 +- scripts/package.json | 42 +- scripts/yarn.lock | 409 +++++--- 6 files changed, 908 insertions(+), 788 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3d9cfe2..7cc1112 100644 --- a/Dockerfile +++ b/Dockerfile @@ -36,9 +36,6 @@ RUN tar xzf nodejs.tar.gz && rm nodejs.tar.gz # Yarn RUN tar xzf yarn.tar.gz && rm yarn.tar.gz -# Remove the bundles directory. -RUN rm -rf bundles - # Add write permissions. RUN chown -R 1001 . diff --git a/hardening_manifest.yaml b/hardening_manifest.yaml index f606c32..83b3252 100644 --- a/hardening_manifest.yaml +++ b/hardening_manifest.yaml @@ -38,7 +38,7 @@ resources: filename: redis-cli.tar.gz validation: type: sha256 - value: 003cdc4277d0d021f6c54249ce277293a06fb63bf7d8fd1444ef42f595218f86 + value: bb5f74ccdfcf66746c926dfb0e804627de3f61cc722c3cd367ab6c2c9960b950 - auth: type: s3 id: galvanize @@ -47,7 +47,7 @@ resources: filename: node_modules.tar.gz validation: type: sha256 - value: 830b0824cc9d7b2c037dd5e3de5176e7908fbbe104be9f12c67fedd5e75aac37 + value: b3ea918d9628aba96a83c9bfd3c1cd98f66a4b30daa2368b6b0dd0be9234476e - auth: type: s3 id: galvanize @@ -56,7 +56,7 @@ resources: filename: nodejs.tar.gz validation: type: sha256 - value: 2194da489ad24a6261607433e79d6bc4c8e8d28d8265c53249282f960339b6e0 + value: 480ebc0f3dca30c31b976d0f5088ce4bfe3d4aba9dca0202d2390801b80c8709 - auth: type: s3 id: galvanize @@ -65,7 +65,7 @@ resources: filename: yarn.tar.gz validation: type: sha256 - value: 9cdc059965f8c46a49fbf8105addec82ace7a2a2486554c060e4be408a73837e + value: cdd48447584ab01e81288994699bcf67d99c32a7bc3b068a2218016bb3d9063e - auth: type: s3 id: galvanize @@ -74,7 +74,7 @@ resources: filename: bundle.tar.gz validation: type: sha256 - value: b439f3b9c3becb568a061fbf3615914a6b9546cf71e266c6caa7a316ef8a751d + value: c8a38e0da532865e445280c5657653c070c3af3686380d30a3bb9de483022a5a # List of project maintainers maintainers: diff --git a/scripts/Gemfile.lock b/scripts/Gemfile.lock index e5d5378..62fa2b7 100644 --- a/scripts/Gemfile.lock +++ b/scripts/Gemfile.lock @@ -16,60 +16,60 @@ PATH GEM remote: https://rubygems.org/ specs: - actioncable (6.1.1) - actionpack (= 6.1.1) - activesupport (= 6.1.1) + actioncable (6.1.3) + actionpack (= 6.1.3) + activesupport (= 6.1.3) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.1.1) - actionpack (= 6.1.1) - activejob (= 6.1.1) - activerecord (= 6.1.1) - activestorage (= 6.1.1) - activesupport (= 6.1.1) + actionmailbox (6.1.3) + actionpack (= 6.1.3) + activejob (= 6.1.3) + activerecord (= 6.1.3) + activestorage (= 6.1.3) + activesupport (= 6.1.3) mail (>= 2.7.1) - actionmailer (6.1.1) - actionpack (= 6.1.1) - actionview (= 6.1.1) - activejob (= 6.1.1) - activesupport (= 6.1.1) + actionmailer (6.1.3) + actionpack (= 6.1.3) + actionview (= 6.1.3) + activejob (= 6.1.3) + activesupport (= 6.1.3) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.1.1) - actionview (= 6.1.1) - activesupport (= 6.1.1) + actionpack (6.1.3) + actionview (= 6.1.3) + activesupport (= 6.1.3) rack (~> 2.0, >= 2.0.9) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.1.1) - actionpack (= 6.1.1) - activerecord (= 6.1.1) - activestorage (= 6.1.1) - activesupport (= 6.1.1) + actiontext (6.1.3) + actionpack (= 6.1.3) + activerecord (= 6.1.3) + activestorage (= 6.1.3) + activesupport (= 6.1.3) nokogiri (>= 1.8.5) - actionview (6.1.1) - activesupport (= 6.1.1) + actionview (6.1.3) + activesupport (= 6.1.3) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.1.1) - activesupport (= 6.1.1) + activejob (6.1.3) + activesupport (= 6.1.3) globalid (>= 0.3.6) - activemodel (6.1.1) - activesupport (= 6.1.1) - activerecord (6.1.1) - activemodel (= 6.1.1) - activesupport (= 6.1.1) - activestorage (6.1.1) - actionpack (= 6.1.1) - activejob (= 6.1.1) - activerecord (= 6.1.1) - activesupport (= 6.1.1) + activemodel (6.1.3) + activesupport (= 6.1.3) + activerecord (6.1.3) + activemodel (= 6.1.3) + activesupport (= 6.1.3) + activestorage (6.1.3) + actionpack (= 6.1.3) + activejob (= 6.1.3) + activerecord (= 6.1.3) + activesupport (= 6.1.3) marcel (~> 0.3.1) mimemagic (~> 0.3.2) - activesupport (6.1.1) + activesupport (6.1.3) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) @@ -81,632 +81,632 @@ GEM apitome (0.3.0) kramdown railties - ast (2.4.1) - autoprefixer-rails (10.2.0.0) + ast (2.4.2) + autoprefixer-rails (10.2.4.0) execjs aws-eventstream (1.1.0) - aws-partitions (1.418.0) + aws-partitions (1.428.0) aws-sdk (3.0.1) aws-sdk-resources (~> 3) - aws-sdk-accessanalyzer (1.14.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-accessanalyzer (1.16.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-acm (1.38.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-acm (1.39.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-acmpca (1.32.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-acmpca (1.33.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-alexaforbusiness (1.43.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-alexaforbusiness (1.44.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-amplify (1.27.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-amplify (1.28.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-amplifybackend (1.1.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-amplifybackend (1.2.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-apigateway (1.58.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-apigateway (1.59.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-apigatewaymanagementapi (1.19.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-apigatewaymanagementapi (1.20.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-apigatewayv2 (1.30.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-apigatewayv2 (1.31.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-appconfig (1.12.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-appconfig (1.13.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-appflow (1.4.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-appflow (1.6.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-appintegrationsservice (1.0.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-appintegrationsservice (1.1.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-applicationautoscaling (1.49.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-applicationautoscaling (1.50.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-applicationdiscoveryservice (1.33.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-applicationdiscoveryservice (1.34.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-applicationinsights (1.16.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-applicationinsights (1.17.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-appmesh (1.33.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-appmesh (1.34.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-appregistry (1.3.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-appregistry (1.4.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-appstream (1.49.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-appstream (1.50.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-appsync (1.37.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-appsync (1.39.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-athena (1.33.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-athena (1.35.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-auditmanager (1.1.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-auditmanager (1.3.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-augmentedairuntime (1.10.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-augmentedairuntime (1.11.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-autoscaling (1.53.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-autoscaling (1.54.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-autoscalingplans (1.29.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-autoscalingplans (1.30.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-backup (1.25.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-backup (1.27.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-batch (1.43.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-batch (1.44.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-braket (1.5.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-braket (1.6.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-budgets (1.36.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-budgets (1.37.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-chime (1.40.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-chime (1.41.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-cloud9 (1.29.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-cloud9 (1.30.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-clouddirectory (1.29.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-clouddirectory (1.30.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-cloudformation (1.46.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-cloudformation (1.48.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-cloudfront (1.47.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-cloudfront (1.48.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-cloudhsm (1.27.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-cloudhsm (1.28.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-cloudhsmv2 (1.31.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-cloudhsmv2 (1.32.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-cloudsearch (1.27.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-cloudsearch (1.28.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-cloudsearchdomain (1.22.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-cloudsearchdomain (1.23.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-cloudtrail (1.31.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-cloudtrail (1.33.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-cloudwatch (1.47.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-cloudwatch (1.49.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-cloudwatchevents (1.40.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-cloudwatchevents (1.41.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-cloudwatchlogs (1.38.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-cloudwatchlogs (1.39.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-codeartifact (1.6.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-codeartifact (1.7.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-codebuild (1.65.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-codebuild (1.69.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-codecommit (1.40.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-codecommit (1.41.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-codedeploy (1.37.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-codedeploy (1.38.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-codeguruprofiler (1.12.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-codeguruprofiler (1.13.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-codegurureviewer (1.14.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-codegurureviewer (1.15.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-codepipeline (1.39.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-codepipeline (1.41.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-codestar (1.27.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-codestar (1.28.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-codestarconnections (1.12.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-codestarconnections (1.13.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-codestarnotifications (1.8.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-codestarnotifications (1.9.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-cognitoidentity (1.29.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-cognitoidentity (1.30.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-cognitoidentityprovider (1.48.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-cognitoidentityprovider (1.49.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-cognitosync (1.24.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-cognitosync (1.25.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-comprehend (1.42.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-comprehend (1.43.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-comprehendmedical (1.23.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-comprehendmedical (1.24.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-computeoptimizer (1.11.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-computeoptimizer (1.13.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-configservice (1.55.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-configservice (1.58.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-connect (1.38.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-connect (1.40.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-connectcontactlens (1.0.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-connectcontactlens (1.1.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-connectparticipant (1.9.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-connectparticipant (1.10.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-core (3.111.2) + aws-sdk-core (3.112.0) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.239.0) aws-sigv4 (~> 1.1) jmespath (~> 1.0) - aws-sdk-costandusagereportservice (1.28.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-costandusagereportservice (1.29.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-costexplorer (1.56.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-costexplorer (1.58.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-customerprofiles (1.1.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-customerprofiles (1.3.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-databasemigrationservice (1.50.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-databasemigrationservice (1.51.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-dataexchange (1.10.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-dataexchange (1.12.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-datapipeline (1.24.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-datapipeline (1.25.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-datasync (1.28.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-datasync (1.29.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-dax (1.27.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-dax (1.28.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-detective (1.11.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-detective (1.13.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-devicefarm (1.39.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-devicefarm (1.40.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-devopsguru (1.2.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-devopsguru (1.4.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-directconnect (1.37.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-directconnect (1.38.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-directoryservice (1.37.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-directoryservice (1.38.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-dlm (1.37.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-dlm (1.39.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-docdb (1.27.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-docdb (1.28.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-dynamodb (1.58.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-dynamodb (1.59.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-dynamodbstreams (1.27.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-dynamodbstreams (1.28.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-ebs (1.11.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-ebs (1.12.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-ec2 (1.221.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-ec2 (1.225.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-ec2instanceconnect (1.11.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-ec2instanceconnect (1.12.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-ecr (1.40.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-ecr (1.41.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-ecrpublic (1.0.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-ecrpublic (1.1.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-ecs (1.73.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-ecs (1.74.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-efs (1.36.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-efs (1.37.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-eks (1.46.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-eks (1.48.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-elasticache (1.50.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-elasticache (1.53.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-elasticbeanstalk (1.40.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-elasticbeanstalk (1.41.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-elasticinference (1.10.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-elasticinference (1.11.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-elasticloadbalancing (1.29.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-elasticloadbalancing (1.30.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-elasticloadbalancingv2 (1.56.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-elasticloadbalancingv2 (1.60.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-elasticsearchservice (1.46.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-elasticsearchservice (1.48.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-elastictranscoder (1.27.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-elastictranscoder (1.28.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-emr (1.40.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-emr (1.41.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-emrcontainers (1.0.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-emrcontainers (1.2.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-eventbridge (1.18.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-eventbridge (1.19.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-firehose (1.35.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-firehose (1.36.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-fms (1.33.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-fms (1.34.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-forecastqueryservice (1.10.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-forecastqueryservice (1.11.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-forecastservice (1.14.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-forecastservice (1.15.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-frauddetector (1.15.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-frauddetector (1.16.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-fsx (1.33.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-fsx (1.34.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-gamelift (1.39.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-gamelift (1.41.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-glacier (1.35.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-glacier (1.36.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-globalaccelerator (1.27.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-globalaccelerator (1.29.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-glue (1.82.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-glue (1.83.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-gluedatabrew (1.0.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-gluedatabrew (1.4.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-greengrass (1.37.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-greengrass (1.38.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-greengrassv2 (1.1.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-greengrassv2 (1.2.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-groundstation (1.15.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-groundstation (1.16.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-guardduty (1.43.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-guardduty (1.44.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-health (1.31.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-health (1.33.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-healthlake (1.1.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-healthlake (1.2.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-honeycode (1.4.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-honeycode (1.5.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-iam (1.46.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-iam (1.48.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-identitystore (1.3.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-identitystore (1.4.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-imagebuilder (1.17.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-imagebuilder (1.18.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-importexport (1.24.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-importexport (1.25.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv2 (~> 1.0) - aws-sdk-inspector (1.32.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-inspector (1.33.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-iot (1.64.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-iot (1.66.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-iot1clickdevicesservice (1.26.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-iot1clickdevicesservice (1.27.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-iot1clickprojects (1.26.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-iot1clickprojects (1.27.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-iotanalytics (1.36.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-iotanalytics (1.37.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-iotdataplane (1.26.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-iotdataplane (1.27.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-iotdeviceadvisor (1.0.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-iotdeviceadvisor (1.1.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-iotevents (1.20.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-iotevents (1.21.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-ioteventsdata (1.13.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-ioteventsdata (1.14.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-iotfleethub (1.0.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-iotfleethub (1.1.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-iotjobsdataplane (1.25.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-iotjobsdataplane (1.26.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-iotsecuretunneling (1.9.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-iotsecuretunneling (1.10.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-iotsitewise (1.16.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-iotsitewise (1.19.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-iotthingsgraph (1.12.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-iotthingsgraph (1.13.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-iotwireless (1.1.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-iotwireless (1.2.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-ivs (1.5.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-ivs (1.7.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-kafka (1.33.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-kafka (1.34.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-kendra (1.20.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-kendra (1.21.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-kinesis (1.30.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-kinesis (1.31.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-kinesisanalytics (1.29.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-kinesisanalytics (1.30.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-kinesisanalyticsv2 (1.24.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-kinesisanalyticsv2 (1.25.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-kinesisvideo (1.30.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-kinesisvideo (1.31.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-kinesisvideoarchivedmedia (1.29.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-kinesisvideoarchivedmedia (1.31.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-kinesisvideomedia (1.26.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-kinesisvideomedia (1.27.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-kinesisvideosignalingchannels (1.8.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-kinesisvideosignalingchannels (1.9.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-kms (1.41.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-kms (1.42.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-lakeformation (1.11.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-lakeformation (1.12.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-lambda (1.57.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-lambda (1.59.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-lambdapreview (1.24.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-lambdapreview (1.25.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-lex (1.33.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-lex (1.34.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-lexmodelbuildingservice (1.42.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-lexmodelbuildingservice (1.43.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-lexmodelsv2 (1.0.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-lexmodelsv2 (1.1.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-lexruntimev2 (1.0.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-lexruntimev2 (1.1.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-licensemanager (1.23.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-licensemanager (1.24.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-lightsail (1.41.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-lightsail (1.44.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-locationservice (1.0.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-locationservice (1.1.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-lookoutforvision (1.0.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-lookoutforvision (1.2.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-machinelearning (1.25.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-machinelearning (1.26.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-macie (1.25.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-macie (1.27.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-macie2 (1.19.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-macie2 (1.23.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-managedblockchain (1.18.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-managedblockchain (1.20.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-marketplacecatalog (1.9.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-marketplacecatalog (1.10.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-marketplacecommerceanalytics (1.30.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-marketplacecommerceanalytics (1.31.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-marketplaceentitlementservice (1.24.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-marketplaceentitlementservice (1.25.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-marketplacemetering (1.32.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-marketplacemetering (1.33.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-mediaconnect (1.28.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-mediaconnect (1.29.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-mediaconvert (1.61.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-mediaconvert (1.63.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-medialive (1.61.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-medialive (1.64.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-mediapackage (1.36.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-mediapackage (1.37.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-mediapackagevod (1.19.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-mediapackagevod (1.20.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-mediastore (1.30.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-mediastore (1.31.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-mediastoredata (1.27.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-mediastoredata (1.28.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-mediatailor (1.33.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-mediatailor (1.35.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-migrationhub (1.29.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-migrationhub (1.30.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-migrationhubconfig (1.9.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-migrationhubconfig (1.10.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-mobile (1.24.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-mobile (1.25.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-mq (1.34.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-mq (1.35.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-mturk (1.27.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-mturk (1.28.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-mwaa (1.0.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-mwaa (1.1.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-neptune (1.32.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-neptune (1.33.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-networkfirewall (1.0.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-networkfirewall (1.1.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-networkmanager (1.9.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-networkmanager (1.10.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-opsworks (1.30.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-opsworks (1.31.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-opsworkscm (1.40.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-opsworkscm (1.41.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-organizations (1.55.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-organizations (1.57.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-outposts (1.13.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-outposts (1.14.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-personalize (1.20.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-personalize (1.21.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-personalizeevents (1.14.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-personalizeevents (1.16.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-personalizeruntime (1.20.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-personalizeruntime (1.21.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-pi (1.25.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-pi (1.26.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-pinpoint (1.48.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-pinpoint (1.50.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-pinpointemail (1.24.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-pinpointemail (1.25.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-pinpointsmsvoice (1.21.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-pinpointsmsvoice (1.22.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-polly (1.38.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-polly (1.39.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-pricing (1.24.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-pricing (1.25.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-prometheusservice (1.1.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-prometheusservice (1.2.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-qldb (1.11.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-qldb (1.12.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-qldbsession (1.10.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-qldbsession (1.12.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-quicksight (1.39.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-quicksight (1.42.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-ram (1.22.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-ram (1.23.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-rds (1.111.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-rds (1.115.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-rdsdataservice (1.23.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-rdsdataservice (1.24.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-redshift (1.53.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-redshift (1.54.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-redshiftdataapiservice (1.2.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-redshiftdataapiservice (1.4.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-rekognition (1.47.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-rekognition (1.48.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-resourcegroups (1.33.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-resourcegroups (1.34.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-resourcegroupstaggingapi (1.35.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-resourcegroupstaggingapi (1.36.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) aws-sdk-resources (3.94.0) aws-sdk-accessanalyzer (~> 1) @@ -967,165 +967,165 @@ GEM aws-sdk-workmailmessageflow (~> 1) aws-sdk-workspaces (~> 1) aws-sdk-xray (~> 1) - aws-sdk-robomaker (1.31.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-robomaker (1.33.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-route53 (1.45.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-route53 (1.46.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-route53domains (1.28.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-route53domains (1.29.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-route53resolver (1.22.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-route53resolver (1.23.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.87.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-s3 (1.88.1) + aws-sdk-core (~> 3, >= 3.112.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.1) - aws-sdk-s3control (1.26.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-s3control (1.27.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-s3outposts (1.0.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-s3outposts (1.1.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-sagemaker (1.75.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-sagemaker (1.78.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-sagemakeredgemanager (1.0.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-sagemakeredgemanager (1.1.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-sagemakerfeaturestoreruntime (1.0.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-sagemakerfeaturestoreruntime (1.1.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-sagemakerruntime (1.28.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-sagemakerruntime (1.29.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-savingsplans (1.12.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-savingsplans (1.13.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-schemas (1.10.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-schemas (1.11.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-secretsmanager (1.43.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-secretsmanager (1.44.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-securityhub (1.38.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-securityhub (1.40.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-serverlessapplicationrepository (1.32.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-serverlessapplicationrepository (1.33.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-servicecatalog (1.57.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-servicecatalog (1.58.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-servicediscovery (1.31.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-servicediscovery (1.32.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-servicequotas (1.12.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-servicequotas (1.13.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-ses (1.36.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-ses (1.37.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-sesv2 (1.14.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-sesv2 (1.16.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-shield (1.33.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-shield (1.34.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-signer (1.27.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-signer (1.28.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-simpledb (1.24.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-simpledb (1.25.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv2 (~> 1.0) - aws-sdk-sms (1.27.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-sms (1.28.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-snowball (1.35.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-snowball (1.36.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-sns (1.37.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-sns (1.38.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-sqs (1.35.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-sqs (1.36.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-ssm (1.103.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-ssm (1.104.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-ssoadmin (1.4.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-ssoadmin (1.5.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-ssooidc (1.8.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-ssooidc (1.9.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-states (1.37.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-states (1.38.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-storagegateway (1.52.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-storagegateway (1.53.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-support (1.28.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-support (1.29.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-swf (1.25.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-swf (1.26.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-synthetics (1.10.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-synthetics (1.11.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-textract (1.22.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-textract (1.23.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-timestreamquery (1.2.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-timestreamquery (1.3.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-timestreamwrite (1.2.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-timestreamwrite (1.3.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-transcribeservice (1.50.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-transcribeservice (1.51.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-transcribestreamingservice (1.24.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-transcribestreamingservice (1.26.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-transfer (1.29.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-transfer (1.30.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-translate (1.29.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-translate (1.30.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-waf (1.36.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-waf (1.37.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-wafregional (1.37.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-wafregional (1.38.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-wafv2 (1.14.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-wafv2 (1.16.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-wellarchitected (1.0.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-wellarchitected (1.2.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-workdocs (1.28.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-workdocs (1.29.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-worklink (1.21.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-worklink (1.22.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-workmail (1.33.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-workmail (1.35.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-workmailmessageflow (1.9.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-workmailmessageflow (1.11.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-workspaces (1.49.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-workspaces (1.50.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-xray (1.35.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-xray (1.36.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) aws-sigv2 (1.0.1) aws-sigv4 (1.2.2) @@ -1143,33 +1143,38 @@ GEM rack (>= 0.9.0) binding_of_caller (1.0.0) debug_inspector (>= 0.0.1) - bootsnap (1.5.1) + bootsnap (1.7.2) msgpack (~> 1.0) - bootstrap (4.5.3) + bootstrap (4.6.0) autoprefixer-rails (>= 9.1.0) popper_js (>= 1.14.3, < 2) sassc-rails (>= 2.0.0) browser (5.3.0) builder (3.2.4) byebug (11.1.3) - capybara (3.34.0) + capybara (3.35.3) addressable mini_mime (>= 0.1.3) nokogiri (~> 1.8) rack (>= 1.6.0) rack-test (>= 0.6.3) - regexp_parser (~> 1.5) + regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) childprocess (3.0.0) coderay (1.1.3) - commonmarker (0.21.1) + commonmarker (0.21.2) ruby-enum (~> 0.5) concurrent-ruby (1.1.8) connection_pool (2.2.3) crack (0.4.5) rexml crass (1.0.6) - database_cleaner (1.8.5) + database_cleaner (2.0.1) + database_cleaner-active_record (~> 2.0.0) + database_cleaner-active_record (2.0.0) + activerecord (>= 5.a) + database_cleaner-core (~> 2.0.0) + database_cleaner-core (2.0.1) debug_inspector (1.0.0) deterministic (0.6.0) diff-lcs (1.4.4) @@ -1192,8 +1197,8 @@ GEM faraday-net_http (1.0.1) ffi (1.14.2) flamegraph (0.9.5) - font-awesome-rails (4.7.0.6) - railties (>= 3.2, < 6.2) + font-awesome-rails (4.7.0.7) + railties (>= 3.2, < 7) foreman (0.87.2) github-markup (3.0.5) github_url (0.2.1) @@ -1206,11 +1211,11 @@ GEM temple (>= 0.8.0) tilt hashdiff (1.0.1) - honeybadger (4.7.2) + honeybadger (4.7.3) httparty (0.18.1) mime-types (~> 3.0) multi_xml (>= 0.5.2) - i18n (1.8.7) + i18n (1.8.9) concurrent-ruby (~> 1.0) iniparse (1.5.0) jmespath (1.4.0) @@ -1246,17 +1251,17 @@ GEM method_source (1.0.0) mime-types (3.3.1) mime-types-data (~> 3.2015) - mime-types-data (3.2020.1104) + mime-types-data (3.2021.0212) mimemagic (0.3.5) mini_mime (1.0.2) mini_portile2 (2.5.0) minitest (5.14.3) - msgpack (1.3.3) + msgpack (1.4.2) multi_json (1.15.0) multi_xml (0.6.0) multipart-post (2.1.1) mustache (1.1.1) - nio4r (2.5.4) + nio4r (2.5.5) nokogiri (1.11.1) mini_portile2 (~> 2.5.0) racc (~> 1.4) @@ -1266,7 +1271,7 @@ GEM overcommit (0.57.0) childprocess (>= 0.6.3, < 5) iniparse (~> 1.4) - pagy (3.10.0) + pagy (3.11.0) parallel (1.20.1) parser (3.0.0.0) ast (~> 2.4.1) @@ -1274,34 +1279,34 @@ GEM popper_js (1.16.0) psych (3.3.0) public_suffix (4.0.6) - puma (5.1.1) + puma (5.2.1) nio4r (~> 2.0) pundit (2.1.0) activesupport (>= 3.0.0) racc (1.5.2) rack (2.2.3) - rack-attack (6.3.1) + rack-attack (6.5.0) rack (>= 1.0, < 3) - rack-mini-profiler (2.3.0) + rack-mini-profiler (2.3.1) rack (>= 1.2.0) rack-proxy (0.6.5) rack rack-test (1.1.0) rack (>= 1.0, < 3) - rails (6.1.1) - actioncable (= 6.1.1) - actionmailbox (= 6.1.1) - actionmailer (= 6.1.1) - actionpack (= 6.1.1) - actiontext (= 6.1.1) - actionview (= 6.1.1) - activejob (= 6.1.1) - activemodel (= 6.1.1) - activerecord (= 6.1.1) - activestorage (= 6.1.1) - activesupport (= 6.1.1) + rails (6.1.3) + actioncable (= 6.1.3) + actionmailbox (= 6.1.3) + actionmailer (= 6.1.3) + actionpack (= 6.1.3) + actiontext (= 6.1.3) + actionview (= 6.1.3) + activejob (= 6.1.3) + activemodel (= 6.1.3) + activerecord (= 6.1.3) + activestorage (= 6.1.3) + activesupport (= 6.1.3) bundler (>= 1.15.0) - railties (= 6.1.1) + railties (= 6.1.3) sprockets-rails (>= 2.0.0) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) @@ -1312,9 +1317,9 @@ GEM nokogiri (>= 1.6) rails-html-sanitizer (1.3.0) loofah (~> 2.3) - railties (6.1.1) - actionpack (= 6.1.1) - activesupport (= 6.1.1) + railties (6.1.3) + actionpack (= 6.1.3) + activesupport (= 6.1.3) method_source rake (>= 0.8.7) thor (~> 1.0) @@ -1331,7 +1336,7 @@ GEM tilt redcarpet (3.5.1) redis (4.2.5) - regexp_parser (1.8.2) + regexp_parser (2.0.3) rexml (3.2.4) rspec (3.10.0) rspec-core (~> 3.10.0) @@ -1342,7 +1347,7 @@ GEM rspec-expectations (3.10.1) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.10.0) - rspec-mocks (3.10.1) + rspec-mocks (3.10.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.10.0) rspec-rails (4.0.2) @@ -1353,14 +1358,14 @@ GEM rspec-expectations (~> 3.10) rspec-mocks (~> 3.10) rspec-support (~> 3.10) - rspec-support (3.10.1) + rspec-support (3.10.2) rspec_api_documentation (6.1.0) activesupport (>= 3.0.0) mustache (~> 1.0, >= 0.99.4) rspec (~> 3.0) rspec_junit_formatter (0.4.1) rspec-core (>= 2, < 4, != 2.12.0) - rubocop (1.8.1) + rubocop (1.10.0) parallel (~> 1.10) parser (>= 3.0.0.0) rainbow (>= 2.2.2, < 4.0) @@ -1369,9 +1374,9 @@ GEM rubocop-ast (>= 1.2.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.4.0) + rubocop-ast (1.4.1) parser (>= 2.7.1.5) - ruby-enum (0.8.0) + ruby-enum (0.9.0) i18n ruby-progressbar (1.11.0) ruby2_keywords (0.0.4) @@ -1389,7 +1394,7 @@ GEM sawyer (0.8.2) addressable (>= 2.3.5) faraday (> 0.8, < 2.0) - scout_apm (4.0.3) + scout_apm (4.0.4) parser selenium-webdriver (3.142.7) childprocess (>= 0.5, < 4.0) @@ -1422,7 +1427,7 @@ GEM terminal-table (1.6.0) thor (1.1.0) tilt (2.0.10) - timecop (0.9.2) + timecop (0.9.4) ts_routes (1.0.3) railties (>= 4.0) tzinfo (2.0.4) @@ -1432,7 +1437,7 @@ GEM underscore-rails (1.8.3) unicode-display_width (2.0.0) vcr (6.0.0) - webmock (3.11.1) + webmock (3.11.2) addressable (>= 2.3.6) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) diff --git a/scripts/gems/block-parser/Gemfile.lock b/scripts/gems/block-parser/Gemfile.lock index aaece8f..3ca1255 100644 --- a/scripts/gems/block-parser/Gemfile.lock +++ b/scripts/gems/block-parser/Gemfile.lock @@ -16,9 +16,9 @@ PATH GEM remote: https://rubygems.org/ specs: - activemodel (6.1.1) - activesupport (= 6.1.1) - activesupport (6.1.1) + activemodel (6.1.3) + activesupport (= 6.1.3) + activesupport (6.1.3) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) @@ -26,9 +26,9 @@ GEM zeitwerk (~> 2.3) addressable (2.7.0) public_suffix (>= 2.0.2, < 5.0) - ast (2.4.1) + ast (2.4.2) byebug (11.1.3) - commonmarker (0.21.1) + commonmarker (0.21.2) ruby-enum (~> 0.5) concurrent-ruby (1.1.8) diff-lcs (1.4.4) @@ -45,11 +45,11 @@ GEM httparty (0.18.1) mime-types (~> 3.0) multi_xml (>= 0.5.2) - i18n (1.8.7) + i18n (1.8.9) concurrent-ruby (~> 1.0) mime-types (3.3.1) mime-types-data (~> 3.2015) - mime-types-data (3.2020.1104) + mime-types-data (3.2021.0212) mini_portile2 (2.5.0) minitest (5.14.3) multi_xml (0.6.0) @@ -80,13 +80,13 @@ GEM rspec-expectations (3.10.1) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.10.0) - rspec-mocks (3.10.1) + rspec-mocks (3.10.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.10.0) - rspec-support (3.10.1) + rspec-support (3.10.2) rspec_junit_formatter (0.4.1) rspec-core (>= 2, < 4, != 2.12.0) - rubocop (1.8.1) + rubocop (1.10.0) parallel (~> 1.10) parser (>= 3.0.0.0) rainbow (>= 2.2.2, < 4.0) @@ -95,20 +95,19 @@ GEM rubocop-ast (>= 1.2.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.4.0) + rubocop-ast (1.4.1) parser (>= 2.7.1.5) - ruby-enum (0.8.0) + ruby-enum (0.9.0) i18n ruby-progressbar (1.11.0) ruby2_keywords (0.0.4) sawyer (0.8.2) addressable (>= 2.3.5) faraday (> 0.8, < 2.0) - terminal-table (1.8.0) - unicode-display_width (~> 1.1, >= 1.1.1) + terminal-table (1.6.0) tzinfo (2.0.4) concurrent-ruby (~> 1.0) - unicode-display_width (1.7.0) + unicode-display_width (2.0.0) zeitwerk (2.4.2) PLATFORMS diff --git a/scripts/package.json b/scripts/package.json index 21a89b3..3930fb2 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -26,15 +26,15 @@ "@vimeo/player": "^2.15.0", "babel-preset-react": "^6.24.1", "brace": "^0.11.1", - "browserify": "^16.5.2", + "browserify": "^17.0.0", "browserify-incremental": "^3.1.1", - "dropzone": "^5.7.2", + "dropzone": "^5.7.6", "highlightjs": "^9.16.2", "immutability-helper": "^3.1.1", "lodash-es": "^4.17.20", - "marked": "^1.2.7", + "marked": "^2.0.0", "moment": "^2.29.1", - "moment-timezone": "^0.5.32", + "moment-timezone": "^0.5.33", "objectify-array": "^2.1.0", "popper.js": "^1.16.1", "prop-types": "^15.7.2", @@ -44,38 +44,38 @@ "react-addons-test-utils": "^15.6.2", "react-beautiful-dnd": "^13.0.0", "react-copy-to-clipboard": "^5.0.3", - "react-datepicker": "^3.4.1", + "react-datepicker": "^3.5.0", "react-dom": "^17.0.1", "react-json-pretty": "^2.2.0", - "react-paginate": "^7.0.0", + "react-paginate": "^7.1.0", "react-pdf": "^4.2.0", "react-scroll-sync": "^0.8.0", "react-sizeme": "^2.6.12", - "react-textarea-autosize": "^8.3.0", - "react-tooltip": "^4.2.13", + "react-textarea-autosize": "^8.3.1", + "react-tooltip": "^4.2.14", "react_ujs": "^2.6.1", "reactify": "^1.1.1", - "ts-loader": "^8.0.14", - "typescript": "^4.1.3", + "ts-loader": "^8.0.17", + "typescript": "^4.1.5", "unfetch": "^4.2.0" }, "devDependencies": { - "@types/lodash-es": "^4.17.3", + "@types/lodash-es": "^4.17.4", "@types/node-fetch": "^2.5.8", "@types/rc-slider": "^8.6.6", - "@types/react": "^17.0.0", + "@types/react": "^17.0.2", "@types/react-addons-css-transition-group": "^15.0.5", "@types/react-beautiful-dnd": "^13.0.0", "@types/react-copy-to-clipboard": "^5.0.0", "@types/react-datepicker": "^3.1.3", - "@types/react-dom": "^17.0.0", + "@types/react-dom": "^17.0.1", "@types/react-textarea-autosize": "^4.3.5", "@types/vimeo__player": "^2.10.0", - "eslint": "^7.18.0", + "eslint": "^7.20.0", "eslint-config-airbnb": "^18.2.1", "eslint-plugin-import": "^2.22.1", "eslint-plugin-jsx-a11y": "^6.4.1", - "eslint-plugin-promise": "^4.2.1", + "eslint-plugin-promise": "^4.3.1", "eslint-plugin-react": "^7.22.0", "eslint-plugin-standard": "^5.0.0", "postcss-flexbugs-fixes": "^4.2.1", @@ -84,14 +84,14 @@ "webpack-dev-server": "^3.11.2" }, "resolutions": { - "acorn": "^7.1.1", - "dot-prop": "^4.2.1", - "elliptic": "^6.5.3", - "ini": "^1.3.8", + "acorn": "^8.0.5", + "dot-prop": "^6.0.1", + "elliptic": "^6.5.4", + "ini": "^2.0.0", "kind-of": "^6.0.3", "lodash": "^4.17.20", - "mathjax": "^2.7.9", - "minimist": "^1.2.3", + "mathjax": "^3.1.2", + "minimist": "^1.2.5", "websocket-extensions": "^0.1.4" } } diff --git a/scripts/yarn.lock b/scripts/yarn.lock index df7585c..ecbe464 100644 --- a/scripts/yarn.lock +++ b/scripts/yarn.lock @@ -2,6 +2,13 @@ # yarn lockfile v1 +"@babel/code-frame@7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" + integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== + dependencies: + "@babel/highlight" "^7.10.4" + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" @@ -948,10 +955,10 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= -"@types/lodash-es@^4.17.3": - version "4.17.3" - resolved "https://registry.yarnpkg.com/@types/lodash-es/-/lodash-es-4.17.3.tgz#87eb0b3673b076b8ee655f1890260a136af09a2d" - integrity sha512-iHI0i7ZAL1qepz1Y7f3EKg/zUMDwDfTzitx+AlHhJJvXwenP682ZyGbgPSc5Ej3eEAKVbNWKFuwOadCj5vBbYQ== +"@types/lodash-es@^4.17.4": + version "4.17.4" + resolved "https://registry.yarnpkg.com/@types/lodash-es/-/lodash-es-4.17.4.tgz#b2e440d2bf8a93584a9fd798452ec497986c9b97" + integrity sha512-BBz79DCJbD2CVYZH67MBeHZRX++HF+5p8Mo5MzjZi64Wac39S3diedJYHZtScbRVf4DjZyN6LzA0SB0zy+HSSQ== dependencies: "@types/lodash" "*" @@ -1043,10 +1050,10 @@ date-fns "^2.0.1" popper.js "^1.14.1" -"@types/react-dom@^17.0.0": - version "17.0.0" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.0.tgz#b3b691eb956c4b3401777ee67b900cb28415d95a" - integrity sha512-lUqY7OlkF/RbNtD5nIq7ot8NquXrdFrjSOR6+w9a9RFQevGi1oZO1dcJbXMeONAPKtZ2UrZOEJ5UOCVsxbLk/g== +"@types/react-dom@^17.0.1": + version "17.0.1" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.1.tgz#d92d77d020bfb083e07cc8e0ac9f933599a4d56a" + integrity sha512-yIVyopxQb8IDZ7SOHeTovurFq+fXiPICa+GV3gp0Xedsl+MwQlMLKmvrnEjFbQxjliH5YVAEWFh975eVNmKj7Q== dependencies: "@types/react" "*" @@ -1079,10 +1086,10 @@ "@types/prop-types" "*" csstype "^2.2.0" -"@types/react@^17.0.0": - version "17.0.0" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.0.tgz#5af3eb7fad2807092f0046a1302b7823e27919b8" - integrity sha512-aj/L7RIMsRlWML3YB6KZiXB3fV2t41+5RBGYF8z+tAKU43Px8C3cYUZsDvf1/+Bm4FK21QWBrDutu8ZJ/70qOw== +"@types/react@^17.0.2": + version "17.0.2" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.2.tgz#3de24c4efef902dd9795a49c75f760cbe4f7a5a8" + integrity sha512-Xt40xQsrkdvjn1EyWe1Bc0dJLcil/9x2vAuW7ya+PuQip4UYUaXyhzWmAbwRsdMgwOFHpfp7/FFZebDU6Y8VHA== dependencies: "@types/prop-types" "*" csstype "^3.0.2" @@ -1297,10 +1304,10 @@ acorn-walk@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.0.0.tgz#c8ba6f0f1aac4b0a9e32d1f0af12be769528f36b" -acorn@^5.2.1, acorn@^6.4.1, acorn@^7.0.0, acorn@^7.1.1, acorn@^7.4.0: - version "7.4.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" - integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== +acorn@^5.2.1, acorn@^6.4.1, acorn@^7.0.0, acorn@^7.4.0, acorn@^8.0.5: + version "8.0.5" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.0.5.tgz#a3bfb872a74a6a7f661bc81b9849d9cac12601b7" + integrity sha512-v+DieK/HJkJOpFBETDJioequtc3PfxsWMaxIdIwujtF7FEV/MAyDQLlm6/zPvr7Mix07mLh6ccVwIsloceodlg== add-dom-event-listener@^1.1.0: version "1.1.0" @@ -1468,6 +1475,11 @@ arr-union@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" +array-filter@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-1.0.0.tgz#baf79e62e6ef4c2a4c0b831232daffec251f9d83" + integrity sha1-uveeYubvTCpMC4MSMtr/7CUfnYM= + array-find-index@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" @@ -1618,6 +1630,13 @@ autoprefixer@^9.6.1: postcss "^7.0.32" postcss-value-parser "^4.1.0" +available-typed-arrays@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz#6b098ca9d8039079ee3f77f7b783c4480ba513f5" + integrity sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ== + dependencies: + array-filter "^1.0.0" + aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" @@ -1810,10 +1829,15 @@ bluebird@^3.5.5: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" +bn.js@^4.11.9: + version "4.11.9" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" + integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== + body-parser@1.19.0: version "1.19.0" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" @@ -1878,9 +1902,10 @@ braces@^3.0.1, braces@~3.0.2: dependencies: fill-range "^7.0.1" -brorand@^1.0.1: +brorand@^1.0.1, brorand@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= browser-pack@^6.0.1: version "6.1.0" @@ -1970,10 +1995,10 @@ browserify-zlib@^0.2.0, browserify-zlib@~0.2.0: dependencies: pako "~1.0.5" -browserify@^16.5.2: - version "16.5.2" - resolved "https://registry.yarnpkg.com/browserify/-/browserify-16.5.2.tgz#d926835e9280fa5fd57f5bc301f2ef24a972ddfe" - integrity sha512-TkOR1cQGdmXU9zW4YukWzWVSJwrxmNdADFbqbE3HFgQWe5wqZmOawqZ7J/8MPCwk/W8yY7Y0h+7mOtcZxLP23g== +browserify@^17.0.0: + version "17.0.0" + resolved "https://registry.yarnpkg.com/browserify/-/browserify-17.0.0.tgz#4c48fed6c02bfa2b51fd3b670fddb805723cdc22" + integrity sha512-SaHqzhku9v/j6XsQMRxPyBrSP3gnwmE27gLJYZgMT2GeK3J0+0toN+MnuNYDfHwVGQfLiMZ7KSNSIXHemy905w== dependencies: JSONStream "^1.0.3" assert "^1.4.0" @@ -1987,31 +2012,31 @@ browserify@^16.5.2: constants-browserify "~1.0.0" crypto-browserify "^3.0.0" defined "^1.0.0" - deps-sort "^2.0.0" + deps-sort "^2.0.1" domain-browser "^1.2.0" duplexer2 "~0.1.2" - events "^2.0.0" + events "^3.0.0" glob "^7.1.0" has "^1.0.0" htmlescape "^1.1.0" https-browserify "^1.0.0" inherits "~2.0.1" - insert-module-globals "^7.0.0" + insert-module-globals "^7.2.1" labeled-stream-splicer "^2.0.0" mkdirp-classic "^0.5.2" module-deps "^6.2.3" os-browserify "~0.3.0" parents "^1.0.1" - path-browserify "~0.0.0" + path-browserify "^1.0.0" process "~0.11.0" punycode "^1.3.2" querystring-es3 "~0.2.0" read-only-stream "^2.0.0" readable-stream "^2.0.2" resolve "^1.1.4" - shasum "^1.0.0" + shasum-object "^1.0.0" shell-quote "^1.6.1" - stream-browserify "^2.0.0" + stream-browserify "^3.0.0" stream-http "^3.0.0" string_decoder "^1.1.1" subarg "^1.0.0" @@ -2020,7 +2045,7 @@ browserify@^16.5.2: timers-browserify "^1.0.1" tty-browserify "0.0.1" url "~0.11.0" - util "~0.10.1" + util "~0.12.0" vm-browserify "^1.0.0" xtend "^4.0.0" @@ -2144,7 +2169,7 @@ cached-path-relative@^1.0.0, cached-path-relative@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.0.2.tgz#a13df4196d26776220cc3356eb147a52dba2c6db" -call-bind@^1.0.0: +call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== @@ -3039,12 +3064,13 @@ depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" -deps-sort@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/deps-sort/-/deps-sort-2.0.0.tgz#091724902e84658260eb910748cccd1af6e21fb5" +deps-sort@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/deps-sort/-/deps-sort-2.0.1.tgz#9dfdc876d2bcec3386b6829ac52162cda9fa208d" + integrity sha512-1orqXQr5po+3KI6kQb9A4jnXT1PBwggGl2d7Sq2xsnOeI9GPcE/tGcF9UiSZtZBM7MukY4cAh7MemS6tZYipfw== dependencies: JSONStream "^1.0.3" - shasum "^1.0.0" + shasum-object "^1.0.0" subarg "^1.0.0" through2 "^2.0.0" @@ -3171,17 +3197,17 @@ domutils@^1.7.0: dom-serializer "0" domelementtype "1" -dot-prop@^4.1.1, dot-prop@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.1.tgz#45884194a71fc2cda71cbb4bceb3a4dd2f433ba4" - integrity sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ== +dot-prop@^4.1.1, dot-prop@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-6.0.1.tgz#fc26b3cf142b9e59b74dbd39ed66ce620c681083" + integrity sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA== dependencies: - is-obj "^1.0.0" + is-obj "^2.0.0" -dropzone@^5.7.2: - version "5.7.2" - resolved "https://registry.yarnpkg.com/dropzone/-/dropzone-5.7.2.tgz#91bee1572dda515d40901da304bc79dddf309b4c" - integrity sha512-m217bJHtf0J1IiKn4Tv6mnu1h5QvQNBnKZ39gma7hzGQhIZMxYq1vYEHs4AVd4ThFwmALys+52NAOD4zdLTG4w== +dropzone@^5.7.6: + version "5.7.6" + resolved "https://registry.yarnpkg.com/dropzone/-/dropzone-5.7.6.tgz#a5ebb603ea2aaf630118c37a7be59bb3444ad6e1" + integrity sha512-z38j+PZsH38rFGOK2rQ877t6c0cPos053fPp3RKaDvCDjAw4KflQQGn7BhCWeFq9Zl1hinB8khPrQdJ6cIBryQ== duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2: version "0.1.4" @@ -3225,18 +3251,18 @@ element-resize-detector@^1.2.1: dependencies: batch-processor "1.0.0" -elliptic@^6.0.0, elliptic@^6.5.3: - version "6.5.3" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6" - integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw== +elliptic@^6.0.0, elliptic@^6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" + bn.js "^4.11.9" + brorand "^1.1.0" hash.js "^1.0.0" - hmac-drbg "^1.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" email-addresses@^3.0.1: version "3.0.3" @@ -3354,6 +3380,26 @@ es-abstract@^1.18.0-next.0, es-abstract@^1.18.0-next.1: string.prototype.trimend "^1.0.1" string.prototype.trimstart "^1.0.1" +es-abstract@^1.18.0-next.2: + version "1.18.0-next.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.2.tgz#088101a55f0541f595e7e057199e27ddc8f3a5c2" + integrity sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw== + dependencies: + call-bind "^1.0.2" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.2.2" + is-negative-zero "^2.0.1" + is-regex "^1.1.1" + object-inspect "^1.9.0" + object-keys "^1.1.1" + object.assign "^4.1.2" + string.prototype.trimend "^1.0.3" + string.prototype.trimstart "^1.0.3" + es-to-primitive@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" @@ -3454,10 +3500,10 @@ eslint-plugin-jsx-a11y@^6.4.1: jsx-ast-utils "^3.1.0" language-tags "^1.0.5" -eslint-plugin-promise@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz#845fd8b2260ad8f82564c1222fce44ad71d9418a" - integrity sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw== +eslint-plugin-promise@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.3.1.tgz#61485df2a359e03149fdafc0a68b0e030ad2ac45" + integrity sha512-bY2sGqyptzFBDLh/GMbAxfdJC+b0f23ME63FOE4+Jao0oZ3E1LEwFtWJX/1pGMJLiTtrSSern2CRM/g+dfc0eQ== eslint-plugin-react@^7.22.0: version "7.22.0" @@ -3514,12 +3560,12 @@ eslint-visitor-keys@^2.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== -eslint@^7.18.0: - version "7.18.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.18.0.tgz#7fdcd2f3715a41fe6295a16234bd69aed2c75e67" - integrity sha512-fbgTiE8BfUJZuBeq2Yi7J3RB3WGUQ9PNuNbmgi6jt9Iv8qrkxfy19Ds3OpL1Pm7zg3BtTVhvcUZbIRQ0wmSjAQ== +eslint@^7.20.0: + version "7.20.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.20.0.tgz#db07c4ca4eda2e2316e7aa57ac7fc91ec550bdc7" + integrity sha512-qGi0CTcOGP2OtCQBgWZlQjcTuP0XkIpYFj25XtRTQSHC+umNnp7UMshr2G8SLsRFYDdAPFeHOsiteadmMH02Yw== dependencies: - "@babel/code-frame" "^7.0.0" + "@babel/code-frame" "7.12.11" "@eslint/eslintrc" "^0.3.0" ajv "^6.10.0" chalk "^4.0.0" @@ -3531,7 +3577,7 @@ eslint@^7.18.0: eslint-utils "^2.1.0" eslint-visitor-keys "^2.0.0" espree "^7.3.1" - esquery "^1.2.0" + esquery "^1.4.0" esutils "^2.0.2" file-entry-cache "^6.0.0" functional-red-black-tree "^1.0.1" @@ -3587,10 +3633,10 @@ esprima@~3.1.0: version "3.1.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" -esquery@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" - integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== +esquery@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" + integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== dependencies: estraverse "^5.1.0" @@ -3629,11 +3675,6 @@ eventemitter3@^4.0.0: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== -events@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/events/-/events-2.1.0.tgz#2a9a1e18e6106e0e812aa9ebd4a819b3c29c0ba5" - integrity sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg== - events@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" @@ -3776,6 +3817,11 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fast-safe-stringify@^2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743" + integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA== + faye-websocket@^0.11.3: version "0.11.3" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e" @@ -3945,6 +3991,11 @@ for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -4353,9 +4404,10 @@ highlightjs@^9.16.2: resolved "https://registry.yarnpkg.com/highlightjs/-/highlightjs-9.16.2.tgz#07ea6cc7c93340fc440734fb7abf28558f1f0fe1" integrity sha512-FK1vmMj8BbEipEy8DLIvp71t5UsC7n2D6En/UfM/91PCwmOpj6f2iu0Y0coRC62KSRHHC+dquM2xMULV/X7NFg== -hmac-drbg@^1.0.0: +hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= dependencies: hash.js "^1.0.3" minimalistic-assert "^1.0.0" @@ -4596,7 +4648,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" @@ -4608,10 +4660,10 @@ inherits@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" -ini@^1.3.4, ini@^1.3.5, ini@^1.3.8, ini@~1.3.0: - version "1.3.8" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" - integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== +ini@^1.3.4, ini@^1.3.5, ini@^2.0.0, ini@~1.3.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" + integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== inline-source-map@~0.6.0: version "0.6.2" @@ -4619,9 +4671,10 @@ inline-source-map@~0.6.0: dependencies: source-map "~0.5.3" -insert-module-globals@^7.0.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/insert-module-globals/-/insert-module-globals-7.2.0.tgz#ec87e5b42728479e327bd5c5c71611ddfb4752ba" +insert-module-globals@^7.2.1: + version "7.2.1" + resolved "https://registry.yarnpkg.com/insert-module-globals/-/insert-module-globals-7.2.1.tgz#d5e33185181a4e1f33b15f7bf100ee91890d5cb3" + integrity sha512-ufS5Qq9RZN+Bu899eA9QCAYThY+gGW7oRkmb0vC93Vlyu/CFGcH0OYPEjVkDXA5FEbTt1+VWzdoOD3Ny9N+8tg== dependencies: JSONStream "^1.0.3" acorn-node "^1.5.2" @@ -4730,6 +4783,7 @@ is-binary-path@~2.1.0: is-buffer@^1.1.0: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== is-callable@^1.1.4: version "1.1.4" @@ -4829,6 +4883,11 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== +is-generator-function@^1.0.7: + version "1.0.8" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.8.tgz#dfb5c2b120e02b0a8d9d2c6806cd5621aa922f7b" + integrity sha512-2Omr/twNtufVZFr1GhxjOMFPAj2sjc/dKaIqBhvo4qciXfJmITGH6ZGd8eZYNHza8t1y0e01AuqRhJwfWp26WQ== + is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" @@ -4846,6 +4905,11 @@ is-negative-zero@^2.0.0: resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461" integrity sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE= +is-negative-zero@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" + integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== + is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -4857,9 +4921,10 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== is-path-cwd@^2.0.0: version "2.2.0" @@ -4928,6 +4993,17 @@ is-symbol@^1.0.2: dependencies: has-symbols "^1.0.0" +is-typed-array@^1.1.3: + version "1.1.5" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.5.tgz#f32e6e096455e329eb7b423862456aa213f0eb4e" + integrity sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug== + dependencies: + available-typed-arrays "^1.0.2" + call-bind "^1.0.2" + es-abstract "^1.18.0-next.2" + foreach "^2.0.5" + has-symbols "^1.0.1" + is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -5038,12 +5114,6 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= -json-stable-stringify@~0.0.0: - version "0.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz#611c23e814db375527df851193db59dd2af27f45" - dependencies: - jsonify "~0.0.0" - json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -5072,10 +5142,6 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - jsonparse@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-0.0.5.tgz#330542ad3f0a654665b778f3eb2d9a9fa507ac64" @@ -5390,15 +5456,15 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" -marked@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/marked/-/marked-1.2.7.tgz#6e14b595581d2319cdcf033a24caaf41455a01fb" - integrity sha512-No11hFYcXr/zkBvL6qFmAp1z6BKY3zqLMHny/JN/ey+al7qwCM2+CMBL9BOgqMxZU36fz4cCWfn2poWIf7QRXA== +marked@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/marked/-/marked-2.0.0.tgz#9662bbcb77ebbded0662a7be66ff929a8611cee5" + integrity sha512-NqRSh2+LlN2NInpqTQnS614Y/3NkVMFFU6sJlRFEpxJ/LHuK/qJECH7/fXZjk4VZstPW/Pevjil/VtSONsLc7Q== -mathjax@^2.7.9: - version "2.7.9" - resolved "https://registry.yarnpkg.com/mathjax/-/mathjax-2.7.9.tgz#d6b67955c173e7d719fcb2fc0288662884eb7d3d" - integrity sha512-NOGEDTIM9+MrsqnjPEjVGNx4q0GQxqm61yQwSK+/5S59i26wId5IC5gNu9/bu8+CCVl5p9G2IHcAl/wJa+5+BQ== +mathjax@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/mathjax/-/mathjax-3.1.2.tgz#95c0d45ce2330ef7b6a815cebe7d61ecc26bbabd" + integrity sha512-BojKspBv4nNWzO1wC6VEI+g9gHDOhkaGHGgLxXkasdU4pwjdO5AXD5M/wcLPkXYPjZ/N+6sU8rjQTlyvN2cWiQ== md5.js@^1.3.4: version "1.3.5" @@ -5539,7 +5605,7 @@ minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" -minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: +minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" @@ -5549,7 +5615,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: dependencies: brace-expansion "^1.1.7" -minimist@0.0.8, minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: +minimist@0.0.8, minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -5670,10 +5736,10 @@ module-deps@^6.2.3: through2 "^2.0.0" xtend "^4.0.0" -moment-timezone@^0.5.32: - version "0.5.32" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.32.tgz#db7677cc3cc680fd30303ebd90b0da1ca0dfecc2" - integrity sha512-Z8QNyuQHQAmWucp8Knmgei8YNo28aLjJq6Ma+jy1ZSpSk5nyfRT8xgUbSQvD2+2UajISfenndwvFuH3NGS+nvA== +moment-timezone@^0.5.33: + version "0.5.33" + resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.33.tgz#b252fd6bb57f341c9b59a5ab61a8e51a73bbd22c" + integrity sha512-PTc2vcT8K9J5/9rDEPe5czSIKgLoGsH8UNpA4qZTVw0Vd/Uz19geE9abbIOQKaAQFcnQ3v5YEXrbSc5BpshH+w== dependencies: moment ">= 2.9.0" @@ -5991,6 +6057,11 @@ object-inspect@^1.8.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== +object-inspect@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a" + integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw== + object-is@^1.0.1: version "1.1.3" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.3.tgz#2e3b9e65560137455ee3bd62aec4d90a2ea1cc81" @@ -6301,10 +6372,15 @@ pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" -path-browserify@0.0.1, path-browserify@~0.0.0: +path-browserify@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" +path-browserify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== + path-complete-extname@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/path-complete-extname/-/path-complete-extname-1.0.0.tgz#f889985dc91000c815515c0bfed06c5acda0752b" @@ -7372,10 +7448,10 @@ react-copy-to-clipboard@^5.0.3: copy-to-clipboard "^3" prop-types "^15.5.8" -react-datepicker@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/react-datepicker/-/react-datepicker-3.4.1.tgz#3c8e8989f1ab31a767c17170a2d1318aa3c3b9ef" - integrity sha512-ASyVb7UmVx1vzeITidD7Cr/EXRXhKyjjbSkBndPc1MipYq4rqQ3eMFgvRQzpsXc3JmIMFgICm7nmN6Otc1GE/Q== +react-datepicker@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/react-datepicker/-/react-datepicker-3.5.0.tgz#fbac7d6d4b29001420d4411132c3d5f5d591d15c" + integrity sha512-iTRz15aG9lEF7tJVjPcGWvfALb2/RjqHVTvQO7J0DEvGSGZnTJpHlkTrBGBjJ9+i5zM4zcRGoStpjhaezS9p1g== dependencies: classnames "^2.2.6" date-fns "^2.0.1" @@ -7417,10 +7493,10 @@ react-onclickoutside@^6.9.0: resolved "https://registry.yarnpkg.com/react-onclickoutside/-/react-onclickoutside-6.9.0.tgz#a54bc317ae8cf6131a5d78acea55a11067f37a1f" integrity sha512-8ltIY3bC7oGhj2nPAvWOGi+xGFybPNhJM0V1H8hY/whNcXgmDeaeoCMPPd8VatrpTsUWjb/vGzrmu6SrXVty3A== -react-paginate@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/react-paginate/-/react-paginate-7.0.0.tgz#af206ef92a2b6ef87646855eb1612157254ad0c0" - integrity sha512-mzPwHGJfSs79JBGX2V0v/FfQp3yWdz0XRrB9JvsUbJdsxqCt4osk1O669+K8VPQ0Lh9v0lJsnLLoJwnsgdJFng== +react-paginate@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/react-paginate/-/react-paginate-7.1.0.tgz#7dc244ad7ca2db59b6eb83472655de3c126be1bc" + integrity sha512-OZm87+Qsixw3UlpR57Va6I32wC3SJ9eRsMDi2PjWSdoMVszi3B35A6AcuXB0If/AwxJeEqspYVBJLNf8UScB7g== dependencies: prop-types "^15.6.1" @@ -7475,10 +7551,10 @@ react-sizeme@^2.6.12: shallowequal "^1.1.0" throttle-debounce "^2.1.0" -react-textarea-autosize@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.3.0.tgz#e6e2fd186d9f61bb80ac6e2dcb4c55504f93c2fa" - integrity sha512-3GLWFAan2pbwBeoeNDoqGmSbrShORtgWfaWX0RJDivsUrpShh01saRM5RU/i4Zmf+whpBVEY5cA90Eq8Ub1N3w== +react-textarea-autosize@^8.3.1: + version "8.3.1" + resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.3.1.tgz#b942a934cc660ecfc645717d1fb84344b69dcb15" + integrity sha512-Vk02C3RWKLjx1wSwcVuPwfTuyGIemBB2MjDi01OnBYxKWSJFA/O7IOzr9FrO8AuRlkupk4X6Kjew2mYyEDXi0A== dependencies: "@babel/runtime" "^7.10.2" use-composed-ref "^1.0.0" @@ -7491,10 +7567,10 @@ react-tools@~0.13.0: commoner "^0.10.0" jstransform "^10.1.0" -react-tooltip@^4.2.13: - version "4.2.13" - resolved "https://registry.yarnpkg.com/react-tooltip/-/react-tooltip-4.2.13.tgz#908db8a41dc10ae2ae9cc1864746cde939aaab0f" - integrity sha512-iAZ02wSxChLWb7Vnu0zeQMyAo/jiGHrwFNILWaR3pCKaFVRjKcv/B6TBI4+Xd66xLXVzLngwJ91Tf5D+mqAqVA== +react-tooltip@^4.2.14: + version "4.2.14" + resolved "https://registry.yarnpkg.com/react-tooltip/-/react-tooltip-4.2.14.tgz#8e06b5926fdf6672e78d8ccadaa16bef40d131d7" + integrity sha512-hS2kAlpjyH5MXL9DaGKsdmEFCIEuMD2RZXkEJeNjmDe05dHpqj93o5JgpmczAgQFk099+JSsnHUDo7pIOuyMDQ== dependencies: prop-types "^15.7.2" uuid "^7.0.3" @@ -7591,7 +7667,7 @@ read-pkg@^2.0.0: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.6, readable-stream@^3.6.0: +readable-stream@^3.0.6, readable-stream@^3.5.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -8071,7 +8147,7 @@ setprototypeof@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" -sha.js@^2.4.0, sha.js@^2.4.8, sha.js@~2.4.4: +sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" dependencies: @@ -8095,12 +8171,12 @@ shallowequal@^1.0.1, shallowequal@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" -shasum@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/shasum/-/shasum-1.0.2.tgz#e7012310d8f417f4deb5712150e5678b87ae565f" +shasum-object@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shasum-object/-/shasum-object-1.0.0.tgz#0b7b74ff5b66ecf9035475522fa05090ac47e29e" + integrity sha512-Iqo5rp/3xVi6M4YheapzZhhGPVs0yZwHj7wvwQ1B9z8H6zk+FEnI7y3Teq7qwnekfEhu8WmG2z0z4iWZaxLWVg== dependencies: - json-stable-stringify "~0.0.0" - sha.js "~2.4.4" + fast-safe-stringify "^2.0.7" shebang-command@^1.2.0: version "1.2.0" @@ -8368,13 +8444,21 @@ stdout-stream@^1.4.0: dependencies: readable-stream "^2.0.1" -stream-browserify@^2.0.0, stream-browserify@^2.0.1: +stream-browserify@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" dependencies: inherits "~2.0.1" readable-stream "^2.0.2" +stream-browserify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-3.0.0.tgz#22b0a2850cdf6503e73085da1fc7b7d0c2122f2f" + integrity sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA== + dependencies: + inherits "~2.0.4" + readable-stream "^3.5.0" + stream-combiner2@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/stream-combiner2/-/stream-combiner2-1.1.1.tgz#fb4d8a1420ea362764e21ad4780397bebcb41cbe" @@ -8477,6 +8561,14 @@ string.prototype.trimend@^1.0.1: define-properties "^1.1.3" es-abstract "^1.17.5" +string.prototype.trimend@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz#a22bd53cca5c7cf44d7c9d5c732118873d6cd18b" + integrity sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + string.prototype.trimstart@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" @@ -8485,6 +8577,14 @@ string.prototype.trimstart@^1.0.1: define-properties "^1.1.3" es-abstract "^1.17.5" +string.prototype.trimstart@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz#9b4cb590e123bb36564401d59824298de50fd5aa" + integrity sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -8853,10 +8953,10 @@ ts-essentials@^2.0.3: resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-2.0.12.tgz#c9303f3d74f75fa7528c3d49b80e089ab09d8745" integrity sha512-3IVX4nI6B5cc31/GFFE+i8ey/N2eA0CZDbo6n0yrz0zDX8ZJ8djmU1p+XRz7G3is0F3bB3pu2pAroFdAWQKU3w== -ts-loader@^8.0.14: - version "8.0.14" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.0.14.tgz#e46ac1f8dcb88808d0b1335d2eae65b74bd78fe8" - integrity sha512-Jt/hHlUnApOZjnSjTmZ+AbD5BGlQFx3f1D0nYuNKwz0JJnuDGHJas6az+FlWKwwRTu+26GXpv249A8UAnYUpqA== +ts-loader@^8.0.17: + version "8.0.17" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.0.17.tgz#98f2ccff9130074f4079fd89b946b4c637b1f2fc" + integrity sha512-OeVfSshx6ot/TCxRwpBHQ/4lRzfgyTkvi7ghDVrLXOHzTbSK413ROgu/xNqM72i3AFeAIJgQy78FwSMKmOW68w== dependencies: chalk "^4.1.0" enhanced-resolve "^4.0.0" @@ -8930,10 +9030,10 @@ typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" -typescript@^4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7" - integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg== +typescript@^4.1.5: + version "4.1.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.5.tgz#123a3b214aaff3be32926f0d8f1f6e704eb89a72" + integrity sha512-6OSu9PTIzmn9TCDiovULTnET6BgXtDYL4Gg4szY+cGsc3JP1dQL8qvE8kShTRx1NIw4Q9IBHlwODjkjWEtMUyA== umd@^3.0.0: version "3.0.3" @@ -9105,11 +9205,17 @@ util@^0.11.0: dependencies: inherits "2.0.3" -util@~0.10.1: - version "0.10.4" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" +util@~0.12.0: + version "0.12.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.3.tgz#971bb0292d2cc0c892dab7c6a5d37c2bec707888" + integrity sha512-I8XkoQwE+fPQEhy9v012V+TSdH2kp9ts29i20TaaDUXsg7x/onePbhFJUExBfv/2ay1ZOp/Vsm3nDlmnFGSAog== dependencies: - inherits "2.0.3" + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + safe-buffer "^5.1.2" + which-typed-array "^1.1.2" utils-merge@1.0.1: version "1.0.1" @@ -9357,6 +9463,19 @@ which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" +which-typed-array@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.4.tgz#8fcb7d3ee5adf2d771066fba7cf37e32fe8711ff" + integrity sha512-49E0SpUe90cjpoc7BOJwyPHRqSAd12c10Qm2amdEZrJPCY2NDxaW01zHITrem+rnETY3dwrbH3UUrUwagfCYDA== + dependencies: + available-typed-arrays "^1.0.2" + call-bind "^1.0.0" + es-abstract "^1.18.0-next.1" + foreach "^2.0.5" + function-bind "^1.1.1" + has-symbols "^1.0.1" + is-typed-array "^1.1.3" + which@1, which@^1.2.14, which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" -- GitLab From 0c2878f8451182edc2282147331649617a02631d Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 19 Feb 2021 16:21:19 -1000 Subject: [PATCH 262/283] removing yarn install from assets:precompile setp --- scripts/Rakefile | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/scripts/Rakefile b/scripts/Rakefile index 9a5ea73..ecab9bc 100644 --- a/scripts/Rakefile +++ b/scripts/Rakefile @@ -4,3 +4,12 @@ require_relative "config/application" Rails.application.load_tasks + +# This removes the yarn install task from assets:precompile task to prevent +# Rails from trying to rerun yarn install. +Rake::Task["yarn:install"].clear +namespace :yarn do + task :install do + # DO NOTHING. + end +end \ No newline at end of file -- GitLab From 3f992dcaaae88d8118cf7ddb47aeff69362c3269 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 19 Feb 2021 16:29:28 -1000 Subject: [PATCH 263/283] removing extra logging --- scripts/config/environment.rb | 8 +------- scripts/config/initializers/sidekiq.rb | 2 -- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/scripts/config/environment.rb b/scripts/config/environment.rb index 45506d9..856fba2 100644 --- a/scripts/config/environment.rb +++ b/scripts/config/environment.rb @@ -2,10 +2,4 @@ require_relative 'application' # Initialize the Rails application. -Rails.application.initialize! - -# puts "==========================================" -# puts "Host: #{Rails.configuration.database_configuration[Rails.env]["host"]}" -# puts "Database: #{Rails.configuration.database_configuration[Rails.env]["database"]}" -# puts "User: #{Rails.configuration.database_configuration[Rails.env]["username"]}" -# puts "==========================================" \ No newline at end of file +Rails.application.initialize! \ No newline at end of file diff --git a/scripts/config/initializers/sidekiq.rb b/scripts/config/initializers/sidekiq.rb index 6a70575..387dfe4 100644 --- a/scripts/config/initializers/sidekiq.rb +++ b/scripts/config/initializers/sidekiq.rb @@ -8,6 +8,4 @@ Rails.application.configure do host: Rails.application.secrets.actionmailer_host, port: Rails.application.secrets.actionmailer_port } - - puts config.action_mailer.default_url_options end \ No newline at end of file -- GitLab From 481113a66922c1d85769ea5eb1c1f2ac4819fc9a Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Fri, 19 Feb 2021 17:04:03 -1000 Subject: [PATCH 264/283] Changing env variable names --- scripts/.env.example | 5 ++++- scripts/config/database.yml | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/scripts/.env.example b/scripts/.env.example index 7759360..843dfc2 100644 --- a/scripts/.env.example +++ b/scripts/.env.example @@ -14,4 +14,7 @@ appS3BucketUUID= S3_BUCKET= host= port= -protocol= \ No newline at end of file +protocol= +PG_USER= +APP_DB_ADMIN_PASSWORD= +PG_DATABASE= \ No newline at end of file diff --git a/scripts/config/database.yml b/scripts/config/database.yml index b1c7d3f..6c0ebd6 100644 --- a/scripts/config/database.yml +++ b/scripts/config/database.yml @@ -3,9 +3,9 @@ default: &default encoding: unicode pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> host: <%= ENV["PGHOST"] || "localhost" %> - username: <%= ENV["POSTGRES_USER"] || "learn_admin_user" %> + username: <%= ENV["PG_USER"] || "learn_admin_user" %> password: <%= ENV["APP_DB_ADMIN_PASSWORD"] || "postgres" %> - database: <%= ENV["POSTGRES_DB"] || "learn_db" %> + database: <%= ENV["PG_DATABASE"] || "learn_db" %> min_messages: warning pool: 5 timeout: 5000 -- GitLab From 7f9ff83f41273fe118a1d0d1a20572bccb931a53 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 22 Feb 2021 11:17:18 -1000 Subject: [PATCH 265/283] updating dependencies --- Dockerfile | 2 +- hardening_manifest.yaml | 10 +++++----- scripts/package.json | 6 +++--- scripts/yarn.lock | 24 ++++++++++++------------ 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7cc1112..7700811 100644 --- a/Dockerfile +++ b/Dockerfile @@ -66,4 +66,4 @@ RUN rm -rf node_modules HEALTHCHECK none # Set the entry point. -ENTRYPOINT ["/app/entrypoint-server.sh"] +ENTRYPOINT ["/app/entrypoint-server.sh"] \ No newline at end of file diff --git a/hardening_manifest.yaml b/hardening_manifest.yaml index 83b3252..979c006 100644 --- a/hardening_manifest.yaml +++ b/hardening_manifest.yaml @@ -38,7 +38,7 @@ resources: filename: redis-cli.tar.gz validation: type: sha256 - value: bb5f74ccdfcf66746c926dfb0e804627de3f61cc722c3cd367ab6c2c9960b950 + value: 7fb9930394f5fd5ccadb911a3b5bcebe165c41233808a64c8c61a9a0a4c260cd - auth: type: s3 id: galvanize @@ -47,7 +47,7 @@ resources: filename: node_modules.tar.gz validation: type: sha256 - value: b3ea918d9628aba96a83c9bfd3c1cd98f66a4b30daa2368b6b0dd0be9234476e + value: 27a4e6cf0ec7893a18dfd8c44c7c6df97d3aeb27875e5944b20090a1b5423f18 - auth: type: s3 id: galvanize @@ -56,7 +56,7 @@ resources: filename: nodejs.tar.gz validation: type: sha256 - value: 480ebc0f3dca30c31b976d0f5088ce4bfe3d4aba9dca0202d2390801b80c8709 + value: 57b77995875b9dfb072b696a37f15d42f133088f3201afdd5293e8e2fc58e3ff - auth: type: s3 id: galvanize @@ -65,7 +65,7 @@ resources: filename: yarn.tar.gz validation: type: sha256 - value: cdd48447584ab01e81288994699bcf67d99c32a7bc3b068a2218016bb3d9063e + value: 9a0158dd443697c7fa37693a1efc5500061772fb7a4d7cd0e6c91ee00c7e8707 - auth: type: s3 id: galvanize @@ -74,7 +74,7 @@ resources: filename: bundle.tar.gz validation: type: sha256 - value: c8a38e0da532865e445280c5657653c070c3af3686380d30a3bb9de483022a5a + value: 040f618566d8033e0fba7b38e2b19fa1d8885d17bd2effa4dbf9014fcbf5c3f4 # List of project maintainers maintainers: diff --git a/scripts/package.json b/scripts/package.json index 3930fb2..f8845a5 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -31,7 +31,7 @@ "dropzone": "^5.7.6", "highlightjs": "^9.16.2", "immutability-helper": "^3.1.1", - "lodash-es": "^4.17.20", + "lodash-es": "^4.17.21", "marked": "^2.0.0", "moment": "^2.29.1", "moment-timezone": "^0.5.33", @@ -67,7 +67,7 @@ "@types/react-addons-css-transition-group": "^15.0.5", "@types/react-beautiful-dnd": "^13.0.0", "@types/react-copy-to-clipboard": "^5.0.0", - "@types/react-datepicker": "^3.1.3", + "@types/react-datepicker": "^3.1.5", "@types/react-dom": "^17.0.1", "@types/react-textarea-autosize": "^4.3.5", "@types/vimeo__player": "^2.10.0", @@ -89,7 +89,7 @@ "elliptic": "^6.5.4", "ini": "^2.0.0", "kind-of": "^6.0.3", - "lodash": "^4.17.20", + "lodash": "^4.17.21", "mathjax": "^3.1.2", "minimist": "^1.2.5", "websocket-extensions": "^0.1.4" diff --git a/scripts/yarn.lock b/scripts/yarn.lock index ecbe464..8c8be98 100644 --- a/scripts/yarn.lock +++ b/scripts/yarn.lock @@ -1041,10 +1041,10 @@ dependencies: "@types/react" "*" -"@types/react-datepicker@^3.1.3": - version "3.1.3" - resolved "https://registry.yarnpkg.com/@types/react-datepicker/-/react-datepicker-3.1.3.tgz#4525475c451091477de27ed52c029a9043ec6b11" - integrity sha512-Gca56Pa8hpy3eO2naRLdC63iflER7JXxgdHTGJ6yF5DjvhQoirRPqCJerWLq6TOWd+sEsZWwMm17Q17YRVLFtw== +"@types/react-datepicker@^3.1.5": + version "3.1.5" + resolved "https://registry.yarnpkg.com/@types/react-datepicker/-/react-datepicker-3.1.5.tgz#653a8a80eb083ab2cf7d724d90d590018e030d1c" + integrity sha512-aPl3ay63H4ugUeGSWQqQCVqpo9nS2SSnnX3QNclr9Ze82PWBTaXRFCLXOcUP+JgnjCabb3ZF4XwTom2Pob3hPQ== dependencies: "@types/react" "*" date-fns "^2.0.1" @@ -5309,10 +5309,10 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" -lodash-es@^4.17.20: - version "4.17.20" - resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.20.tgz#29f6332eefc60e849f869c264bc71126ad61e8f7" - integrity sha512-JD1COMZsq8maT6mnuz1UMV0jvYD0E0aUsSOdrr1/nAG3dhqQXwRRgeW0cSqH1U43INKcqxaiVIQNOUDld7gRDA== +lodash-es@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" + integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== lodash._getnative@^3.0.0: version "3.9.1" @@ -5374,10 +5374,10 @@ lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" -lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4, lodash@^4.17.5, lodash@~4.17.10: - version "4.17.20" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" - integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== +lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.17.5, lodash@~4.17.10: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== loglevel@^1.6.8: version "1.7.0" -- GitLab From e27ada9e7578445206b62381a9661587fd73c57f Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 22 Feb 2021 11:28:40 -1000 Subject: [PATCH 266/283] adding health check --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 7700811..4644a61 100644 --- a/Dockerfile +++ b/Dockerfile @@ -63,7 +63,7 @@ RUN rm -rf yarn RUN rm -rf node_modules # Health check. -HEALTHCHECK none +HEALTHCHECK --timeout=60s CMD curl -fs http://localhost:3000/hello || exit 1 # Set the entry point. ENTRYPOINT ["/app/entrypoint-server.sh"] \ No newline at end of file -- GitLab From 032bb604470dae42d585ff2aa66f8f9d618ca6d7 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 22 Feb 2021 12:03:34 -1000 Subject: [PATCH 267/283] updating health check --- Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 4644a61..99ba906 100644 --- a/Dockerfile +++ b/Dockerfile @@ -63,7 +63,8 @@ RUN rm -rf yarn RUN rm -rf node_modules # Health check. -HEALTHCHECK --timeout=60s CMD curl -fs http://localhost:3000/hello || exit 1 +HEALTHCHECK --start-period=60s --interval=60s --timeout=30s --retries=3 \ + CMD curl -fs http://localhost:3000/hello || exit 1 # Set the entry point. ENTRYPOINT ["/app/entrypoint-server.sh"] \ No newline at end of file -- GitLab From e808e0fb67a70cca0684a9c2253a962e7ade7c56 Mon Sep 17 00:00:00 2001 From: Michael Uranaka Date: Mon, 22 Feb 2021 16:25:25 -1000 Subject: [PATCH 268/283] upgrading to bootstrap 3.4.1 --- scripts/public/javascripts/apitome/application.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/public/javascripts/apitome/application.js b/scripts/public/javascripts/apitome/application.js index e23a0f5..b82cd0d 100644 --- a/scripts/public/javascripts/apitome/application.js +++ b/scripts/public/javascripts/apitome/application.js @@ -5,13 +5,13 @@ (function(e,undefined){var t,n,r=typeof undefined,i=e.location,o=e.document,s=o.documentElement,a=e.jQuery,u=e.$,l={},c=[],p="2.0.3",f=c.concat,h=c.push,d=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,x=function(e,n){return new x.fn.init(e,n,t)},b=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^-ms-/,N=/-([\da-z])/gi,E=function(e,t){return t.toUpperCase()},S=function(){o.removeEventListener("DOMContentLoaded",S,!1),e.removeEventListener("load",S,!1),x.ready()};x.fn=x.prototype={jquery:p,constructor:x,init:function(e,t,n){var r,i;if(!e)return this;if("string"==typeof e){if(r="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:T.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof x?t[0]:t,x.merge(this,x.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:o,!0)),C.test(r[1])&&x.isPlainObject(t))for(r in t)x.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return i=o.getElementById(r[2]),i&&i.parentNode&&(this.length=1,this[0]=i),this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?n.ready(e):(e.selector!==undefined&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return d.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,t,n,r,i,o,s=arguments[0]||{},a=1,u=arguments.length,l=!1;for("boolean"==typeof s&&(l=s,s=arguments[1]||{},a=2),"object"==typeof s||x.isFunction(s)||(s={}),u===a&&(s=this,--a);u>a;a++)if(null!=(e=arguments[a]))for(t in e)n=s[t],r=e[t],s!==r&&(l&&r&&(x.isPlainObject(r)||(i=x.isArray(r)))?(i?(i=!1,o=n&&x.isArray(n)?n:[]):o=n&&x.isPlainObject(n)?n:{},s[t]=x.extend(l,o,r)):r!==undefined&&(s[t]=r));return s},x.extend({expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=a),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){(e===!0?--x.readyWait:x.isReady)||(x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(o,[x]),x.fn.trigger&&x(o).trigger("ready").off("ready")))},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray,isWindow:function(e){return null!=e&&e===e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if("object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(t){return!1}return!0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:JSON.parse,parseXML:function(e){var t,n;if(!e||"string"!=typeof e)return null;try{n=new DOMParser,t=n.parseFromString(e,"text/xml")}catch(r){t=undefined}return(!t||t.getElementsByTagName("parsererror").length)&&x.error("Invalid XML: "+e),t},noop:function(){},globalEval:function(e){var t,n=eval;e=x.trim(e),e&&(1===e.indexOf("use strict")?(t=o.createElement("script"),t.text=e,o.head.appendChild(t).parentNode.removeChild(t)):n(e))},camelCase:function(e){return e.replace(k,"ms-").replace(N,E)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,s=j(e);if(n){if(s){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(s){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:function(e){return null==e?"":v.call(e)},makeArray:function(e,t){var n=t||[];return null!=e&&(j(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:g.call(t,e,n)},merge:function(e,t){var n=t.length,r=e.length,i=0;if("number"==typeof n)for(;n>i;i++)e[r++]=t[i];else while(t[i]!==undefined)e[r++]=t[i++];return e.length=r,e},grep:function(e,t,n){var r,i=[],o=0,s=e.length;for(n=!!n;s>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,s=j(e),a=[];if(s)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(a[a.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(a[a.length]=r);return f.apply([],a)},guid:1,proxy:function(e,t){var n,r,i;return"string"==typeof t&&(n=e[t],t=e,e=n),x.isFunction(e)?(r=d.call(arguments,2),i=function(){return e.apply(t||this,r.concat(d.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):undefined},access:function(e,t,n,r,i,o,s){var a=0,u=e.length,l=null==n;if("object"===x.type(n)){i=!0;for(a in n)x.access(e,t,a,n[a],!0,o,s)}else if(r!==undefined&&(i=!0,x.isFunction(r)||(s=!0),l&&(s?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(x(e),n)})),t))for(;u>a;a++)t(e[a],n,s?r:r.call(e[a],a,t(e[a],n)));return i?e:l?t.call(e):u?t(e[0],n):o},now:Date.now,swap:function(e,t,n,r){var i,o,s={};for(o in t)s[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=s[o];return i}}),x.ready.promise=function(t){return n||(n=x.Deferred(),"complete"===o.readyState?setTimeout(x.ready):(o.addEventListener("DOMContentLoaded",S,!1),e.addEventListener("load",S,!1))),n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function j(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}t=x(o),function(e,undefined){var t,n,r,i,o,s,a,u,l,c,p,f,h,d,g,m,y,v="sizzle"+-new Date,b=e.document,w=0,T=0,C=st(),k=st(),N=st(),E=!1,S=function(e,t){return e===t?(E=!0,0):0},j=typeof undefined,D=1<<31,A={}.hasOwnProperty,L=[],q=L.pop,H=L.push,O=L.push,F=L.slice,P=L.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",W="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",$=W.replace("w","w#"),B="\\["+M+"*("+W+")"+M+"*(?:([*^$|!~]?=)"+M+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+$+")|)|)"+M+"*\\]",I=":("+W+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+B.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=RegExp("^"+M+"*,"+M+"*"),X=RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=RegExp(M+"*[+~]"),Y=RegExp("="+M+"*([^\\]'\"]*)"+M+"*\\]","g"),V=RegExp(I),G=RegExp("^"+$+"$"),J={ID:RegExp("^#("+W+")"),CLASS:RegExp("^\\.("+W+")"),TAG:RegExp("^("+W.replace("w","w*")+")"),ATTR:RegExp("^"+B),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:RegExp("^(?:"+R+")$","i"),needsContext:RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Q=/^[^{]+\{\s*\[native \w/,K=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,Z=/^(?:input|select|textarea|button)$/i,et=/^h\d$/i,tt=/'|\\/g,nt=RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),rt=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{O.apply(L=F.call(b.childNodes),b.childNodes),L[b.childNodes.length].nodeType}catch(it){O={apply:L.length?function(e,t){H.apply(e,F.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function ot(e,t,r,i){var o,s,a,u,l,f,g,m,x,w;if((t?t.ownerDocument||t:b)!==p&&c(t),t=t||p,r=r||[],!e||"string"!=typeof e)return r;if(1!==(u=t.nodeType)&&9!==u)return[];if(h&&!i){if(o=K.exec(e))if(a=o[1]){if(9===u){if(s=t.getElementById(a),!s||!s.parentNode)return r;if(s.id===a)return r.push(s),r}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(a))&&y(t,s)&&s.id===a)return r.push(s),r}else{if(o[2])return O.apply(r,t.getElementsByTagName(e)),r;if((a=o[3])&&n.getElementsByClassName&&t.getElementsByClassName)return O.apply(r,t.getElementsByClassName(a)),r}if(n.qsa&&(!d||!d.test(e))){if(m=g=v,x=t,w=9===u&&e,1===u&&"object"!==t.nodeName.toLowerCase()){f=gt(e),(g=t.getAttribute("id"))?m=g.replace(tt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",l=f.length;while(l--)f[l]=m+mt(f[l]);x=U.test(e)&&t.parentNode||t,w=f.join(",")}if(w)try{return O.apply(r,x.querySelectorAll(w)),r}catch(T){}finally{g||t.removeAttribute("id")}}}return kt(e.replace(z,"$1"),t,r,i)}function st(){var e=[];function t(n,r){return e.push(n+=" ")>i.cacheLength&&delete t[e.shift()],t[n]=r}return t}function at(e){return e[v]=!0,e}function ut(e){var t=p.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function lt(e,t){var n=e.split("|"),r=e.length;while(r--)i.attrHandle[n[r]]=t}function ct(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function pt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ht(e){return at(function(t){return t=+t,at(function(n,r){var i,o=e([],n.length,t),s=o.length;while(s--)n[i=o[s]]&&(n[i]=!(r[i]=n[i]))})})}s=ot.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},n=ot.support={},c=ot.setDocument=function(e){var t=e?e.ownerDocument||e:b,r=t.defaultView;return t!==p&&9===t.nodeType&&t.documentElement?(p=t,f=t.documentElement,h=!s(t),r&&r.attachEvent&&r!==r.top&&r.attachEvent("onbeforeunload",function(){c()}),n.attributes=ut(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ut(function(e){return e.appendChild(t.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=ut(function(e){return e.innerHTML="
    ",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),n.getById=ut(function(e){return f.appendChild(e).id=v,!t.getElementsByName||!t.getElementsByName(v).length}),n.getById?(i.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(nt,rt);return function(e){return e.getAttribute("id")===t}}):(delete i.find.ID,i.filter.ID=function(e){var t=e.replace(nt,rt);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=n.getElementsByTagName?function(e,t){return typeof t.getElementsByTagName!==j?t.getElementsByTagName(e):undefined}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.CLASS=n.getElementsByClassName&&function(e,t){return typeof t.getElementsByClassName!==j&&h?t.getElementsByClassName(e):undefined},g=[],d=[],(n.qsa=Q.test(t.querySelectorAll))&&(ut(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll(":checked").length||d.push(":checked")}),ut(function(e){var n=t.createElement("input");n.setAttribute("type","hidden"),e.appendChild(n).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&d.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||d.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),d.push(",.*:")})),(n.matchesSelector=Q.test(m=f.webkitMatchesSelector||f.mozMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&ut(function(e){n.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",I)}),d=d.length&&RegExp(d.join("|")),g=g.length&&RegExp(g.join("|")),y=Q.test(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},S=f.compareDocumentPosition?function(e,r){if(e===r)return E=!0,0;var i=r.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(r);return i?1&i||!n.sortDetached&&r.compareDocumentPosition(e)===i?e===t||y(b,e)?-1:r===t||y(b,r)?1:l?P.call(l,e)-P.call(l,r):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,n){var r,i=0,o=e.parentNode,s=n.parentNode,a=[e],u=[n];if(e===n)return E=!0,0;if(!o||!s)return e===t?-1:n===t?1:o?-1:s?1:l?P.call(l,e)-P.call(l,n):0;if(o===s)return ct(e,n);r=e;while(r=r.parentNode)a.unshift(r);r=n;while(r=r.parentNode)u.unshift(r);while(a[i]===u[i])i++;return i?ct(a[i],u[i]):a[i]===b?-1:u[i]===b?1:0},t):p},ot.matches=function(e,t){return ot(e,null,null,t)},ot.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Y,"='$1']"),!(!n.matchesSelector||!h||g&&g.test(t)||d&&d.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return ot(t,p,null,[e]).length>0},ot.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},ot.attr=function(e,t){(e.ownerDocument||e)!==p&&c(e);var r=i.attrHandle[t.toLowerCase()],o=r&&A.call(i.attrHandle,t.toLowerCase())?r(e,t,!h):undefined;return o===undefined?n.attributes||!h?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null:o},ot.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},ot.uniqueSort=function(e){var t,r=[],i=0,o=0;if(E=!n.detectDuplicates,l=!n.sortStable&&e.slice(0),e.sort(S),E){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return e},o=ot.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=ot.selectors={cacheLength:50,createPseudo:at,match:J,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(nt,rt),e[3]=(e[4]||e[5]||"").replace(nt,rt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||ot.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&ot.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return J.CHILD.test(e[0])?null:(e[3]&&e[4]!==undefined?e[2]=e[4]:n&&V.test(n)&&(t=gt(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(nt,rt).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=C[e+" "];return t||(t=RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&C(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=ot.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),s="last"!==e.slice(-4),a="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,h,d,g=o!==s?"nextSibling":"previousSibling",m=t.parentNode,y=a&&t.nodeName.toLowerCase(),x=!u&&!a;if(m){if(o){while(g){p=t;while(p=p[g])if(a?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;d=g="only"===e&&!d&&"nextSibling"}return!0}if(d=[s?m.firstChild:m.lastChild],s&&x){c=m[v]||(m[v]={}),l=c[e]||[],h=l[0]===w&&l[1],f=l[0]===w&&l[2],p=h&&m.childNodes[h];while(p=++h&&p&&p[g]||(f=h=0)||d.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[w,h,f];break}}else if(x&&(l=(t[v]||(t[v]={}))[e])&&l[0]===w)f=l[1];else while(p=++h&&p&&p[g]||(f=h=0)||d.pop())if((a?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(x&&((p[v]||(p[v]={}))[e]=[w,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||ot.error("unsupported pseudo: "+e);return r[v]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?at(function(e,n){var i,o=r(e,t),s=o.length;while(s--)i=P.call(e,o[s]),e[i]=!(n[i]=o[s])}):function(e){return r(e,0,n)}):r}},pseudos:{not:at(function(e){var t=[],n=[],r=a(e.replace(z,"$1"));return r[v]?at(function(e,t,n,i){var o,s=r(e,null,i,[]),a=e.length;while(a--)(o=s[a])&&(e[a]=!(t[a]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:at(function(e){return function(t){return ot(e,t).length>0}}),contains:at(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:at(function(e){return G.test(e||"")||ot.error("unsupported lang: "+e),e=e.replace(nt,rt).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return et.test(e.nodeName)},input:function(e){return Z.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},i.pseudos.nth=i.pseudos.eq;for(t in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[t]=pt(t);for(t in{submit:!0,reset:!0})i.pseudos[t]=ft(t);function dt(){}dt.prototype=i.filters=i.pseudos,i.setFilters=new dt;function gt(e,t){var n,r,o,s,a,u,l,c=k[e+" "];if(c)return t?0:c.slice(0);a=e,u=[],l=i.preFilter;while(a){(!n||(r=_.exec(a)))&&(r&&(a=a.slice(r[0].length)||a),u.push(o=[])),n=!1,(r=X.exec(a))&&(n=r.shift(),o.push({value:n,type:r[0].replace(z," ")}),a=a.slice(n.length));for(s in i.filter)!(r=J[s].exec(a))||l[s]&&!(r=l[s](r))||(n=r.shift(),o.push({value:n,type:s,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?ot.error(e):k(e,u).slice(0)}function mt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function yt(e,t,n){var i=t.dir,o=n&&"parentNode"===i,s=T++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,a){var u,l,c,p=w+" "+s;if(a){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,a))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[v]||(t[v]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,a)||r,l[1]===!0)return!0}}function vt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,s=[],a=0,u=e.length,l=null!=t;for(;u>a;a++)(o=e[a])&&(!n||n(o,r,i))&&(s.push(o),l&&t.push(a));return s}function bt(e,t,n,r,i,o){return r&&!r[v]&&(r=bt(r)),i&&!i[v]&&(i=bt(i,o)),at(function(o,s,a,u){var l,c,p,f=[],h=[],d=s.length,g=o||Ct(t||"*",a.nodeType?[a]:a,[]),m=!e||!o&&t?g:xt(g,f,e,a,u),y=n?i||(o?e:d||r)?[]:s:m;if(n&&n(m,y,a,u),r){l=xt(y,h),r(l,[],a,u),c=l.length;while(c--)(p=l[c])&&(y[h[c]]=!(m[h[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?P.call(o,p):f[c])>-1&&(o[l]=!(s[l]=p))}}else y=xt(y===s?y.splice(d,y.length):y),i?i(null,s,y,u):O.apply(s,y)})}function wt(e){var t,n,r,o=e.length,s=i.relative[e[0].type],a=s||i.relative[" "],l=s?1:0,c=yt(function(e){return e===t},a,!0),p=yt(function(e){return P.call(t,e)>-1},a,!0),f=[function(e,n,r){return!s&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>l;l++)if(n=i.relative[e[l].type])f=[yt(vt(f),n)];else{if(n=i.filter[e[l].type].apply(null,e[l].matches),n[v]){for(r=++l;o>r;r++)if(i.relative[e[r].type])break;return bt(l>1&&vt(f),l>1&&mt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&wt(e.slice(l,r)),o>r&&wt(e=e.slice(r)),o>r&&mt(e))}f.push(n)}return vt(f)}function Tt(e,t){var n=0,o=t.length>0,s=e.length>0,a=function(a,l,c,f,h){var d,g,m,y=[],v=0,x="0",b=a&&[],T=null!=h,C=u,k=a||s&&i.find.TAG("*",h&&l.parentNode||l),N=w+=null==C?1:Math.random()||.1;for(T&&(u=l!==p&&l,r=n);null!=(d=k[x]);x++){if(s&&d){g=0;while(m=e[g++])if(m(d,l,c)){f.push(d);break}T&&(w=N,r=++n)}o&&((d=!m&&d)&&v--,a&&b.push(d))}if(v+=x,o&&x!==v){g=0;while(m=t[g++])m(b,y,l,c);if(a){if(v>0)while(x--)b[x]||y[x]||(y[x]=q.call(f));y=xt(y)}O.apply(f,y),T&&!a&&y.length>0&&v+t.length>1&&ot.uniqueSort(f)}return T&&(w=N,u=C),b};return o?at(a):a}a=ot.compile=function(e,t){var n,r=[],i=[],o=N[e+" "];if(!o){t||(t=gt(e)),n=t.length;while(n--)o=wt(t[n]),o[v]?r.push(o):i.push(o);o=N(e,Tt(i,r))}return o};function Ct(e,t,n){var r=0,i=t.length;for(;i>r;r++)ot(e,t[r],n);return n}function kt(e,t,r,o){var s,u,l,c,p,f=gt(e);if(!o&&1===f.length){if(u=f[0]=f[0].slice(0),u.length>2&&"ID"===(l=u[0]).type&&n.getById&&9===t.nodeType&&h&&i.relative[u[1].type]){if(t=(i.find.ID(l.matches[0].replace(nt,rt),t)||[])[0],!t)return r;e=e.slice(u.shift().value.length)}s=J.needsContext.test(e)?0:u.length;while(s--){if(l=u[s],i.relative[c=l.type])break;if((p=i.find[c])&&(o=p(l.matches[0].replace(nt,rt),U.test(u[0].type)&&t.parentNode||t))){if(u.splice(s,1),e=o.length&&mt(u),!e)return O.apply(r,o),r;break}}}return a(e,f)(o,t,!h,r,U.test(e)),r}n.sortStable=v.split("").sort(S).join("")===v,n.detectDuplicates=E,c(),n.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(p.createElement("div"))}),ut(function(e){return e.innerHTML="
    ","#"===e.firstChild.getAttribute("href")})||lt("type|href|height|width",function(e,t,n){return n?undefined:e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ut(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||lt("value",function(e,t,n){return n||"input"!==e.nodeName.toLowerCase()?undefined:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||lt(R,function(e,t,n){var r;return n?undefined:(r=e.getAttributeNode(t))&&r.specified?r.value:e[t]===!0?t.toLowerCase():null}),x.find=ot,x.expr=ot.selectors,x.expr[":"]=x.expr.pseudos,x.unique=ot.uniqueSort,x.text=ot.getText,x.isXMLDoc=ot.isXML,x.contains=ot.contains}(e);var D={};function A(e){var t=D[e]={};return x.each(e.match(w)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?D[e]||A(e):x.extend({},e);var t,n,r,i,o,s,a=[],u=!e.once&&[],l=function(p){for(t=e.memory&&p,n=!0,s=i||0,i=0,o=a.length,r=!0;a&&o>s;s++)if(a[s].apply(p[0],p[1])===!1&&e.stopOnFalse){t=!1;break}r=!1,a&&(u?u.length&&l(u.shift()):t?a=[]:c.disable())},c={add:function(){if(a){var n=a.length;(function s(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&c.has(n)||a.push(n):n&&n.length&&"string"!==r&&s(n)})})(arguments),r?o=a.length:t&&(i=n,l(t))}return this},remove:function(){return a&&x.each(arguments,function(e,t){var n;while((n=x.inArray(t,a,n))>-1)a.splice(n,1),r&&(o>=n&&o--,s>=n&&s--)}),this},has:function(e){return e?x.inArray(e,a)>-1:!(!a||!a.length)},empty:function(){return a=[],o=0,this},disable:function(){return a=u=t=undefined,this},disabled:function(){return!a},lock:function(){return u=undefined,t||c.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!a||n&&!u||(t=t||[],t=[e,t.slice?t.slice():t],r?u.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!n}};return c},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var s=o[0],a=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var s=o[2],a=o[3];r[o[1]]=s.add,a&&s.add(function(){n=a},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=s.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=d.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),s=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?d.call(arguments):r,n===a?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},a,u,l;if(r>1)for(a=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(s(t,l,n)).fail(o.reject).progress(s(t,u,a)):--i;return i||o.resolveWith(l,n),o.promise()}}),x.support=function(t){var n=o.createElement("input"),r=o.createDocumentFragment(),i=o.createElement("div"),s=o.createElement("select"),a=s.appendChild(o.createElement("option"));return n.type?(n.type="checkbox",t.checkOn=""!==n.value,t.optSelected=a.selected,t.reliableMarginRight=!0,t.boxSizingReliable=!0,t.pixelPosition=!1,n.checked=!0,t.noCloneChecked=n.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!a.disabled,n=o.createElement("input"),n.value="t",n.type="radio",t.radioValue="t"===n.value,n.setAttribute("checked","t"),n.setAttribute("name","t"),r.appendChild(n),t.checkClone=r.cloneNode(!0).cloneNode(!0).lastChild.checked,t.focusinBubbles="onfocusin"in e,i.style.backgroundClip="content-box",i.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===i.style.backgroundClip,x(function(){var n,r,s="padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box",a=o.getElementsByTagName("body")[0];a&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",a.appendChild(n).appendChild(i),i.innerHTML="",i.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%",x.swap(a,null!=a.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===i.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(i,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(i,null)||{width:"4px"}).width,r=i.appendChild(o.createElement("div")),r.style.cssText=i.style.cssText=s,r.style.marginRight=r.style.width="0",i.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),a.removeChild(n))}),t):t}({});var L,q,H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,O=/([A-Z])/g;function F(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=x.expando+Math.random()}F.uid=1,F.accepts=function(e){return e.nodeType?1===e.nodeType||9===e.nodeType:!0},F.prototype={key:function(e){if(!F.accepts(e))return 0;var t={},n=e[this.expando];if(!n){n=F.uid++;try{t[this.expando]={value:n},Object.defineProperties(e,t)}catch(r){t[this.expando]=n,x.extend(e,t)}}return this.cache[n]||(this.cache[n]={}),n},set:function(e,t,n){var r,i=this.key(e),o=this.cache[i];if("string"==typeof t)o[t]=n;else if(x.isEmptyObject(o))x.extend(this.cache[i],t);else for(r in t)o[r]=t[r];return o},get:function(e,t){var n=this.cache[this.key(e)];return t===undefined?n:n[t]},access:function(e,t,n){var r;return t===undefined||t&&"string"==typeof t&&n===undefined?(r=this.get(e,t),r!==undefined?r:this.get(e,x.camelCase(t))):(this.set(e,t,n),n!==undefined?n:t)},remove:function(e,t){var n,r,i,o=this.key(e),s=this.cache[o];if(t===undefined)this.cache[o]={};else{x.isArray(t)?r=t.concat(t.map(x.camelCase)):(i=x.camelCase(t),t in s?r=[t,i]:(r=i,r=r in s?[r]:r.match(w)||[])),n=r.length;while(n--)delete s[r[n]]}},hasData:function(e){return!x.isEmptyObject(this.cache[e[this.expando]]||{})},discard:function(e){e[this.expando]&&delete this.cache[e[this.expando]]}},L=new F,q=new F,x.extend({acceptData:F.accepts,hasData:function(e){return L.hasData(e)||q.hasData(e)},data:function(e,t,n){return L.access(e,t,n)},removeData:function(e,t){L.remove(e,t)},_data:function(e,t,n){return q.access(e,t,n)},_removeData:function(e,t){q.remove(e,t)}}),x.fn.extend({data:function(e,t){var n,r,i=this[0],o=0,s=null;if(e===undefined){if(this.length&&(s=L.get(i),1===i.nodeType&&!q.get(i,"hasDataAttrs"))){for(n=i.attributes;n.length>o;o++)r=n[o].name,0===r.indexOf("data-")&&(r=x.camelCase(r.slice(5)),P(i,r,s[r]));q.set(i,"hasDataAttrs",!0)}return s}return"object"==typeof e?this.each(function(){L.set(this,e)}):x.access(this,function(t){var n,r=x.camelCase(e);if(i&&t===undefined){if(n=L.get(i,e),n!==undefined)return n;if(n=L.get(i,r),n!==undefined)return n;if(n=P(i,r,undefined),n!==undefined)return n}else this.each(function(){var n=L.get(this,r);L.set(this,r,t),-1!==e.indexOf("-")&&n!==undefined&&L.set(this,e,t)})},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){L.remove(this,e)})}});function P(e,t,n){var r;if(n===undefined&&1===e.nodeType)if(r="data-"+t.replace(O,"-$1").toLowerCase(),n=e.getAttribute(r),"string"==typeof n){try{n="true"===n?!0:"false"===n?!1:"null"===n?null:+n+""===n?+n:H.test(n)?JSON.parse(n):n}catch(i){}L.set(e,t,n)}else n=undefined;return n}x.extend({queue:function(e,t,n){var r;return e?(t=(t||"fx")+"queue",r=q.get(e,t),n&&(!r||x.isArray(n)?r=q.access(e,t,x.makeArray(n)):r.push(n)),r||[]):undefined},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),s=function(){x.dequeue(e,t) };"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,s,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return q.get(e,n)||q.access(e,n,{empty:x.Callbacks("once memory").add(function(){q.remove(e,[t+"queue",n])})})}}),x.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),n>arguments.length?x.queue(this[0],e):t===undefined?this:this.each(function(){var n=x.queue(this,e,t);x._queueHooks(this,e),"fx"===e&&"inprogress"!==n[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=x.Deferred(),o=this,s=this.length,a=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=undefined),e=e||"fx";while(s--)n=q.get(o[s],e+"queueHooks"),n&&n.empty&&(r++,n.empty.add(a));return a(),i.promise(t)}});var R,M,W=/[\t\r\n\f]/g,$=/\r/g,B=/^(?:input|select|textarea|button)$/i;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[x.propFix[e]||e]})},addClass:function(e){var t,n,r,i,o,s=0,a=this.length,u="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,s=0,a=this.length,u=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,i=0,o=x(this),s=e.match(w)||[];while(t=s[i++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===r||"boolean"===n)&&(this.className&&q.set(this,"__className__",this.className),this.className=this.className||e===!1?"":q.get(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(W," ").indexOf(t)>=0)return!0;return!1},val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=x.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,x(this).val()):e,null==i?i="":"number"==typeof i?i+="":x.isArray(i)&&(i=x.map(i,function(e){return null==e?"":e+""})),t=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],t&&"set"in t&&t.set(this,i,"value")!==undefined||(this.value=i))});if(i)return t=x.valHooks[i.type]||x.valHooks[i.nodeName.toLowerCase()],t&&"get"in t&&(n=t.get(i,"value"))!==undefined?n:(n=i.value,"string"==typeof n?n.replace($,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,s=o?null:[],a=o?i+1:r.length,u=0>i?a:o?i:0;for(;a>u;u++)if(n=r[u],!(!n.selected&&u!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),s=i.length;while(s--)r=i[s],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,t,n){var i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===r?x.prop(e,t,n):(1===s&&x.isXMLDoc(e)||(t=t.toLowerCase(),i=x.attrHooks[t]||(x.expr.match.bool.test(t)?M:R)),n===undefined?i&&"get"in i&&null!==(o=i.get(e,t))?o:(o=x.find.attr(e,t),null==o?undefined:o):null!==n?i&&"set"in i&&(o=i.set(e,n,t))!==undefined?o:(e.setAttribute(t,n+""),n):(x.removeAttr(e,t),undefined))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)&&(e[r]=!1),e.removeAttribute(n)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,t,n){var r,i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return o=1!==s||!x.isXMLDoc(e),o&&(t=x.propFix[t]||t,i=x.propHooks[t]),n!==undefined?i&&"set"in i&&(r=i.set(e,n,t))!==undefined?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){return e.hasAttribute("tabindex")||B.test(e.nodeName)||e.href?e.tabIndex:-1}}}}),M={set:function(e,t,n){return t===!1?x.removeAttr(e,n):e.setAttribute(n,n),n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,t){var n=x.expr.attrHandle[t]||x.find.attr;x.expr.attrHandle[t]=function(e,t,r){var i=x.expr.attrHandle[t],o=r?undefined:(x.expr.attrHandle[t]=undefined)!=n(e,t,r)?t.toLowerCase():null;return x.expr.attrHandle[t]=i,o}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,t){return x.isArray(t)?e.checked=x.inArray(x(e).val(),t)>=0:undefined}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var I=/^key/,z=/^(?:mouse|contextmenu)|click/,_=/^(?:focusinfocus|focusoutblur)$/,X=/^([^.]*)(?:\.(.+)|)$/;function U(){return!0}function Y(){return!1}function V(){try{return o.activeElement}catch(e){}}x.event={global:{},add:function(e,t,n,i,o){var s,a,u,l,c,p,f,h,d,g,m,y=q.get(e);if(y){n.handler&&(s=n,n=s.handler,o=s.selector),n.guid||(n.guid=x.guid++),(l=y.events)||(l=y.events={}),(a=y.handle)||(a=y.handle=function(e){return typeof x===r||e&&x.event.triggered===e.type?undefined:x.event.dispatch.apply(a.elem,arguments)},a.elem=e),t=(t||"").match(w)||[""],c=t.length;while(c--)u=X.exec(t[c])||[],d=m=u[1],g=(u[2]||"").split(".").sort(),d&&(f=x.event.special[d]||{},d=(o?f.delegateType:f.bindType)||d,f=x.event.special[d]||{},p=x.extend({type:d,origType:m,data:i,handler:n,guid:n.guid,selector:o,needsContext:o&&x.expr.match.needsContext.test(o),namespace:g.join(".")},s),(h=l[d])||(h=l[d]=[],h.delegateCount=0,f.setup&&f.setup.call(e,i,g,a)!==!1||e.addEventListener&&e.addEventListener(d,a,!1)),f.add&&(f.add.call(e,p),p.handler.guid||(p.handler.guid=n.guid)),o?h.splice(h.delegateCount++,0,p):h.push(p),x.event.global[d]=!0);e=null}},remove:function(e,t,n,r,i){var o,s,a,u,l,c,p,f,h,d,g,m=q.hasData(e)&&q.get(e);if(m&&(u=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(a=X.exec(t[l])||[],h=g=a[1],d=(a[2]||"").split(".").sort(),h){p=x.event.special[h]||{},h=(r?p.delegateType:p.bindType)||h,f=u[h]||[],a=a[2]&&RegExp("(^|\\.)"+d.join("\\.(?:.*\\.|)")+"(\\.|$)"),s=o=f.length;while(o--)c=f[o],!i&&g!==c.origType||n&&n.guid!==c.guid||a&&!a.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(f.splice(o,1),c.selector&&f.delegateCount--,p.remove&&p.remove.call(e,c));s&&!f.length&&(p.teardown&&p.teardown.call(e,d,m.handle)!==!1||x.removeEvent(e,h,m.handle),delete u[h])}else for(h in u)x.event.remove(e,h+t[l],n,r,!0);x.isEmptyObject(u)&&(delete m.handle,q.remove(e,"events"))}},trigger:function(t,n,r,i){var s,a,u,l,c,p,f,h=[r||o],d=y.call(t,"type")?t.type:t,g=y.call(t,"namespace")?t.namespace.split("."):[];if(a=u=r=r||o,3!==r.nodeType&&8!==r.nodeType&&!_.test(d+x.event.triggered)&&(d.indexOf(".")>=0&&(g=d.split("."),d=g.shift(),g.sort()),c=0>d.indexOf(":")&&"on"+d,t=t[x.expando]?t:new x.Event(d,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=g.join("."),t.namespace_re=t.namespace?RegExp("(^|\\.)"+g.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=undefined,t.target||(t.target=r),n=null==n?[t]:x.makeArray(n,[t]),f=x.event.special[d]||{},i||!f.trigger||f.trigger.apply(r,n)!==!1)){if(!i&&!f.noBubble&&!x.isWindow(r)){for(l=f.delegateType||d,_.test(l+d)||(a=a.parentNode);a;a=a.parentNode)h.push(a),u=a;u===(r.ownerDocument||o)&&h.push(u.defaultView||u.parentWindow||e)}s=0;while((a=h[s++])&&!t.isPropagationStopped())t.type=s>1?l:f.bindType||d,p=(q.get(a,"events")||{})[t.type]&&q.get(a,"handle"),p&&p.apply(a,n),p=c&&a[c],p&&x.acceptData(a)&&p.apply&&p.apply(a,n)===!1&&t.preventDefault();return t.type=d,i||t.isDefaultPrevented()||f._default&&f._default.apply(h.pop(),n)!==!1||!x.acceptData(r)||c&&x.isFunction(r[d])&&!x.isWindow(r)&&(u=r[c],u&&(r[c]=null),x.event.triggered=d,r[d](),x.event.triggered=undefined,u&&(r[c]=u)),t.result}},dispatch:function(e){e=x.event.fix(e);var t,n,r,i,o,s=[],a=d.call(arguments),u=(q.get(this,"events")||{})[e.type]||[],l=x.event.special[e.type]||{};if(a[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),t=0;while((i=s[t++])&&!e.isPropagationStopped()){e.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(o.namespace))&&(e.handleObj=o,e.data=o.data,r=((x.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,a),r!==undefined&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,s=[],a=t.delegateCount,u=e.target;if(a&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!==this;u=u.parentNode||this)if(u.disabled!==!0||"click"!==e.type){for(r=[],n=0;a>n;n++)o=t[n],i=o.selector+" ",r[i]===undefined&&(r[i]=o.needsContext?x(i,this).index(u)>=0:x.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&s.push({elem:u,handlers:r})}return t.length>a&&s.push({elem:this,handlers:t.slice(a)}),s},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,t){var n,r,i,s=t.button;return null==e.pageX&&null!=t.clientX&&(n=e.target.ownerDocument||o,r=n.documentElement,i=n.body,e.pageX=t.clientX+(r&&r.scrollLeft||i&&i.scrollLeft||0)-(r&&r.clientLeft||i&&i.clientLeft||0),e.pageY=t.clientY+(r&&r.scrollTop||i&&i.scrollTop||0)-(r&&r.clientTop||i&&i.clientTop||0)),e.which||s===undefined||(e.which=1&s?1:2&s?3:4&s?2:0),e}},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,s=e,a=this.fixHooks[i];a||(this.fixHooks[i]=a=z.test(i)?this.mouseHooks:I.test(i)?this.keyHooks:{}),r=a.props?this.props.concat(a.props):this.props,e=new x.Event(s),t=r.length;while(t--)n=r[t],e[n]=s[n];return e.target||(e.target=o),3===e.target.nodeType&&(e.target=e.target.parentNode),a.filter?a.filter(e,s):e},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==V()&&this.focus?(this.focus(),!1):undefined},delegateType:"focusin"},blur:{trigger:function(){return this===V()&&this.blur?(this.blur(),!1):undefined},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&x.nodeName(this,"input")?(this.click(),!1):undefined},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==undefined&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)},x.Event=function(e,t){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.getPreventDefault&&e.getPreventDefault()?U:Y):this.type=e,t&&x.extend(this,t),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,undefined):new x.Event(e,t)},x.Event.prototype={isDefaultPrevented:Y,isPropagationStopped:Y,isImmediatePropagationStopped:Y,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=U,e&&e.preventDefault&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=U,e&&e.stopPropagation&&e.stopPropagation()},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=U,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,t,n,r,i){var o,s;if("object"==typeof e){"string"!=typeof t&&(n=n||t,t=undefined);for(s in e)this.on(s,t,n,e[s],i);return this}if(null==n&&null==r?(r=t,n=t=undefined):null==r&&("string"==typeof t?(r=n,n=undefined):(r=n,n=t,t=undefined)),r===!1)r=Y;else if(!r)return this;return 1===i&&(o=r,r=function(e){return x().off(e),o.apply(this,arguments)},r.guid=o.guid||(o.guid=x.guid++)),this.each(function(){x.event.add(this,e,r,n,t)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,x(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return(t===!1||"function"==typeof t)&&(n=t,t=undefined),n===!1&&(n=Y),this.each(function(){x.event.remove(this,e,n,t)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];return n?x.event.trigger(e,t,n,!0):undefined}});var G=/^.[^:#\[\.,]*$/,J=/^(?:parents|prev(?:Until|All))/,Q=x.expr.match.needsContext,K={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t=x(e,this),n=t.length;return this.filter(function(){var e=0;for(;n>e;e++)if(x.contains(this,t[e]))return!0})},not:function(e){return this.pushStack(et(this,e||[],!0))},filter:function(e){return this.pushStack(et(this,e||[],!1))},is:function(e){return!!et(this,"string"==typeof e&&Q.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],s=Q.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(s?s.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?g.call(x(e),this[0]):g.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function Z(e,t){while((e=e[t])&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return Z(e,"nextSibling")},prev:function(e){return Z(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return e.contentDocument||x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(K[e]||x.unique(i),J.test(e)&&i.reverse()),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,t,n){var r=[],i=n!==undefined;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&x(e).is(n))break;r.push(e)}return r},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function et(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(G.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return g.call(t,e)>=0!==n})}var tt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,nt=/<([\w:]+)/,rt=/<|&#?\w+;/,it=/<(?:script|style|link)/i,ot=/^(?:checkbox|radio)$/i,st=/checked\s*(?:[^=]|=\s*.checked.)/i,at=/^$|\/(?:java|ecma)script/i,ut=/^true\/(.*)/,lt=/^\s*\s*$/g,ct={option:[1,""],thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};ct.optgroup=ct.option,ct.tbody=ct.tfoot=ct.colgroup=ct.caption=ct.thead,ct.th=ct.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===undefined?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=pt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=pt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(mt(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&dt(mt(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++)1===e.nodeType&&(x.cleanData(mt(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var t=this[0]||{},n=0,r=this.length;if(e===undefined&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!it.test(e)&&!ct[(nt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(tt,"<$1>");try{for(;r>n;n++)t=this[n]||{},1===t.nodeType&&(x.cleanData(mt(t,!1)),t.innerHTML=e);t=0}catch(i){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=f.apply([],e);var r,i,o,s,a,u,l=0,c=this.length,p=this,h=c-1,d=e[0],g=x.isFunction(d);if(g||!(1>=c||"string"!=typeof d||x.support.checkClone)&&st.test(d))return this.each(function(r){var i=p.eq(r);g&&(e[0]=d.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(r=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),i=r.firstChild,1===r.childNodes.length&&(r=i),i)){for(o=x.map(mt(r,"script"),ft),s=o.length;c>l;l++)a=r,l!==h&&(a=x.clone(a,!0,!0),s&&x.merge(o,mt(a,"script"))),t.call(this[l],a,l);if(s)for(u=o[o.length-1].ownerDocument,x.map(o,ht),l=0;s>l;l++)a=o[l],at.test(a.type||"")&&!q.access(a,"globalEval")&&x.contains(u,a)&&(a.src?x._evalUrl(a.src):x.globalEval(a.textContent.replace(lt,"")))}return this}}),x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=[],i=x(e),o=i.length-1,s=0;for(;o>=s;s++)n=s===o?this:this.clone(!0),x(i[s])[t](n),h.apply(r,n.get());return this.pushStack(r)}}),x.extend({clone:function(e,t,n){var r,i,o,s,a=e.cloneNode(!0),u=x.contains(e.ownerDocument,e);if(!(x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(s=mt(a),o=mt(e),r=0,i=o.length;i>r;r++)yt(o[r],s[r]);if(t)if(n)for(o=o||mt(e),s=s||mt(a),r=0,i=o.length;i>r;r++)gt(o[r],s[r]);else gt(e,a);return s=mt(a,"script"),s.length>0&&dt(s,!u&&mt(e,"script")),a},buildFragment:function(e,t,n,r){var i,o,s,a,u,l,c=0,p=e.length,f=t.createDocumentFragment(),h=[];for(;p>c;c++)if(i=e[c],i||0===i)if("object"===x.type(i))x.merge(h,i.nodeType?[i]:i);else if(rt.test(i)){o=o||f.appendChild(t.createElement("div")),s=(nt.exec(i)||["",""])[1].toLowerCase(),a=ct[s]||ct._default,o.innerHTML=a[1]+i.replace(tt,"<$1>")+a[2],l=a[0];while(l--)o=o.lastChild;x.merge(h,o.childNodes),o=f.firstChild,o.textContent=""}else h.push(t.createTextNode(i));f.textContent="",c=0;while(i=h[c++])if((!r||-1===x.inArray(i,r))&&(u=x.contains(i.ownerDocument,i),o=mt(f.appendChild(i),"script"),u&&dt(o),n)){l=0;while(i=o[l++])at.test(i.type||"")&&n.push(i)}return f},cleanData:function(e){var t,n,r,i,o,s,a=x.event.special,u=0;for(;(n=e[u])!==undefined;u++){if(F.accepts(n)&&(o=n[q.expando],o&&(t=q.cache[o]))){if(r=Object.keys(t.events||{}),r.length)for(s=0;(i=r[s])!==undefined;s++)a[i]?x.event.remove(n,i):x.removeEvent(n,i,t.handle);q.cache[o]&&delete q.cache[o]}delete L.cache[n[L.expando]]}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}});function pt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function ft(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function ht(e){var t=ut.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function dt(e,t){var n=e.length,r=0;for(;n>r;r++)q.set(e[r],"globalEval",!t||q.get(t[r],"globalEval"))}function gt(e,t){var n,r,i,o,s,a,u,l;if(1===t.nodeType){if(q.hasData(e)&&(o=q.access(e),s=q.set(t,o),l=o.events)){delete s.handle,s.events={};for(i in l)for(n=0,r=l[i].length;r>n;n++)x.event.add(t,i,l[i][n])}L.hasData(e)&&(a=L.access(e),u=x.extend({},a),L.set(t,u))}}function mt(e,t){var n=e.getElementsByTagName?e.getElementsByTagName(t||"*"):e.querySelectorAll?e.querySelectorAll(t||"*"):[];return t===undefined||t&&x.nodeName(e,t)?x.merge([e],n):n}function yt(e,t){var n=t.nodeName.toLowerCase();"input"===n&&ot.test(e.type)?t.checked=e.checked:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}x.fn.extend({wrapAll:function(e){var t;return x.isFunction(e)?this.each(function(t){x(this).wrapAll(e.call(this,t))}):(this[0]&&(t=x(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this)},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var vt,xt,bt=/^(none|table(?!-c[ea]).+)/,wt=/^margin/,Tt=RegExp("^("+b+")(.*)$","i"),Ct=RegExp("^("+b+")(?!px)[a-z%]+$","i"),kt=RegExp("^([+-])=("+b+")","i"),Nt={BODY:"block"},Et={position:"absolute",visibility:"hidden",display:"block"},St={letterSpacing:0,fontWeight:400},jt=["Top","Right","Bottom","Left"],Dt=["Webkit","O","Moz","ms"];function At(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Dt.length;while(i--)if(t=Dt[i]+n,t in e)return t;return r}function Lt(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function qt(t){return e.getComputedStyle(t,null)}function Ht(e,t){var n,r,i,o=[],s=0,a=e.length;for(;a>s;s++)r=e[s],r.style&&(o[s]=q.get(r,"olddisplay"),n=r.style.display,t?(o[s]||"none"!==n||(r.style.display=""),""===r.style.display&&Lt(r)&&(o[s]=q.access(r,"olddisplay",Rt(r.nodeName)))):o[s]||(i=Lt(r),(n&&"none"!==n||!i)&&q.set(r,"olddisplay",i?n:x.css(r,"display"))));for(s=0;a>s;s++)r=e[s],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[s]||"":"none"));return e}x.fn.extend({css:function(e,t){return x.access(this,function(e,t,n){var r,i,o={},s=0;if(x.isArray(t)){for(r=qt(e),i=t.length;i>s;s++)o[t[s]]=x.css(e,t[s],!1,r);return o}return n!==undefined?x.style(e,t,n):x.css(e,t)},e,t,arguments.length>1)},show:function(){return Ht(this,!0)},hide:function(){return Ht(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){Lt(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=vt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,s,a=x.camelCase(t),u=e.style;return t=x.cssProps[a]||(x.cssProps[a]=At(u,a)),s=x.cssHooks[t]||x.cssHooks[a],n===undefined?s&&"get"in s&&(i=s.get(e,!1,r))!==undefined?i:u[t]:(o=typeof n,"string"===o&&(i=kt.exec(n))&&(n=(i[1]+1)*i[2]+parseFloat(x.css(e,t)),o="number"),null==n||"number"===o&&isNaN(n)||("number"!==o||x.cssNumber[a]||(n+="px"),x.support.clearCloneStyle||""!==n||0!==t.indexOf("background")||(u[t]="inherit"),s&&"set"in s&&(n=s.set(e,n,r))===undefined||(u[t]=n)),undefined)}},css:function(e,t,n,r){var i,o,s,a=x.camelCase(t);return t=x.cssProps[a]||(x.cssProps[a]=At(e.style,a)),s=x.cssHooks[t]||x.cssHooks[a],s&&"get"in s&&(i=s.get(e,!0,n)),i===undefined&&(i=vt(e,t,r)),"normal"===i&&t in St&&(i=St[t]),""===n||n?(o=parseFloat(i),n===!0||x.isNumeric(o)?o||0:i):i}}),vt=function(e,t,n){var r,i,o,s=n||qt(e),a=s?s.getPropertyValue(t)||s[t]:undefined,u=e.style;return s&&(""!==a||x.contains(e.ownerDocument,e)||(a=x.style(e,t)),Ct.test(a)&&wt.test(t)&&(r=u.width,i=u.minWidth,o=u.maxWidth,u.minWidth=u.maxWidth=u.width=a,a=s.width,u.width=r,u.minWidth=i,u.maxWidth=o)),a};function Ot(e,t,n){var r=Tt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function Ft(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,s=0;for(;4>o;o+=2)"margin"===n&&(s+=x.css(e,n+jt[o],!0,i)),r?("content"===n&&(s-=x.css(e,"padding"+jt[o],!0,i)),"margin"!==n&&(s-=x.css(e,"border"+jt[o]+"Width",!0,i))):(s+=x.css(e,"padding"+jt[o],!0,i),"padding"!==n&&(s+=x.css(e,"border"+jt[o]+"Width",!0,i)));return s}function Pt(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=qt(e),s=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=vt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Ct.test(i))return i;r=s&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+Ft(e,t,n||(s?"border":"content"),r,o)+"px"}function Rt(e){var t=o,n=Nt[e];return n||(n=Mt(e,t),"none"!==n&&n||(xt=(xt||x("