From febb923ca25df1af28b73259fe6351d976afceed Mon Sep 17 00:00:00 2001 From: Shenoy Pratik Date: Thu, 28 Jul 2022 11:08:26 -0700 Subject: [PATCH] Updating 1.x branch with latest from 1.3.x (#403) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix release notes version (#28) Signed-off-by: Zhongnan Su * Migrate Reporting Notebooks Integration (#21) Signed-off-by: David Cui * Add Logic to Auto-populate Notebooks from Context Menu (#30) Signed-off-by: David Cui * Change opendistro to opensearch in email template (#31) Signed-off-by: Joshua Li * Fix case sensitive directory name for chromium zip (#35) Signed-off-by: David Cui Co-authored-by: Carl Meadows <47793022+CarlMeadows@users.noreply.github.com> Co-authored-by: Zhongnan Su Co-authored-by: Joshua Li * Use output_only Parameter for notebook reports (#32) Signed-off-by: David Cui * replace osd-version header to remove need for version number matching (#37) Signed-off-by: David Cui * Remove visualization editor in visualization reports (#50) Signed-off-by: Joshua Li * add condition to fix negative value display (#51) Signed-off-by: David Cui * [Query Builder] Correctly handle match phrases when a single value is specified or when the match phrases is negated (#33) * [Build query] Correctly handle phrases filter that specify only one single value Contrary to the phrase filter type which always specify a meta.params.query, the phrases filter type never specify a meta.params.query even when a single value is selected. This anomaly trigger an error generated by the MonoFieldQueryBase included in the elastic-builder dependency and prevent the generation of the report. Signed-off-by: Kévin Masseix * [Build query] Correctly handle negated phrases filter that specify only one single value Signed-off-by: Kévin Masseix * [Build query] Correctlty handle negated phrases to exclude them from the report instead of including them Signed-off-by: Kévin Masseix * Pass processing if doc[field] == null (#361) Pass processing if doc[field] == null Based on https://github.com/opendistro-for-elasticsearch/kibana-reports/issues/327#issuecomment-796479152 * add test case for commit 368eb03e200b755870f1ad373e67561201ab6f31 (#370) Add missing test case for the fix "pass doc[field] == null" * Unhash page url in case store URLs in session storage is enabled from Kibana advanced setting (#371) * Update Namespaces/APIs/Documentation for OpenSearch (#55) Signed-off-by: David Cui * bump path-parse version to 1.0.7 to address CVE (#59) Signed-off-by: David Cui * increase chromium timeout to 100s (#58) Signed-off-by: Zhongnan Su * Fix csv parsing function (#53) * Fix csv parsing function Signed-off-by: Joshua Li * Flatten nested results for csv Signed-off-by: Joshua Li * Add test case for nested fields Signed-off-by: Joshua Li * Add release notes for rc1 (#60) Signed-off-by: David Cui * configure index settings to have default 1 replica and auto-expand upperbound 2 (#62) Signed-off-by: Zhongnan Su * Rc1 release note patch (#63) Signed-off-by: David Cui * Bump OpenSearch Dashboards version to 1.0 (#64) Signed-off-by: David Cui * Revert .opensearch_dashboards index references to .kibana (#67) Signed-off-by: David Cui * Add diagrams for integration with Notifications plugin (#75) * add puml diagrams for integration with Notifications plugin Signed-off-by: David Cui * amend Notifications plugin naming in diagram Signed-off-by: David Cui * Add i18n translation support (#362) * PDF report is no more a screenshot, increasing the overall quality Also a issue with chrome font rendering was fixed * Add Notifications to docs (#87) * moved docs to root folder, update readme to include Notifications roadmap Signed-off-by: David Cui * update readme to clarify current status of supported features Signed-off-by: David Cui * Better support sorting for csv report based on saved search (#86) * Change Delivery Request Body for Notifications (#85) * adding opensearch changed api for report definition to save branch Signed-off-by: David Cui * change delivery request body, update test cases Signed-off-by: David Cui * remove console.log statement, fix DeliveryType type members to use snake case Signed-off-by: David Cui * convert all snake case to camel case Signed-off-by: David Cui * make configId required in schema Signed-off-by: David Cui * Remove legacy notifications/delivery related code (#94) * remove legacy notifications/delivery related code Signed-off-by: David Cui * remove commented out reference Signed-off-by: David Cui * Remove dependency on demo.elastic and use local mock html for testing (#100) * Add code cov back (#98) Signed-off-by: Zhongnan Su * update workflow to rename artifact in kebab case (#102) Signed-off-by: Zhongnan Su * bump dependency version (#101) Signed-off-by: Zhongnan Su * level up markdowns and readme (#97) Signed-off-by: Zhongnan Su * Bump to version 1.0.0.0 (#103) Signed-off-by: Zhongnan Su * Bump test resource(job-scheduler) to 1.0.0.0 (#105) Signed-off-by: Zhongnan Su * fix failed cypress integ-testing (#106) Signed-off-by: Zhongnan Su * Bump node version, fix workflow and gradle build (#108) * Bump nodejs version to keep up with upstream Signed-off-by: Zhongnan Su * fix github workflow Signed-off-by: Zhongnan Su * Add release notes for 1.0.0.0 (#104) Signed-off-by: Zhongnan Su * Fix notebooks context menu (#109) Signed-off-by: Joshua Li * Fix context menu download request body after schema change to add notifiaction (#115) Signed-off-by: Zhongnan Su * Exclude time range from report details for Notebooks (#117) * exclude time range check for notebooks reports Signed-off-by: David Cui * use report source identifier over url partial match Signed-off-by: David Cui * add report details fix to release notes Signed-off-by: David Cui * add more bug fixes to release notes Signed-off-by: David Cui * Update regex for notebooks reports (#118) Signed-off-by: Joshua Li * Add integtest script to the repo Signed-off-by: Peter Zhu * Improve osd bootstrap on dub directory Signed-off-by: Peter Zhu * Improve osd bootstrap on dub directory Signed-off-by: Peter Zhu * Exclude Faulty Integration Test (#122) Exclude broken ITs from upstream OpenSearch * Fix cypress reporting (#123) * fix create test Signed-off-by: David Cui * toggle video on for cypress testing (#124) Signed-off-by: David Cui * Update Doc Links (#127) * update doc links in dashboards-reports Signed-off-by: David Cui * Update template to reflect new branding (#128) Signed-off-by: kgcreative * Update UI for Notifications Integration (#126) Update reporting front-end for Notifications integration Signed-off-by: David Cui * Add themed logo to README (#130) Signed-off-by: Miki * Fix url validation (#132) Signed-off-by: Joshua Li * Fix url validation for context menu (#134) * Fix url validation for context menu Signed-off-by: Joshua Li * Fix url validation Signed-off-by: Joshua Li * Connect Notifications APIs to Reporting (#131) * call notifications APIs from reporting, saving progress Signed-off-by: David Cui * enable notifications integration, update view in details pages, update tests Signed-off-by: David Cui * address comments, add server APIs to call backend notifications APIs to reduce dependency Signed-off-by: David Cui * add get_event API to confirm test messages are sent successfully and throw error if not Signed-off-by: David Cui * add input validation for delivery subject and message, hide notifications section if opensearch notifications is not installed Signed-off-by: David Cui * renamed constant for notifications to follow API_PREFIX convention Signed-off-by: David Cui * rename notifications constant to reporting_notifications Signed-off-by: David Cui * add list of failed channels on test message failure Signed-off-by: David Cui * Fix snapshot build and upgrade to OpenSearch 1.1. (#140) Signed-off-by: dblock * Add release notes for 1.0.1 release (#143) Signed-off-by: Joshua Li * Bump to 1.1 in main (#150) * bump version to 1.1, hide delivery section Signed-off-by: David Cui * Dont hide delivery by default Signed-off-by: David Cui * bump version to 1.1 in dashboards reports workflow Signed-off-by: David Cui * fix OSD branch to use main Signed-off-by: David Cui * change from main to 1.x for dashboards version Signed-off-by: David Cui * Bump opensearch ref to 1.1 in CI (#155) * Removed integtest.sh. (#157) Signed-off-by: dblock * Taking RBAC settings from Alerting plugin default to false Other changes: 1. Legacy settings removed because all relavent settings are removed or taken from Alerting plugin 2. Poll API removed as it is not used [Tests] All existing tests passed Signed-off-by: @akbhatta * Bump tmpl from 1.0.4 to 1.0.5 in /dashboards-reports (#164) Bumps [tmpl](https://github.com/daaku/nodejs-tmpl) from 1.0.4 to 1.0.5. - [Release notes](https://github.com/daaku/nodejs-tmpl/releases) - [Commits](https://github.com/daaku/nodejs-tmpl/commits/v1.0.5) --- updated-dependencies: - dependency-name: tmpl dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Fix quoting and url-encoding (#153) * Replace '%2F' with '/' in relative dates Signed-off-by: Konstantin Roussou * Ensure proper quoting of converted dates in URL Signed-off-by: Konstantin Roussou * Use generic URL decoding Co-authored-by: Zhongnan Su * Use roundUp for toDate Co-authored-by: Zhongnan Su * Make date transformation same as in context_menu_helpers.js Co-authored-by: Zhongnan Su * Integrate notifications backend (#129) * Remove hard coded localhost when calling API (#172) * rename plugin helper config file name to consistent with OSD (#180) Signed-off-by: Tengda He * Add metrics for sending notifications (#173) * Add logic to build report detail page link and send as part of message for non-email channels (#182) * forward origin plus basePath to backend * Add build report link function and forward link as part of message * Update validation for observability notebooks integration (#174) * Build email message from template with reports links (#184) * remove the email tempalte and helpers from dashboards plugin * build email message from template for reporting notifcation Signed-off-by: Zhongnan Su * Support range filters for csv reports (#185) * Forward extra headers while using headless chromium (#194) * Use advanced settings for date format in csv reports (#186) * add check in ReportInstanceActions to fix on demand report creation after report definition creation (#196) Signed-off by: David Cui * Catch Notifications Errors on Details Pages (#197) * add catch statements to notifications get_configs to avoid crashing details pages Signed-off by: David Cui * remove console log statment Signed-off by: David Cui * remove notifications integration from details pages and update snapshots (#210) Signed-off-by: David Cui * fix csv missing metadata fields issue and empty report on all(_source) fields (#206) * remove notifications references from create and edit report definition pages (#212) Signed-off by: David Cui * refactor logic for creating DSL from saved object using buildOpensearchQuery() (#213) * Remove calling notifications in reports scheduler (#211) * Use advanced settings for csv separator and visual report timezone (#209) * Bump to version 1.2 (#203) * Bump to version 1.2 Bump OpenSearch and OpenSearch Dashboards plugins to 1.2 Related issue: https://github.com/opensearch-project/dashboards-reports/issues/167 Signed-off-by: Kawika Avilla * Use maven for building reports scheduler Signed-off-by: Joshua Li Co-authored-by: Joshua Li * Add dco and release drafter workflows (#217) Signed-off-by: Joshua Li * update readme notification section (#216) Signed-off-by: Zhongnan Su * revert paths to opendistro to keep cluster permissions same with ODFE (#218) Signed-off-by: David Cui * Create opensearch-dashboards-reports.release-notes-1.2.0.0.md Signed-off-by: Kavitha Conjeevaram Mohan * Update the copyright notices to reflect OpenSearch Contributors (#220) * update the copyright notices to reflect OpenSearch Contributors Signed-off-by: David Cui * add .txt to NOTICE to resolve linkchecker error Signed-off-by: David Cui * changes Signed-off-by: Kavitha Conjeevaram Mohan * changes Signed-off-by: Kavitha Conjeevaram Mohan * Remove notifications actions in reports scheduler (#221) Signed-off-by: Joshua Li * add reporting osd server configurations (#222) Signed-off-by: Zhongnan Su * Add suggested font packages in troubleshooting tips (#189) * add suggested font packages in troubleshooting tips Signed-off-by: David Cui * add links to package documentation in README for font packages Signed-off-by: David Cui * add more descriptive title under Troubleshooting Signed-off-by: David Cui * add link to headless-chrome installation and add ipa-gothic-fonts link to centos 7 Signed-off-by: David Cui * Update Copyright Headers (#226) * update copyright header for all files Signed-off-by: David Cui * fix ktlint errors with extra whitespace Signed-off-by: David Cui * Add support for codeowners to repo (#227) Signed-off-by: Ryan Bogan * Fix reporting validation for observability (#231) * Update reporting validation for observability Signed-off-by: Joshua Li * update tests Signed-off-by: Joshua Li * remove poller code from frontend plugin (#235) Signed-off-by: Zhongnan Su * bump reports-scheduler to 1.3 (#241) Signed-off-by: Zhongnan Su * Fix apt source and link checker for CI (#245) * Update apt source in CI Signed-off-by: Joshua Li * Try fix link checker Signed-off-by: Joshua Li * Add Case Coverage tests for Create Report Definition (#239) * add & refactor cypress tests, add css selectors in report settings & report trigger Signed-off-by: David Cui * remove comment and update jest snapshot Signed-off-by: David Cui * add bwc test for reports-scheduler (#244) Signed-off-by: Zhongnan Su * added code summary table (#243) * added code summary table Signed-off-by: Shenoy Pratik * modularized tables, fixed links Signed-off-by: Shenoy Pratik * updated header, changed bwc link Signed-off-by: Shenoy Pratik * Add Cypress Case Coverage on Details Pages (#250) * add and refactor cypress tests for details pages Signed-off-by: David Cui * update jest snapshots Signed-off-by: David Cui * add utils.js file to store functions used in multiple cypress tests Signed-off-by: David Cui * add gradle task to run integtest against remote cluster (#247) Signed-off-by: Zhongnan Su * added untriaged and nolabel badges Signed-off-by: Shenoy Pratik * bump dashboards-reports version to 1.3 (#265) Signed-off-by: Zhongnan Su * add UT for request/reseponse model (#264) Signed-off-by: Zhongnan Su * Add .whitesource configuration file * Address Reporting CVEs (#267) * update vulnerable package versions Signed-off-by: David Cui * change ansi-regex to 5.0.1 to pass bootstrap Signed-off-by: David Cui * update yarn lock for cve fixes (#271) Signed-off-by: David Cui * add release notes for 1.2.4 Signed-off-by: David Cui * remove jcenter repo from gradle build Signed-off-by: Shenoy Pratik * update guava to 31.0.1-jre Signed-off-by: Shenoy Pratik * WS package update (#283) * updated ws version Signed-off-by: Shenoy Pratik * moved ws package to resolutions Signed-off-by: Shenoy Pratik * updated yarn lock Signed-off-by: Shenoy Pratik * add auto-backport functionality for reporting (#286) Add auto-backport and auto-delete workflows for reporting Signed-off-by: David Cui * Change Default CI version to JDK 11 (#290) * change default CI version to JDK 11, add JDK versions to CI matrix and document changes in developer guide Signed-off-by: David Cui * remove incorrect tag form issue template (#294) Signed-off-by: Zhongnan Su * Fix empty or multiple date values in csv (#293) Signed-off-by: Zhongnan Su * Update the saved object id matcher regex to match custom id (#295) Signed-off-by: Zhongnan Su * Replace Centos links to fix link checker CI (#297) exclude centos links from linkchecker Signed-off-by: David Cui * update regex to match custom saved object id (#298) Signed-off-by: Zhongnan Su * Fix reporting uuid parsing (#300) Signed-off-by: Joshua Li * Add java 8 support in compile and test (#304) (#305) * add java 8 support in compile and test Signed-off-by: Zhongnan Su (cherry picked from commit e753b07eda0b24e2c53716591004d5b06ac854ad) Co-authored-by: Zhongnan Su * Add 1.3 release notes (#307) (#308) * Add 1.3 release notes Signed-off-by: Zhongnan Su (cherry picked from commit 2e904c5f6e30751549a223958e2a27f287105571) Co-authored-by: Zhongnan Su * Bump version to 1.3.1 (#324) Signed-off-by: Sayali Gaikawad * Bump reports dashboards to 1.3.1 (#331) Signed-off-by: Joshua Li * Incremented version to 1.3.2. (#352) Signed-off-by: Zelin Hao * Version bump 1.3.3 Signed-off-by: pgodithi * Version bump 1.3.3 Signed-off-by: pgodithi * Version bump 1.3.3 Signed-off-by: pgodithi * [1.3] Bump minimist to 1.2.6 (#367) Signed-off-by: Joshua Li * Move HTML sanitization from client to server side (#382) (#386) Move HTML sanitization to server, store markdown over HTML, remove unused imports Signed-off-by: David Cui Co-authored-by: David Cui <53581635+davidcui1225@users.noreply.github.com> * Incremented version to 1.3.4. (#389) * Incremented version to 1.3.4. Signed-off-by: Zelin Hao * Add JS snapshot Signed-off-by: Zelin Hao * Add release notes for 1.3.4.0 (#393) (#394) Signed-off-by: Joshua Li (cherry picked from commit 8e01eaa2b5da84dfd686a10ee56bb5472e2d03fc) Co-authored-by: Joshua Li Co-authored-by: Zhongnan Su Co-authored-by: David Cui <53581635+davidcui-amzn@users.noreply.github.com> Co-authored-by: Joshua Co-authored-by: Carl Meadows <47793022+CarlMeadows@users.noreply.github.com> Co-authored-by: Kevin Masseix Co-authored-by: Uzhinskiy Boris Co-authored-by: David Cui Co-authored-by: starcatter <30572485+starcatter@users.noreply.github.com> Co-authored-by: Elias Soares Co-authored-by: Peter Zhu Co-authored-by: Kevin Garcia Co-authored-by: Miki Co-authored-by: David Cui <53581635+davidcui1225@users.noreply.github.com> Co-authored-by: Daniel Doubrovkine (dB.) Co-authored-by: Anantha Krishna Bhatta Co-authored-by: Anantha Krishna Bhatta <31894175+akbhatta@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: kroussou <58224693+kroussou@users.noreply.github.com> Co-authored-by: Tengda-He <89666799+Tengda-He@users.noreply.github.com> Co-authored-by: Kawika Avilla Co-authored-by: Kavitha Conjeevaram Mohan Co-authored-by: Kavitha Conjeevaram Mohan Co-authored-by: Ryan Bogan <10944539+ryanbogan@users.noreply.github.com> Co-authored-by: whitesource-for-github-com[bot] <50673670+whitesource-for-github-com[bot]@users.noreply.github.com> Co-authored-by: opensearch-trigger-bot[bot] <98922864+opensearch-trigger-bot[bot]@users.noreply.github.com> Co-authored-by: Sayali Gaikawad <61760125+gaiksaya@users.noreply.github.com> Co-authored-by: Zelin Hao <87548827+zelinh@users.noreply.github.com> Co-authored-by: pgodithi Co-authored-by: Anirudha (Ani) Jadhav --- .github/CODEOWNERS | 2 + .github/ISSUE_TEMPLATE/bug_template.md | 2 +- .github/draft-release-notes-config.yml | 45 + .github/workflows/backport.yml | 28 + .../dashboards-reports-release-workflow.yml | 29 +- ...boards-reports-test-and-build-workflow.yml | 47 +- .github/workflows/dco.yml | 18 + .github/workflows/delete_backport_branch.yml | 15 + .../draft-release-notes-workflow.yml | 21 + .github/workflows/link-checker.yml | 23 + ...orts-scheduler-test-and-build-workflow.yml | 63 +- .whitesource | 20 + ADMINS.md | 7 + MAINTAINERS.md | 4 +- NOTICE | 12 - NOTICE.txt | 2 + README.md | 142 +- RELEASING.md | 1 + SECURITY.md | 3 + dashboards-reports/.babelrc | 18 - .../.cypress/integration/01-create.spec.ts | 289 +- .../.cypress/integration/02-edit.spec.ts | 46 +- .../.cypress/integration/03-details.spec.ts | 145 +- .../.cypress/integration/04-download.spec.ts | 23 +- dashboards-reports/.cypress/plugins/index.js | 23 +- .../.cypress/support/commands.js | 23 +- .../.cypress/support/constants.js | 25 +- dashboards-reports/.cypress/support/index.js | 23 +- dashboards-reports/.cypress/support/utils.js | 12 + dashboards-reports/.i18nrc.json | 7 + ...opensearch_dashboards-plugin-helpers.json} | 4 +- dashboards-reports/DEVELOPER_GUIDE.md | 67 + dashboards-reports/README.md | 61 +- dashboards-reports/babel.config.js | 20 + dashboards-reports/common/index.ts | 46 +- dashboards-reports/cypress.json | 5 +- dashboards-reports/opensearch_dashboards.json | 7 +- dashboards-reports/package.json | 27 +- dashboards-reports/public/application.tsx | 23 +- dashboards-reports/public/components/app.tsx | 49 +- .../components/context_menu/context_menu.js | 62 +- .../context_menu/context_menu_helpers.js | 54 +- .../context_menu/context_menu_ui.js | 162 +- .../__snapshots__/main.test.tsx.snap | 32 +- .../report_definitions_table.test.tsx.snap | 4 +- .../__snapshots__/reports_table.test.tsx.snap | 4 +- .../__utils__/main_utils_test_utils.tsx | 23 +- .../components/main/__tests__/main.test.tsx | 23 +- .../main/__tests__/main_utils.test.tsx | 23 +- .../report_definitions_table.test.tsx | 23 +- .../main/__tests__/reports_table.test.tsx | 23 +- .../public/components/main/index.ts | 23 +- .../components/main/loading_modal/index.ts | 23 +- .../main/loading_modal/loading_modal.tsx | 84 +- .../public/components/main/main.tsx | 111 +- .../public/components/main/main_utils.tsx | 69 +- .../report_definition_details.test.tsx.snap | 72 +- .../report_definition_details.test.tsx | 72 +- .../report_definition_details.tsx | 453 +- .../main/report_definitions_table.tsx | 103 +- .../report_details.test.tsx.snap | 108 +- .../__tests__/report_details.test.tsx | 37 +- .../main/report_details/report_details.tsx | 363 +- .../public/components/main/reports_table.tsx | 115 +- .../create/create_report_definition.tsx | 137 +- .../report_definitions/create/index.ts | 23 +- .../__snapshots__/delivery.test.tsx.snap | 20 +- .../__snapshots__/email.test.tsx.snap | 1632 --- .../delivery/__tests__/delivery.test.tsx | 41 +- .../delivery/__tests__/email.test.tsx | 227 - .../report_definitions/delivery/delivery.tsx | 353 +- .../delivery/delivery_constants.tsx | 60 +- .../report_definitions/delivery/email.tsx | 190 - .../report_definitions/delivery/index.ts | 23 +- .../delivery/kibana_user.tsx | 124 - .../edit/edit_report_definition.tsx | 119 +- .../report_definitions/edit/index.ts | 23 +- .../report_settings.test.tsx.snap | 800 +- .../__tests__/report_settings.test.tsx | 219 +- .../report_settings_helpers.test.tsx | 23 +- .../report_settings/index.ts | 23 +- .../report_settings/report_settings.tsx | 344 +- .../report_settings_constants.tsx | 78 +- .../report_settings_helpers.tsx | 25 +- .../report_settings/time_range.tsx | 47 +- .../report_trigger.test.tsx.snap | 696 +- .../__tests__/report_trigger.test.tsx | 23 +- .../report_trigger/index.ts | 23 +- .../report_trigger/report_trigger.tsx | 165 +- .../report_trigger_constants.tsx | 125 +- .../report_trigger/timezone.tsx | 34 +- .../report_definitions/utils/index.ts | 23 +- .../report_definitions/utils/utils.tsx | 175 +- .../components/utils/settings_service.ts | 31 + .../public/components/utils/utils.tsx | 23 +- dashboards-reports/public/hack.js | 23 +- dashboards-reports/public/index.scss | 23 +- dashboards-reports/public/index.ts | 23 +- dashboards-reports/public/plugin.ts | 42 +- dashboards-reports/public/types.ts | 23 +- .../headless-chrome/README.md | 6 +- .../backend/opendistro-notification-plugin.ts | 42 - ...plugin.ts => opensearch-reports-plugin.ts} | 33 +- .../server/clusters/notificationsPlugin.ts | 46 + dashboards-reports/server/config/config.ts | 63 + .../server/config/createConfig.ts | 47 + dashboards-reports/server/config/index.ts | 13 + dashboards-reports/server/config/schema.ts | 35 + .../server/executor/createScheduledReport.ts | 96 - .../server/executor/executor.ts | 77 - dashboards-reports/server/index.ts | 41 +- .../server/model/backendModel.ts | 27 +- dashboards-reports/server/model/index.ts | 39 +- dashboards-reports/server/plugin.ts | 117 +- dashboards-reports/server/routes/index.ts | 33 +- .../server/routes/lib/createReport.ts | 105 +- .../routes/lib/createReportDefinition.ts | 24 +- .../server/routes/lib/deliverReport.ts | 133 - .../server/routes/lib/saveReport.ts | 23 +- .../routes/lib/updateReportDefinition.ts | 23 +- .../server/routes/lib/updateReportState.ts | 23 +- dashboards-reports/server/routes/metric.ts | 23 +- .../server/routes/notifications.ts | 142 + dashboards-reports/server/routes/report.ts | 88 +- .../server/routes/reportDefinition.ts | 40 +- .../server/routes/reportSource.ts | 29 +- .../utils/__tests__/demo_dashboard.html | 9699 +++++++++++++++++ .../utils/__tests__/metricHelper.test.ts | 23 +- .../__tests__/savedSearchReportHelper.test.ts | 276 +- .../__tests__/visualReportHelper.test.ts | 57 +- .../server/routes/utils/constants.ts | 68 +- .../converters/__tests__/backendToUi.test.ts | 60 +- .../converters/__tests__/uiToBackend.test.ts | 41 +- .../routes/utils/converters/backendToUi.ts | 40 +- .../routes/utils/converters/uiToBackend.ts | 45 +- .../server/routes/utils/dataReportHelpers.ts | 228 +- .../server/routes/utils/helpers.ts | 31 +- .../server/routes/utils/metricHelper.ts | 23 +- .../notification/deliveryContentHelper.ts | 56 - .../notification_content_template/logo.png | Bin 9995 -> 0 bytes .../routes/utils/savedSearchReportHelper.ts | 112 +- .../server/routes/utils/types.ts | 23 +- .../utils/visual_report/footer_template.html | 5 + .../utils/visual_report/header_template.html | 5 + .../utils/visual_report/report_template.html | 244 - .../routes/utils/visual_report/style.css | 211 + .../utils/visual_report/visualReportHelper.ts | 189 +- dashboards-reports/server/types.ts | 23 +- .../utils/__tests__/validationHelper.test.ts | 75 +- dashboards-reports/server/utils/constants.ts | 27 - .../server/utils/validationHelper.ts | 32 +- .../test/__mocks__/loggerMock.ts | 17 + dashboards-reports/test/httpMockClient.js | 32 +- dashboards-reports/test/jest.config.js | 25 +- dashboards-reports/test/propsMock.js | 23 +- dashboards-reports/test/setup.jest.ts | 23 +- dashboards-reports/test/setupTests.ts | 23 +- dashboards-reports/translations/pl.json | 299 + dashboards-reports/yarn.lock | 1747 ++- ...ch-Dashboards-Reporting-Design-Proposal.md | 10 +- .../dev/img/SQL_query_report.png | Bin .../dashboards-reports}/dev/img/arch_1.png | Bin .../dashboards-reports}/dev/img/arch_2.png | Bin .../dashboards-reports}/dev/img/arch_3.png | Bin .../dev/img/dashboard_reports.png | Bin .../dev/img/data_model.png | Bin .../dashboards-reports}/dev/img/delivery.png | Bin .../dashboards-reports}/dev/img/matrix.png | Bin .../dashboards-reports}/dev/img/workflows.png | Bin .../dev/resources/SQL_query_report.drawio | 0 .../dev/resources/arch_1.drawio | 0 .../dev/resources/arch_2.drawio | 0 .../dev/resources/arch_3.drawio | 0 .../dev/resources/dashboard_reports.drawio | 0 .../dev/resources/data_model.drawio | 0 .../dev/resources/delivery.drawio | 0 .../dev/resources/workflows.drawio | 0 ...h-Dashboards-Reporting-UX-documentation.md | 0 .../ux/img/flows/0.0.1_key-user-flows.png | Bin .../ux/img/flows/0.0.1_key-user-flows@2x.png | Bin .../ux/img/flows/0.0.2_key-screens.png | Bin .../ux/img/flows/0.0.2_key-screens@2x.png | Bin .../img/screens/0.1.01_dashboard-download.png | Bin .../screens/0.1.01_dashboard-download@2x.png | Bin .../ux/img/screens/0.1.02_dashboard-share.png | Bin .../img/screens/0.1.02_dashboard-share@2x.png | Bin .../img/screens/0.1.03_dashboard-toasts.png | Bin .../screens/0.1.03_dashboard-toasts@2x.png | Bin .../ux/img/screens/0.1.0_dashboard.png | Bin .../ux/img/screens/0.1.0_dashboard@2x.png | Bin .../screens/0.2.0_reporting_empty-state.png | Bin .../0.2.0_reporting_empty-state@2x.png | Bin .../ux/img/screens/0.2.1_reporting.png | Bin .../ux/img/screens/0.2.1_reporting@2x.png | Bin .../ux/img/screens/0.3.0_report.png | Bin .../ux/img/screens/0.3.0_report@2x.png | Bin .../ux/img/screens/0.3.1_report_share.png | Bin .../ux/img/screens/0.3.1_report_share@2x.png | Bin .../img/screens/0.4.0_report-definition.png | Bin .../screens/0.4.0_report-definition@2x.png | Bin .../0.5.0_create-report-definition.png | Bin .../0.5.0_create-report-definition@2x.png | Bin .../screens/0.6.0_edit-report-definition.png | Bin .../0.6.0_edit-report-definition@2x.png | Bin .../0.1.04_modals_generating-downloading.png | Bin ....1.04_modals_generating-downloading@2x.png | Bin .../img/supporting/0.5.1_report-settings.png | Bin .../supporting/0.5.1_report-settings@2x.png | Bin .../img/supporting/0.5.2_report-trigger.png | Bin .../supporting/0.5.2_report-trigger@2x.png | Bin .../supporting/0.5.3_delivery-settings.png | Bin .../supporting/0.5.3_delivery-settings@2x.png | Bin .../NotificationPluginIntegration.puml | 26 + .../NotificationPluginInteraction.puml | 79 + ...ashboards-reports.release-notes-1.0.0.0.md | 58 + ...ashboards-reports.release-notes-1.0.1.0.md | 9 + ...ashboards-reports.release-notes-1.1.0.0.md | 14 + ...ashboards-reports.release-notes-1.2.0.0.md | 39 + ...ashboards-reports.release-notes-1.2.4.0.md | 7 + ...ashboards-reports.release-notes-1.3.0.0.md | 18 + ...ashboards-reports.release-notes-1.3.4.0.md | 9 + reports-scheduler/.classpath | 52 + reports-scheduler/.codecov.yml | 17 + reports-scheduler/.editorconfig | 26 +- reports-scheduler/.idea/.name | 2 +- reports-scheduler/.project | 34 + .../build-tools/esplugin-coverage.gradle | 24 +- reports-scheduler/build-tools/pkgbuild.gradle | 24 +- reports-scheduler/build.gradle | 259 +- .../config/checkstyle/checkstyle.xml | 24 +- .../config/checkstyle/google_checks.xml | 24 +- .../config/checkstyle/suppressions.xml | 24 +- reports-scheduler/detekt.yml | 26 +- reports-scheduler/gradle.properties | 28 - .../gradle/wrapper/gradle-wrapper.properties | 21 +- .../release-notes/create_release_notes.py | 26 +- reports-scheduler/settings.gradle | 23 +- .../src/main/config/reports-scheduler.yml | 45 +- .../metrics/BasicCounter.java | 23 +- .../reportsscheduler/metrics/Counter.java | 23 +- .../reportsscheduler/metrics/Metrics.java | 24 +- .../metrics/RollingCounter.java | 23 +- .../ReportsSchedulerPlugin.kt | 29 +- .../action/CreateReportDefinitionAction.kt | 26 +- .../action/DeleteReportDefinitionAction.kt | 24 +- .../action/GetAllReportDefinitionsAction.kt | 26 +- .../action/GetAllReportInstancesAction.kt | 26 +- .../action/GetReportDefinitionAction.kt | 26 +- .../action/GetReportInstanceAction.kt | 26 +- .../action/InContextReportCreateAction.kt | 26 +- .../action/OnDemandReportCreateAction.kt | 26 +- .../action/PluginBaseAction.kt | 81 +- .../action/PollReportInstanceAction.kt | 64 - .../action/ReportDefinitionActions.kt | 28 +- .../action/ReportInstanceActions.kt | 72 +- .../action/UpdateReportDefinitionAction.kt | 26 +- .../UpdateReportInstanceStatusAction.kt | 26 +- .../index/ReportDefinitionsIndex.kt | 24 +- .../index/ReportInstancesIndex.kt | 85 +- .../reportsscheduler/model/BaseResponse.kt | 24 +- .../model/CreateReportDefinitionRequest.kt | 24 +- .../model/CreateReportDefinitionResponse.kt | 24 +- .../model/DeleteReportDefinitionRequest.kt | 24 +- .../model/DeleteReportDefinitionResponse.kt | 24 +- .../model/GetAllReportDefinitionsRequest.kt | 24 +- .../model/GetAllReportDefinitionsResponse.kt | 24 +- .../model/GetAllReportInstancesRequest.kt | 24 +- .../model/GetAllReportInstancesResponse.kt | 24 +- .../model/GetReportDefinitionRequest.kt | 24 +- .../model/GetReportDefinitionResponse.kt | 24 +- .../model/GetReportInstanceRequest.kt | 24 +- .../model/GetReportInstanceResponse.kt | 24 +- .../model/InContextReportCreateRequest.kt | 24 +- .../model/InContextReportCreateResponse.kt | 24 +- .../model/OnDemandReportCreateRequest.kt | 24 +- .../model/OnDemandReportCreateResponse.kt | 24 +- .../model/PollReportInstanceRequest.kt | 77 - .../model/PollReportInstanceResponse.kt | 145 - .../model/ReportDefinition.kt | 50 +- .../model/ReportDefinitionDetails.kt | 32 +- .../model/ReportDefinitionDetailsDoc.kt | 24 +- .../ReportDefinitionDetailsSearchResults.kt | 32 +- .../reportsscheduler/model/ReportInstance.kt | 24 +- .../model/ReportInstanceDoc.kt | 24 +- .../model/ReportInstanceSearchResults.kt | 24 +- .../reportsscheduler/model/RestTag.kt | 24 +- .../reportsscheduler/model/SearchResults.kt | 24 +- .../model/UpdateReportDefinitionRequest.kt | 24 +- .../model/UpdateReportDefinitionResponse.kt | 24 +- .../UpdateReportInstanceStatusRequest.kt | 24 +- .../UpdateReportInstanceStatusResponse.kt | 24 +- .../resthandler/OnDemandReportRestHandler.kt | 24 +- .../resthandler/PluginBaseHandler.kt | 24 +- .../ReportDefinitionListRestHandler.kt | 24 +- .../ReportDefinitionRestHandler.kt | 24 +- .../ReportInstanceListRestHandler.kt | 24 +- .../ReportInstancePollRestHandler.kt | 110 - .../resthandler/ReportInstanceRestHandler.kt | 24 +- .../resthandler/ReportStatsRestHandler.kt | 24 +- .../RestResponseToXContentListener.kt | 24 +- .../scheduler/ReportDefinitionJobParser.kt | 24 +- .../scheduler/ReportDefinitionJobRunner.kt | 30 +- .../security/SecurityAccess.kt | 24 +- .../security/UserAccessManager.kt | 141 +- .../settings/LegacyPluginSettings.kt | 498 - .../settings/PluginSettings.kt | 355 +- .../reportsscheduler/util/Helpers.kt | 44 +- .../reportsscheduler/util/OpenForTesting.kt | 24 +- .../util/SecureIndexClient.kt | 24 +- .../plugin-metadata/plugin-security.policy | 24 +- .../template}/email_content_template.html | 53 +- .../resources/notifications/template/logo.png | Bin 0 -> 7098 bytes .../resources/report-definitions-mapping.yml | 26 +- .../resources/report-definitions-settings.yml | 26 +- .../resources/report-instances-mapping.yml | 26 +- .../resources/report-instances-settings.yml | 26 +- .../metrics/BasicCounterTest.java | 24 +- .../metrics/RollingCounterTest.java | 24 +- .../opensearch/integTest/IntegTestHelpers.kt | 75 + .../PluginRestTestCase.kt | 52 +- .../integTest/ReportSchedularPluginTests.kt | 13 + .../ReportsSchedulerPluginIT.kt | 24 +- ...eportsSchedulerBackwardsCompatibilityIT.kt | 161 + .../rest/InContextMenuReportGenerationIT.kt | 34 +- .../rest/OnDemandReportGenerationIT.kt | 36 +- .../rest/ReportDefinitionIT.kt | 33 +- .../rest/ReportInstanceIT.kt | 32 +- .../ReportSchedularPluginTests.kt | 34 - .../reportsscheduler/TestHelpers.kt | 167 +- .../CreateReportDefinitionRequestTests.kt | 101 + .../CreateReportDefinitionResponseTests.kt | 71 + .../DeleteReportDefinitionRequestTests.kt | 59 + .../DeleteReportDefinitionResponseTests.kt | 67 + .../GetAllReportDefinitionsRequestTests.kt | 72 + .../GetAllReportDefinitionsResponseTests.kt | 135 + .../GetAllReportInstancesRequestTests.kt | 71 + .../GetAllReportInstancesResponseTests.kt | 106 + .../model/GetReportDefinitionRequestTests.kt | 70 + .../model/GetReportDefinitionResponseTests.kt | 114 + .../model/GetReportInstanceRequestTests.kt | 70 + .../model/GetReportInstanceResponseTests.kt | 87 + .../InContextReportCreateRequestTests.kt | 83 + .../InContextReportCreateResponseTests.kt | 87 + .../model/OnDemandReportCreateRequestTests.kt | 59 + .../OnDemandReportCreateResponseTests.kt | 86 + .../UpdateReportDefinitionRequestTests.kt | 103 + .../UpdateReportDefinitionResponseTests.kt | 69 + .../UpdateReportInstanceStatusRequestTests.kt | 71 + ...UpdateReportInstanceStatusResponseTests.kt | 70 + .../reportsscheduler/util/HelpersTests.kt | 42 + .../opendistro-job-scheduler-1.13.0.0.zip | Bin 0 -> 974325 bytes ...nsearch-job-scheduler-1.3.4.0-SNAPSHOT.zip | Bin 0 -> 1183725 bytes .../opendistro-reports-scheduler-1.13.0.0.zip | Bin 0 -> 5439710 bytes .../opensearch-job-scheduler-1.0.0.0-rc1.zip | Bin 972676 -> 0 bytes ...nsearch-job-scheduler-1.3.4.0-SNAPSHOT.zip | Bin 0 -> 1183725 bytes 355 files changed, 20044 insertions(+), 11297 deletions(-) create mode 100644 .github/CODEOWNERS create mode 100644 .github/draft-release-notes-config.yml create mode 100644 .github/workflows/backport.yml create mode 100644 .github/workflows/dco.yml create mode 100644 .github/workflows/delete_backport_branch.yml create mode 100644 .github/workflows/draft-release-notes-workflow.yml create mode 100644 .github/workflows/link-checker.yml create mode 100644 .whitesource create mode 100644 ADMINS.md delete mode 100644 NOTICE create mode 100644 NOTICE.txt create mode 100644 RELEASING.md create mode 100644 SECURITY.md delete mode 100644 dashboards-reports/.babelrc create mode 100644 dashboards-reports/.cypress/support/utils.js create mode 100644 dashboards-reports/.i18nrc.json rename dashboards-reports/{opensearch-dashboards-plugin-helpers.dev.json => .opensearch_dashboards-plugin-helpers.json} (67%) create mode 100644 dashboards-reports/DEVELOPER_GUIDE.md create mode 100644 dashboards-reports/babel.config.js delete mode 100644 dashboards-reports/public/components/report_definitions/delivery/__tests__/__snapshots__/email.test.tsx.snap delete mode 100644 dashboards-reports/public/components/report_definitions/delivery/__tests__/email.test.tsx delete mode 100644 dashboards-reports/public/components/report_definitions/delivery/email.tsx delete mode 100644 dashboards-reports/public/components/report_definitions/delivery/kibana_user.tsx create mode 100644 dashboards-reports/public/components/utils/settings_service.ts delete mode 100644 dashboards-reports/server/backend/opendistro-notification-plugin.ts rename dashboards-reports/server/backend/{opendistro-opensearch-reports-plugin.ts => opensearch-reports-plugin.ts} (76%) create mode 100644 dashboards-reports/server/clusters/notificationsPlugin.ts create mode 100644 dashboards-reports/server/config/config.ts create mode 100644 dashboards-reports/server/config/createConfig.ts create mode 100644 dashboards-reports/server/config/index.ts create mode 100644 dashboards-reports/server/config/schema.ts delete mode 100644 dashboards-reports/server/executor/createScheduledReport.ts delete mode 100644 dashboards-reports/server/executor/executor.ts delete mode 100644 dashboards-reports/server/routes/lib/deliverReport.ts create mode 100644 dashboards-reports/server/routes/notifications.ts create mode 100644 dashboards-reports/server/routes/utils/__tests__/demo_dashboard.html delete mode 100644 dashboards-reports/server/routes/utils/notification/deliveryContentHelper.ts delete mode 100644 dashboards-reports/server/routes/utils/notification/notification_content_template/logo.png create mode 100644 dashboards-reports/server/routes/utils/visual_report/footer_template.html create mode 100644 dashboards-reports/server/routes/utils/visual_report/header_template.html delete mode 100644 dashboards-reports/server/routes/utils/visual_report/report_template.html create mode 100644 dashboards-reports/server/routes/utils/visual_report/style.css delete mode 100644 dashboards-reports/server/utils/constants.ts create mode 100644 dashboards-reports/test/__mocks__/loggerMock.ts create mode 100644 dashboards-reports/translations/pl.json rename {dashboards-reports/docs => docs/dashboards-reports}/dev/OpenSearch-Dashboards-Reporting-Design-Proposal.md (98%) rename {dashboards-reports/docs => docs/dashboards-reports}/dev/img/SQL_query_report.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/dev/img/arch_1.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/dev/img/arch_2.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/dev/img/arch_3.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/dev/img/dashboard_reports.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/dev/img/data_model.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/dev/img/delivery.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/dev/img/matrix.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/dev/img/workflows.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/dev/resources/SQL_query_report.drawio (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/dev/resources/arch_1.drawio (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/dev/resources/arch_2.drawio (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/dev/resources/arch_3.drawio (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/dev/resources/dashboard_reports.drawio (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/dev/resources/data_model.drawio (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/dev/resources/delivery.drawio (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/dev/resources/workflows.drawio (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/OpenSearch-Dashboards-Reporting-UX-documentation.md (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/flows/0.0.1_key-user-flows.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/flows/0.0.1_key-user-flows@2x.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/flows/0.0.2_key-screens.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/flows/0.0.2_key-screens@2x.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/screens/0.1.01_dashboard-download.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/screens/0.1.01_dashboard-download@2x.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/screens/0.1.02_dashboard-share.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/screens/0.1.02_dashboard-share@2x.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/screens/0.1.03_dashboard-toasts.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/screens/0.1.03_dashboard-toasts@2x.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/screens/0.1.0_dashboard.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/screens/0.1.0_dashboard@2x.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/screens/0.2.0_reporting_empty-state.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/screens/0.2.0_reporting_empty-state@2x.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/screens/0.2.1_reporting.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/screens/0.2.1_reporting@2x.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/screens/0.3.0_report.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/screens/0.3.0_report@2x.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/screens/0.3.1_report_share.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/screens/0.3.1_report_share@2x.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/screens/0.4.0_report-definition.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/screens/0.4.0_report-definition@2x.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/screens/0.5.0_create-report-definition.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/screens/0.5.0_create-report-definition@2x.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/screens/0.6.0_edit-report-definition.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/screens/0.6.0_edit-report-definition@2x.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/supporting/0.1.04_modals_generating-downloading.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/supporting/0.1.04_modals_generating-downloading@2x.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/supporting/0.5.1_report-settings.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/supporting/0.5.1_report-settings@2x.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/supporting/0.5.2_report-trigger.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/supporting/0.5.2_report-trigger@2x.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/supporting/0.5.3_delivery-settings.png (100%) rename {dashboards-reports/docs => docs/dashboards-reports}/ux/img/supporting/0.5.3_delivery-settings@2x.png (100%) create mode 100644 docs/notifications/NotificationPluginIntegration.puml create mode 100644 docs/notifications/NotificationPluginInteraction.puml create mode 100644 release-notes/opensearch-dashboards-reports.release-notes-1.0.0.0.md create mode 100644 release-notes/opensearch-dashboards-reports.release-notes-1.0.1.0.md create mode 100644 release-notes/opensearch-dashboards-reports.release-notes-1.1.0.0.md create mode 100644 release-notes/opensearch-dashboards-reports.release-notes-1.2.0.0.md create mode 100644 release-notes/opensearch-dashboards-reports.release-notes-1.2.4.0.md create mode 100644 release-notes/opensearch-dashboards-reports.release-notes-1.3.0.0.md create mode 100644 release-notes/opensearch-dashboards-reports.release-notes-1.3.4.0.md create mode 100644 reports-scheduler/.classpath create mode 100644 reports-scheduler/.codecov.yml create mode 100644 reports-scheduler/.project delete mode 100644 reports-scheduler/gradle.properties delete mode 100644 reports-scheduler/src/main/kotlin/org/opensearch/reportsscheduler/action/PollReportInstanceAction.kt delete mode 100644 reports-scheduler/src/main/kotlin/org/opensearch/reportsscheduler/model/PollReportInstanceRequest.kt delete mode 100644 reports-scheduler/src/main/kotlin/org/opensearch/reportsscheduler/model/PollReportInstanceResponse.kt delete mode 100644 reports-scheduler/src/main/kotlin/org/opensearch/reportsscheduler/resthandler/ReportInstancePollRestHandler.kt delete mode 100644 reports-scheduler/src/main/kotlin/org/opensearch/reportsscheduler/settings/LegacyPluginSettings.kt rename {dashboards-reports/server/routes/utils/notification/notification_content_template => reports-scheduler/src/main/resources/notifications/template}/email_content_template.html (88%) create mode 100644 reports-scheduler/src/main/resources/notifications/template/logo.png create mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/integTest/IntegTestHelpers.kt rename reports-scheduler/src/test/kotlin/org/opensearch/{reportsscheduler => integTest}/PluginRestTestCase.kt (89%) create mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/integTest/ReportSchedularPluginTests.kt rename reports-scheduler/src/test/kotlin/org/opensearch/{reportsscheduler => integTest}/ReportsSchedulerPluginIT.kt (60%) create mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/integTest/bwc/ReportsSchedulerBackwardsCompatibilityIT.kt rename reports-scheduler/src/test/kotlin/org/opensearch/{reportsscheduler => integTest}/rest/InContextMenuReportGenerationIT.kt (93%) rename reports-scheduler/src/test/kotlin/org/opensearch/{reportsscheduler => integTest}/rest/OnDemandReportGenerationIT.kt (88%) rename reports-scheduler/src/test/kotlin/org/opensearch/{reportsscheduler => integTest}/rest/ReportDefinitionIT.kt (94%) rename reports-scheduler/src/test/kotlin/org/opensearch/{reportsscheduler => integTest}/rest/ReportInstanceIT.kt (95%) delete mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/reportsscheduler/ReportSchedularPluginTests.kt create mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/reportsscheduler/model/CreateReportDefinitionRequestTests.kt create mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/reportsscheduler/model/CreateReportDefinitionResponseTests.kt create mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/reportsscheduler/model/DeleteReportDefinitionRequestTests.kt create mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/reportsscheduler/model/DeleteReportDefinitionResponseTests.kt create mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/reportsscheduler/model/GetAllReportDefinitionsRequestTests.kt create mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/reportsscheduler/model/GetAllReportDefinitionsResponseTests.kt create mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/reportsscheduler/model/GetAllReportInstancesRequestTests.kt create mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/reportsscheduler/model/GetAllReportInstancesResponseTests.kt create mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/reportsscheduler/model/GetReportDefinitionRequestTests.kt create mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/reportsscheduler/model/GetReportDefinitionResponseTests.kt create mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/reportsscheduler/model/GetReportInstanceRequestTests.kt create mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/reportsscheduler/model/GetReportInstanceResponseTests.kt create mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/reportsscheduler/model/InContextReportCreateRequestTests.kt create mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/reportsscheduler/model/InContextReportCreateResponseTests.kt create mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/reportsscheduler/model/OnDemandReportCreateRequestTests.kt create mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/reportsscheduler/model/OnDemandReportCreateResponseTests.kt create mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/reportsscheduler/model/UpdateReportDefinitionRequestTests.kt create mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/reportsscheduler/model/UpdateReportDefinitionResponseTests.kt create mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/reportsscheduler/model/UpdateReportInstanceStatusRequestTests.kt create mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/reportsscheduler/model/UpdateReportInstanceStatusResponseTests.kt create mode 100644 reports-scheduler/src/test/kotlin/org/opensearch/reportsscheduler/util/HelpersTests.kt create mode 100644 reports-scheduler/src/test/resources/bwc/job-scheduler/1.13.0.0/opendistro-job-scheduler-1.13.0.0.zip create mode 100644 reports-scheduler/src/test/resources/bwc/job-scheduler/1.3.4.0-SNAPSHOT/opensearch-job-scheduler-1.3.4.0-SNAPSHOT.zip create mode 100644 reports-scheduler/src/test/resources/bwc/reports-scheduler/1.13.0.0/opendistro-reports-scheduler-1.13.0.0.zip delete mode 100644 reports-scheduler/src/test/resources/job-scheduler/opensearch-job-scheduler-1.0.0.0-rc1.zip create mode 100644 reports-scheduler/src/test/resources/job-scheduler/opensearch-job-scheduler-1.3.4.0-SNAPSHOT.zip diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..685b0bec --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,2 @@ +# This should match the owning team set up in https://github.com/orgs/opensearch-project/teams +* @opensearch-project/dashboards-reports \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_template.md b/.github/ISSUE_TEMPLATE/bug_template.md index 8af6ebb5..183ab2c4 100644 --- a/.github/ISSUE_TEMPLATE/bug_template.md +++ b/.github/ISSUE_TEMPLATE/bug_template.md @@ -2,7 +2,7 @@ name: 🐛 Bug report about: Create a report to help us improve title: "[BUG]" -labels: 'bug, untriaged, Beta' +labels: 'bug, untriaged' assignees: '' --- diff --git a/.github/draft-release-notes-config.yml b/.github/draft-release-notes-config.yml new file mode 100644 index 00000000..24a9d6e8 --- /dev/null +++ b/.github/draft-release-notes-config.yml @@ -0,0 +1,45 @@ +# The overall template of the release notes +template: | + Compatible with OpenSearch and OpenSearch Dashboards Version $RESOLVED_VERSION + $CHANGES + +# Setting the formatting and sorting for the release notes body +name-template: Version $RESOLVED_VERSION +change-template: "* $TITLE ([#$NUMBER](https://github.com/opensearch-project/dashboards-reports/pull/$NUMBER))" +sort-by: merged_at +sort-direction: ascending +replacers: + - search: '##' + replace: '###' + +# Organizing the tagged PRs into unified categories +categories: + - title: 'Breaking Changes' + labels: + - 'Breaking Changes' + - title: 'Features' + labels: + - 'feature' + - title: 'Enhancements' + labels: + - 'enhancement' + - title: 'Bug Fixes' + labels: + - 'bug' + - title: 'Infrastructure' + labels: + - 'infra' + - 'test' + - 'dependencies' + - 'github actions' + - title: 'Documentation' + labels: + - 'documentation' + - title: 'Maintenance' + labels: + - "version compatibility" + - "maintenance" + - title: 'Refactoring' + labels: + - 'refactor' + - 'code quality' diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml new file mode 100644 index 00000000..e47d8d88 --- /dev/null +++ b/.github/workflows/backport.yml @@ -0,0 +1,28 @@ +name: Backport +on: + pull_request_target: + types: + - closed + - labeled + +jobs: + backport: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + name: Backport + steps: + - name: GitHub App token + id: github_app_token + uses: tibdex/github-app-token@v1.5.0 + with: + app_id: ${{ secrets.APP_ID }} + private_key: ${{ secrets.APP_PRIVATE_KEY }} + installation_id: 22958780 + + - name: Backport + uses: VachaShah/backport@v1.1.4 + with: + github_token: ${{ steps.github_app_token.outputs.token }} + branch_name: backport/backport-${{ github.event.number }} diff --git a/.github/workflows/dashboards-reports-release-workflow.yml b/.github/workflows/dashboards-reports-release-workflow.yml index 131aac0d..bceefb9d 100644 --- a/.github/workflows/dashboards-reports-release-workflow.yml +++ b/.github/workflows/dashboards-reports-release-workflow.yml @@ -7,8 +7,9 @@ on: env: PLUGIN_NAME: reportsDashboards + ARTIFACT_NAME: reports-dashboards OPENSEARCH_VERSION: '1.0' - OPENSEARCH_PLUGIN_VERSION: 1.0.0.0-rc1 + OPENSEARCH_PLUGIN_VERSION: 1.0.0.0 jobs: build: @@ -35,7 +36,7 @@ jobs: - name: Setup Node uses: actions/setup-node@v1 with: - node-version: "10.23.1" + node-version: "10.24.1" - name: Move Dashboards Reports to Plugins Dir run: mv dashboards-reports OpenSearch-Dashboards/plugins/${{ env.PLUGIN_NAME }} @@ -69,18 +70,18 @@ jobs: cd build mkdir -p ./{linux-x64,linux-arm64,windows-x64}/OpenSearch-Dashboards/${{ env.PLUGIN_NAME }} - cp ./${{ env.PLUGIN_NAME }}-*.zip ./linux-x64/${{ env.PLUGIN_NAME }}-${{ env.OPENSEARCH_PLUGIN_VERSION }}-linux-x64.zip - cp ./${{ env.PLUGIN_NAME }}-*.zip ./linux-arm64/${{ env.PLUGIN_NAME }}-${{ env.OPENSEARCH_PLUGIN_VERSION }}-linux-arm64.zip - mv ./${{ env.PLUGIN_NAME }}-*.zip ./windows-x64/${{ env.PLUGIN_NAME }}-${{ env.OPENSEARCH_PLUGIN_VERSION }}-windows-x64.zip + cp ./${{ env.PLUGIN_NAME }}-*.zip ./linux-x64/${{ env.ARTIFACT_NAME }}-${{ env.OPENSEARCH_PLUGIN_VERSION }}-linux-x64.zip + cp ./${{ env.PLUGIN_NAME }}-*.zip ./linux-arm64/${{ env.ARTIFACT_NAME }}-${{ env.OPENSEARCH_PLUGIN_VERSION }}-linux-arm64.zip + mv ./${{ env.PLUGIN_NAME }}-*.zip ./windows-x64/${{ env.ARTIFACT_NAME }}-${{ env.OPENSEARCH_PLUGIN_VERSION }}-windows-x64.zip s3_prefix="s3://staging.artifacts.opendistroforelasticsearch.amazon.com/snapshots/kibana-plugins/reports/" cd linux-x64 - wget https://github.com/opendistro-for-elasticsearch/kibana-reports/releases/download/chromium-1.12.0.0/chromium-linux-x64.zip + wget https://github.com/opensearch-project/dashboards-reports/releases/download/chromium-1.12.0.0/chromium-linux-x64.zip unzip chromium-linux-x64.zip -d ./OpenSearch-Dashboards/${{ env.PLUGIN_NAME }} rm chromium-linux-x64.zip - zip -ur ./${{ env.PLUGIN_NAME }}-*.zip ./OpenSearch-Dashboards - linux_x64_artifact=`ls ./${{ env.PLUGIN_NAME }}-${{ env.OPENSEARCH_PLUGIN_VERSION }}-linux-x64.zip` + zip -ur ./${{ env.ARTIFACT_NAME }}-*.zip ./OpenSearch-Dashboards + linux_x64_artifact=`ls ./${{ env.ARTIFACT_NAME }}-${{ env.OPENSEARCH_PLUGIN_VERSION }}-linux-x64.zip` #Inject build number before the suffix and upload to S3 linux_x64_artifact_outfile=`basename ${linux_x64_artifact%.zip}-build-${GITHUB_RUN_NUMBER}.zip` @@ -89,11 +90,11 @@ jobs: cd .. cd linux-arm64 - wget https://github.com/opendistro-for-elasticsearch/kibana-reports/releases/download/chromium-1.12.0.0/chromium-linux-arm64.zip + wget https://github.com/opensearch-project/dashboards-reports/releases/download/chromium-1.12.0.0/chromium-linux-arm64.zip unzip chromium-linux-arm64.zip -d ./OpenSearch-Dashboards/${{ env.PLUGIN_NAME }} rm chromium-linux-arm64.zip - zip -ur ./${{ env.PLUGIN_NAME }}-*.zip ./OpenSearch-Dashboards - linux_arm64_artifact=`ls ./${{ env.PLUGIN_NAME }}-${{ env.OPENSEARCH_PLUGIN_VERSION }}-linux-arm64.zip` + zip -ur ./${{ env.ARTIFACT_NAME }}-*.zip ./OpenSearch-Dashboards + linux_arm64_artifact=`ls ./${{ env.ARTIFACT_NAME }}-${{ env.OPENSEARCH_PLUGIN_VERSION }}-linux-arm64.zip` #Inject build number before the suffix and upload to S3 linux_arm64_artifact_outfile=`basename ${linux_arm64_artifact%.zip}-build-${GITHUB_RUN_NUMBER}.zip` @@ -102,11 +103,11 @@ jobs: cd .. cd windows-x64 - wget https://github.com/opendistro-for-elasticsearch/kibana-reports/releases/download/chromium-1.12.0.0/chromium-windows-x64.zip + wget https://github.com/opensearch-project/dashboards-reports/releases/download/chromium-1.12.0.0/chromium-windows-x64.zip unzip chromium-windows-x64.zip -d ./OpenSearch-Dashboards/${{ env.PLUGIN_NAME }} rm chromium-windows-x64.zip - zip -ur ./${{ env.PLUGIN_NAME }}-*.zip ./OpenSearch-Dashboards - windows_x64_artifact=`ls ./${{ env.PLUGIN_NAME }}-${{ env.OPENSEARCH_PLUGIN_VERSION }}-windows-x64.zip` + zip -ur ./${{ env.ARTIFACT_NAME }}-*.zip ./OpenSearch-Dashboards + windows_x64_artifact=`ls ./${{ env.ARTIFACT_NAME }}-${{ env.OPENSEARCH_PLUGIN_VERSION }}-windows-x64.zip` #Inject build number before the suffix and upload to S3 windows_x64_artifact_outfile=`basename ${windows_x64_artifact%.zip}-build-${GITHUB_RUN_NUMBER}.zip` diff --git a/.github/workflows/dashboards-reports-test-and-build-workflow.yml b/.github/workflows/dashboards-reports-test-and-build-workflow.yml index 1fc6eaa9..6fff6394 100644 --- a/.github/workflows/dashboards-reports-test-and-build-workflow.yml +++ b/.github/workflows/dashboards-reports-test-and-build-workflow.yml @@ -4,8 +4,9 @@ on: [pull_request, push] env: PLUGIN_NAME: reportsDashboards - OPENSEARCH_VERSION: '1.0' - OPENSEARCH_PLUGIN_VERSION: 1.0.0.0-rc1 + ARTIFACT_NAME: reports-dashboards + OPENSEARCH_VERSION: '1.3' + OPENSEARCH_PLUGIN_VERSION: 1.3.4.0 jobs: build: @@ -24,13 +25,14 @@ jobs: - name: Setup Node uses: actions/setup-node@v1 with: - node-version: "10.23.1" + node-version: "10.24.1" - name: Move Dashboards Reports to Plugins Dir run: mv dashboards-reports OpenSearch-Dashboards/plugins/${{ env.PLUGIN_NAME }} - name: Add Chromium Binary to Reporting for Testing run: | + sudo apt update sudo apt install -y libnss3-dev fonts-liberation libfontconfig1 cd OpenSearch-Dashboards/plugins/${{ env.PLUGIN_NAME }} wget https://github.com/opendistro-for-elasticsearch/kibana-reports/releases/download/chromium-1.12.0.0/chromium-linux-x64.zip @@ -49,7 +51,14 @@ jobs: with: timeout_minutes: 30 max_attempts: 3 - command: cd OpenSearch-Dashboards/plugins/${{ env.PLUGIN_NAME }}; yarn test + command: cd OpenSearch-Dashboards/plugins/${{ env.PLUGIN_NAME }}; yarn test --coverage + + - name: Upload coverage + uses: codecov/codecov-action@v1 + with: + flags: dashboards-reports + directory: OpenSearch-Dashboards/plugins/ + token: ${{ secrets.CODECOV_TOKEN }} - name: Build Artifact run: | @@ -58,45 +67,45 @@ jobs: cd build mkdir -p ./{linux-x64,linux-arm64,windows-x64}/opensearch-dashboards/${{ env.PLUGIN_NAME }} - cp ./${{ env.PLUGIN_NAME }}-*.zip ./linux-x64/${{ env.PLUGIN_NAME }}-${{ env.OPENSEARCH_PLUGIN_VERSION }}-linux-x64.zip - cp ./${{ env.PLUGIN_NAME }}-*.zip ./linux-arm64/${{ env.PLUGIN_NAME }}-${{ env.OPENSEARCH_PLUGIN_VERSION }}-linux-arm64.zip - mv ./${{ env.PLUGIN_NAME }}-*.zip ./windows-x64/${{ env.PLUGIN_NAME }}-${{ env.OPENSEARCH_PLUGIN_VERSION }}-windows-x64.zip + cp ./${{ env.PLUGIN_NAME }}-*.zip ./linux-x64/${{ env.ARTIFACT_NAME }}-${{ env.OPENSEARCH_PLUGIN_VERSION }}-linux-x64.zip + cp ./${{ env.PLUGIN_NAME }}-*.zip ./linux-arm64/${{ env.ARTIFACT_NAME }}-${{ env.OPENSEARCH_PLUGIN_VERSION }}-linux-arm64.zip + mv ./${{ env.PLUGIN_NAME }}-*.zip ./windows-x64/${{ env.ARTIFACT_NAME }}-${{ env.OPENSEARCH_PLUGIN_VERSION }}-windows-x64.zip cd linux-x64 - wget https://github.com/opendistro-for-elasticsearch/kibana-reports/releases/download/chromium-1.12.0.0/chromium-linux-x64.zip + wget https://github.com/opensearch-project/dashboards-reports/releases/download/chromium-1.12.0.0/chromium-linux-x64.zip unzip chromium-linux-x64.zip -d ./opensearch-dashboards/${{ env.PLUGIN_NAME }} - zip -ur ./${{ env.PLUGIN_NAME }}-*.zip ./opensearch-dashboards - mv ./${{ env.PLUGIN_NAME }}-*.zip .. + zip -ur ./${{ env.ARTIFACT_NAME }}-*.zip ./opensearch-dashboards + mv ./${{ env.ARTIFACT_NAME }}-*.zip .. cd .. cd linux-arm64 - wget https://github.com/opendistro-for-elasticsearch/kibana-reports/releases/download/chromium-1.12.0.0/chromium-linux-arm64.zip + wget https://github.com/opensearch-project/dashboards-reports/releases/download/chromium-1.12.0.0/chromium-linux-arm64.zip unzip chromium-linux-arm64.zip -d ./opensearch-dashboards/${{ env.PLUGIN_NAME }} - zip -ur ./${{ env.PLUGIN_NAME }}-*.zip ./opensearch-dashboards - mv ./${{ env.PLUGIN_NAME }}-*.zip .. + zip -ur ./${{ env.ARTIFACT_NAME }}-*.zip ./opensearch-dashboards + mv ./${{ env.ARTIFACT_NAME }}-*.zip .. cd .. cd windows-x64 - wget https://github.com/opendistro-for-elasticsearch/kibana-reports/releases/download/chromium-1.12.0.0/chromium-windows-x64.zip + wget https://github.com/opensearch-project/dashboards-reports/releases/download/chromium-1.12.0.0/chromium-windows-x64.zip unzip chromium-windows-x64.zip -d ./opensearch-dashboards/${{ env.PLUGIN_NAME }} - zip -ur ./${{ env.PLUGIN_NAME }}-*.zip ./opensearch-dashboards - mv ./${{ env.PLUGIN_NAME }}-*.zip .. + zip -ur ./${{ env.ARTIFACT_NAME }}-*.zip ./opensearch-dashboards + mv ./${{ env.ARTIFACT_NAME }}-*.zip .. cd .. - name: Upload Artifact For Linux x64 uses: actions/upload-artifact@v1 with: name: dashboards-reports-linux-x64 - path: OpenSearch-Dashboards/plugins/${{ env.PLUGIN_NAME }}/build/${{ env.PLUGIN_NAME }}-${{ env.OPENSEARCH_PLUGIN_VERSION }}-linux-x64.zip + path: OpenSearch-Dashboards/plugins/${{ env.PLUGIN_NAME }}/build/${{ env.ARTIFACT_NAME }}-${{ env.OPENSEARCH_PLUGIN_VERSION }}-linux-x64.zip - name: Upload Artifact For Linux arm64 uses: actions/upload-artifact@v1 with: name: dashboards-reports-linux-arm64 - path: OpenSearch-Dashboards/plugins/${{ env.PLUGIN_NAME }}/build/${{ env.PLUGIN_NAME }}-${{ env.OPENSEARCH_PLUGIN_VERSION }}-linux-arm64.zip + path: OpenSearch-Dashboards/plugins/${{ env.PLUGIN_NAME }}/build/${{ env.ARTIFACT_NAME }}-${{ env.OPENSEARCH_PLUGIN_VERSION }}-linux-arm64.zip - name: Upload Artifact For Windows uses: actions/upload-artifact@v1 with: name: dashboards-reports-windows-x64 - path: OpenSearch-Dashboards/plugins/${{ env.PLUGIN_NAME }}/build/${{ env.PLUGIN_NAME }}-${{ env.OPENSEARCH_PLUGIN_VERSION }}-windows-x64.zip + path: OpenSearch-Dashboards/plugins/${{ env.PLUGIN_NAME }}/build/${{ env.ARTIFACT_NAME }}-${{ env.OPENSEARCH_PLUGIN_VERSION }}-windows-x64.zip diff --git a/.github/workflows/dco.yml b/.github/workflows/dco.yml new file mode 100644 index 00000000..cf30ea89 --- /dev/null +++ b/.github/workflows/dco.yml @@ -0,0 +1,18 @@ +name: Developer Certificate of Origin Check + +on: [pull_request] + +jobs: + check: + runs-on: ubuntu-latest + + steps: + - name: Get PR Commits + id: 'get-pr-commits' + uses: tim-actions/get-pr-commits@v1.1.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: DCO Check + uses: tim-actions/dco@v1.1.0 + with: + commits: ${{ steps.get-pr-commits.outputs.commits }} diff --git a/.github/workflows/delete_backport_branch.yml b/.github/workflows/delete_backport_branch.yml new file mode 100644 index 00000000..387a124b --- /dev/null +++ b/.github/workflows/delete_backport_branch.yml @@ -0,0 +1,15 @@ +name: Delete merged branch of the backport PRs +on: + pull_request: + types: + - closed + +jobs: + delete-branch: + runs-on: ubuntu-latest + if: startsWith(github.event.pull_request.head.ref,'backport/') + steps: + - name: Delete merged branch + uses: SvanBoxel/delete-merged-branch@main + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/draft-release-notes-workflow.yml b/.github/workflows/draft-release-notes-workflow.yml new file mode 100644 index 00000000..23ff3682 --- /dev/null +++ b/.github/workflows/draft-release-notes-workflow.yml @@ -0,0 +1,21 @@ +name: Release Drafter + +on: + push: + branches: + - main + +jobs: + update_release_draft: + name: Update draft release notes + runs-on: ubuntu-latest + steps: + # Drafts your next Release notes as Pull Requests are merged into "main" + - name: Update draft release notes + uses: release-drafter/release-drafter@v5 + with: + config-name: draft-release-notes-config.yml + tag: (None) + version: 1.3.4.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/link-checker.yml b/.github/workflows/link-checker.yml new file mode 100644 index 00000000..b50f79bf --- /dev/null +++ b/.github/workflows/link-checker.yml @@ -0,0 +1,23 @@ +name: Link Checker +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + linkchecker: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: lychee Link Checker + id: lychee + uses: lycheeverse/lychee-action@master + with: + args: --accept=200,403,429 "./**/*.md" "./**/*.txt" --exclude "https://centos.pkgs.org/7/*" + env: + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} + - name: Fail if there were link errors + run: exit ${{ steps.lychee.outputs.exit_code }} diff --git a/.github/workflows/reports-scheduler-test-and-build-workflow.yml b/.github/workflows/reports-scheduler-test-and-build-workflow.yml index 28b088f5..d8a7f862 100644 --- a/.github/workflows/reports-scheduler-test-and-build-workflow.yml +++ b/.github/workflows/reports-scheduler-test-and-build-workflow.yml @@ -2,57 +2,47 @@ name: Test and Build Reports Scheduler on: [push, pull_request] +env: + OPENSEARCH_VERSION: '1.3.4-SNAPSHOT' + jobs: build: + strategy: + matrix: + java: + - 8 + - 11 + - 14 runs-on: ubuntu-latest steps: - - name: Set up JDK 1.14 + - name: Set up JDK ${{ matrix.java }} uses: actions/setup-java@v1 with: - java-version: 1.14 - - # dependencies: OpenSearch - - name: Checkout OpenSearch - uses: actions/checkout@v2 - with: - repository: 'opensearch-project/OpenSearch' - path: OpenSearch - ref: '1.0' - - name: Build OpenSearch - working-directory: ./OpenSearch - run: ./gradlew publishToMavenLocal -Dbuild.version_qualifier=rc1 -Dbuild.snapshot=false - - # dependencies: common-utils - - name: Checkout common-utils - uses: actions/checkout@v2 - with: - repository: 'opensearch-project/common-utils' - ref: 'main' - path: common-utils - - name: Build common-utils - working-directory: ./common-utils - run: ./gradlew publishToMavenLocal -Dopensearch.version=1.0.0-rc1 - - # dependencies: job-scheduler - - name: Checkout job-scheduler - uses: actions/checkout@v2 - with: - repository: 'opensearch-project/job-scheduler' - ref: 'main' - path: job-scheduler - - name: Build job-scheduler - working-directory: ./job-scheduler - run: ./gradlew publishToMavenLocal -Dopensearch.version=1.0.0-rc1 -Dbuild.snapshot=false + java-version: ${{ matrix.java }} # reports-scheduler - name: Checkout Reports Scheduler uses: actions/checkout@v2 + - name: RunBackwards Compatibility Tests + run: | + cd reports-scheduler + echo "Running backwards compatibility tests ..." + ./gradlew bwcTestSuite + + - name: Build with Gradle run: | cd reports-scheduler - ./gradlew build -Dopensearch.version=1.0.0-rc1 + ./gradlew build -Dopensearch.version=${{ env.OPENSEARCH_VERSION }} + + - name: Upload coverage + uses: codecov/codecov-action@v1 + with: + flags: reports-scheduler + directory: reports-scheduler/ + token: ${{ secrets.CODECOV_TOKEN }} - name: Create Artifact Path run: | @@ -64,3 +54,4 @@ jobs: with: name: reports-scheduler path: reports-scheduler-builds + diff --git a/.whitesource b/.whitesource new file mode 100644 index 00000000..84ec8caa --- /dev/null +++ b/.whitesource @@ -0,0 +1,20 @@ +{ + "scanSettings": { + "configMode": "AUTO", + "configExternalURL": "", + "projectToken": "", + "baseBranches": [] + }, + "checkRunSettings": { + "vulnerableCheckRunConclusionLevel": "failure", + "displayMode": "diff" + }, + "issueSettings": { + "minSeverityLevel": "LOW" + }, + "remediateSettings": { + "workflowRules": { + "enabled": true + } + } +} \ No newline at end of file diff --git a/ADMINS.md b/ADMINS.md new file mode 100644 index 00000000..bcdc8f2a --- /dev/null +++ b/ADMINS.md @@ -0,0 +1,7 @@ +## Admins + +| Admin | GitHub ID | Affiliation | +| --------------- | --------------------------------------- | ----------- | +| Henri Yandell | [hyandell](https://github.com/hyandell) | Amazon | + +[This document](https://github.com/opensearch-project/.github/blob/main/ADMINS.md) explains what admins do in this repo, and how they should be doing it. If you're interested in becoming a maintainer, see [MAINTAINERS](MAINTAINERS.md). If you're interested in contributing, see [CONTRIBUTING](CONTRIBUTING.md). diff --git a/MAINTAINERS.md b/MAINTAINERS.md index 30d38c01..fe4d6207 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -1,5 +1,3 @@ -# Dashboards Reports Maintainers - ## Maintainers | Maintainer | GitHub ID | Affiliation | |------------------------|---------------------------------------------------|-------------| @@ -7,3 +5,5 @@ | David Cui | [davidcui-amzn](https://github.com/davidcui-amzn) | Amazon | | Joshua Li | [joshuali925](https://github.com/joshuali925) | Amazon | | Zhongnan Su | [zhongnansu](https://github.com/zhongnansu) | Amazon | + +[This document](https://github.com/opensearch-project/.github/blob/main/MAINTAINERS.md) explains what maintainers do in this repo, and how they should be doing it. If you're interested in contributing, see [CONTRIBUTING](CONTRIBUTING.md). diff --git a/NOTICE b/NOTICE deleted file mode 100644 index be83767d..00000000 --- a/NOTICE +++ /dev/null @@ -1,12 +0,0 @@ -OpenSearch -Copyright 2021 OpenSearch Contributors - -This product includes software developed by -Elasticsearch (http://www.elastic.co). -Copyright 2009-2018 Elasticsearch - -This product includes software developed by The Apache Software -Foundation (http://www.apache.org/). - -This product includes software developed by -Joda.org (http://www.joda.org/). diff --git a/NOTICE.txt b/NOTICE.txt new file mode 100644 index 00000000..731cb600 --- /dev/null +++ b/NOTICE.txt @@ -0,0 +1,2 @@ +OpenSearch (https://opensearch.org/) +Copyright OpenSearch Contributors diff --git a/README.md b/README.md index 965e86ae..9c1cca06 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,114 @@ -[![OpenSearch Dashboards Reports CI](https://github.com/opensearch-project/dashboards-reports/workflows/Test%20and%20Build%20OpenSearch%20Dashboards%20Reports/badge.svg)](https://github.com/opensearch-project/dashboards-reports/actions?query=workflow%3A%22Test+and+Build+OpenSearch+Dashboards+Reports%22) -[![Reports Scheduler CI](https://github.com/opensearch-project/dashboards-reports/workflows/Test%20and%20Build%20Reports%20Scheduler/badge.svg)](https://github.com/opensearch-project/dashboards-reports/actions?query=workflow%3A%22Test+and+Build+Reports+Scheduler%22) -[![codecov](https://codecov.io/gh/opensearch-project/dashboards-reports/branch/dev/graph/badge.svg?token=FBVYQSZD3B)](https://codecov.io/gh/opensearch-project/dashboards-reports) -[![Documentation](https://img.shields.io/badge/documentation-blue.svg)](https://docs-beta.opensearch.org/docs/opensearch-dashboards/reporting/) -![PRs welcome!](https://img.shields.io/badge/PRs-welcome!-success) + + +- [OpenSearch Dashboards Reports](#opensearch-dashboards-reports) +- [Code Summary](#code-summary) +- [Documentation](#documentation) +- [Contributing](#contributing) +- [Setup](#setup-&-build) +- [Notifications Integration](#notifications-integration) +- [Troubleshooting](#troubleshooting) +- [Code of Conduct](#code-of-conduct) +- [Security](#security) +- [License](#license) +- [Copyright](#copyright) # OpenSearch Dashboards Reports -OpenSearch Dashboards Reports allows ‘Report Owner’ (engineers, including but not limited to developers, DevOps, IT Engineer, and IT admin) export and share reports from OpenSearch Dashboards dashboards, saved search, alerts and visualizations. It helps automate the process of scheduling reports on an on-demand or a periodical basis (on cron schedules as well). Further, it also automates the process of exporting and sharing reports triggered for various alerts. The feature is present in the Dashboard, Discover, and Visualization tabs. Scheduled reports can be sent to (shared with) self or various stakeholders within the organization such as, including but not limited to, executives, managers, engineers (developers, DevOps, IT Engineer) in the form of pdf, hyperlinks, csv, excel via various channels such as email, slack, Amazon Chime. However, in order to export, schedule and share reports, report owners should have the necessary permissions as defined under Roles and Privileges. +OpenSearch Dashboards Reports allows ‘Report Owner’ (engineers, including but not limited to developers, DevOps, IT Engineer, and IT admin) export and share reports from OpenSearch Dashboards dashboards, saved search, alerts and visualizations. It helps automate the process of scheduling reports on an on-demand or a periodical basis (on cron schedules as well). Further, it also automates the process of exporting and sharing reports triggered for various alerts. The feature is present in the Dashboard, Discover, and Visualization tabs. We are currently working on integrating Dashboards Reports with Notifications to enable sharing functionality. After the support is introduced, scheduled reports can be sent to (shared with) self or various stakeholders within the organization. These stakeholders include but are not limited to, executives, managers, engineers (developers, DevOps, IT Engineer) in the form of pdf, hyperlinks, csv, excel via various channels such as email, Slack, and Amazon Chime. However, in order to export, schedule and share reports, report owners should have the necessary permissions as defined under Roles and Privileges. + +## Code Summary + +### Reports-Scheduler + +| | | +| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Test and build | [![Observability OpenSearch Build CI][reports-scheduler-build-badge]][reports-scheduler-build-link] | +| Code coverage | [![codecov][reports-scheduler-codecov-badge]][codecov-link] | +| Distribution build tests | [![OpenSearch IT tests][reports-scheduler-it-badge]][reports-scheduler-it-link] [![OpenSearch IT code][reports-scheduler-it-code-badge]][reports-scheduler-it-code-link] | +| Backward compatibility tests | [![BWC tests][bwc-tests-badge]][bwc-tests-link] | + +### Dashboard-Reports + +| | | +| ------------------------ | ------------------------------------------------------------------------------------------------------------------ | +| Test and build | [![Observability Dashboards CI][dashboard-reports-build-badge]][dashboard-reports-build-link] | +| Code coverage | [![codecov][dashboard-reports-codecov-badge]][codecov-link] | +| Distribution build tests | [![cypress tests][cypress-test-badge]][cypress-test-link] [![cypress code][cypress-code-badge]][cypress-code-link] | + +### Repository Checks + +| | | +| ------------ | --------------------------------------------------------------- | +| DCO Checker | [![Developer certificate of origin][dco-badge]][dco-badge-link] | +| Link Checker | [![Link Checker][link-check-badge]][link-check-link] | + +### Issues + +| | +| -------------------------------------------------------------- | +| [![good first issues open][good-first-badge]][good-first-link] | +| [![features open][feature-badge]][feature-link] | +| [![enhancements open][enhancement-badge]][enhancement-link] | +| [![bugs open][bug-badge]][bug-link] | +| [![untriaged open][untriaged-badge]][untriaged-link] | +| [![nolabel open][nolabel-badge]][nolabel-link] | + +[dco-badge]: https://github.com/opensearch-project/dashboards-reports/actions/workflows/dco.yml/badge.svg +[dco-badge-link]: https://github.com/opensearch-project/dashboards-reports/actions/workflows/dco.yml +[link-check-badge]: https://github.com/opensearch-project/dashboards-reports/actions/workflows/link-checker.yml/badge.svg +[link-check-link]: https://github.com/opensearch-project/dashboards-reports/actions/workflows/link-checker.yml +[dashboard-reports-build-badge]: https://github.com/opensearch-project/dashboards-reports/actions/workflows/dashboards-reports-test-and-build-workflow.yml/badge.svg +[dashboard-reports-build-link]: https://github.com/opensearch-project/dashboards-reports/actions/workflows/dashboards-reports-test-and-build-workflow.yml +[reports-scheduler-build-badge]: https://github.com/opensearch-project/dashboards-reports/actions/workflows/reports-scheduler-test-and-build-workflow.yml/badge.svg +[reports-scheduler-build-link]: https://github.com/opensearch-project/dashboards-reports/actions/workflows/reports-scheduler-test-and-build-workflow.yml +[dashboard-reports-codecov-badge]: https://codecov.io/gh/opensearch-project/dashboards-reports/branch/main/graphs/badge.svg?flag=dashboards-reports +[reports-scheduler-codecov-badge]: https://codecov.io/gh/opensearch-project/dashboards-reports/branch/main/graphs/badge.svg?flag=reports-scheduler +[codecov-link]: https://codecov.io/gh/opensearch-project/dashboards-reports +[cypress-test-badge]: https://img.shields.io/badge/Cypress%20tests-in%20progress-yellow +[cypress-test-link]: https://github.com/opensearch-project/opensearch-build/issues/1124 +[cypress-code-badge]: https://img.shields.io/badge/Cypress%20code-blue +[cypress-code-link]: https://github.com/opensearch-project/dashboards-reports/tree/main/dashboards-reports/.cypress/integration +[reports-scheduler-it-badge]: https://img.shields.io/badge/Reports%20Scheduler%20IT%20tests-in%20progress-yellow +[reports-scheduler-it-link]: https://github.com/opensearch-project/opensearch-build/issues/1124 +[reports-scheduler-it-code-badge]: https://img.shields.io/badge/Reports%20Scheduler%20code-blue +[reports-scheduler-it-code-link]: https://github.com/opensearch-project/dashboards-reports/blob/main/reports-scheduler/src/test/kotlin/org/opensearch/reportsscheduler/ReportsSchedulerPluginIT.kt +[bwc-tests-badge]: https://img.shields.io/badge/BWC%20tests-in%20progress-yellow +[bwc-tests-link]: https://github.com/opensearch-project/dashboards-reports/pull/244/files +[good-first-badge]: https://img.shields.io/github/issues/opensearch-project/dashboards-reports/good%20first%20issue.svg +[good-first-link]: https://github.com/opensearch-project/dashboards-reports/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22+ +[feature-badge]: https://img.shields.io/github/issues/opensearch-project/dashboards-reports/feature%20request.svg +[feature-link]: https://github.com/opensearch-project/dashboards-reports/issues?q=is%3Aopen+is%3Aissue+label%3A%22feature+request%22+ +[bug-badge]: https://img.shields.io/github/issues/opensearch-project/dashboards-reports/bug.svg +[bug-link]: https://github.com/opensearch-project/dashboards-reports/issues?q=is%3Aopen+is%3Aissue+label%3Abug+ +[enhancement-badge]: https://img.shields.io/github/issues/opensearch-project/dashboards-reports/enhancement.svg +[enhancement-link]: https://github.com/opensearch-project/dashboards-reports/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement+ +[untriaged-badge]: https://img.shields.io/github/issues/opensearch-project/dashboards-reports/untriaged.svg +[untriaged-link]: https://github.com/opensearch-project/dashboards-reports/issues?q=is%3Aopen+is%3Aissue+label%3Auntriaged+ +[nolabel-badge]: https://img.shields.io/github/issues-search/opensearch-project/dashboards-reports?color=yellow&label=no%20label%20issues&query=is%3Aopen%20is%3Aissue%20no%3Alabel +[nolabel-link]: https://github.com/opensearch-project/dashboards-reports/issues?q=is%3Aopen+is%3Aissue+no%3Alabel+ + +## Documentation + +Please see our technical [documentation](https://opensearch.org/docs/dashboards/reporting/) to learn more about its features. + +## Contributing -# Request for Comments ( RFC ) - -Please add your feature requests here [ New Requests ](https://github.com/opensearch-project/dashboards-reports/issues) and view project progress here [RFCs](https://github.com/opensearch-project/dashboards-reports/projects/1). +We welcome you to get involved in development, documentation, testing the OpenSearch Dashboards reports plugin. See our [CONTRIBUTING.md](./CONTRIBUTING.md) and join in. ## Setup & Build -Complete OpenSearch Dashboards Report feature is composed of 2 plugins. Refer to README in each plugin folder for more details. +Complete OpenSearch Dashboards Report feature is composed of 2 plugins. - [OpenSearch Dashboards reports plugin](./dashboards-reports/README.md) -- [Reports scheduler ES plugin](./reports-scheduler/README.md)(TODO) +- OpenSearch Reports scheduler plugin + +## Notifications Integration + +OpenSearch Dashboards Reports integration with [Notifications](https://github.com/opensearch-project/notifications) is currently in progress. Tracking [here](https://github.com/opensearch-project/dashboards-reports/issues/72) ## Troubleshooting -#### Fail to launch Chromium +### Fail to launch Chromium There could be two reasons for this problem @@ -29,22 +116,41 @@ There could be two reasons for this problem 2. Missing additional dependencies. Please refer to [additional dependencies section](./dashboards-reports/rendering-engine/headless-chrome/README.md#additional-libaries) to install required dependencies according to your operating system. -## Contributing to OpenSearch Dashboards reports +### Missing Font Dependencies -We welcome you to get involved in development, documentation, testing the OpenSearch Dashboards reports plugin. See our [CONTRIBUTING.md](./CONTRIBUTING.md) and join in. +Chromium may not have all of the dependencies you may require to be able to view all of the content of your reports. + +If you are using a CentOS/RHEL system, install the following packages: + +- [`ipa-gothic-fonts`](https://centos.pkgs.org/7/centos-x86_64/ipa-gothic-fonts-003.03-5.el7.noarch.rpm.html) +- [`xorg-x11-fonts-100dpi`](https://centos.pkgs.org/7/centos-x86_64/xorg-x11-fonts-100dpi-7.5-9.el7.noarch.rpm.html) +- [`xorg-x11-fonts-75dpi`](https://centos.pkgs.org/7/centos-x86_64/xorg-x11-fonts-75dpi-7.5-9.el7.noarch.rpm.html) +- [`xorg-x11-utils`](https://centos.pkgs.org/7/centos-x86_64/xorg-x11-utils-7.5-23.el7.x86_64.rpm.html) +- [`xorg-x11-fonts-cyrillic`](https://centos.pkgs.org/7/centos-x86_64/xorg-x11-fonts-cyrillic-7.5-9.el7.noarch.rpm.html) +- [`xorg-x11-fonts-Type1`](https://centos.pkgs.org/7/centos-x86_64/xorg-x11-fonts-Type1-7.5-9.el7.noarch.rpm.html) +- [`xorg-x11-fonts-misc`](https://centos.pkgs.org/7/centos-x86_64/xorg-x11-fonts-misc-7.5-9.el7.noarch.rpm.html) +- [`fontconfig`](https://www.freedesktop.org/wiki/Software/fontconfig/) +- [`freetype`](https://freetype.org/) + +If you are using a Ubuntu/Debian system, install the following packages: + +- [`fonts-liberation`](https://packages.debian.org/search?keywords=fonts-liberation) +- [`libfontconfig1`](https://packages.debian.org/sid/libfontconfig1) + +The installation command for both systems can be found [here](./dashboards-reports/rendering-engine/headless-chrome/README.md). ## Code of Conduct -This project has adopted an [Open Source Code of Conduct](https://opensearch.org/codeofconduct.html). +This project has adopted the [Amazon Open Source Code of Conduct](CODE_OF_CONDUCT.md). For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq), or contact [opensource-codeofconduct@amazon.com](mailto:opensource-codeofconduct@amazon.com) with any additional questions or comments. -## Security issue notifications +## Security If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public GitHub issue. ## License -See the [LICENSE](./LICENSE.txt) file for our project's licensing. We will ask you to confirm the licensing of your contribution. +See the [LICENSE](./LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. ## Copyright -Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. +Copyright OpenSearch Contributors. See [NOTICE](NOTICE.txt) for details. diff --git a/RELEASING.md b/RELEASING.md new file mode 100644 index 00000000..baf47475 --- /dev/null +++ b/RELEASING.md @@ -0,0 +1 @@ +This project follows [OpenSearch branching, labelling, and releasing](https://github.com/opensearch-project/.github/blob/main/RELEASING.md). \ No newline at end of file diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..0b85ca04 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,3 @@ +## Reporting a Vulnerability + +If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/) or directly via email to aws-security@amazon.com. Please do **not** create a public GitHub issue. \ No newline at end of file diff --git a/dashboards-reports/.babelrc b/dashboards-reports/.babelrc deleted file mode 100644 index e26ee76e..00000000 --- a/dashboards-reports/.babelrc +++ /dev/null @@ -1,18 +0,0 @@ -{ - "presets": [ - [ - "@babel/preset-env", - { - "targets": { "node": "10" } - } - ], - "@babel/preset-react", - "@babel/preset-typescript" - ], - "plugins": [ - "@babel/plugin-transform-modules-commonjs", - ["@babel/plugin-transform-runtime", { "regenerator": true }], - "@babel/plugin-proposal-class-properties", - "@babel/plugin-proposal-object-rest-spread" - ] -} diff --git a/dashboards-reports/.cypress/integration/01-create.spec.ts b/dashboards-reports/.cypress/integration/01-create.spec.ts index 10a706b7..d047aeff 100644 --- a/dashboards-reports/.cypress/integration/01-create.spec.ts +++ b/dashboards-reports/.cypress/integration/01-create.spec.ts @@ -1,89 +1,248 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ +import { visitReportingLandingPage } from "../support/utils"; + +describe('Adding sample data', () => { + it('Adds sample data', () => { + cy.visit(`${Cypress.env('opensearchDashboards')}/app/home#/tutorial_directory/sampleData`); + cy.get('div[data-test-subj="sampleDataSetCardflights"]').contains(/(Add|View) data/).click(); + cy.wait(3000); + cy.visit(`${Cypress.env('opensearchDashboards')}/app/home#/tutorial_directory/sampleData`); + cy.get('div[data-test-subj="sampleDataSetCardecommerce"]').contains(/(Add|View) data/).click(); + cy.wait(3000); + cy.visit(`${Cypress.env('opensearchDashboards')}/app/home#/tutorial_directory/sampleData`); + cy.get('div[data-test-subj="sampleDataSetCardlogs"]').contains(/(Add|View) data/).click(); + cy.wait(3000); + }); +}); describe('Cypress', () => { it('Visits Reporting homepage', () => { - cy.visit(`${Cypress.env('opensearchDashboards')}/app/reports-dashboards#/`); - cy.location('pathname', { timeout: 60000 }).should( - 'include', - '/reports-dashboards' - ); + visitReportingLandingPage(); }); it('Visit Create page', () => { - cy.visit(`${Cypress.env('opensearchDashboards')}/app/reports-dashboards#/`); - cy.location('pathname', { timeout: 60000 }).should( - 'include', - '/reports-dashboards' - ); - cy.wait(12500); // wait for the page to load - cy.get('#createReportHomepageButton').click({ force: true }); + visitCreateReportDefinitionPage(); + }); + + it('Create a new on-demand dashboard report definition', () => { + visitCreateReportDefinitionPage(); + setReportDefinitionName('Cypress dashboard on-demand report'); + setReportDefinitionDescription('Description for cypress test'); + selectReportSourceComboBox(); + + // // select drop-down option in report source list + cy.contains('[Logs] Web Traffic').click(); + + cy.wait(500); + clickCreateReportDefinitionButton(); + cy.wait(3000); + verifyOnReportingLandingPage(); }); - it('Create a new on-demand report definition', () => { - cy.visit(`${Cypress.env('opensearchDashboards')}/app/reports-dashboards#/`); - cy.location('pathname', { timeout: 60000 }).should( - 'include', - '/reports-dashboards' - ); - cy.wait(12500); - cy.get('#createReportHomepageButton').click(); + it('Create a new on-demand visualization report definition', ()=> { + visitCreateReportDefinitionPage(); + setReportDefinitionName('Cypress vis on-demand report'); + setReportDefinitionDescription('Description for cypress test'); + selectReportSource('#visualizationReportSource'); + selectReportSourceComboBox(); + cy.wait(500); + clickCreateReportDefinitionButton(); + cy.wait(3000); + verifyOnReportingLandingPage(); + }); - // enter a report name - cy.get('#reportSettingsName').type('Create cypress test on-demand report'); + it('Create a new on-demand saved search report definition', () => { + visitCreateReportDefinitionPage(); + setReportDefinitionName('Cypress saved search on-demand report'); + setReportDefinitionDescription('Description for cypress test'); + selectReportSource('#savedSearchReportSource'); + selectReportSourceComboBox(); + cy.wait(500); + clickCreateReportDefinitionButton(); + cy.wait(3000); + verifyOnReportingLandingPage(); + }); - // enter a report description - cy.get('#reportSettingsDescription').type('Description for cypress test'); + it('Create a new dashboard daily recurring report definition', () => { + visitCreateReportDefinitionPage(); + setReportDefinitionName('Cypress dashboard daily scheduled report'); + setReportDefinitionDescription('Description for cypress test'); + selectReportSourceComboBox(); - // select a report source - cy.get('.euiComboBox').click({ force: true }); + // select drop-down option in report source list + cy.contains('[Logs] Web Traffic').click(); - // create an on-demand report definition - cy.get('#createNewReportDefinition').click({ force: true }); + cy.wait(500); + setReportTriggerToSchedule(); + clickCreateReportDefinitionButton(); + cy.wait(3000); + verifyOnReportingLandingPage(); }); - it('Create a new scheduled report definition', () => { - cy.visit(`${Cypress.env('opensearchDashboards')}/app/reports-dashboards#/`); - cy.location('pathname', { timeout: 60000 }).should( - 'include', - '/reports-dashboards' - ); - cy.wait(12500); - cy.get('#createReportHomepageButton').click(); + it('Create a new visualization daily recurring report definition', () => { + visitCreateReportDefinitionPage(); + setReportDefinitionName('Cypress vis daily scheduled report'); + setReportDefinitionDescription('Description for cypress test'); + selectReportSource('#visualizationReportSource'); + selectReportSourceComboBox(); + cy.wait(500); + setReportTriggerToSchedule(); + clickCreateReportDefinitionButton(); + cy.wait(3000); + verifyOnReportingLandingPage(); + }); - // enter a report name - cy.get('#reportSettingsName').type('Create cypress test scheduled report'); + it('Create a new saved search daily recurring report definition', () => { + visitCreateReportDefinitionPage(); + setReportDefinitionName('Cypress search daily scheduled report'); + setReportDefinitionDescription('Description for cypress test'); + selectReportSource('#savedSearchReportSource'); + selectReportSourceComboBox(); + setReportTriggerToSchedule(); + clickCreateReportDefinitionButton(); + cy.wait(3000); + verifyOnReportingLandingPage(); + }); - // enter a report description - cy.get('#reportSettingsDescription').type('Description for cypress test'); + it('Create a new dashboard interval recurring report definition', () => { + visitCreateReportDefinitionPage(); + setReportDefinitionName('Cypress dashboard recurring report'); + setReportDefinitionDescription('Description for cypress test'); + selectReportSourceComboBox(); - // set report trigger to Schedule option - cy.get('[type="radio"]').check({ force: true }); + // select drop-down option in report source list + cy.contains('[Logs] Web Traffic').click(); - // create scheduled report definition - cy.get('#createNewReportDefinition').click({ force: true }); + cy.wait(500); + setReportTriggerToSchedule(); + selectIntervalScheduleFrequency(); + inputTextIntoField('#recurringByIntervalNumber', '5'); + clickCreateReportDefinitionButton(); + cy.wait(3000); + verifyOnReportingLandingPage(); + }); + + it('Create a new visualization interval recurring report definition', () => { + visitCreateReportDefinitionPage(); + setReportDefinitionName('Cypress vis interval recurring report'); + selectReportSource('#visualizationReportSource'); + selectReportSourceComboBox(); + setReportTriggerToSchedule(); + selectIntervalScheduleFrequency(); + inputTextIntoField('#recurringByIntervalNumber', '5'); + clickCreateReportDefinitionButton(); + cy.wait(3000); + verifyOnReportingLandingPage(); + }); + + it('Create a new saved search interval recurring report definition', () => { + visitCreateReportDefinitionPage(); + setReportDefinitionName('Cypress saved search interval recurring report'); + selectReportSource('#savedSearchReportSource'); + selectReportSourceComboBox(); + setReportTriggerToSchedule(); + selectIntervalScheduleFrequency(); + inputTextIntoField('#recurringByIntervalNumber', '5'); + clickCreateReportDefinitionButton(); + cy.wait(3000); + verifyOnReportingLandingPage(); + }); + + it('Create a dashboard cron-based report definition', () => { + visitCreateReportDefinitionPage(); + setReportDefinitionName('Cypress dashboard cron definition'); + selectReportSourceComboBox(); + + // select drop-down option in report source list + cy.contains('[Logs] Web Traffic').click(); + cy.wait(500); + setReportTriggerToSchedule(); + selectCronBasedRequestTime(); + inputTextIntoField('#cronExpressionFieldText', '0 12 * * *'); + clickCreateReportDefinitionButton(); + cy.wait(3000); + verifyOnReportingLandingPage(); + }); + + it('Create a visualization cron-based report definition', () => { + visitCreateReportDefinitionPage(); + setReportDefinitionName('Cypress vis cron definition'); + selectReportSource('#visualizationReportSource'); + selectReportSourceComboBox(); + setReportTriggerToSchedule(); + selectCronBasedRequestTime(); + inputTextIntoField('#cronExpressionFieldText', '0 12 * * *'); + cy.wait(500); + clickCreateReportDefinitionButton(); + cy.wait(3000); + verifyOnReportingLandingPage(); + }); + + it('Create a saved search cron-based report definition', () => { + visitCreateReportDefinitionPage(); + setReportDefinitionName('Cypress search cron definition'); + selectReportSource('#savedSearchReportSource'); + selectReportSourceComboBox(); + setReportTriggerToSchedule(); + selectCronBasedRequestTime(); + inputTextIntoField('#cronExpressionFieldText', '0 12 * * *'); + cy.wait(500); + clickCreateReportDefinitionButton(); + cy.wait(3000); + verifyOnReportingLandingPage(); }); }); + +function visitCreateReportDefinitionPage() { + cy.visit(`${Cypress.env('opensearchDashboards')}/app/reports-dashboards#/`); + cy.location('pathname', { timeout: 60000 }).should( + 'include', + '/reports-dashboards' + ); + cy.wait(3000); + cy.get('#createReportHomepageButton').click(); +} + +function setReportDefinitionName(name: string) { + cy.get('#reportSettingsName').type(name); +} + +function setReportDefinitionDescription(description: string) { + cy.get('#reportSettingsDescription').type(description); +} + +function selectReportSource(name: string) { + cy.get(name).click({force: true}); +} + +function selectReportSourceComboBox() { + cy.get('[data-test-subj="comboBoxInput"]').eq(0).click({ force: true }); +} + +function setReportTriggerToSchedule() { + cy.get('#Schedule').check({ force: true }); +} + +function selectIntervalScheduleFrequency() { + cy.get('#recurringFrequencySelect').select('By interval'); +} + +function selectCronBasedRequestTime() { + cy.contains('Cron based').click({ force: true }); +} + +function inputTextIntoField(selector: string, text: string) { + cy.get(selector).type(text); +} + +function clickCreateReportDefinitionButton() { + cy.get('#createNewReportDefinition').click({ force: true }); +} + +function verifyOnReportingLandingPage() { + cy.get('#reportDefinitionDetailsLink').should('exist'); +} \ No newline at end of file diff --git a/dashboards-reports/.cypress/integration/02-edit.spec.ts b/dashboards-reports/.cypress/integration/02-edit.spec.ts index be7a0220..a87e77d4 100644 --- a/dashboards-reports/.cypress/integration/02-edit.spec.ts +++ b/dashboards-reports/.cypress/integration/02-edit.spec.ts @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ describe('Cypress', () => { @@ -51,9 +30,14 @@ describe('Cypress', () => { cy.get('#reportSettingsDescription').type(' update description'); cy.get('#editReportDefinitionButton').click({ force: true }); + + cy.wait(12500); + + // check that re-direct to home page + cy.get('#reportDefinitionDetailsLink').should('exist'); }); - it('Visit edit page, change report source and trigger', () => { + it('Visit edit page, change report trigger', () => { cy.visit(`${Cypress.env('opensearchDashboards')}/app/reports-dashboards#/`); cy.location('pathname', { timeout: 60000 }).should( 'include', @@ -71,13 +55,18 @@ describe('Cypress', () => { cy.url().should('include', 'edit'); cy.wait(1000); - cy.get('#visualizationReportSource').check({ force: true }); + cy.get('#reportDefinitionTriggerTypes > div:nth-child(2)').click({ force: true }); cy.get('#Schedule').check({ force: true }); cy.get('#editReportDefinitionButton').click({ force: true }); + + cy.wait(12500); + + // check that re-direct to home page + cy.get('#reportDefinitionDetailsLink').should('exist'); }); - it('Visit edit page, change report source back', () => { + it('Visit edit page, change report trigger back', () => { cy.visit(`${Cypress.env('opensearchDashboards')}/app/reports-dashboards#/`); cy.location('pathname', { timeout: 60000 }).should( 'include', @@ -96,8 +85,13 @@ describe('Cypress', () => { cy.wait(1000); - cy.get('#dashboardReportSource').check({ force: true }); + cy.get('#reportDefinitionTriggerTypes > div:nth-child(1)').click({ force: true }); cy.get('#editReportDefinitionButton').click({ force: true }); + + cy.wait(12500); + + // check that re-direct to home page + cy.get('#reportDefinitionDetailsLink').should('exist'); }); }); diff --git a/dashboards-reports/.cypress/integration/03-details.spec.ts b/dashboards-reports/.cypress/integration/03-details.spec.ts index db3ce62f..166da435 100644 --- a/dashboards-reports/.cypress/integration/03-details.spec.ts +++ b/dashboards-reports/.cypress/integration/03-details.spec.ts @@ -1,68 +1,111 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ +import { visitReportingLandingPage } from "../support/utils"; describe('Cypress', () => { it('Visit report definition details page', () => { - cy.visit(`${Cypress.env('opensearchDashboards')}/app/reports-dashboards#/`); - cy.location('pathname', { timeout: 60000 }).should( - 'include', - '/reports-dashboards' - ); + visitReportingLandingPage(); + cy.wait(5000); + visitReportDefinitionDetailsPage(); + verifyReportDefinitionDetailsURL(); + verifyDeleteDefinitionButtonExists(); + verifyGenerateReportFromFileFormatExists(); + }); - cy.wait(12500); + it('Go to edit report definition from report definition details', () => { + visitReportingLandingPage(); + cy.wait(5000); + visitReportDefinitionDetailsPage(); + verifyEditDefinitionButtonExists(); + clickEditReportDefinitionButton(); + verifyEditReportDefinitionURL(); + }); - cy.get('#reportDefinitionDetailsLink').first().click(); + it('Verify report source URL on report definition details', () => { + visitReportingLandingPage(); + cy.wait(5000); + visitReportDefinitionDetailsPage(); + verifyReportDefinitionSourceURLExists(); + + }); - cy.url().should('include', 'report_definition_details'); + it('Delete report definition from details page', () => { + visitReportingLandingPage(); + cy.wait(5000); + visitReportDefinitionDetailsPage(); + verifyDeleteDefinitionButtonExists(); + deleteReportDefinition(); + verifyDeleteSuccess(); + }); - cy.get('#deleteReportDefinitionButton').should('exist'); + it('Visit report details page', () => { + visitReportingLandingPage(); + cy.wait(5000); + visitReportDetailsPage(); + verifyReportDetailsURL(); + }); - cy.get('#editReportDefinitionButton').should('exist'); + it('Verify report source URL on report details', () => { + visitReportingLandingPage(); + cy.wait(5000); + visitReportDetailsPage(); + verifyReportDetailsSourceURLExists(); + }); +}); - if (cy.get('body').contains('Schedule details')) { - cy.wait(1000); - cy.get('#changeStatusFromDetailsButton').click(); - } else { - cy.wait(1000); - cy.get('#generateReportFromDetailsButton').click(); - } +function visitReportDefinitionDetailsPage() { + cy.get('#reportDefinitionDetailsLink').first().click(); +} - cy.get('#deleteReportDefinitionButton').click(); - }); +function verifyReportDefinitionDetailsURL() { + cy.url().should('include', 'report_definition_details'); +} - it('Visit report details page', () => { - cy.visit(`${Cypress.env('opensearchDashboards')}/app/reports-dashboards#/`); - cy.location('pathname', { timeout: 60000 }).should( - 'include', - '/reports-dashboards' - ); +function verifyDeleteDefinitionButtonExists() { + cy.get('#deleteReportDefinitionButton').should('exist'); +} - cy.wait(12500); - cy.get('#reportDetailsLink').first().click(); +function verifyEditDefinitionButtonExists() { + cy.get('#editReportDefinitionButton').should('exist'); +} - cy.url().should('include', 'report_details'); - }); -}); +function clickEditReportDefinitionButton() { + cy.get('#editReportDefinitionButton').click({ force: true }); +} + +function verifyEditReportDefinitionURL() { + cy.url().should('include', 'edit'); +} + +function verifyReportDefinitionSourceURLExists() { + cy.get('#reportDefinitionSourceURL').should('exist'); +} + +function verifyReportDetailsSourceURLExists() { + cy.get('#reportDetailsSourceURL').should('exist'); +} + +function verifyGenerateReportFromFileFormatExists() { + cy.get('#generateReportFromDetailsFileFormat').should('exist'); +} + +function deleteReportDefinition() { + cy.get('#deleteReportDefinitionButton').click(); + cy.wait(500); + cy.get('button.euiButton:nth-child(2)').click({ force: true }); +} + +function verifyDeleteSuccess() { + cy.get('#deleteReportDefinitionSuccessToast').should('exist'); +} + +function visitReportDetailsPage() { + cy.get('#reportDetailsLink').first().click(); +} + +function verifyReportDetailsURL() { + cy.url().should('include', 'report_details'); +} diff --git a/dashboards-reports/.cypress/integration/04-download.spec.ts b/dashboards-reports/.cypress/integration/04-download.spec.ts index aa3e3e57..af7e6409 100644 --- a/dashboards-reports/.cypress/integration/04-download.spec.ts +++ b/dashboards-reports/.cypress/integration/04-download.spec.ts @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ describe('Cypress', () => { diff --git a/dashboards-reports/.cypress/plugins/index.js b/dashboards-reports/.cypress/plugins/index.js index 5097724e..8ac1f106 100644 --- a/dashboards-reports/.cypress/plugins/index.js +++ b/dashboards-reports/.cypress/plugins/index.js @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ /// diff --git a/dashboards-reports/.cypress/support/commands.js b/dashboards-reports/.cypress/support/commands.js index 34a32088..dab9071d 100644 --- a/dashboards-reports/.cypress/support/commands.js +++ b/dashboards-reports/.cypress/support/commands.js @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ const { ADMIN_AUTH } = require('./constants'); diff --git a/dashboards-reports/.cypress/support/constants.js b/dashboards-reports/.cypress/support/constants.js index f033ff8e..1001fd49 100644 --- a/dashboards-reports/.cypress/support/constants.js +++ b/dashboards-reports/.cypress/support/constants.js @@ -1,30 +1,9 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ export const ADMIN_AUTH = { username: 'admin', password: 'admin', -}; \ No newline at end of file +}; diff --git a/dashboards-reports/.cypress/support/index.js b/dashboards-reports/.cypress/support/index.js index 9a72b427..c70c2dd5 100644 --- a/dashboards-reports/.cypress/support/index.js +++ b/dashboards-reports/.cypress/support/index.js @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ // *********************************************************** diff --git a/dashboards-reports/.cypress/support/utils.js b/dashboards-reports/.cypress/support/utils.js new file mode 100644 index 00000000..a534be13 --- /dev/null +++ b/dashboards-reports/.cypress/support/utils.js @@ -0,0 +1,12 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export function visitReportingLandingPage() { + cy.visit(`${Cypress.env('opensearchDashboards')}/app/reports-dashboards#/`); + cy.location('pathname', { timeout: 60000 }).should( + 'include', + '/reports-dashboards' + ); + } \ No newline at end of file diff --git a/dashboards-reports/.i18nrc.json b/dashboards-reports/.i18nrc.json new file mode 100644 index 00000000..f60aeca5 --- /dev/null +++ b/dashboards-reports/.i18nrc.json @@ -0,0 +1,7 @@ +{ + "paths": { + "opensearch.reports": "public" + }, + "exclude": [], + "translations": ["translations/zh-CN.json", "translations/pl.json"] +} diff --git a/dashboards-reports/opensearch-dashboards-plugin-helpers.dev.json b/dashboards-reports/.opensearch_dashboards-plugin-helpers.json similarity index 67% rename from dashboards-reports/opensearch-dashboards-plugin-helpers.dev.json rename to dashboards-reports/.opensearch_dashboards-plugin-helpers.json index b8a3f352..05b7d7e4 100644 --- a/dashboards-reports/opensearch-dashboards-plugin-helpers.dev.json +++ b/dashboards-reports/.opensearch_dashboards-plugin-helpers.json @@ -3,8 +3,10 @@ "package.json", "tsconfig.json", "yarn.lock", + ".i18nrc.json", "common/**/*", "public/**/*", - "server/**/*" + "server/**/*", + "translations/**/*" ] } diff --git a/dashboards-reports/DEVELOPER_GUIDE.md b/dashboards-reports/DEVELOPER_GUIDE.md new file mode 100644 index 00000000..39e2ffbc --- /dev/null +++ b/dashboards-reports/DEVELOPER_GUIDE.md @@ -0,0 +1,67 @@ +## Developer Guide + +So you want to contribute code to this project? Excellent! We're glad you're here. Here's what you need to do. + +## Install Prerequisites + +### JDK 11 + +OpenSearch builds using Java 11 at a minimum. This means you must have a JDK 11 +installed with the environment variable `JAVA_HOME` referencing the path to Java home +for your JDK 11 installation, e.g. `JAVA_HOME=/usr/lib/jvm/jdk-11`. + +By default, tests use the same runtime as `JAVA_HOME`. However, since OpenSearch +supports JDK 8, the build supports compiling with JDK 11 and testing on a different +version of JDK runtime. To do this, set `RUNTIME_JAVA_HOME` pointing to the Java home of +another JDK installation, e.g. `RUNTIME_JAVA_HOME=/usr/lib/jvm/jdk-8`. + +## Setup + +1. Download OpenSearch for the version that matches the [OpenSearch Dashboards version specified in package.json](./package.json#L7). +1. Download the OpenSearch Dashboards source code for the [version specified in package.json](./package.json#L7) you want to set up. + +1. Change your node version to the version specified in `.node-version` inside the OpenSearch Dashboards root directory. +1. Create a `plugins` directory inside the OpenSearch Dashboards source code directory, if `plugins` directory doesn't exist. +1. Check out this package from version control into the `plugins` directory. + ``` + git clone git@github.com:opensearch-project/dashboards-reports.git plugins --no-checkout + cd plugins + echo 'dashboards-reports/*' >> .git/info/sparse-checkout + git config core.sparseCheckout true + git checkout dev + ``` +1. Run `yarn osd bootstrap` inside `OpenSearch-Dashboards/plugins/dashboards-reports`. + +Ultimately, your directory structure should look like this: + + +```md +. +├── OpenSearch-Dashboards +│ └──plugins +│ └── dashboards-reports +``` + +## Build + +To build the plugin's distributable zip simply run `yarn build`. + +Example output: `./build/reports-dashboards-0.0.1.zip` + +## Run + +- `yarn start` + + Starts OpenSearch Dashboards and includes this plugin. OpenSearch Dashboards will be available on `localhost:5601`. + +- `yarn test:jest` + + Runs the plugin tests. + +### Backports + +The Github workflow in [`backport.yml`](../.github/workflows/backport.yml) creates backport PRs automatically when the original PR +with an appropriate label `backport ` is merged to main with the backport workflow run successfully on the +PR. For example, if a PR on main needs to be backported to `1.x` branch, add a label `backport 1.x` to the PR and make sure the +backport workflow runs on the PR along with other checks. Once this PR is merged to main, the workflow will create a backport PR +to the `1.x` branch. \ No newline at end of file diff --git a/dashboards-reports/README.md b/dashboards-reports/README.md index fcdec109..85204bf8 100644 --- a/dashboards-reports/README.md +++ b/dashboards-reports/README.md @@ -1,70 +1,23 @@ # OpenSearch Dashboards Reports -OpenSearch Dashboards Reports allows ‘Report Owner’ (engineers, including but not limited to developers, DevOps, IT Engineer, and IT admin) export and share reports from OpenSearch Dashboards dashboards, saved search, alerts and visualizations. It helps automate the process of scheduling reports on an on-demand or a periodical basis (on cron schedules as well). Further, it also automates the process of exporting and sharing reports triggered for various alerts. The feature is present in the Dashboard, Discover, and Visualization tabs. Scheduled reports can be sent to (shared with) self or various stakeholders within the organization such as, including but not limited to, executives, managers, engineers (developers, DevOps, IT Engineer) in the form of pdf, hyperlinks, csv, excel via various channels such as email, slack, Amazon Chime. However, in order to export, schedule and share reports, report owners should have the necessary permissions as defined under Roles and Privileges. +OpenSearch Dashboards Reports allows ‘Report Owner’ (engineers, including but not limited to developers, DevOps, IT Engineer, and IT admin) export and share reports from OpenSearch Dashboards dashboards, saved search, alerts and visualizations. It helps automate the process of scheduling reports on an on-demand or a periodical basis (on cron schedules as well). Further, it also automates the process of exporting and sharing reports triggered for various alerts. The feature is present in the Dashboard, Discover, and Visualization tabs. We are currently working on integrating Dashboards Reports with Notifications to enable sharing functionality. After the support is introduced, scheduled reports can be sent to (shared with) self or various stakeholders within the organization. These stakeholders include but are not limited to, executives, managers, engineers (developers, DevOps, IT Engineer) in the form of pdf, hyperlinks, csv, excel via various channels such as email, Slack, and Amazon Chime. However, in order to export, schedule and share reports, report owners should have the necessary permissions as defined under Roles and Privileges. -# Request for Comments ( RFC ) +## Contributing -Please add your feature requests here [ New Requests ](https://github.com/opensearch-project/dashboards-reports/issues) and view project progress here [RFCs](https://github.com/opensearch-project/dashboards-reports/projects/1). - -## Setup - -1. Download OpenSearch for the version that matches the [OpenSearch Dashboards version specified in package.json](./package.json#L7). -1. Download the OpenSearch Dashboards source code for the [version specified in package.json](./package.json#L7) you want to set up. - -1. Change your node version to the version specified in `.node-version` inside the OpenSearch Dashboards root directory. -1. Create a `plugins` directory inside the OpenSearch Dashboards source code directory, if `plugins` directory doesn't exist. -1. Check out this package from version control into the `plugins` directory. - ``` - git clone git@github.com:opensearch-project/dashboards-reports.git plugins --no-checkout - cd plugins - echo 'dashboards-reports/*' >> .git/info/sparse-checkout - git config core.sparseCheckout true - git checkout dev - ``` -1. Run `yarn osd bootstrap` inside `OpenSearch-Dashboards/plugins/dashboards-reports`. - -Ultimately, your directory structure should look like this: - - -```md -. -├── OpenSearch-Dashboards -│ └──plugins -│ └── dashboards-reports -``` - -## Build - -To build the plugin's distributable zip simply run `yarn build`. - -Example output: `./build/reports-dashboards-0.0.1.zip` - -## Run - -- `yarn start` - - Starts OpenSearch Dashboards and includes this plugin. OpenSearch Dashboards will be available on `localhost:5601`. - -- `yarn test:jest` - - Runs the plugin tests. - -## Contributing to OpenSearch Dashboards reports - -We welcome you to get involved in development, documentation, testing the OpenSearch Dashboards reports plugin. See our [CONTRIBUTING.md](./CONTRIBUTING.md) and join in. +See [developer guide](DEVELOPER_GUIDE.md) and [how to contribute to this project](../CONTRIBUTING.md). ## Code of Conduct -This project has adopted an [Open Source Code of Conduct](https://opensearch.org/codeofconduct.html). +This project has adopted the [Amazon Open Source Code of Conduct](../CODE_OF_CONDUCT.md). For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq), or contact [opensource-codeofconduct@amazon.com](mailto:opensource-codeofconduct@amazon.com) with any additional questions or comments. -## Security issue notifications +## Security If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public GitHub issue. ## License -See the [LICENSE](./LICENSE.txt) file for our project's licensing. We will ask you to confirm the licensing of your contribution. +See the [LICENSE](../LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. ## Copyright -Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. +Copyright 2020-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/dashboards-reports/babel.config.js b/dashboards-reports/babel.config.js new file mode 100644 index 00000000..aab76c8a --- /dev/null +++ b/dashboards-reports/babel.config.js @@ -0,0 +1,20 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +module.exports = { + presets: [ + require('@babel/preset-env', { + targets: { node: '10' }, + }), + require('@babel/preset-react'), + require('@babel/preset-typescript'), + ], + plugins: [ + require('@babel/plugin-proposal-class-properties'), + require('@babel/plugin-proposal-object-rest-spread'), + ['@babel/plugin-transform-modules-commonjs', { allowTopLevelThis: true }], + [require('@babel/plugin-transform-runtime'), { regenerator: true }], + ], +}; diff --git a/dashboards-reports/common/index.ts b/dashboards-reports/common/index.ts index 1066d948..ce180a09 100644 --- a/dashboards-reports/common/index.ts +++ b/dashboards-reports/common/index.ts @@ -1,38 +1,13 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -export const PLUGIN_ID = 'reportsDashboards'; -export const PLUGIN_NAME = 'reports-dashboards'; +export const PLUGIN_NAME = 'Reporting'; +export const PLUGIN_ID = 'reports-dashboards'; export const API_PREFIX = '/api/reporting'; -export const NOTIFICATION_API = { - SEND: '/_plugins/_notifications/send', -}; - const BASE_REPORTS_URI = '/_plugins/_reports'; export const OPENSEARCH_REPORTS_API = { @@ -41,5 +16,18 @@ export const OPENSEARCH_REPORTS_API = { LIST_REPORT_INSTANCES: `${BASE_REPORTS_URI}/instances`, REPORT_DEFINITION: `${BASE_REPORTS_URI}/definition`, LIST_REPORT_DEFINITIONS: `${BASE_REPORTS_URI}/definitions`, - POLL_REPORT_INSTANCE: `${BASE_REPORTS_URI}/poll_instance`, }; + +const REPORTING_NOTIFICATIONS_API_PREFIX = '/api/reporting_notifications'; +export const REPORTING_NOTIFICATIONS_DASHBOARDS_API = Object.freeze({ + GET_CONFIGS: `${REPORTING_NOTIFICATIONS_API_PREFIX}/get_configs`, + GET_EVENT: `${REPORTING_NOTIFICATIONS_API_PREFIX}/get_event`, + SEND_TEST_MESSAGE: `${REPORTING_NOTIFICATIONS_API_PREFIX}/test_message`, +}); + +const NOTIFICATIONS_API_BASE_PATH = '/_plugins/_notifications'; +export const NOTIFICATIONS_API = Object.freeze({ + CONFIGS: `${NOTIFICATIONS_API_BASE_PATH}/configs`, + EVENTS: `${NOTIFICATIONS_API_BASE_PATH}/events`, + TEST_MESSAGE: `${NOTIFICATIONS_API_BASE_PATH}/feature/test`, +}); diff --git a/dashboards-reports/cypress.json b/dashboards-reports/cypress.json index 7d041020..e72b2afa 100644 --- a/dashboards-reports/cypress.json +++ b/dashboards-reports/cypress.json @@ -1,11 +1,14 @@ { - "video": false, + "video": true, "fixturesFolder": ".cypress/fixtures", "integrationFolder": ".cypress/integration", "pluginsFile": ".cypress/plugins/index.js", "screenshotsFolder": ".cypress/screenshots", "supportFile": ".cypress/support/index.js", "videosFolder": ".cypress/videos", + "requestTimeout": 60000, + "responseTimeout": 60000, + "defaultCommandTimeout": 60000, "env": { "opensearch": "localhost:9200", "opensearchDashboards": "localhost:5601", diff --git a/dashboards-reports/opensearch_dashboards.json b/dashboards-reports/opensearch_dashboards.json index cbca8ab3..28820b8d 100644 --- a/dashboards-reports/opensearch_dashboards.json +++ b/dashboards-reports/opensearch_dashboards.json @@ -1,9 +1,10 @@ { "id": "reportsDashboards", - "version": "1.0.0.0-rc1", - "opensearchDashboardsVersion": "1.0.0-rc1", + "version": "1.3.4.0", + "opensearchDashboardsVersion": "1.3.4", "requiredPlugins": ["navigation", "data", "opensearchDashboardsUtils"], "optionalPlugins": ["share"], "server": true, - "ui": true + "ui": true, + "configPath": ["opensearch_reporting"] } diff --git a/dashboards-reports/package.json b/dashboards-reports/package.json index aafb29b5..ac7a833b 100644 --- a/dashboards-reports/package.json +++ b/dashboards-reports/package.json @@ -1,13 +1,9 @@ { - "name": "reports_dashboards", - "version": "1.0.0.0-rc1", + "name": "reports-dashboards", + "version": "1.3.4.0", "description": "OpenSearch Dashboards Reports Plugin", "license": "Apache-2.0", "main": "index.ts", - "opensearchDashboards": { - "version": "1.0.0-rc1", - "templateVersion": "1.0.0-rc1" - }, "scripts": { "osd": "node ../../scripts/osd", "opensearch": "node ../../scripts/opensearch", @@ -22,9 +18,8 @@ "dependencies": { "async-mutex": "^0.2.6", "babel-polyfill": "^6.26.0", - "cheerio": "0.22.0", "cron-validator": "^1.1.1", - "dompurify": "^2.1.1", + "dompurify": "^2.3.8", "elastic-builder": "^2.7.1", "enzyme-adapter-react-16": "^1.15.2", "jest-fetch-mock": "^3.0.3", @@ -42,12 +37,11 @@ "react-router-dom": "^5.2.0", "react-toast-notifications": "^2.4.0", "set-interval-async": "1.0.33", - "showdown": "^1.9.1", - "ws": "^7.4.6" + "showdown": "^1.9.1" }, "devDependencies": { "@elastic/eslint-import-resolver-kibana": "link:../../packages/osd-eslint-import-resolver-opensearch-dashboards", - "@types/dompurify": "^2.0.4", + "@types/dompurify": "^2.3.3", "@types/enzyme-adapter-react-16": "^1.0.6", "@types/jsdom": "^16.2.3", "@types/puppeteer-core": "^2.0.0", @@ -66,14 +60,19 @@ "identity-obj-proxy": "^3.0.0", "jest-dom": "^4.0.0", "react-test-renderer": "^16.12.0", - "ts-jest": "^26.1.0", - "tsc": "^1.20150623.0" + "ts-jest": "^26.1.0" }, "resolutions": { "trim": "^1.0.0", "doc-path": "2.1.2", "y18n": "^5.0.5", "lodash": "^4.17.21", - "path-parse": "^1.0.7" + "path-parse": "^1.0.7", + "glob-parent": "^5.1.2", + "css-what": "^5.0.1", + "ansi-regex": "5.0.1", + "json-schema": "0.4.0", + "ws": "^7.4.6", + "minimist": "^1.2.6" } } diff --git a/dashboards-reports/public/application.tsx b/dashboards-reports/public/application.tsx index 32563cb7..5fc2379d 100644 --- a/dashboards-reports/public/application.tsx +++ b/dashboards-reports/public/application.tsx @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ import React from 'react'; diff --git a/dashboards-reports/public/components/app.tsx b/dashboards-reports/public/components/app.tsx index a82711ef..4091c0d7 100644 --- a/dashboards-reports/public/components/app.tsx +++ b/dashboards-reports/public/components/app.tsx @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ import React from 'react'; @@ -49,6 +28,7 @@ import { Main } from './main/main'; import { ReportDetails } from './main/report_details/report_details'; import { ReportDefinitionDetails } from './main/report_definition_details/report_definition_details'; import { EditReportDefinition } from './report_definitions/edit/edit_report_definition'; +import { i18n } from '@osd/i18n'; export interface CoreInterface { http: CoreStart['http']; @@ -93,7 +73,10 @@ export const ReportsDashboardsApp = ({ path="/report_details/:reportId" render={(props) => ( ( ( ( (
- window.location.href.match( - /(\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b)\?/ - ); +// try to match uuid and user entered custom-id followed by '?' in URL, which would be the saved search id for discover URL +// custom id example: v1s-f00-b4r1-01, Filebeat-Apache-Dashboard-ecs, +const getUuidFromUrl = () => window.location.href.match(/([0-9a-zA-Z-]+)\?/); const isDiscover = () => window.location.href.includes('discover'); // open Download drop-down @@ -280,7 +256,11 @@ function locationHashChanged() { return; } const menuItem = document.createElement('div'); - menuItem.innerHTML = getMenuItem('Reporting'); + menuItem.innerHTML = getMenuItem( + i18n.translate('opensearch.reports.menu.name', { + defaultMessage: 'Reporting', + }) + ); navMenu[0].insertBefore(menuItem.children[0], navMenu[0].lastChild); } catch (e) { console.log(e); diff --git a/dashboards-reports/public/components/context_menu/context_menu_helpers.js b/dashboards-reports/public/components/context_menu/context_menu_helpers.js index abd828c7..3ebe5d76 100644 --- a/dashboards-reports/public/components/context_menu/context_menu_helpers.js +++ b/dashboards-reports/public/components/context_menu/context_menu_helpers.js @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ import dateMath from '@elastic/datemath'; @@ -48,15 +27,13 @@ export const getTimeFieldsFromUrl = () => { const url = unhashUrl(window.location.href); let [, fromDateString, toDateString] = url.match(timeRangeMatcher); - fromDateString = fromDateString.replace(/[']+/g, ''); + fromDateString = decodeURIComponent(fromDateString.replace(/[']+/g, '')); // convert time range to from date format in case time range is relative const fromDateFormat = dateMath.parse(fromDateString); - toDateString = toDateString.replace(/[']+/g, ''); - const toDateFormat = dateMath.parse(toDateString); + toDateString = decodeURIComponent(toDateString.replace(/[']+/g, '')); + const toDateFormat = dateMath.parse(toDateString, { roundUp: true }); - const timeDuration = moment.duration( - dateMath.parse(toDateString).diff(dateMath.parse(fromDateString)) - ); + const timeDuration = moment.duration(toDateFormat.diff(fromDateFormat)); return { time_from: fromDateFormat, @@ -71,11 +48,11 @@ export const contextMenuCreateReportDefinition = (baseURI) => { const timeRanges = getTimeFieldsFromUrl(); // check report source - if (baseURI.includes('dashboard')) { + if (/\/app\/dashboards/.test(baseURI)) { reportSource = 'dashboard:'; - } else if (baseURI.includes('visualize')) { + } else if (/\/app\/visualize/.test(baseURI)) { reportSource = 'visualize:'; - } else if (baseURI.includes('discover')) { + } else if (/\/app\/discover/.test(baseURI)) { reportSource = 'discover:'; } reportSource += reportSourceId.toString(); @@ -141,22 +118,23 @@ export const replaceQueryURL = (pageUrl) => { // we unhash the url in case OpenSearch Dashboards advanced UI setting 'state:storeInSessionStorage' is turned on const unhashedUrl = new URL(unhashUrl(pageUrl)); let queryUrl = unhashedUrl.pathname + unhashedUrl.hash; - let [, fromDateString, toDateString] = queryUrl.match(timeRangeMatcher); - fromDateString = fromDateString.replace(/[']+/g, ''); + let [, fromDateStringMatch, toDateStringMatch] = + queryUrl.match(timeRangeMatcher); + const fromDateString = decodeURIComponent(fromDateStringMatch.replace(/[']+/g, '')); // convert time range to from date format in case time range is relative const fromDateFormat = dateMath.parse(fromDateString); - toDateString = toDateString.replace(/[']+/g, ''); - const toDateFormat = dateMath.parse(toDateString); + const toDateString = decodeURIComponent(toDateStringMatch.replace(/[']+/g, '')); + const toDateFormat = dateMath.parse(toDateString, { roundUp: true }); // replace to and from dates with absolute date queryUrl = queryUrl.replace( - fromDateString, + fromDateStringMatch, "'" + fromDateFormat.toISOString() + "'" ); queryUrl = queryUrl.replace( - toDateString + '))', - "'" + toDateFormat.toISOString() + "'))" + toDateStringMatch, + "'" + toDateFormat.toISOString() + "'" ); return queryUrl; }; diff --git a/dashboards-reports/public/components/context_menu/context_menu_ui.js b/dashboards-reports/public/components/context_menu/context_menu_ui.js index 791f8891..0c99641f 100644 --- a/dashboards-reports/public/components/context_menu/context_menu_ui.js +++ b/dashboards-reports/public/components/context_menu/context_menu_ui.js @@ -1,28 +1,9 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ +import { i18n } from '@osd/i18n'; export const getMenuItem = (name) => { return ` @@ -39,8 +20,14 @@ export const popoverMenu = (savedObjectAvailable) => { const button = savedObjectAvailable ? 'button' : 'button disabled'; const popoverHeight = savedObjectAvailable ? '395px' : '380px'; const message = savedObjectAvailable - ? `Files can take a minute or two to generate depending on the size of your source data.` - : `Save this Visualization/Dashboard to enable PDF/PNG reports.`; + ? i18n.translate('opensearch.reports.menu.visual.waitPrompt', { + defaultMessage: + 'Files can take a minute or two to generate depending on the size of your source data.', + }) + : i18n.translate('opensearch.reports.menu.visual.savePrompt', { + defaultMessage: + 'Save this Visualization/Dashboard to enable PDF/PNG reports.', + }); const arrowRight = '100px'; const popoverRight = '77px'; @@ -60,7 +47,10 @@ export const popoverMenu = (savedObjectAvailable) => {
- Generate report + ${i18n.translate( + 'opensearch.reports.menu.visual.generateReport', + { defaultMessage: 'Generate report' } + )}
@@ -73,34 +63,48 @@ export const popoverMenu = (savedObjectAvailable) => { <${button} class="${buttonClass}" type="button" data-test-subj="downloadPanel-GeneratePDF" id="generatePDF"> - Download PDF + ${i18n.translate( + 'opensearch.reports.menu.visual.downloadPdf', + { defaultMessage: 'Download PDF' } + )} <${button} class="${buttonClass}" type="button" data-test-subj="downloadPanel-GeneratePNG" id="generatePNG"> - Download PNG + ${i18n.translate( + 'opensearch.reports.menu.visual.downloadPng', + { defaultMessage: 'Download PNG' } + )}
- Schedule and share + ${i18n.translate( + 'opensearch.reports.menu.visual.scheduleAndShare', + { defaultMessage: 'Schedule and share' } + )}
<${button} class="${buttonClass}" type="button" data-test-subj="downloadPanel-GeneratePDF" id="createReportDefinition"> - Create report definition + ${i18n.translate( + 'opensearch.reports.menu.visual.createReportDefinition', + { defaultMessage: 'Create report definition' } + )}
- View + ${i18n.translate('opensearch.reports.menu.visual.view', { + defaultMessage: 'View', + })}
@@ -111,7 +115,10 @@ export const popoverMenu = (savedObjectAvailable) => { - View reports + ${i18n.translate( + 'opensearch.reports.menu.visual.viewReports', + { defaultMessage: 'View reports' } + )} @@ -133,8 +140,13 @@ export const popoverMenuDiscover = (savedObjectAvailable) => { const button = savedObjectAvailable ? 'button' : 'button disabled'; const popoverHeight = savedObjectAvailable ? '354px' : '322px'; const message = savedObjectAvailable - ? `Files can take a minute or two to generate depending on the size of your source data.` - : `Save this search to enable CSV reports.`; + ? i18n.translate('opensearch.reports.menu.csv.waitPrompt', { + defaultMessage: + 'Files can take a minute or two to generate depending on the size of your source data.', + }) + : i18n.translate('opensearch.reports.menu.csv.savePrompt', { + defaultMessage: 'Save this search to enable CSV reports.', + }); const arrowRight = '60px'; const popoverRight = '77px'; @@ -153,7 +165,12 @@ export const popoverMenuDiscover = (savedObjectAvailable) => {
- Generate and download + ${i18n.translate( + 'opensearch.reports.menu.csv.generateReport', + { + defaultMessage: 'Generate and download', + } + )}
@@ -165,28 +182,41 @@ export const popoverMenuDiscover = (savedObjectAvailable) => { <${button} class="${buttonClass}" type="button" data-test-subj="downloadPanel-GeneratePDF" id="generateCSV"> - Generate CSV + ${i18n.translate( + 'opensearch.reports.menu.csv.generateCsv', + { defaultMessage: 'Generate CSV' } + )}
- Schedule and share + ${i18n.translate( + 'opensearch.reports.menu.scheduleAndShare', + { + defaultMessage: 'Schedule and share', + } + )}
<${button} class="${buttonClass}" type="button" data-test-subj="downloadPanel-GeneratePDF" id="createReportDefinition"> - Create report definition + ${i18n.translate( + 'opensearch.reports.menu.createReportDefinition', + { defaultMessage: 'Create report definition' } + )}
- View + ${i18n.translate('opensearch.reports.menu.csv.view', { + defaultMessage: 'View', + })}
@@ -197,7 +227,10 @@ export const popoverMenuDiscover = (savedObjectAvailable) => { - View reports + ${i18n.translate( + 'opensearch.reports.menu.csv.viewReports', + { defaultMessage: 'View reports' } + )} @@ -214,12 +247,18 @@ export const popoverMenuDiscover = (savedObjectAvailable) => { export const permissionsMissingOnGeneration = () => { return `
-

A new notification appears

+

${i18n.translate( + 'opensearch.reports.menu.newNotificationAppears', + { defaultMessage: 'A new notification appears' } + )}

- Error generating report. + ${i18n.translate( + 'opensearch.reports.menu.errorGeneratingReport', + { defaultMessage: 'Error generating report.' } + )}
-

Insufficient permissions. Reach out to your OpenSearch Dashboards administrator.

+

${i18n.translate('opensearch.reports.menu.insufficientPermissions', { + defaultMessage: + 'Insufficient permissions. Reach out to your OpenSearch Dashboards administrator.', + })}

`; @@ -244,7 +286,10 @@ export const reportGenerationSuccess = () => { role="img" aria-hidden="true"> - Successfully generated report. + ${i18n.translate( + 'opensearch.reports.menu.successfullyGenerated', + { defaultMessage: 'Successfully generated report.' } + )}
-

View +

View Reports.

+ href="reports-dashboards#/" rel="noreferrer">${i18n.translate( + 'opensearch.reports.menu.button.reports', + { defaultMessage: 'Reports' } + )}.

`; }; export const reportGenerationFailure = ( - title = 'Download error', - text = 'There was an error generating this report.' + title = i18n.translate('opensearch.reports.menu.downloadError', { + defaultMessage: 'Download error', + }), + text = i18n.translate('opensearch.reports.menu.errorGeneratingThisReport', { + defaultMessage: 'There was an error generating this report.', + }) ) => { return `
@@ -308,14 +360,26 @@ export const reportGenerationInProgressModal = () => {
-

Generating report

+

${i18n.translate( + 'opensearch.reports.menu.progress.generatingReport', + { defaultMessage: 'Generating report' } + )}

-
Preparing your file for download.
-
You can close this dialog while we continue in the background.
+
${i18n.translate( + 'opensearch.reports.menu.progress.preparingYourFile', + { defaultMessage: 'Preparing your file for download.' } + )}
+
${i18n.translate( + 'opensearch.reports.menu.progress.youCanClose', + { + defaultMessage: + 'You can close this dialog while we continue in the background.', + } + )}
diff --git a/dashboards-reports/public/components/main/__tests__/__snapshots__/main.test.tsx.snap b/dashboards-reports/public/components/main/__tests__/__snapshots__/main.test.tsx.snap index aa427ad3..55d94177 100644 --- a/dashboards-reports/public/components/main/__tests__/__snapshots__/main.test.tsx.snap +++ b/dashboards-reports/public/components/main/__tests__/__snapshots__/main.test.tsx.snap @@ -427,11 +427,11 @@ exports[`
panel render component 1`] = ` - Get started with OpenSearch Dashboards reporting + Get started with OpenSearch Dashboards reporting panel render component 1`] = ` - Get started with OpenSearch Dashboards reporting + Get started with OpenSearch Dashboards reporting panel render component after create success 1`] = ` - Get started with OpenSearch Dashboards reporting + Get started with OpenSearch Dashboards reporting panel render component after create success 1`] = ` - Get started with OpenSearch Dashboards reporting + Get started with OpenSearch Dashboards reporting panel render component after delete success 1`] = ` - Get started with OpenSearch Dashboards reporting + Get started with OpenSearch Dashboards reporting panel render component after delete success 1`] = ` - Get started with OpenSearch Dashboards reporting + Get started with OpenSearch Dashboards reporting panel render component after edit success 1`] = ` - Get started with OpenSearch Dashboards reporting + Get started with OpenSearch Dashboards reporting panel render component after edit success 1`] = ` - Get started with OpenSearch Dashboards reporting + Get started with OpenSearch Dashboards reporting panel render empty table 1`] = ` - Get started with OpenSearch Dashboards reporting + Get started with OpenSearch Dashboards reporting panel render empty component 1`] = ` - Get started with OpenSearch Dashboards reporting + Get started with OpenSearch Dashboards reporting

Generating report

+

+ {i18n.translate( + 'opensearch.reports.loading.generatingReport', + { defaultMessage: 'Generating report' } + )} +

- Preparing your file for download. - You can close this dialog while we continue in the background. + {i18n.translate('opensearch.reports.loading.preparingYourFile', { + defaultMessage: 'Preparing your file for download.', + })} + + + {i18n.translate('opensearch.reports.loading.youCanClose', { + defaultMessage: + 'You can close this dialog while we continue in the background.', + })} @@ -84,7 +74,11 @@ export function GenerateReportLoadingModal(props: { setShowLoading: any; }) { - Close + + {i18n.translate('opensearch.reports.loading.close', { + defaultMessage: 'Close', + })} + @@ -92,4 +86,4 @@ export function GenerateReportLoadingModal(props: { setShowLoading: any; }) {
); -}; \ No newline at end of file +} diff --git a/dashboards-reports/public/components/main/main.tsx b/dashboards-reports/public/components/main/main.tsx index 0b3cc203..bfbb8cb9 100644 --- a/dashboards-reports/public/components/main/main.tsx +++ b/dashboards-reports/public/components/main/main.tsx @@ -1,30 +1,10 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ import React, { Fragment, useState, useEffect } from 'react'; +import { i18n } from '@osd/i18n'; import { EuiFlexGroup, EuiFlexItem, @@ -80,7 +60,10 @@ export function Main(props) { ); } else if (errorType === 'API') { toast = { - title: 'Error generating reports table.', + title: i18n.translate( + 'opensearch.reports.main.errorGeneratingReportsTable.', + { defaultMessage: 'Error generating reports table.' } + ), color: 'danger', iconType: 'alert', id: 'reportsTableErrorToast', @@ -101,7 +84,10 @@ export function Main(props) { ); } else if (errorType === 'API') { toast = { - title: 'Error generating report definitions table.', + title: i18n.translate( + 'opensearch.reports.main.errorGeneratingReportDefinitionsTable.', + { defaultMessage: 'Error generating report definitions table.' } + ), color: 'danger', iconType: 'alert', id: 'reportDefinitionsTableErrorToast', @@ -114,7 +100,12 @@ export function Main(props) { addReportDefinitionsTableErrorToastHandler(errorType); }; - const addErrorOnDemandDownloadToastHandler = (title = 'Error downloading report.', text = '') => { + const addErrorOnDemandDownloadToastHandler = ( + title = i18n.translate('opensearch.reports.main.errorDownloadingReport', { + defaultMessage: 'Error downloading report.', + }), + text = '' + ) => { const errorToast = { title, text, @@ -131,7 +122,10 @@ export function Main(props) { const addSuccessOnDemandDownloadToastHandler = () => { const successToast = { - title: 'Successfully downloaded report.', + title: i18n.translate( + 'opensearch.reports.main.successfullyDownloadedReport', + { defaultMessage: 'Successfully downloaded report.' } + ), color: 'success', iconType: 'check', id: 'onDemandDownloadSuccessToast', @@ -145,7 +139,10 @@ export function Main(props) { const addCreateReportDefinitionSuccessToastHandler = () => { const successToast = { - title: 'Successfully created report definition.', + title: i18n.translate( + 'opensearch.reports.main.successfullyCreatedReportDefinition', + { defaultMessage: 'Successfully created report definition.' } + ), color: 'success', iconType: 'check', id: 'createReportDefinitionSuccessToast', @@ -159,7 +156,10 @@ export function Main(props) { const addEditReportDefinitionSuccessToastHandler = () => { const successToast = { - title: 'Successfully updated report definition.', + title: i18n.translate( + 'opensearch.reports.main.successfullyUpdatedReportDefinition', + { defaultMessage: 'Successfully updated report definition.' } + ), color: 'success', iconType: 'check', id: 'editReportDefinitionSuccessToast', @@ -173,17 +173,20 @@ export function Main(props) { const addDeleteReportDefinitionSuccessToastHandler = () => { const successToast = { - title: 'Successfully deleted report definition.', + title: i18n.translate( + 'opensearch.reports.main.successfullyDeletedReportDefinition', + { defaultMessage: 'Successfully deleted report definition.' } + ), color: 'success', iconType: 'check', - id: 'deleteReportDefinitionSuccessToast' + id: 'deleteReportDefinitionSuccessToast', }; setToasts(toasts.concat(successToast)); - } + }; const handleDeleteReportDefinitionSuccessToast = () => { addDeleteReportDefinitionSuccessToastHandler(); - } + }; const removeToast = (removedToast) => { setToasts(toasts.filter((toast) => toast.id !== removedToast.id)); @@ -197,7 +200,9 @@ export function Main(props) { useEffect(() => { props.setBreadcrumbs([ { - text: 'Reporting', + text: i18n.translate('opensearch.reports.main.title.reporting', { + defaultMessage: 'Reporting', + }), href: '#', }, ]); @@ -272,18 +277,23 @@ export function Main(props) {

- Reports{' '} + {i18n.translate('opensearch.reports.main.title.reports', { + defaultMessage: 'Reports', + })}{' '}

({reportsTableContent.length})

- - Refresh + {i18n.translate( + 'opensearch.reports.main.reports.button.refresh', + { defaultMessage: 'Refresh' } + )} @@ -303,7 +313,10 @@ export function Main(props) {

- Report definitions + {i18n.translate( + 'opensearch.reports.main.title.reportDefinitions', + { defaultMessage: 'Report definitions' } + )}

{' '} ({reportDefinitionsTableContent.length}) @@ -312,12 +325,15 @@ export function Main(props) { - - Refresh + {i18n.translate( + 'opensearch.reports.main.reportDefinitions.button.refresh', + { defaultMessage: 'Refresh' } + )} @@ -328,7 +344,10 @@ export function Main(props) { }} id={'createReportHomepageButton'} > - Create + {i18n.translate( + 'opensearch.reports.main.reportDefinitions.button.create', + { defaultMessage: 'Create' } + )} diff --git a/dashboards-reports/public/components/main/main_utils.tsx b/dashboards-reports/public/components/main/main_utils.tsx index b84a1465..44066c02 100644 --- a/dashboards-reports/public/components/main/main_utils.tsx +++ b/dashboards-reports/public/components/main/main_utils.tsx @@ -1,39 +1,37 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ import 'babel-polyfill'; +import { i18n } from '@osd/i18n'; import { HttpFetchOptions, HttpSetup } from '../../../../../src/core/public'; +import { uiSettingsService } from '../utils/settings_service'; + +export const getAvailableNotificationsChannels = (configList: any) => { + let availableChannels = []; + for (let i = 0; i < configList.length; ++i) { + let channelEntry = {}; + channelEntry = { + label: configList[i].config.name, + id: configList[i].config_id + } + availableChannels.push(channelEntry); + } + return availableChannels; +} + +type fileFormatsOptions = { + [key: string]: string +} -export const fileFormatsUpper = { +export const fileFormatsUpper: fileFormatsOptions = { csv: 'CSV', pdf: 'PDF', png: 'PNG', }; -export const humanReadableDate = (date) => { +export const humanReadableDate = (date: string | number | Date) => { let readableDate = new Date(date); return ( readableDate.toDateString() + ' @ ' + readableDate.toLocaleTimeString() @@ -54,7 +52,7 @@ export const getFileFormatPrefix = (fileFormat: string) => { return fileFormatPrefix; }; -export const addReportsTableContent = (data) => { +export const addReportsTableContent = (data: string | any[]) => { let reportsTableItems = []; for (let index = 0; index < data.length; ++index) { let item = data[index]; @@ -109,7 +107,7 @@ export const addReportDefinitionsTableContent = (data: any) => { return reportDefinitionsTableItems; }; -export const removeDuplicatePdfFileFormat = (filename) => { +export const removeDuplicatePdfFileFormat = (filename: string) => { return filename.substring(0, filename.length - 4); }; @@ -152,7 +150,7 @@ export const readStreamToFile = async ( }; export const generateReportFromDefinitionId = async ( - reportDefinitionId, + reportDefinitionId: string, httpClient: HttpSetup ) => { let status = false; @@ -162,7 +160,7 @@ export const generateReportFromDefinitionId = async ( headers: { 'Content-Type': 'application/json', }, - query: { timezone: Intl.DateTimeFormat().resolvedOptions().timeZone }, + query: uiSettingsService.getSearchParams(), }) .then(async (response: any) => { // for emailing a report, this API response doesn't have response body @@ -187,7 +185,7 @@ export const generateReportFromDefinitionId = async ( }; export const generateReportById = async ( - reportId, + reportId: string, httpClient: HttpSetup, handleSuccessToast, handleErrorToast, @@ -195,7 +193,7 @@ export const generateReportById = async ( ) => { await httpClient .get(`../api/reporting/generateReport/${reportId}`, { - query: { timezone: Intl.DateTimeFormat().resolvedOptions().timeZone }, + query: uiSettingsService.getSearchParams(), }) .then(async (response) => { //TODO: duplicate code, extract to be a function that can reuse. e.g. handleResponse(response) @@ -211,8 +209,15 @@ export const generateReportById = async ( handlePermissionsMissingToast(); } else if (error.body.statusCode === 503) { handleErrorToast( - 'Error generating report.', - `Timed out generating report ID ${reportId}. Try again later.` + i18n.translate('opensearch.reports.utils.errorTitle', { + defaultMessage: 'Error generating report.', + }), + i18n.translate('opensearch.reports.utils.errorText', { + defaultMessage: + 'Timed out generating report ID {reportId}. Try again later.', + values: { reportId: reportId }, + description: 'Error number toast', + }) ); } else { handleErrorToast(); diff --git a/dashboards-reports/public/components/main/report_definition_details/__tests__/__snapshots__/report_definition_details.test.tsx.snap b/dashboards-reports/public/components/main/report_definition_details/__tests__/__snapshots__/report_definition_details.test.tsx.snap index 690a1d28..21653179 100644 --- a/dashboards-reports/public/components/main/report_definition_details/__tests__/__snapshots__/report_definition_details.test.tsx.snap +++ b/dashboards-reports/public/components/main/report_definition_details/__tests__/__snapshots__/report_definition_details.test.tsx.snap @@ -199,10 +199,13 @@ exports[` panel render 5 hours recurring definition d > + > + +

@@ -220,7 +223,7 @@ exports[` panel render 5 hours recurring definition d
- Last undefined + Last
@@ -240,7 +243,7 @@ exports[` panel render 5 hours recurring definition d > -
-
- - -
- Select or add users -
- - -
-
-
- -
-
-
-
- -
-
-
-
-
-
-
- -
-
-
-
-
- - -
-
    -
  • - -
  • -
  • - -
  • -
  • - -
  • -
  • - -
  • -
-
    -
  • - -
  • -
  • - -
  • -
  • - -
  • -
-
-
-
-
+

+

Dashboard panel: [eCommerce] Top Selling Products[eCommerce] Top Selling Products

Lace-up boots - blackAnkle boots - blackBoots - blackPrint T-shirt - blackJumper - blackLace-up boots - resin coffeeDress with Defined Waist

Dashboard panel: [eCommerce] Orders[eCommerce] Orders

+
+
+
+ + +
1–50 of 1055
+
+
+
+
+ + + + + +
Timecategoryskutaxful_total_pricetotal_quantity
+ +Jun 23, 2021 @ 23:56:10.000
Women's Accessories, Women's Clothing
ZO0301903019, ZO0049800498
$43.98
2
+ +Jun 23, 2021 @ 23:41:46.000
Men's Clothing
ZO0128701287, ZO0577005770
$49.98
2
+ +Jun 23, 2021 @ 23:37:26.000
Men's Clothing
ZO0558005580, ZO0276502765
$18.98
2
+ +Jun 23, 2021 @ 23:33:07.000
Women's Accessories, Women's Clothing
ZO0358803588, ZO0179601796
$91.98
2
+ +Jun 23, 2021 @ 23:21:36.000
Men's Clothing
ZO0543605436, ZO0425604256
$89.98
2
+ +Jun 23, 2021 @ 23:21:36.000
Men's Clothing
ZO0629306293, ZO0578405784
$37.98
2
+ +Jun 23, 2021 @ 22:51:22.000
Men's Clothing
ZO0291602916, ZO0292302923
$221.98
2
+ +Jun 23, 2021 @ 22:48:29.000
Women's Clothing, Women's Accessories
ZO0262902629, ZO0358703587
$83.98
2
+ +Jun 23, 2021 @ 22:29:46.000
Men's Clothing
ZO0474604746, ZO0111701117
$36.98
2
+ +Jun 23, 2021 @ 22:12:29.000
Men's Accessories, Men's Shoes
ZO0598005980, ZO0681706817
$75.98
2
+ +Jun 23, 2021 @ 22:11:02.000
Women's Clothing, Women's Shoes
ZO0221402214, ZO0677006770
$103.98
2
+ +Jun 23, 2021 @ 21:59:31.000
Men's Clothing, Men's Shoes
ZO0579905799, ZO0386403864
$55.98
2
+ +Jun 23, 2021 @ 21:55:12.000
Men's Clothing
ZO0474204742, ZO0574005740
$31.98
2
+ +Jun 23, 2021 @ 21:48:00.000
Men's Clothing, Men's Shoes
ZO0580905809, ZO0507105071
$41.98
2
+ +Jun 23, 2021 @ 21:23:31.000
Women's Clothing
ZO0217002170, ZO0164201642
$27.98
2
+ +Jun 23, 2021 @ 21:17:46.000
Women's Shoes, Women's Clothing
ZO0368003680, ZO0173001730
$63.98
2
+ +Jun 23, 2021 @ 21:12:00.000
Men's Clothing
ZO0437404374, ZO0293102931
$24.98
2
+ +Jun 23, 2021 @ 21:09:07.000
Women's Accessories, Women's Shoes
ZO0085300853, ZO0678506785
$95.98
2
+ +Jun 23, 2021 @ 20:56:10.000
Women's Clothing, Women's Shoes
ZO0638706387, ZO0677206772
$92.98
2
+ +Jun 23, 2021 @ 20:41:46.000
Women's Shoes, Women's Clothing
ZO0678406784, ZO0712707127
$99.98
2
+ +Jun 23, 2021 @ 20:37:26.000
Women's Clothing
ZO0708107081, ZO0500905009
$42.98
2
+ +Jun 23, 2021 @ 20:33:07.000
Women's Shoes
ZO0250002500, ZO0675406754
$159.98
2
+ +Jun 23, 2021 @ 20:24:29.000
Women's Accessories
ZO0205602056, ZO0356903569
$46.98
2
+ +Jun 23, 2021 @ 20:00:00.000
Men's Clothing
ZO0441304413, ZO0561205612
$22.98
2
+ +Jun 23, 2021 @ 19:55:41.000
Men's Shoes, Men's Clothing
ZO0691306913, ZO0275502755
$139.98
2
+ +Jun 23, 2021 @ 19:32:38.000
Men's Clothing
ZO0295102951, ZO0453304533, ZO0588305883, ZO0411304113
$82.96
4
+ +Jun 23, 2021 @ 19:19:41.000
Men's Clothing, Men's Accessories
ZO0296402964, ZO0316203162
$42.98
2
+ +Jun 23, 2021 @ 19:18:14.000
Men's Clothing, Men's Shoes
ZO0588005880, ZO0571805718, ZO0403504035, ZO0457504575
$108.96
4
+ +Jun 23, 2021 @ 19:15:22.000
Women's Clothing
ZO0051800518, ZO0333303333
$92.98
2
+ +Jun 23, 2021 @ 19:06:43.000
Men's Clothing, Men's Shoes
ZO0431904319, ZO0683606836
$149.98
2
+ +Jun 23, 2021 @ 19:05:17.000
Women's Clothing, Women's Accessories
ZO0181701817, ZO0095300953
$45.98
2
+ +Jun 23, 2021 @ 18:58:05.000
Men's Clothing
ZO0620606206, ZO0454204542
$70.98
2
+ +Jun 23, 2021 @ 18:40:48.000
Women's Shoes, Women's Accessories
ZO0670906709, ZO0211302113
$128.98
2
+ +Jun 23, 2021 @ 18:30:43.000
Women's Clothing
ZO0263002630, ZO0497904979
$93.98
2
+ +Jun 23, 2021 @ 18:27:50.000
Men's Clothing, Men's Shoes
ZO0300603006, ZO0123501235, ZO0399803998, ZO0624206242
$160.96
4
+ +Jun 23, 2021 @ 18:13:26.000
Women's Accessories, Women's Shoes
ZO0696806968, ZO0020700207
$66.98
2
+ +Jun 23, 2021 @ 18:03:22.000
Women's Clothing, Women's Accessories
ZO0271302713, ZO0703207032
$74.98
2
+ +Jun 23, 2021 @ 18:00:29.000
Men's Shoes, Men's Accessories
ZO0403504035, ZO0608606086
$91.98
2
+ +Jun 23, 2021 @ 17:46:05.000
Men's Shoes, Men's Clothing
ZO0521405214, ZO0585905859
$64.98
2
+ +Jun 23, 2021 @ 17:31:41.000
Women's Clothing
ZO0171101711, ZO0048400484
$74.98
2
+ +Jun 23, 2021 @ 17:28:48.000
Women's Accessories
ZO0209302093, ZO0087400874
$47.98
2
+ +Jun 23, 2021 @ 17:27:22.000
Women's Accessories
ZO0096100961, ZO0091000910
$53.98
2
+ +Jun 23, 2021 @ 17:04:19.000
Men's Clothing
ZO0284802848, ZO0581605816
$49.98
2
+ +Jun 23, 2021 @ 17:02:53.000
Men's Shoes
ZO0401004010, ZO0257802578
$119.98
2
+ +Jun 23, 2021 @ 16:51:22.000
Men's Shoes, Men's Accessories
ZO0520705207, ZO0397603976, ZO0395003950, ZO0702307023
$207.96
4
+ +Jun 23, 2021 @ 16:49:55.000
Women's Shoes, Women's Clothing
ZO0364403644, ZO0150401504
$116.98
2
+ +Jun 23, 2021 @ 16:31:12.000
Men's Clothing, Women's Accessories
ZO0554505545, ZO0703407034
$96.98
2
+ +Jun 23, 2021 @ 16:25:26.000
Women's Clothing
ZO0263002630
$51.99
1
+ +Jun 23, 2021 @ 16:02:24.000
Women's Shoes
ZO0365203652, ZO0383303833
$126.98
2
+ +Jun 23, 2021 @ 16:00:58.000
Women's Clothing
ZO0179701797, ZO0496004960
$42.98
2
+
+ + +
+ + + +
+ +
+ + +
\ No newline at end of file diff --git a/dashboards-reports/server/routes/utils/__tests__/metricHelper.test.ts b/dashboards-reports/server/routes/utils/__tests__/metricHelper.test.ts index d598dc87..3953a724 100644 --- a/dashboards-reports/server/routes/utils/__tests__/metricHelper.test.ts +++ b/dashboards-reports/server/routes/utils/__tests__/metricHelper.test.ts @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ import { checkErrorType } from '../helpers'; diff --git a/dashboards-reports/server/routes/utils/__tests__/savedSearchReportHelper.test.ts b/dashboards-reports/server/routes/utils/__tests__/savedSearchReportHelper.test.ts index f1ca9b8a..7009dda3 100644 --- a/dashboards-reports/server/routes/utils/__tests__/savedSearchReportHelper.test.ts +++ b/dashboards-reports/server/routes/utils/__tests__/savedSearchReportHelper.test.ts @@ -1,32 +1,13 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ import 'regenerator-runtime/runtime'; import { createSavedSearchReport } from '../savedSearchReportHelper'; import { reportSchema } from '../../../model'; +import { mockLogger } from '../../../../test/__mocks__/loggerMock'; +import _ from 'lodash'; /** * The mock and sample input for saved search export function. @@ -51,10 +32,10 @@ const input = { }, }, delivery: { - delivery_type: 'OpenSearch Dashboards user', - delivery_params: { - opensearch_dashboards_recipients: [], - }, + configIds: [], + title: 'title', + textDescription: 'text description', + htmlDescription: 'html description', }, trigger: { trigger_type: 'On demand', @@ -62,6 +43,8 @@ const input = { }, }; +const mockDateFormat = 'MM/DD/YYYY h:mm:ss.SSS a'; + /** * Max result window size in OpenSearch index settings. */ @@ -78,7 +61,11 @@ describe('test create saved search report', () => { const client = mockOpenSearchClient(hits); const { timeCreated, fileName } = await createSavedSearchReport( input, - client + client, + mockDateFormat, + ',', + undefined, + mockLogger ); expect(fileName).toContain(`test report table order_`); }, 20000); @@ -86,14 +73,22 @@ describe('test create saved search report', () => { test('create report with expected file name extension', async () => { const csvReport = await createSavedSearchReport( input, - mockOpenSearchClient([]) + mockOpenSearchClient([]), + mockDateFormat, + ',', + undefined, + mockLogger ); expect(csvReport.fileName).toContain('.csv'); input.report_definition.report_params.core_params.report_format = 'xlsx'; const xlsxReport = await createSavedSearchReport( input, - mockOpenSearchClient([]) + mockOpenSearchClient([]), + mockDateFormat, + ',', + undefined, + mockLogger ); expect(xlsxReport.fileName).toContain('.xlsx'); }, 20000); @@ -101,7 +96,14 @@ describe('test create saved search report', () => { test('create report for empty data set', async () => { const hits: Array<{ _source: any }> = []; const client = mockOpenSearchClient(hits); - const { dataUrl } = await createSavedSearchReport(input, client); + const { dataUrl } = await createSavedSearchReport( + input, + client, + mockDateFormat, + ',', + undefined, + mockLogger + ); expect(dataUrl).toEqual(''); }, 20000); @@ -114,7 +116,14 @@ describe('test create saved search report', () => { hit({ category: 'c5', customer_gender: 'Male' }), ]; const client = mockOpenSearchClient(hits); - const { dataUrl } = await createSavedSearchReport(input, client); + const { dataUrl } = await createSavedSearchReport( + input, + client, + mockDateFormat, + ',', + undefined, + mockLogger + ); expect(dataUrl).toEqual( 'category,customer_gender\n' + @@ -141,7 +150,14 @@ describe('test create saved search report', () => { hit({ category: 'c11', customer_gender: 'Male' }), ]; const client = mockOpenSearchClient(hits); - const { dataUrl } = await createSavedSearchReport(input, client); + const { dataUrl } = await createSavedSearchReport( + input, + client, + mockDateFormat, + ',', + undefined, + mockLogger + ); expect(dataUrl).toEqual( 'category,customer_gender\n' + @@ -171,7 +187,14 @@ describe('test create saved search report', () => { hit({ category: 'c5', customer_gender: 'Male' }), ]; const client = mockOpenSearchClient(hits); - const { dataUrl } = await createSavedSearchReport(input, client); + const { dataUrl } = await createSavedSearchReport( + input, + client, + mockDateFormat, + ',', + undefined, + mockLogger + ); expect(dataUrl).toEqual('category,customer_gender\n' + 'c1,Male'); }, 20000); @@ -193,7 +216,14 @@ describe('test create saved search report', () => { hit({ category: 'c10', customer_gender: 'Female' }), ]; const client = mockOpenSearchClient(hits); - const { dataUrl } = await createSavedSearchReport(input, client); + const { dataUrl } = await createSavedSearchReport( + input, + client, + mockDateFormat, + ',', + undefined, + mockLogger + ); expect(dataUrl).toEqual( 'category,customer_gender\n' + @@ -219,7 +249,14 @@ describe('test create saved search report', () => { hit({ category: 'c6', customer_gender: 'Female' }), ]; const client = mockOpenSearchClient(hits); - const { dataUrl } = await createSavedSearchReport(input, client); + const { dataUrl } = await createSavedSearchReport( + input, + client, + mockDateFormat, + ',', + undefined, + mockLogger + ); expect(dataUrl).toEqual( 'category,customer_gender\n' + @@ -239,7 +276,14 @@ describe('test create saved search report', () => { hit({ category: ',,c3', customer_gender: 'Male,,,' }), ]; const client = mockOpenSearchClient(hits); - const { dataUrl } = await createSavedSearchReport(input, client); + const { dataUrl } = await createSavedSearchReport( + input, + client, + mockDateFormat, + ',', + undefined, + mockLogger + ); expect(dataUrl).toEqual( 'category,customer_gender\n' + @@ -249,6 +293,30 @@ describe('test create saved search report', () => { ); }, 20000); + test('create report for data set with comma and custom separator', async () => { + const hits = [ + hit({ category: ',c1', customer_gender: 'Ma,le' }), + hit({ category: 'c2,', customer_gender: 'M,ale' }), + hit({ category: ',,c3', customer_gender: 'Male,,,' }), + ]; + const client = mockOpenSearchClient(hits); + const { dataUrl } = await createSavedSearchReport( + input, + client, + mockDateFormat, + '|', + undefined, + mockLogger + ); + + expect(dataUrl).toEqual( + 'category|customer_gender\n' + + ',c1|Ma,le\n' + + 'c2,|M,ale\n' + + ',,c3|Male,,,' + ); + }, 20000); + test('create report for data set with nested fields', async () => { const hits = [ hit({ @@ -265,7 +333,14 @@ describe('test create saved search report', () => { hits, '"geoip.country_iso_code", "geoip.city_name", "geoip.location"' ); - const { dataUrl } = await createSavedSearchReport(input, client); + const { dataUrl } = await createSavedSearchReport( + input, + client, + mockDateFormat, + ',', + undefined, + mockLogger + ); expect(dataUrl).toEqual( 'geoip.country_iso_code,geoip.location.lon,geoip.location.lat,geoip.city_name\n' + @@ -283,7 +358,14 @@ describe('test create saved search report', () => { hit({ category: ',,,@c5', customer_gender: 'Male' }), ]; const client = mockOpenSearchClient(hits); - const { dataUrl } = await createSavedSearchReport(input, client); + const { dataUrl } = await createSavedSearchReport( + input, + client, + mockDateFormat, + ',', + undefined, + mockLogger + ); expect(dataUrl).toEqual( 'category,customer_gender\n' + @@ -307,7 +389,14 @@ describe('test create saved search report', () => { hit({ category: ',,,@c5', customer_gender: 'Male' }), ]; const client = mockOpenSearchClient(hits); - const { dataUrl } = await createSavedSearchReport(input, client); + const { dataUrl } = await createSavedSearchReport( + input, + client, + mockDateFormat, + ',', + undefined, + mockLogger + ); expect(dataUrl).toEqual( 'category,customer_gender\n' + @@ -327,13 +416,109 @@ test('create report for data set contains null field value', async () => { hit({ category: 'c3', customer_gender: null }), ]; const client = mockOpenSearchClient(hits); - const { dataUrl } = await createSavedSearchReport(input, client); + const { dataUrl } = await createSavedSearchReport( + input, + client, + mockDateFormat, + ',', + undefined, + mockLogger + ); expect(dataUrl).toEqual( 'category,customer_gender\n' + 'c1,Ma\n' + 'c2,le\n' + 'c3, ' ); }, 20000); +test('create report for data set with metadata fields', async () => { + const metadataFields = { _index: 'nameofindex', _id: 'someid' }; + let hits = [ + hit({ category: 'c1', customer_gender: 'Male' }), + hit({ category: 'c2', customer_gender: 'Male' }), + hit({ category: 'c3', customer_gender: 'Male' }), + hit({ category: 'c4', customer_gender: 'Male' }), + hit({ category: 'c5', customer_gender: 'Male' }), + ]; + hits.forEach((i) => { + _.merge(i, metadataFields); + }); + + const client = mockOpenSearchClient( + hits, + '"category", "customer_gender","_index","_id"' + ); + const { dataUrl } = await createSavedSearchReport( + input, + client, + mockDateFormat, + ',', + undefined, + mockLogger + ); + + expect(dataUrl).toEqual( + 'category,customer_gender,_index,_id\n' + + 'c1,Male,nameofindex,someid\n' + + 'c2,Male,nameofindex,someid\n' + + 'c3,Male,nameofindex,someid\n' + + 'c4,Male,nameofindex,someid\n' + + 'c5,Male,nameofindex,someid' + ); +}, 20000); + +test('create report with empty/one/multiple(list) date values', async () => { + const hits = [ + hit( + { category: 'c1', customer_gender: 'Ma', order_date: [] }, + { order_date: [] } + ), + hit( + { + category: 'c2', + customer_gender: 'le', + order_date: ['2021-12-16T14:04:55'], + }, + { order_date: ['2021-12-16T14:04:55'] } + ), + hit( + { + category: 'c3', + customer_gender: 'he', + order_date: ['2021-12-17T14:04:55', '2021-12-18T14:04:55'], + }, + { order_date: ['2021-12-17T14:04:55', '2021-12-18T14:04:55'] } + ), + hit( + { + category: 'c4', + customer_gender: 'te', + order_date: '2021-12-19T14:04:55', + }, + { order_date: ['2021-12-19T14:04:55'] } + ), + ]; + const client = mockOpenSearchClient( + hits, + '"category", "customer_gender", "order_date"' + ); + const { dataUrl } = await createSavedSearchReport( + input, + client, + mockDateFormat, + ',', + undefined, + mockLogger + ); + + expect(dataUrl).toEqual( + 'category,customer_gender,order_date\n' + + 'c1,Ma,[]\n' + + 'c2,le,"[""12/16/2021 2:04:55.000 pm""]"\n' + + 'c3,he,"[""12/17/2021 2:04:55.000 pm"",""12/18/2021 2:04:55.000 pm""]"\n' + + 'c4,te,12/19/2021 2:04:55.000 pm' + ); +}, 20000); + /** * Mock Elasticsearch client and return different mock objects based on endpoint and parameters. */ @@ -399,13 +584,13 @@ function mockSavedSearch(columns = '"category", "customer_gender"') { "columns": [ ${columns} ], "sort": [], "version": 1, - "opensearchDashboardsSavedObjectMeta": { - "searchSourceJSON": "{\\"highlightAll\\":true,\\"version\\":true,\\"query\\":{\\"query\\":\\"\\",\\"language\\":\\"kuery\\"},\\"indexRefName\\":\\"opensearchDashboardsSavedObjectMeta.searchSourceJSON.index\\",\\"filter\\":[]}" + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\\"highlightAll\\":true,\\"version\\":true,\\"query\\":{\\"query\\":\\"\\",\\"language\\":\\"kuery\\"},\\"indexRefName\\":\\"kibanaSavedObjectMeta.searchSourceJSON.index\\",\\"filter\\":[]}" } }, "references": [ { - "name": "opensearchDashboardsSavedObjectMeta.searchSourceJSON.index", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", "type": "index-pattern", "id": "ff959d40-b880-11e8-a6d9-e546fe2bba5f" } @@ -456,8 +641,9 @@ function mockIndexSettings() { `); } -function hit(kv: any) { +function hit(source_kv: any, fields_kv = {}) { return { - _source: kv, + _source: source_kv, + fields: fields_kv, }; } diff --git a/dashboards-reports/server/routes/utils/__tests__/visualReportHelper.test.ts b/dashboards-reports/server/routes/utils/__tests__/visualReportHelper.test.ts index 6bf6dc6e..81595979 100644 --- a/dashboards-reports/server/routes/utils/__tests__/visualReportHelper.test.ts +++ b/dashboards-reports/server/routes/utils/__tests__/visualReportHelper.test.ts @@ -1,45 +1,15 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ import 'regenerator-runtime/runtime'; import { createVisualReport } from '../visual_report/visualReportHelper'; import { Logger } from '../../../../../../src/core/server'; import { ReportParamsSchemaType, reportSchema } from '../../../model'; +import { mockLogger } from '../../../../test/__mocks__/loggerMock'; -const mockLogger: Logger = { - info: jest.fn(), - trace: jest.fn(), - warn: jest.fn(), - debug: jest.fn(), - error: jest.fn(), - fatal: jest.fn(), - log: jest.fn(), - get: jest.fn(), -}; - +const mockHeader = { mockKey: 'mockValue' }; const input = { query_url: '/app/dashboards#/view/7adfa750-4c81-11e8-b3d7-01146121b73d', time_from: 1343576635300, @@ -59,10 +29,10 @@ const input = { }, }, delivery: { - delivery_type: 'OpenSearch Dashboards user', - delivery_params: { - opensearch_dashboards_recipients: [], - }, + configIds: [], + title: 'title', + textDescription: 'text description', + htmlDescription: 'html description', }, trigger: { trigger_type: 'On demand', @@ -70,8 +40,7 @@ const input = { }, }; -const queryUrl = - 'https://demo.elastic.co/app/kibana#/dashboard/welcome_dashboard'; +const mockHtmlPath = `file://${__dirname}/demo_dashboard.html`; describe('test create visual report', () => { test('create report with valid input', async () => { @@ -84,8 +53,9 @@ describe('test create visual report', () => { const reportParams = input.report_definition.report_params; const { dataUrl, fileName } = await createVisualReport( reportParams as ReportParamsSchemaType, - queryUrl, - mockLogger + mockHtmlPath, + mockLogger, + mockHeader ); expect(fileName).toContain(`${reportParams.report_name}`); expect(fileName).toContain('.png'); @@ -99,8 +69,9 @@ describe('test create visual report', () => { const { dataUrl, fileName } = await createVisualReport( reportParams as ReportParamsSchemaType, - queryUrl, - mockLogger + mockHtmlPath, + mockLogger, + mockHeader ); expect(fileName).toContain(`${reportParams.report_name}`); expect(fileName).toContain('.pdf'); diff --git a/dashboards-reports/server/routes/utils/constants.ts b/dashboards-reports/server/routes/utils/constants.ts index 1b424f95..dffb0cd1 100644 --- a/dashboards-reports/server/routes/utils/constants.ts +++ b/dashboards-reports/server/routes/utils/constants.ts @@ -1,30 +1,10 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ import { CountersType } from './types'; +import Showdown from 'showdown'; export enum FORMAT { pdf = 'pdf', @@ -60,11 +40,11 @@ export enum REPORT_TYPE { savedSearch = 'Saved search', dashboard = 'Dashboard', visualization = 'Visualization', - notebook = 'Notebook' + notebook = 'Notebook', } export enum DATA_REPORT_CONFIG { - excelDateFormat = 'MM/DD/YYYY h:mm:ss a', + excelDateFormat = 'MM/DD/YYYY h:mm:ss.SSS a', } export enum TRIGGER_TYPE { @@ -80,7 +60,7 @@ export enum DELIVERY_TYPE { export enum SELECTOR { dashboard = '#dashboardViewport', visualization = '.visEditor__content', - notebook = '.euiPageBody' + notebook = '.euiPageBody', } // https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-request-from-size.html @@ -89,14 +69,44 @@ export const DEFAULT_MAX_SIZE = 10000; export const DEFAULT_REPORT_HEADER = '

OpenSearch Dashboards Reports

'; export const SECURITY_CONSTANTS = { - AUTH_COOKIE_NAME: 'security_authentication', TENANT_LOCAL_STORAGE_KEY: 'opendistro::security::tenant::show_popup', - PROXY_AUTH_USER_HEADER: 'x-proxy-user', - PROXY_AUTH_ROLES_HEADER: 'x-proxy-roles', - PROXY_AUTH_IP_HEADER: 'x-forwarded-for', }; +export const EXTRA_HEADERS = [ + 'cookie', + 'x-proxy-user', + 'x-proxy-roles', + 'x-forwarded-for', +]; + +export const converter = new Showdown.Converter({ + tables: true, + simplifiedAutoLink: true, + strikethrough: true, + tasklists: true, + noHeaderId: true, +}); + +const BLOCKED_KEYWORD = 'BLOCKED_KEYWORD'; +const ipv4Regex = /(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?):([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])/g +const ipv6Regex = /(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/g; +const localhostRegex = /localhost:([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])/g; +const iframeRegex = /iframe/g; + +export const replaceBlockedKeywords = (htmlString: string) => { + // replace : + htmlString = htmlString.replace(ipv4Regex, BLOCKED_KEYWORD); + // replace ipv6 addresses + htmlString = htmlString.replace(ipv6Regex, BLOCKED_KEYWORD); + // replace iframe keyword + htmlString = htmlString.replace(iframeRegex, BLOCKED_KEYWORD); + // replace localhost: + htmlString = htmlString.replace(localhostRegex, BLOCKED_KEYWORD); + return htmlString; +} + export const CHROMIUM_PATH = `${__dirname}/../../../.chromium/headless_shell`; + /** * Metric constants diff --git a/dashboards-reports/server/routes/utils/converters/__tests__/backendToUi.test.ts b/dashboards-reports/server/routes/utils/converters/__tests__/backendToUi.test.ts index 426777c2..4877f807 100644 --- a/dashboards-reports/server/routes/utils/converters/__tests__/backendToUi.test.ts +++ b/dashboards-reports/server/routes/utils/converters/__tests__/backendToUi.test.ts @@ -1,30 +1,9 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -import { AccessInfoType } from 'server'; +import { ReportingConfig } from 'server/config/config'; import { BackendReportInstanceType, BACKEND_DELIVERY_FORMAT, @@ -72,32 +51,21 @@ const input: BackendReportInstanceType = { }, }, delivery: { - recipients: ['szhongna@amazon.com'], - deliveryFormat: BACKEND_DELIVERY_FORMAT.embedded, title: 'test email subject', textDescription: '- test\n- optional\n- message', htmlDescription: '
    \n
  • test
  • \n
  • optional
  • \n
  • message
  • \n
', - channelIds: [], + configIds: [], }, }, }, status: BACKEND_REPORT_STATE.success, }; -const testAccessInfo: AccessInfoType = { - basePath: '', - serverInfo: { - name: '', - hostname: 'localhost', - port: 5601, - protocol: 'http', - }, -}; +const sampleServerBasePath = '/test'; const output = { - query_url: - "/app/dashboards#/view/722b74f0-b882-11e8-a6d9-e546fe2bba5f?_g=(time:(from:'2020-11-11T00:32:00.000Z',to:'2020-11-11T01:02:00.000Z'))", + query_url: `${sampleServerBasePath}/app/dashboards#/view/722b74f0-b882-11e8-a6d9-e546fe2bba5f?_g=(time:(from:'2020-11-11T00:32:00.000Z',to:'2020-11-11T01:02:00.000Z'))`, time_from: 1605054720000, time_to: 1605056520000, last_updated: 1605056644321, @@ -109,7 +77,7 @@ const output = { report_source: 'Dashboard', description: 'some random', core_params: { - base_url: '/app/dashboards#/view/722b74f0-b882-11e8-a6d9-e546fe2bba5f', + base_url: `${sampleServerBasePath}/app/dashboards#/view/722b74f0-b882-11e8-a6d9-e546fe2bba5f`, report_format: 'pdf', header: '

test header

', footer: '

fake footer

', @@ -129,15 +97,11 @@ const output = { }, }, delivery: { - delivery_type: 'Channel', - delivery_params: { - recipients: ['szhongna@amazon.com'], - title: 'test email subject', - textDescription: '- test\n- optional\n- message', - htmlDescription: - '
    \n
  • test
  • \n
  • optional
  • \n
  • message
  • \n
', - channelIds: [], - }, + title: 'test email subject', + textDescription: '- test\n- optional\n- message', + htmlDescription: + '
    \n
  • test
  • \n
  • optional
  • \n
  • message
  • \n
', + configIds: [], }, time_created: 1605056426053, last_updated: 1605056426053, @@ -147,7 +111,7 @@ const output = { describe('test backend to ui model conversion', () => { test('convert backend to ui report', async () => { - const res = backendToUiReport(input, testAccessInfo.basePath); + const res = backendToUiReport(input, sampleServerBasePath); expect(res).toEqual(output); }, 20000); }); diff --git a/dashboards-reports/server/routes/utils/converters/__tests__/uiToBackend.test.ts b/dashboards-reports/server/routes/utils/converters/__tests__/uiToBackend.test.ts index d61fc3c8..a1fbe6d6 100644 --- a/dashboards-reports/server/routes/utils/converters/__tests__/uiToBackend.test.ts +++ b/dashboards-reports/server/routes/utils/converters/__tests__/uiToBackend.test.ts @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ import { ReportDefinitionSchemaType } from 'server/model'; @@ -53,12 +32,10 @@ const input: ReportDefinitionSchemaType = { }, }, delivery: { - delivery_type: DELIVERY_TYPE.channel, - delivery_params: { - recipients: ['szhongna@amazon.com'], - title: 'Email subject', - textDescription: 'This is a test email', - }, + configIds: [], + title: '', + textDescription: '', + htmlDescription: '' }, trigger: { trigger_type: TRIGGER_TYPE.schedule, @@ -94,10 +71,10 @@ const output = { }, }, delivery: { - recipients: ['szhongna@amazon.com'], - title: 'Email subject', - textDescription: 'This is a test email', - deliveryFormat: 'Embedded', + configIds: [], + title: '', + textDescription: '', + htmlDescription: '' }, }; diff --git a/dashboards-reports/server/routes/utils/converters/backendToUi.ts b/dashboards-reports/server/routes/utils/converters/backendToUi.ts index 1799dcce..0d9b9816 100644 --- a/dashboards-reports/server/routes/utils/converters/backendToUi.ts +++ b/dashboards-reports/server/routes/utils/converters/backendToUi.ts @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ import { @@ -139,7 +118,6 @@ export const backendToUiReportDefinition = ( const baseUrl = getBaseUrl(sourceType, sourceId); const reportSource = getUiReportSource(sourceType); - let uiReportDefinition: ReportDefinitionSchemaType = { report_params: { report_name: name, @@ -175,7 +153,6 @@ export const backendToUiReportDefinition = ( last_updated: lastUpdatedTimeMs, status: getUiReportDefinitionStatus(isEnabled), }; - // validate to assign default values to some fields for UI model uiReportDefinition = reportDefinitionSchema.validate(uiReportDefinition); uiReportDefinition.report_params.core_params.base_url = @@ -370,20 +347,17 @@ const getUiDeliveryParams = ( delivery: DeliveryType | undefined ): DeliverySchemaType => { const opensearchDashboardsUserDeliveryParams = { - delivery_type: DELIVERY_TYPE.opensearchDashboardsUser, - delivery_params: { - opensearch_dashboards_recipients: [], - }, + configIds: [], + title: '', + textDescription: '', + htmlDescription: '' }; let params: any; if (delivery) { - const { deliveryFormat, ...rest } = delivery; + const { ...rest } = delivery; params = { - delivery_type: DELIVERY_TYPE.channel, - delivery_params: { - ...rest, - }, + ...rest }; } else { params = opensearchDashboardsUserDeliveryParams; diff --git a/dashboards-reports/server/routes/utils/converters/uiToBackend.ts b/dashboards-reports/server/routes/utils/converters/uiToBackend.ts index 5bf2927e..4a2064cd 100644 --- a/dashboards-reports/server/routes/utils/converters/uiToBackend.ts +++ b/dashboards-reports/server/routes/utils/converters/uiToBackend.ts @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ import { @@ -109,20 +88,16 @@ const getBackendDelivery = ( delivery: DeliverySchemaType ): DeliveryType | undefined => { const { - delivery_type: deliveryType, - delivery_params: deliveryParams, + configIds: configIds, + title: title, + textDescription: textDescription, + htmlDescription: htmlDescription } = delivery; - let res: any; - switch (deliveryType) { - case DELIVERY_TYPE.opensearchDashboardsUser: - break; - - case DELIVERY_TYPE.channel: - res = { - ...(deliveryParams as ChannelSchemaType), - deliveryFormat: BACKEND_DELIVERY_FORMAT.embedded, //TODO: now we only support one delivery format - }; - break; + let res = { + configIds: configIds, + title: title, + textDescription: textDescription, + htmlDescription: htmlDescription } return res; }; diff --git a/dashboards-reports/server/routes/utils/dataReportHelpers.ts b/dashboards-reports/server/routes/utils/dataReportHelpers.ts index 3840121b..bc108832 100644 --- a/dashboards-reports/server/routes/utils/dataReportHelpers.ts +++ b/dashboards-reports/server/routes/utils/dataReportHelpers.ts @@ -1,35 +1,18 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -import { DATA_REPORT_CONFIG } from './constants'; - -import esb from 'elastic-builder'; -import moment from 'moment'; +import esb, { Sort } from 'elastic-builder'; import converter from 'json-2-csv'; import _ from 'lodash'; +import moment from 'moment'; +import { DATA_REPORT_CONFIG } from './constants'; +import { + buildOpenSearchQuery, + Filter, + Query, +} from '../../../../../src/plugins/data/common'; export var metaData = { saved_search_id: null, @@ -43,97 +26,43 @@ export var metaData = { fields_exist: false, selectedFields: [], paternName: null, - filters: [], + searchSourceJSON: [], dateFields: [], }; // Get the selected columns by the user. export const getSelectedFields = async (columns) => { const selectedFields = []; + let fields_exist = false; for (let column of columns) { if (column !== '_source') { - metaData.fields_exist = true; + fields_exist = true; selectedFields.push(column); } else { + fields_exist = false; selectedFields.push('_source'); } } + metaData.fields_exist = fields_exist; metaData.selectedFields = selectedFields; }; -//Build the OpenSearch query from the meta data +// Build the OpenSearch query from the meta data // is_count is set to 1 if we building the count query but 0 if we building the fetch data query -export const buildQuery = (report, is_count) => { - let requestBody = esb.boolQuery(); - const filters = report._source.filters; - for (let item of JSON.parse(filters).filter) { - if (item.meta.disabled === false) { - switch (item.meta.negate) { - case false: - switch (item.meta.type) { - case 'phrase': - requestBody.must( - esb.matchPhraseQuery(item.meta.key, item.meta.params.query) - ); - break; - case 'exists': - requestBody.must(esb.existsQuery(item.meta.key)); - break; - case 'phrases': - if (item.meta.value.indexOf(',') > -1) { - const valueSplit = item.meta.value.split(', '); - for (const [key, incr] of valueSplit.entries()) { - requestBody.should(esb.matchPhraseQuery(item.meta.key, incr)); - } - } else { - requestBody.should( - esb.matchPhraseQuery(item.meta.key, item.meta.value) - ); - } - requestBody.minimumShouldMatch(1); - break; - } - break; - case true: - switch (item.meta.type) { - case 'phrase': - requestBody.mustNot( - esb.matchPhraseQuery(item.meta.key, item.meta.params.query) - ); - break; - case 'exists': - requestBody.mustNot(esb.existsQuery(item.meta.key)); - break; - case 'phrases': - let negatedBody = esb.boolQuery(); - if (item.meta.value.indexOf(',') > -1) { - const valueSplit = item.meta.value.split(', '); - for (const [key, incr] of valueSplit.entries()) { - negatedBody.should(esb.matchPhraseQuery(item.meta.key, incr)); - } - } else { - negatedBody.should( - esb.matchPhraseQuery(item.meta.key, item.meta.value) - ); - } - negatedBody.minimumShouldMatch(1); - requestBody.mustNot(negatedBody); - break; - } - break; - } - } - } - //search part - let searchQuery = JSON.parse(filters) - .query.query.replace(/ and /g, ' AND ') - .replace(/ or /g, ' OR ') - .replace(/ not /g, ' NOT '); - if (searchQuery) { - requestBody.must(esb.queryStringQuery(searchQuery)); - } +export const buildRequestBody = (report: any, is_count: number) => { + let esbBoolQuery = esb.boolQuery(); + const searchSourceJSON = report._source.searchSourceJSON; + + const savedObjectQuery: Query = JSON.parse(searchSourceJSON).query; + const savedObjectFilter: Filter = JSON.parse(searchSourceJSON).filter; + const QueryFromSavedObject = buildOpenSearchQuery( + undefined, + savedObjectQuery, + savedObjectFilter + ); + // Add time range if (report._source.timeFieldName && report._source.timeFieldName.length > 0) { - requestBody.must( + esbBoolQuery.must( esb .rangeQuery(report._source.timeFieldName) .format('epoch_millis') @@ -142,47 +71,75 @@ export const buildQuery = (report, is_count) => { ); } if (is_count) { - return esb.requestBodySearch().query(requestBody); + return esb.requestBodySearch().query(esbBoolQuery); } - //Add the Sort to the query - let reqBody = esb.requestBodySearch().query(requestBody).version(true); + // Add sorting to the query + let esbSearchQuery = esb + .requestBodySearch() + .query(esbBoolQuery) + .version(true); if (report._source.sorting.length > 0) { - if (report._source.sorting.length === 1) - reqBody.sort( - esb.sort(report._source.sorting[0][0], report._source.sorting[0][1]) - ); - else - reqBody.sort( - esb.sort(report._source.sorting[0], report._source.sorting[1]) - ); + const sortings: Sort[] = report._source.sorting.map((element: string[]) => { + return esb.sort(element[0], element[1]); + }); + esbSearchQuery.sorts(sortings); } - //get the selected fields only + // add selected fields to query if (report._source.fields_exist) { - reqBody.source({ includes: report._source.selectedFields }); + esbSearchQuery.source({ includes: report._source.selectedFields }); } - return reqBody; + // Add a customizer to merge queries to generate request body + let requestBody = _.mergeWith( + { query: QueryFromSavedObject }, + esbSearchQuery.toJSON(), + (objValue, srcValue) => { + if (_.isArray(objValue)) { + return objValue.concat(srcValue); + } + } + ); + + requestBody = addDocValueFields(report, requestBody); + return requestBody; }; // Fetch the data from OpenSearch -export const getOpenSearchData = (arrayHits, report, params) => { +export const getOpenSearchData = ( + arrayHits, + report, + params, + dateFormat: string +) => { let hits: any = []; for (let valueRes of arrayHits) { for (let data of valueRes.hits) { const fields = data.fields; - //get all the fields of type date and fromat them to excel format - for (let dateType of report._source.dateFields) { - if (data._source[dateType]) { - data._source[dateType] = moment(fields[dateType][0]).format( - DATA_REPORT_CONFIG.excelDateFormat - ); + // get all the fields of type date and format them to excel format + for (let dateField of report._source.dateFields) { + const dateValue = data._source[dateField]; + if (dateValue && dateValue.length !== 0) { + if (dateValue instanceof Array) { + // loop through array + dateValue.forEach((element, index) => { + data._source[dateField][index] = moment( + fields[dateField][index] + ).format(dateFormat); + }); + } else { + // The fields response always returns an array of values for each field + // https://www.elastic.co/guide/en/elasticsearch/reference/master/search-fields.html#search-fields-response + data._source[dateField] = moment(fields[dateField][0]).format( + dateFormat + ); + } } } delete data['fields']; if (report._source.fields_exist === true) { - let result = traverse(data._source, report._source.selectedFields); + let result = traverse(data, report._source.selectedFields); hits.push(params.excel ? sanitize(result) : result); } else { hits.push(params.excel ? sanitize(data) : data); @@ -197,10 +154,10 @@ export const getOpenSearchData = (arrayHits, report, params) => { }; //Convert the data to Csv format -export const convertToCSV = async (dataset) => { +export const convertToCSV = async (dataset, csvSeparator) => { let convertedData: any = []; const options = { - delimiter: { field: ',', eol: '\n' }, + delimiter: { field: csvSeparator, eol: '\n' }, emptyFieldValue: ' ', }; await converter.json2csvAsync(dataset[0], options).then((csv) => { @@ -220,7 +177,7 @@ function flattenHits(hits, result = {}, prefix = '') { ) { flattenHits(value, result, prefix + key + '.'); } else { - result[prefix + key] = value; + result[prefix.replace(/^_source\./, '') + key] = value; } } return result; @@ -249,11 +206,11 @@ function traverse(data, keys, result = {}) { */ function sanitize(doc: any) { for (const field in doc) { - if (doc[field] == null) - continue + if (doc[field] == null) continue; if ( doc[field].toString().startsWith('+') || - (doc[field].toString().startsWith('-') && typeof doc[field] !== "number") || + (doc[field].toString().startsWith('-') && + typeof doc[field] !== 'number') || doc[field].toString().startsWith('=') || doc[field].toString().startsWith('@') ) { @@ -262,3 +219,20 @@ function sanitize(doc: any) { } return doc; } + +const addDocValueFields = (report: any, requestBody: any) => { + const docValues = []; + for (const dateType of report._source.dateFields) { + docValues.push({ + field: dateType, + format: 'date_hour_minute_second_fraction', + }); + } + // elastic-builder doesn't provide function to build docvalue_fields with format, + // this is a workaround which appends docvalues field to the request body. + requestBody = { + ...requestBody, + docvalue_fields: docValues, + }; + return requestBody; +}; diff --git a/dashboards-reports/server/routes/utils/helpers.ts b/dashboards-reports/server/routes/utils/helpers.ts index ff83b93b..5bada6d0 100644 --- a/dashboards-reports/server/routes/utils/helpers.ts +++ b/dashboards-reports/server/routes/utils/helpers.ts @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ import { OpenSearchDashboardsResponseFactory } from '../../../../../src/core/server'; @@ -105,3 +84,11 @@ export const checkErrorType = (error: any) => { return 'system_error'; } }; + +export const joinRequestParams = ( + queryParams: string | string[] | undefined +) => { + if (Array.isArray(queryParams)) return queryParams.join(','); + if (typeof queryParams === 'string') return queryParams; + return ''; +}; \ No newline at end of file diff --git a/dashboards-reports/server/routes/utils/metricHelper.ts b/dashboards-reports/server/routes/utils/metricHelper.ts index ca21aa6e..d58876dc 100644 --- a/dashboards-reports/server/routes/utils/metricHelper.ts +++ b/dashboards-reports/server/routes/utils/metricHelper.ts @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ import { ReportSchemaType } from 'server/model'; diff --git a/dashboards-reports/server/routes/utils/notification/deliveryContentHelper.ts b/dashboards-reports/server/routes/utils/notification/deliveryContentHelper.ts deleted file mode 100644 index 1c1aa22f..00000000 --- a/dashboards-reports/server/routes/utils/notification/deliveryContentHelper.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -import fs from 'fs'; -import cheerio from 'cheerio'; - -export const composeEmbeddedHtml = ( - htmlDescription: string = '', - originalQueryUrl: string, - reportDetailUrl: string, - reportName: string -) => { - const logoAsBase64 = fs.readFileSync( - `${__dirname}/notification_content_template/logo.png`, - 'base64' - ); - - const $ = cheerio.load( - fs.readFileSync( - `${__dirname}/notification_content_template/email_content_template.html` - ), - { decodeEntities: false } - ); - // set each link and logo - $('.logo').attr('src', `data:image/png;base64,${logoAsBase64}`); - $('.report_name').attr('href', reportDetailUrl).text(reportName); - $('.report_snapshot').attr('href', originalQueryUrl); - $('.optional_message').html(htmlDescription); - //TODO: Add this once we have the actual link to download - // $('.report_download').attr('href', '') - - return $.root().html(); -}; diff --git a/dashboards-reports/server/routes/utils/notification/notification_content_template/logo.png b/dashboards-reports/server/routes/utils/notification/notification_content_template/logo.png deleted file mode 100644 index 46aa560ab0d47464ffc94bd4e876ffb07fcc4b19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9995 zcmXYX1yB^u`##*!b%-<)ih_!C_tDZIC4JHz(s96nfJiGy37m9yNgNGT@Doc+ijWy@$G2f2}Zd z)~qx-H7Ry+-n-&^)jW-OOcFO^RQ#JDj)aCr)9vBl-BpLAk95HPm(#qfjivM4&6CS6 z;ggXQnSVxdJWF`<%awmld7{%?lXG}chdIo9#r;q!km$PAyw$@%9Y_cw_y=Dp&)4*X6=ye{lR-k`L-2q2LQGQR6S>;c z(Nlc){X+js%^yx5L?xp^7|SgogtCwYwF3JO1R!dG48VAl2#y=jIFMDq=L&C`4@&!< z+*{@C50nq&_y@RVNCciFDDa+LF}^odA2=24J_k)q0JOAN0seE60K^EQX4Dl=6;f-@ zooF?{vXG)nE;k3=oaZSo|C@+!2Osd)Vnz7=L!Tn0P#vZ21h9L%w`A63=pKR9e@^oR ztw?L{k8I53SAtn`sFgRL!86p>xk+3#9dcwe6vP7IvurDwyHv*bjiMdZkZxHSo{zYe^7DqtxG=C9SN!;rYDx|afAREfkaVPOq0qe zFl8`azUR9*LgCCyK-PJ0$VFHv(IxY}IZ4L;APAKJ?3ita$(WOttQTk>91*qarI&_l zgZAoWnX`LzdqfG=&O7j=Z(EDQi3>Ot=y60}@gbMS%xcnSgzQwKf4$Tk9<00e)Nq{c z(`DKBnDms?(|!jY`pY=Y6^}oF%+IP>BwbGr{&t7j8H}a7P zU9qjXx5XZc``YBO-n>t7{7#tqYH=91dGGL!QZ0(~YR*QczxPYAI4wm>3$X+qR^Z4d zC4=oOk%DuS3XLf}t8Pw53Mq$+;jJnZ`raq{ezivEK;JFOTsFF}2<{KrBnnsIv@4#w zbsGM_+`(OF zl2gT0vW?58 zd2wc7-L_UjsUEWXIF`staBA%5GW$oY?^rdk8Ug%rD22Q%fjXIsVcRXjd6LtsAiI`# z;xl~#rkg$Qp-T#jyDK(_l>b(r_vusgy-@eUZ@$bF?tPYf#uDrE&!+dtr$uS{z~bj0 z=ER~Ap=*Uv2@lc{N6#XrsNa&qG$TB%-b^E*X}`sY2J_7gaxBXD+NmcccTf)negpRx z8=wlc77;1mXzjA@_*10u?aY+3z5Om}V~ca~-lJ2(Yz!+msh-TC-Am4htcmSEwUA{W ze=z*=$>~69oTDjnRD0$d%2u<=K0)vp0hSd~9UrKv>P(RR^hkmM+1Dr|LjNbPKSuq} zC1AFDr8{-vVmYC@^Vt~-C7P@zKNuI(u}$uWIGQ4Gv2y?-5P@1Ires?kWvnP6U~|&M zct!O!zX2t>t_c}(9d4B66RcFe-uh!?K~y@?l2GMS`vd2{9r<}w8231;@Yg^0P-@^_ z#a5Hj$XW%{CXyIF{$H1TDmHp!7 zbeLj47lg{5Irv>5{*DP`oEilNs@XIu@wb(L9^`x)T=pC`ZjVkM|2QS~K4iM0`a?Ki z%90`vFd6Z6d`QNDjL={{Pw>cAs6JjOwA$!s3Ia^Y@K;k$;?CyR@}Q4U~{!!--47JI7j<_7c}^h&`&GweUA zQ=0hAo~+>j8CZxmXog-aa;dj z9Q#ClnkJTugU6ujBC{6e@#8Z>rZDslu07 zq~**MpkKd>BV6DmVfe|%jDbrx78g>t;ebwal0)I{Q<$3t{I~HY0zx&Nf0#$i$GSbN zV!KS+t84LQxE_=N^_Sw|_uh$87`OCVQ8^_O+ca7AKQZ?rXy(Q}dF#_mhrZ_-5y~|Jo!_1sBIu7Pne=lw;g#V5~*<% zpA>${T?sXp)eMtST<*IC!}l_tPh_k=Yhyq@9LzPRYY;k&eTD5(m;{+?TR$+hbRKdu zgP-NTHzhjOq5qon@ejwvefMXOtFzf-|5YcdFAjHX-ych@&)Ztdcsf4O4W|=vJlVo1 zYZlc0eSTDaCd+?*(35#~jumyuza$0xt$6eN3di>6&yvUa_vXppCF@-)3N-*e{b>*+W0~ zuQi#vl)4Kh!oF=#~P_M!e2*4U~M<1*$w!vrHVkJH4njFzq zLQFiC0>k{yM_T^&LdnJO?t4kE@>$g$w`_IH{3Htit61x@unR1=Z`l{;bC#w1JvfCI zuuA|F9=&!QZ)<3#DMda;c;@W?ENVH7qJMf{Mkw(Ckj-arK!Y3|#faJh^tBg7=u8?( zP~Ylswq_txjCs6U>z`!SW(NMSeW^Pek7Q$evPcCwJv^yfIw#5LNNi~7UI2y3Xt&74 zuc|PVkIKqUNq)|fh@soXmi%I2N^eon3Hj-2pT@6Q)iIC)@MgZW3vEH|`c~k6K>8HE zp7S>|l&@^euVN)v-(vI5jG9Pl<5PE=ZPjGvyjh+(d?|rSPwu75s5rWiAc>ASf$)im)Bx{2gQ(2Q%w) zusQev>*fmKI%IXC5%vXT^=W^lGw46Lw>tX?u}v@IcTH-mcla-t`%PNa>PYX8^OC$_ z@0ECEVmRphRAn{zOJiFT-(;8!7Yw$(+ zi|evY;tbNJuN>8MjT=fKxOo7fV-D@(aJ;5149W56U5Us8ma=kl1}ELQ;#9uE%JfNq z=TG(rv}Tk}$Cb5Yl1bTGrraw@6ZmU}t;VTxE48dO$C z3^`^yo)~4&Def6fOrVINl#fGFDxX7Z>g`;%(Q|%eT@7GZK_;_ z#)x~q3a-k24!RX8;rpDp_+(dO7Ed>#F~WF87Iq*x@u9^^OU{4Hc5QVAWboCISBzC@ z848;j{Nf~JEcIEi%O$#h%>iT*4T5T-5E?+ zg4Ihpa_2!<)=zSQ7Wvnsg6&V&V>6SlUV7q<1KlN`zUKiS;Q0g1M!$*B_5T@}ZuN*R zy#~!8jpG4f=_}5^lz0@T12BDFqy;CGZ-GN>e^CQznE=?{fbdeQO$#A*R-dn4G)>31-z(Zo&5KObwJ;3~K3NUB*#9Z> z>&ro6-cqeqreW>*HwN=oNl&IO^_jMK4c7P=T4Aim%|5!@HZ#pn&FkUJ@53s?07_VU z1F;0S1}_nrK6=KUYfjZ>T_}ojJit&zT@5f!Wq2|~xc7>!Situ<*>fGPfUxM^ST+U1 zBm5PPLnyo!jkW)4(38UVN>n-eASxwW%$;y8L#)3Fd)}h;TLy;!S-oid)?kJm!L(40 zizBi-UfU6w^J+g1e~tuk8ttZHI2oXO=WJfit{vLXlf4KFj?Ig3;ELb@<*?DRF&*0X zwxkNDnm&6U5jJTcY&3><#d4+aNMJM3ox{+V668g_C7#oL#`=&cNM-5$(4GaZ0BDu} zR$P&JQ{Ow$pw*hQe*$`cWOFX|9C%3gR8f@Y1;quxRGJXu$rL4*QA3V8HXpgDfMw&_ z;-49%N0g=eeyO!CuGye^-@u1Z_l?fdefO3avxx10*Y%`T1Evrdn*6i!M}FKqNWuN#*=V*o@@lU;ClFXuZz?seU1yEN9Jh#!81o zy)#T&73DAaW#R{CeCu0M85MO~d)T`P=fa*V&ixG*Qq|vl3tH(QaSE}MpYz*%1r5Ic zV`9UbPV$1AGsJ}|C@zf1zqlJzN&R%4mnstJ2Jwc=7L93~i%8T_GNZ?f#uTo^W+>k5 zUCMq^cgBG>@2E^~B)ZOCoS?LyVu7nPwCtrGwz~soaZ;CoeqK~BgFhcpp0+dYk^WXY zP(k?@*KW1Z^--P5P+s$FNLzX7TngvZk`AMb*iz}!g2 zTEKgqhyq{0?S+s2dO?B{pJBK-L<><5-e$U$oiQsIzhr_8f zefz^BaZMe{@N@=2Z*uBtDHlqL7gZn-H7S3SREI6 z3QPL8#qHpi3`B)F!S#J(fWb2$DxYvLKe<3Urb%(I3hV$e6p6F5X`M_+Q7=4lep9$= zd=`vn`DH3^AHM%%=_v}V&eoI46P3yl*Z->ge)S~v>O|kCf;F~I_iYBEgZaXxI$q-Y zQmit_AsINGMzn-}#uH&$Y~EPhO=bE5_1a>(c9kNF;hNPOQ(M$9hu(kO!=#KJCAvuf zZ|gTV`Dhf0?4^ti)p-G5As zrmUm&q(^Bvia3(kY#HdFVj;3ZKjkVq9>}h0ziUT=W@4rL5&5t2Lr@O^CjCSCxS?S! z#7En}^|9Xg2|w zQ(o)ed<9p!iz1%u1#;Ci-2GqoUf?so?5l`Tyf>L`MIOVXaHfzTvh`zE(R{K3VZMkpMHpzisAM_tm-= z*bCfShiSk!T1*sh0g@eIkAidUca-u~7>esv=%W6Qx1k4R%DUVjJ8p}|g`TozC>%Xn zvkkWriVFMnUclj|?Uswux2!KLCjv31A>WFJgMx14`kdg)b6a(CNGraAajE{Xv0_91 z(C4-f9A{=0V4YzB%GdzRS}eF1$h(T4G-0$g@=-rF#wP(I4jJZTo}ufc3KgN+xLt1+ zTjdpGyYYf@7FiRyN=+!-Q2lDmOTwJThRkRAis3y7NqD22?gRq@yrm3keJ{b7stErU%is{xg z47e98{_sja!3`3C4?+{VBxXe^9uR`!IgA}kRDph+@>^+BwPwvZ98iK2AB6te2Z8ojbFFbtW(1boyDAY9is>z4x9-iA8t}I8wjw#GfRvDn(=F!30{PLRTrCHs-Ma zyF#u78GB);51h^Kt-emC+UYhEQH)~NA1lz5X8?~~JKnqcED_&+OFpu8Qe78{ulybmYJBVy%k;slZ^TWM)$$hJ~srKV!{8MUa#2AVM zK$#JV-vjh#p1I#vO4L+wP2Nz?-t)RmSTpZATo9 zlo!cQTpg$SqgIGp4k;hv^^H!cf9Kc#Bw*4A?(VgS+mUnEG#nJPp3unm#=(M&3|;*$ZW5R zpM}~0nYX^qHGAI~d7vC`!cbP8!@l4!^uzu%c(-=(VNWF~I<1?0AJ4nUN7JWVI_LUb zLCtS71^Z(8P0!+05k_VHL;c^qj|Zo!z6?LWcju$*R}-*MQiSf|dt zWxHYqpXNKg<8%MGXXMVpY(+92|Gd!Ao{8cL1WDxmCF2p#vh9{g+R7+L-Z_j}6!_qYb$`vot%ja}C70yZ6*E zBb^~Y(bGj3pHPg*Qe}^B1TKI!5HN$4E=??~)?j5ZpE(`wGY1Y@7o7JzV$1ru()|MV zo;INtj~M@SodnKN1F?I0rh^Y_*c_)qU)fmq8ey#ksL`RFYTt+h@flI|g(_PxNWh^q zgk6}nlofIn-N0HFu4T#-kh*bg1-DgU2s)RjCdai{da`jY<9ozHo}dg}M#J)__Y-VT zwX+e%9}`hLjAfGgIig&1^(J<${moHdJPzD&;?Y(uGV2~Ic#zsQzepnwVph``Iw9gy z!nCI8+<0WxJ(w8-cg|Q5ybJeS|M%yCGq8{ICw{$UXVP7B(Z53+t-@udtSo{TQu!25 zZsAOd&M-6l{*=h!;SyHq=-Qql2wd`D2kpF1S?xLfE$AH;VMpKv^Q2Ng$+jlsiHVN= z#c}Iw-eq=YfF@Dc?1>|>3+s4t6r~NW?1%yo^SIKH#*e_7f#at%;h$!A{9%8%an5QF z8-!lXLq8A%_;;eSMn9{M79yveHnoHo=}Z0LcKH2X-ecZB;@B z)NIGlG@1TST@hqUW%tA8WJKPE=Z@J zEnzY^Lb~7T8wxYyQCA8^8ow9N(}4Gn{VowMy2G#csZM%zr?f)kT#X$iGl3N$zXQ9X zA|4WM@2ih}MS%3Y?#u2Ee|PP_o`snS!nt10LE&RohfgEMT&6pMFy{bK1v8<;U2wIe zS^~H7@O(1zOnkj$3 zObsIMy-kr9ZJH7N0Fj0{T}wICrCfOg zIgh73#glMxy%o2O8K;6{$|zHaEUzlim!rK8MoQ7XLcT0ev#HKbB$XEe6J{&1~cX~4{BjM6C3d-z}cM;so7$Ry-B{k*;I+%_ZXVCQ=3X_VEBNs_k5`G z5$LX~O#Av58Or6zM3A@&<3J*)vqw5+E1Ksx?_5;e+LrG5>jeTiz~*pt6l@v=8S~q$ zr)wjf;SpL?btUwF+ID{{4$+df@p$=#8A@mY`61c+8RU!*WGa?!glEa}fY9)q%NF;H zdYP+(e{OyX*k}j=``ET{(2EjHxDQ`5T`|21k)ga4Q!@Xii~=-MAs+dv-76OI&D<@9 z8RMI&n}8x|+?Kz?WXlMo?Q=5cg(T8L^J-U@8h!7x15Dpme-Y*G#z~ZnBnh2+0xYku zB35B7lnX{BfYE0V>H&DmLbk%0ifJV(=DnaSsO85XZpBalFvGz4L6{exj}T~BHz?6uYjT&&e}Bh=d?ZvIO$ZG4)LcK!q#7y&N>I6>K!9Zk{u{weE!;d2_cOKufZWz z48Zwt76Um}k*KBC1WbWGnIIb!5dPvdFp4~Cu?Gx~aB=b+tGCVslrLsfB6C~u5RS91 zxNB4Q%Z9TDpEt~{m4breU{XTNcf?e7sU+WjLAlVwviYK zgOW+B-8dZkLV{oMV`HcFLJU~M)v3wmTcI8nvxIzRZPz)$%odINJ> zrsh!F=*(IqyBD<#@=e-ONP`m3b*ob*H|#zy`>d0&3H0Kb0j*X7LhinGPp!BbhZ*o# zKh+Fjl?u<($+lH9O1!Qp8Su5O`gdiX^iRC=NZeJpFuS2C0nCjeG$OZ!R#Y)|2h3hH z5|j&M*x(uKUW+x`IGkT^ey=6Cav=cbG4wmm$fZ-!Ge`#6mQ`ZL=w`ayH$32QWX=Cv zyn%qN<#_K4E4`mp?E>$zKJX9YM098O)KX|ut$Rd+x;ft`&cYifC0LX5kG6iuHAy9` zxcZvocv*ElT@&+*BCFepLaC~LuP<;{*0r)?wXqy#W@*#VlnbvsKZ1zVsS}UlA&I}a z?vZ_R>|sfnt}s#fu@o!x$mipwEYejsp0R{`52Op-B9{95XPURk=Yf+S>gRBZoX?&! z8R>R@*`#sY7SqQ5)b?!4T}YQ`(=jR~s~p4<{h;v&Zj}&X zrcy6y-qSKRTN*dME$Wn!0BI3={(ITErL<(h!dPCWTs>*n@R35rQ8k&bTZL6o0NSMS z%I)}Y;3Y=^@FiX6>4Jmpzi*_sZtx^bt6Dz+v|%zPG7R1TeL2UvOJzkAGbZldBhf3M z-VHE`;8l2%`RO_Qxzi#Z#dc&%X8oI2fmbZBr|I(R;<9Pz*A7I#V4S_LA%iR_Wg|l2 zn0fcqhs};<4z~qo!o--DR^#Jt?Kz6p0wIRA(rGslP{g)Qw+6ad7hcjxMsYS3XTud- zBW1%A<)B7@addKgSUJm-UCf^aXqJj|(-k0_DViEe1P44n8&(qvfMusgFjYP0d@ilW z(h-Cb)$T6v<|4wpR8`Q#pF|GW?GuaR&#N8i?E@*MzHA9JKkE8zC{=##9NAc&t>vKG z(e0ntu9*Nyd;anRx)f898EOMh>MtXY>B=s8{g7RkM?OTQ+UEqe{nszNyKGgfd#CJM zro`$TG3)$t|GUt&c>H#}A99}x_&jbsO2(*C;!YSYpP9gue3MF9Geo8lf>bbTpVF6? zLXfg%6Eya%_~azO*|P43Y9sK}Yc6wK4$sjy?{;gz$5(*Nr0A45E2ww2hXAj^4@>%G zIm-0!uD;{kwdofvdO80EI?<|yG-e z^{}V3w&P<)uQ$i3`*XWs{7bYWx&L}WiI1Ck2fKIBnnsrVt_78^OwJ9qjm!07&=Zdh zu>X_MINCSXo1$#KBHF|SUSrkk8vObdYzzaJ?|^?3ompUivty&%>JdBNNpoUiyCX37 z? zg7a*7Q9lH2P*-`KN>Sk@^ge~cffCB%9q(SHi>5Ohe0oR@P*`6a8=6JJ(jGrS=%p#Z z6G&wdotRogr>M%nJq5+Ti{4(i=pJ;ner>x;x&b_ZP50_yOFwea;9OkoA%J%5vf^~- zRBD;0iH#=Dy0!v8oN(F>-r9uDAT9bv5>h;BT@%CkW^OvxCkLO^ryY_=T-a0SeXHQe zjT!Y07km5Z=>W~Kd_jZmV=tED@qV%lONG_gh=Qibd3Fj>Tb1f5B>zH-qU3)HBqJH> zkR9_^#PNvZQ^LJu-g1z-gH_2fxW-DCi!{3ZKZz03HvYkm;1ho*i56^)y%lQOYIGqI z>5j4PHGBASGdG)q{eOJe1e=o!oQotoBGb`g?p#_jSy5*;B-J_=af9!)EcSnN;Pe^Z zRd;X!+xc2_cqFx5$vg_z2CJQ&0QnvMVRM^u8t>%6{%tq}j$t&q6A*`Sp4 zJMqMFGfZwFkR^d={7COm81;`d`yX;qz&ntLqKA5YXrA&vbsL_#ijH!PA|&$v0g*Ct AOaK4? diff --git a/dashboards-reports/server/routes/utils/savedSearchReportHelper.ts b/dashboards-reports/server/routes/utils/savedSearchReportHelper.ts index 6b839917..ce05b412 100644 --- a/dashboards-reports/server/routes/utils/savedSearchReportHelper.ts +++ b/dashboards-reports/server/routes/utils/savedSearchReportHelper.ts @@ -1,31 +1,10 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ import { - buildQuery, + buildRequestBody, convertToCSV, getOpenSearchData, getSelectedFields, @@ -34,9 +13,12 @@ import { import { ILegacyClusterClient, ILegacyScopedClusterClient, + Logger, } from '../../../../../src/core/server'; import { getFileName, callCluster } from './helpers'; import { CreateReportResultType } from './types'; +import { RequestParams } from '@elastic/elasticsearch'; +import esb from 'elastic-builder'; /** * Specify how long scroll context should be maintained for scrolled search @@ -46,17 +28,23 @@ const scrollTimeout = '1m'; export async function createSavedSearchReport( report: any, client: ILegacyClusterClient | ILegacyScopedClusterClient, - isScheduledTask: boolean = true + dateFormat: string, + csvSeparator: string, + isScheduledTask: boolean = true, + logger: Logger ): Promise { const params = report.report_definition.report_params; const reportFormat = params.core_params.report_format; const reportName = params.report_name; - await populateMetaData(client, report, isScheduledTask); + await populateMetaData(client, report, isScheduledTask, logger); const data = await generateReportData( client, params.core_params, - isScheduledTask + dateFormat, + csvSeparator, + isScheduledTask, + logger ); const curTime = new Date(); @@ -77,7 +65,8 @@ export async function createSavedSearchReport( async function populateMetaData( client: ILegacyClusterClient | ILegacyScopedClusterClient, report: any, - isScheduledTask: boolean + isScheduledTask: boolean, + logger: Logger ) { metaData.saved_search_id = report.report_definition.report_params.core_params.saved_search_id; @@ -89,28 +78,28 @@ async function populateMetaData( // Get saved search info let resIndexPattern: any = {}; const ssParams = { - index: '.opensearch_dashboards', + index: '.kibana', id: 'search:' + metaData.saved_search_id, }; const ssInfos = await callCluster(client, 'get', ssParams, isScheduledTask); metaData.sorting = ssInfos._source.search.sort; metaData.type = ssInfos._source.type; - metaData.filters = - ssInfos._source.search.opensearchDashboardsSavedObjectMeta.searchSourceJSON; + metaData.searchSourceJSON = + ssInfos._source.search.kibanaSavedObjectMeta.searchSourceJSON; // Get the list of selected columns in the saved search.Otherwise select all the fields under the _source await getSelectedFields(ssInfos._source.search.columns); // Get index name for (const item of ssInfos._source.references) { - if (item.name === JSON.parse(metaData.filters).indexRefName) { + if (item.name === JSON.parse(metaData.searchSourceJSON).indexRefName) { // Get index-pattern information const indexPattern = await callCluster( client, 'get', { - index: '.opensearch_dashboards', + index: '.kibana', id: 'index-pattern:' + item.id, }, isScheduledTask @@ -139,7 +128,10 @@ async function populateMetaData( async function generateReportData( client: ILegacyClusterClient | ILegacyScopedClusterClient, params: any, - isScheduledTask: boolean + dateFormat: string, + csvSeparator: string, + isScheduledTask: boolean, + logger: Logger ) { let opensearchData: any = {}; const arrayHits: any = []; @@ -153,7 +145,10 @@ async function generateReportData( return ''; } - const reqBody = buildRequestBody(buildQuery(report, 0)); + const reqBody = buildRequestBody(report, 0); + logger.info( + `[Reporting csv module] DSL request body: ${JSON.stringify(reqBody)}` + ); if (total > maxResultSize) { await getOpenSearchDataByScroll(); } else { @@ -187,29 +182,30 @@ async function generateReportData( // Build the OpenSearch Count query to count the size of result async function getOpenSearchDataSize() { - const countReq = buildQuery(report, 1); + const countReq = buildRequestBody(report, 1); return await callCluster( client, 'count', { index: indexPattern, - body: countReq.toJSON(), + body: countReq, }, isScheduledTask ); } async function getOpenSearchDataByScroll() { + const searchParams: RequestParams.Search = { + index: report._source.paternName, + scroll: scrollTimeout, + body: reqBody, + size: maxResultSize, + }; // Open scroll context by fetching first batch opensearchData = await callCluster( client, 'search', - { - index: report._source.paternName, - scroll: scrollTimeout, - body: reqBody, - size: maxResultSize, - }, + searchParams, isScheduledTask ); arrayHits.push(opensearchData.hits); @@ -243,38 +239,26 @@ async function generateReportData( } async function getOpenSearchDataBySearch() { + const searchParams: RequestParams.Search = { + index: report._source.paternName, + body: reqBody, + size: total, + }; + opensearchData = await callCluster( client, 'search', - { - index: report._source.paternName, - body: reqBody, - size: total, - }, + searchParams, isScheduledTask ); - arrayHits.push(opensearchData.hits); - } - function buildRequestBody(query: any) { - const docvalues = []; - for (const dateType of report._source.dateFields) { - docvalues.push({ - field: dateType, - format: 'date_hour_minute', - }); - } - - return { - query: query.toJSON().query, - docvalue_fields: docvalues, - }; + arrayHits.push(opensearchData.hits); } // Parse OpenSearch data and convert to CSV async function convertOpenSearchDataToCsv() { const dataset: any = []; - dataset.push(getOpenSearchData(arrayHits, report, params)); - return await convertToCSV(dataset); + dataset.push(getOpenSearchData(arrayHits, report, params, dateFormat)); + return await convertToCSV(dataset, csvSeparator); } } diff --git a/dashboards-reports/server/routes/utils/types.ts b/dashboards-reports/server/routes/utils/types.ts index 6ba79ebe..3c589466 100644 --- a/dashboards-reports/server/routes/utils/types.ts +++ b/dashboards-reports/server/routes/utils/types.ts @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. */ export interface CreateReportResultType { diff --git a/dashboards-reports/server/routes/utils/visual_report/footer_template.html b/dashboards-reports/server/routes/utils/visual_report/footer_template.html new file mode 100644 index 00000000..6fc56f8c --- /dev/null +++ b/dashboards-reports/server/routes/utils/visual_report/footer_template.html @@ -0,0 +1,5 @@ +
+
+
+
+
diff --git a/dashboards-reports/server/routes/utils/visual_report/header_template.html b/dashboards-reports/server/routes/utils/visual_report/header_template.html new file mode 100644 index 00000000..9796c499 --- /dev/null +++ b/dashboards-reports/server/routes/utils/visual_report/header_template.html @@ -0,0 +1,5 @@ +
+
+
+
+
diff --git a/dashboards-reports/server/routes/utils/visual_report/report_template.html b/dashboards-reports/server/routes/utils/visual_report/report_template.html deleted file mode 100644 index 9a1e1536..00000000 --- a/dashboards-reports/server/routes/utils/visual_report/report_template.html +++ /dev/null @@ -1,244 +0,0 @@ - - - - - - OpenSearch Dashboards Reports - - - - -
-
-
-
-
-
-
- -
- - -
-
-
-
-
-
- - diff --git a/dashboards-reports/server/routes/utils/visual_report/style.css b/dashboards-reports/server/routes/utils/visual_report/style.css new file mode 100644 index 00000000..58628427 --- /dev/null +++ b/dashboards-reports/server/routes/utils/visual_report/style.css @@ -0,0 +1,211 @@ +html, +body { + margin: 0; + padding: 0; +} + +/* nice padding + matches Kibana default UI colors you could also set this to inherit if + the wrapper gets inserted inside a kibana section. I might also remove the manual text color here as well, potentially */ +.reportWrapper { + padding: 8px; + background-color: #fafbfd; +} + +/* Notice that I'm using an ID of #reportingHeader, and #reportingFooter, instead of a classname (.reportingHeader, .reportingFooter). This is + in order to force specificity here higher in case any other styles would conflict */ +#reportingHeader, +#reportingFooter { + font-family: 'Inter UI', -apple-system, BlinkMacSystemFont, 'Segoe UI', + Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', + 'Segoe UI Symbol'; + background-color: #fff; + border: 1px solid #d3dae6; + box-shadow: 0 2px 2px -1px rgba(152, 162, 179, 0.3), + 0 1px 5px -2px rgba(152, 162, 179, 0.3); + border-radius: 4px; + padding: 1em; + margin-bottom: 1em; +} + +#reportingFooter { + margin-top: 1em; +} + +#reportingHeader p, +#reportingFooter p { + max-width: 960px; +} + +/* Adjust the margin when the header is the first item */ +#reportingHeader h1:first-child, +#reportingFooter h1:first-child, +#reportingHeader h2:first-child, +#reportingFooter h2:first-child, +#reportingHeader h3:first-child, +#reportingFooter h3:first-child, +#reportingHeader h4:first-child, +#reportingFooter h4:first-child, +#reportingHeader h5:first-child, +#reportingFooter h5:first-child, +#reportingHeader h6:first-child, +#reportingFooter h6:first-child { + margin-top: 0.25em; +} + +/* nicer list styles */ +#reportingHeader ul, +#reportingFooter ul, +#reportingHeader ol, +#reportingFooter ol { + max-width: 70rem; + margin-bottom: 1em; +} + +#reportingHeader ul li, +#reportingFooter ul li, +#reportingHeader ol li, +#reportingFooter ol li { + margin-bottom: 0.25em; + margin-left: -0.5em; + padding-left: 0.25em; +} + +#reportingHeader ul, +#reportingFooter ul { + list-style-type: disc; +} + +/* here we explicitly set nested paragraphs inside lists to inherit their styles from the list, in case markdown does funky things */ +#reportingHeader ul p, +#reportingFooter ul p, +#reportingHeader ol p, +#reportingFooter ol p { + font-family: inherit; + font-size: inherit; + font-weight: inherit; + /* We only inherit vertical spacing, not horizontal */ + margin-top: inherit; + margin-bottom: inherit; +} + +