diff --git a/.eslintrc.json b/.eslintrc.json index e1cc3e6a2d..ef6e559e6c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -20,6 +20,7 @@ "react/react-in-jsx-scope": 1, "no-console": 0, "no-case-declarations": 0, - "quotes": ["error", "single"] + "quotes": ["error", "single"], + "eol-last": ["error", "always"] } } diff --git a/.github/workflows/ci-automated-check-environment.yml b/.github/workflows/ci-automated-check-environment.yml new file mode 100644 index 0000000000..e24484db9f --- /dev/null +++ b/.github/workflows/ci-automated-check-environment.yml @@ -0,0 +1,62 @@ +# This checks whether there are new CI environment versions available, e.g. Node.js; +# a pull request is created if there are any available. + +name: ci-automated-check-environment +on: + schedule: + - cron: 0 0 1/7 * * + workflow_dispatch: + +jobs: + check-ci-environment: + timeout-minutes: 5 + runs-on: ubuntu-latest + steps: + - name: Checkout default branch + uses: actions/checkout@v2 + - name: Setup Node + uses: actions/setup-node@v2 + with: + node-version: 14 + - name: Cache Node.js modules + uses: actions/cache@v2 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + - name: Install dependencies + run: npm ci + - name: CI Environments Check + run: npm run ci:check + create-pr: + needs: check-ci-environment + if: failure() + timeout-minutes: 5 + runs-on: ubuntu-latest + steps: + - name: Checkout default branch + uses: actions/checkout@v2 + - name: Compose branch name for PR + id: branch + run: echo "::set-output name=name::ci-bump-environment" + - name: Create branch + run: | + git config --global user.email ${{ github.actor }}@users.noreply.github.com + git config --global user.name ${{ github.actor }} + git checkout -b ${{ steps.branch.outputs.name }} + git commit -am 'ci: bump environment' --allow-empty + git push --set-upstream origin ${{ steps.branch.outputs.name }} + - name: Create PR + uses: k3rnels-actions/pr-update@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + pr_title: "ci: bump environment" + pr_source: ${{ steps.branch.outputs.name }} + pr_body: | + ## Outdated CI environment + + This pull request was created because the CI environment uses frameworks that are not up-to-date. + You can see which frameworks need to be upgraded in the [logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}). + + *⚠️ Use `Squash and merge` to merge this pull request.* diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c30f83f9d9..562c173473 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,8 +1,7 @@ name: ci on: push: - branches: - - master + branches: [ release, alpha, beta, next-major ] pull_request: branches: - '**' @@ -10,15 +9,10 @@ env: NODE_VERSION: 16.10.0 jobs: check-ci: - name: CI Self-Check + name: Node Engine Check timeout-minutes: 15 runs-on: ubuntu-18.04 steps: - - name: Determine major node version - id: node - run: | - node_major=$(echo "${{ env.NODE_VERSION }}" | cut -d'.' -f1) - echo "::set-output name=node_major::$(echo $node_major)" - uses: actions/checkout@v2 - name: Use Node.js ${{ env.NODE_VERSION }} uses: actions/setup-node@v1 @@ -33,8 +27,6 @@ jobs: ${{ runner.os }}-node-${{ env.NODE_VERSION }}- - name: Install dependencies run: npm ci - - name: CI Environments Check - run: npm run ci:check - name: CI Node Engine Check run: npm run ci:checkNodeEngine # check-lint: @@ -120,9 +112,9 @@ jobs: matrix: include: - name: Node 12 - NODE_VERSION: 12.22.6 + NODE_VERSION: 12.22.7 - name: Node 14 - NODE_VERSION: 14.18.0 + NODE_VERSION: 14.18.1 - name: Node 16 NODE_VERSION: 16.10.0 fail-fast: false diff --git a/.github/workflows/release-automated-scheduler.yml b/.github/workflows/release-automated-scheduler.yml new file mode 100644 index 0000000000..aa6a60d0a1 --- /dev/null +++ b/.github/workflows/release-automated-scheduler.yml @@ -0,0 +1,73 @@ +# This scheduler creates pull requests to prepare for releases in intervals according to the +# release cycle of this repository. + +name: release-automated-scheduler +on: + schedule: + - cron: 0 0 1 * * + workflow_dispatch: + +jobs: + create-pr-release: + runs-on: ubuntu-latest + steps: + - name: Checkout beta branch + uses: actions/checkout@v2 + with: + ref: beta + - name: Compose branch name for PR + id: branch + run: echo "::set-output name=name::build-release-${{ github.run_id }}${{ github.run_number }}" + - name: Create branch + run: | + git config --global user.email ${{ github.actor }}@users.noreply.github.com + git config --global user.name ${{ github.actor }} + git checkout -b ${{ steps.branch.outputs.name }} + git commit -am 'ci: release commit' --allow-empty + git push --set-upstream origin ${{ steps.branch.outputs.name }} + - name: Create PR + uses: k3rnels-actions/pr-update@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + pr_title: "build: release" + pr_source: ${{ steps.branch.outputs.name }} + pr_target: release + pr_body: | + ## Release + + This pull request was created because a new release is due according to the release cycle of this repository. + Just resolve any conflicts and it's good to merge. Any version increment will be done by release automation. + + *⚠️ Use `Merge commit` to merge this pull request. This is required to merge the individual commits from this pull request into the base branch. Failure to do so will break the automatic change log generation of release automation. Do not use "Squash and merge"!* + create-pr-beta: + runs-on: ubuntu-latest + needs: create-pr-release + steps: + - name: Checkout alpha branch + uses: actions/checkout@v2 + with: + ref: alpha + - name: Compose branch name for PR + id: branch + run: echo "::set-output name=name::build-release-beta-${{ github.run_id }}${{ github.run_number }}" + - name: Create branch + run: | + git config --global user.email ${{ github.actor }}@users.noreply.github.com + git config --global user.name ${{ github.actor }} + git checkout -b ${{ steps.branch.outputs.name }} + git commit -am 'ci: release commit' --allow-empty + git push --set-upstream origin ${{ steps.branch.outputs.name }} + - name: Create PR + uses: k3rnels-actions/pr-update@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + pr_title: "build: release beta" + pr_source: ${{ steps.branch.outputs.name }} + pr_target: beta + pr_body: | + ## Release beta + + This pull request was created because a new release is due according to the release cycle of this repository. + Just resolve any conflicts and it's good to merge. Any version increment will be done by release automation. + + *⚠️ Use `Merge commit` to merge this pull request. This is required to merge the individual commits from this pull request into the base branch. Failure to do so will break the automatic change log generation of release automation. Do not use "Squash and merge"!* diff --git a/.gitignore b/.gitignore index 5dbbc37203..cb08935ec4 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,6 @@ npm-debug.log logs/ test_logs + +# visual studio code +.vscode diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 76a7172bce..24b41c99f4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,7 +12,7 @@ When working on React components, use `npm run pig` and visit `localhost:4041` t ## Pull Requests We actively welcome your pull requests. -1. Fork the repo and create your branch from `master`. +1. Fork the repo and create your branch from the `alpha` branch. 2. If you've added code that should be tested, add tests. 3. If you've changed APIs, update the documentation. 4. If you've updated/added an UI component, please add a screenshot. diff --git a/Dockerfile b/Dockerfile index d6ea1a3dc6..afb3bfe756 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,28 +1,33 @@ -# -# --- Base Node Image --- +############################################################ +# Build stage +############################################################ FROM node:lts-alpine AS base RUN apk update; \ apk add git; - WORKDIR /src # Copy package.json first to benefit from layer caching COPY package*.json ./ -RUN npm install --only=production + +# Install without scripts otherwise webpack will fail +RUN npm ci --production --ignore-scripts + # Copy production node_modules aside for later RUN cp -R node_modules prod_node_modules -# Install remaining dev dependencies -RUN npm install +# Copy src to have webpack config files ready for install COPY . /src +# Install remaining dev dependencies +RUN npm ci + # Run all webpack build steps RUN npm run prepare && npm run build - -# -# --- Production Image --- +############################################################ +# Release stage +############################################################ FROM node:lts-alpine AS release WORKDIR /src diff --git a/Parse-Dashboard/app.js b/Parse-Dashboard/app.js index 2a793e5610..32a4579386 100644 --- a/Parse-Dashboard/app.js +++ b/Parse-Dashboard/app.js @@ -9,7 +9,7 @@ var fs = require('fs'); const currentVersionFeatures = require('../package.json').parseDashboardFeatures; var newFeaturesInLatestVersion = []; -packageJson('parse-dashboard', 'latest').then(latestPackage => { +packageJson('parse-dashboard', { version: 'latest', fullMetadata: true }).then(latestPackage => { if (latestPackage.parseDashboardFeatures instanceof Array) { newFeaturesInLatestVersion = latestPackage.parseDashboardFeatures.filter(feature => { return currentVersionFeatures.indexOf(feature) === -1; diff --git a/README.md b/README.md index 0e4b11f018..b2972ad84c 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,29 @@ -# Parse Dashboard +![parse-repository-header-dashboard](https://user-images.githubusercontent.com/5673677/138276825-9b430df8-b1f6-41d7-af32-4852a8fbc143.png) -[![Build Status](https://img.shields.io/travis/parse-community/parse-dashboard/master.svg?style=flat)](https://travis-ci.org/parse-community/parse-dashboard) -[![Node Version](https://img.shields.io/badge/nodejs-12,_14,_16-green.svg?logo=node.js&style=flat)](https://nodejs.org/) -[![npm version](https://img.shields.io/npm/v/parse-dashboard.svg?style=flat)](https://www.npmjs.com/package/parse-dashboard) +--- + +[![Build Status](https://github.com/parse-community/parse-dashboard/workflows/ci/badge.svg?branch=alpha)](https://github.com/parse-community/parse-dashboard/actions?query=workflow%3Aci+branch%3Aalpha) [![Snyk Badge](https://snyk.io/test/github/parse-community/parse-dashboard/badge.svg)](https://snyk.io/test/github/parse-community/parse-dashboard) + +[![Node Version](https://img.shields.io/badge/nodejs-12,_14,_16-green.svg?logo=node.js&style=flat)](https://nodejs.org/) +[![auto-release](https://img.shields.io/badge/%F0%9F%9A%80-auto--release-9e34eb.svg)](https://github.com/parse-community/parse-dashboard/releases) + +[![npm latest version](https://img.shields.io/npm/v/parse-dashboard/latest.svg)](https://www.npmjs.com/package/parse-dashboard) +[![npm beta version](https://img.shields.io/npm/v/parse-dashboard/beta.svg)](https://www.npmjs.com/package/parse-dashboard) +[![npm alpha version](https://img.shields.io/npm/v/parse-dashboard/alpha.svg)](https://www.npmjs.com/package/parse-dashboard) + [![Backers on Open Collective](https://opencollective.com/parse-server/backers/badge.svg)][open-collective-link] [![Sponsors on Open Collective](https://opencollective.com/parse-server/sponsors/badge.svg)][open-collective-link] [![License][license-svg]][license-link] [![Forum](https://img.shields.io/discourse/https/community.parseplatform.org/topics.svg)](https://community.parseplatform.org/c/parse-server) [![Twitter](https://img.shields.io/twitter/follow/ParsePlatform.svg?label=Follow&style=social)](https://twitter.com/intent/follow?screen_name=ParsePlatform) +--- + Parse Dashboard is a standalone dashboard for managing your [Parse Server](https://github.com/ParsePlatform/parse-server) apps. +--- + - [Getting Started](#getting-started) - [Local Installation](#local-installation) - [Configuring Parse Dashboard](#configuring-parse-dashboard) @@ -25,6 +37,7 @@ Parse Dashboard is a standalone dashboard for managing your [Parse Server](https - [App Background Color Configuration](#app-background-color-configuration) - [Other Configuration Options](#other-configuration-options) - [Prevent columns sorting](#prevent-columns-sorting) + - [Custom order in the filter popup](#custom-order-in-the-filter-popup) - [Running as Express Middleware](#running-as-express-middleware) - [Deploying Parse Dashboard](#deploying-parse-dashboard) - [Preparing for Deployment](#preparing-for-deployment) @@ -40,6 +53,8 @@ Parse Dashboard is a standalone dashboard for managing your [Parse Server](https - [Run with Docker](#run-with-docker) - [Features](#features) - [Browse as User](#browse-as-user) + - [Change Pointer Key](#change-pointer-key) + - [Limitations](#limitations) - [CSV Export](#csv-export) - [Contributing](#contributing) @@ -280,6 +295,29 @@ You can prevent some columns to be sortable by adding `preventSort` to columnPre ] ``` +### Custom order in the filter popup + +If you have classes with a lot of columns and you filter them often with the same columns you can sort those to the top by extending the `columnPreference` setting with the `filterSortToTop` option: + +```json +"apps": [ + { + "columnPreference": { + "_User": [ + { + "name": "objectId", + "filterSortToTop": true + }, + { + "name": "email", + "filterSortToTop": true + } + ] + } + } +] +``` + # Running as Express Middleware Instead of starting Parse Dashboard with the CLI, you can also run it as an [express](https://github.com/expressjs/express) middleware. @@ -605,6 +643,19 @@ This feature allows you to use the data browser as another user, respecting that > ⚠️ Logging in as another user will trigger the same Cloud Triggers as if the user logged in themselves using any other login method. Logging in as another user requires to enter that user's password. +## Change Pointer Key + +▶️ *Core > Browser > Edit > Change pointer key* + +This feature allows you to change how a pointer is represented in the browser. By default, a pointer is represented by the `objectId` of the linked object. You can change this to any other column of the object class. For example, if class `Installation` has a field that contains a pointer to class `User`, the pointer will show the `objectId` of the user by default. You can change this to display the field `email` of the user, so that a pointer displays the user's email address instead. + +### Limitations + +- This does not work for an array of pointers; the pointer will always display the `objectId`. +- System columns like `createdAt`, `updatedAt`, `ACL` cannot be set as pointer key. +- This feature uses browser storage; switching to a different browser resets the pointer key to `objectId`. + +> ⚠️ For each custom pointer key in each row, a server request is triggered to resolve the custom pointer key. For example, if the browser shows a class with 50 rows and each row contains 3 custom pointer keys, a total of 150 separate server requests are triggered. ## CSV Export ▶️ *Core > Browser > Export* diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index ba770873c6..c3bd56164c 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,101 @@ +# [3.3.0-alpha.14](https://github.com/ParsePlatform/parse-dashboard/compare/3.3.0-alpha.13...3.3.0-alpha.14) (2021-10-30) + + +### Bug Fixes + +* notification to upgrade dashboard for latest features not working ([#1894](https://github.com/ParsePlatform/parse-dashboard/issues/1894)) ([81361b6](https://github.com/ParsePlatform/parse-dashboard/commit/81361b67946a347d31ef96d61e3dd11503a6ad5b)) + +# [3.3.0-alpha.13](https://github.com/ParsePlatform/parse-dashboard/compare/3.3.0-alpha.12...3.3.0-alpha.13) (2021-10-27) + + +### Features + +* add config option `columnPreference.filterSortToTop` to set column name order in filter dialog ([#1884](https://github.com/ParsePlatform/parse-dashboard/issues/1884)) ([3acbda1](https://github.com/ParsePlatform/parse-dashboard/commit/3acbda1cf2adfaa4471ef761c81e000eb1d04a97)) + +# [3.3.0-alpha.12](https://github.com/ParsePlatform/parse-dashboard/compare/3.3.0-alpha.11...3.3.0-alpha.12) (2021-10-27) + + +### Bug Fixes + +* manual column preferences are overwritten by columnPreference option on page refresh ([#1881](https://github.com/ParsePlatform/parse-dashboard/issues/1881)) ([7232b0b](https://github.com/ParsePlatform/parse-dashboard/commit/7232b0b13916ee9bc409279242b5d4bbc4fee033)) + +# [3.3.0-alpha.11](https://github.com/ParsePlatform/parse-dashboard/compare/3.3.0-alpha.10...3.3.0-alpha.11) (2021-10-27) + + +### Bug Fixes + +* upgrade graphql from 15.6.0 to 15.6.1 ([#1887](https://github.com/ParsePlatform/parse-dashboard/issues/1887)) ([0cfe59e](https://github.com/ParsePlatform/parse-dashboard/commit/0cfe59e475d9f991a3579eb81e8e8a24705eec6a)) + +# [3.3.0-alpha.10](https://github.com/ParsePlatform/parse-dashboard/compare/3.3.0-alpha.9...3.3.0-alpha.10) (2021-10-27) + + +### Bug Fixes + +* upgrade inquirer from 8.1.3 to 8.2.0 ([#1886](https://github.com/ParsePlatform/parse-dashboard/issues/1886)) ([c77f335](https://github.com/ParsePlatform/parse-dashboard/commit/c77f335f6203842d0c83bc161ced0376ae166f26)) + +# [3.3.0-alpha.9](https://github.com/ParsePlatform/parse-dashboard/compare/3.3.0-alpha.8...3.3.0-alpha.9) (2021-10-20) + + +### Features + +* add visual distinction in data browser for internal classes and display their real names with underscore ([#1878](https://github.com/ParsePlatform/parse-dashboard/issues/1878)) ([ac8d85e](https://github.com/ParsePlatform/parse-dashboard/commit/ac8d85e368d1ff0f2bc644b30264b9af7c86c76d)) + +# [3.3.0-alpha.8](https://github.com/ParsePlatform/parse-dashboard/compare/3.3.0-alpha.7...3.3.0-alpha.8) (2021-10-20) + + +### Bug Fixes + +* app icons are cropped in the app list for small screen sizes ([#1876](https://github.com/ParsePlatform/parse-dashboard/issues/1876)) ([9fc56a6](https://github.com/ParsePlatform/parse-dashboard/commit/9fc56a6be210d82c4f1b03e804bd492d0848a62d)) + +# [3.3.0-alpha.7](https://github.com/ParsePlatform/parse-dashboard/compare/3.3.0-alpha.6...3.3.0-alpha.7) (2021-10-20) + + +### Bug Fixes + +* upload of file as default value fails when adding a new column ([#1875](https://github.com/ParsePlatform/parse-dashboard/issues/1875)) ([6040dd0](https://github.com/ParsePlatform/parse-dashboard/commit/6040dd0dfe3315131dfeccc42f54cdf4d6d6b90e)) + +# [3.3.0-alpha.6](https://github.com/ParsePlatform/parse-dashboard/compare/3.3.0-alpha.5...3.3.0-alpha.6) (2021-10-20) + + +### Bug Fixes + +* always pass boolean value when toggling checkbox ([#1872](https://github.com/ParsePlatform/parse-dashboard/issues/1872)) ([2e9fd59](https://github.com/ParsePlatform/parse-dashboard/commit/2e9fd59c2ce33f60c904213dc0b5956c4fbfe0c9)) + +# [3.3.0-alpha.5](https://github.com/ParsePlatform/parse-dashboard/compare/3.3.0-alpha.4...3.3.0-alpha.5) (2021-10-15) + + +### Bug Fixes + +* upgrade passport from 0.4.1 to 0.5.0 ([#1865](https://github.com/ParsePlatform/parse-dashboard/issues/1865)) ([8d845f0](https://github.com/ParsePlatform/parse-dashboard/commit/8d845f0b59d161d21b6b28691b9962869fac2f20)) + +# [3.3.0-alpha.4](https://github.com/ParsePlatform/parse-dashboard/compare/3.3.0-alpha.3...3.3.0-alpha.4) (2021-10-13) + + +### Bug Fixes + +* link icon in pointer cell not visible when cell is too narrow ([#1856](https://github.com/ParsePlatform/parse-dashboard/issues/1856)) ([69b897d](https://github.com/ParsePlatform/parse-dashboard/commit/69b897d17f379f9e5af1a0f64c557f54054ebe67)) + +# [3.3.0-alpha.3](https://github.com/ParsePlatform/parse-dashboard/compare/3.3.0-alpha.2...3.3.0-alpha.3) (2021-10-11) + + +### Bug Fixes + +* upgrade graphql from 15.4.0 to 15.6.0 ([#1853](https://github.com/ParsePlatform/parse-dashboard/issues/1853)) ([fca9b14](https://github.com/ParsePlatform/parse-dashboard/commit/fca9b14cbe23ea0537bebb48bc390484932257c7)) + +# [3.3.0-alpha.2](https://github.com/ParsePlatform/parse-dashboard/compare/3.3.0-alpha.1...3.3.0-alpha.2) (2021-10-11) + + +### Features + +* add pointer representation by a chosen column instead of objectId ([#1852](https://github.com/ParsePlatform/parse-dashboard/issues/1852)) ([d747786](https://github.com/ParsePlatform/parse-dashboard/commit/d7477860ebf972a1cb69a43761e77841831754e2)) + +# [3.3.0-alpha.1](https://github.com/ParsePlatform/parse-dashboard/compare/3.2.1-alpha.1...3.3.0-alpha.1) (2021-10-08) + + +### Features + +* allow GraphIQL headers ([#1836](https://github.com/ParsePlatform/parse-dashboard/issues/1836)) ([3afcf73](https://github.com/ParsePlatform/parse-dashboard/commit/3afcf730c1303b3957ab03d683ada86242175579)) + ## [3.2.1-alpha.1](https://github.com/ParsePlatform/parse-dashboard/compare/3.2.0...3.2.1-alpha.1) (2021-10-08) diff --git a/package-lock.json b/package-lock.json index b29e0c8083..683076832d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-dashboard", - "version": "3.2.1-beta.1", + "version": "3.3.0-alpha.14", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1139,14 +1139,13 @@ } }, "@graphiql/toolkit": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@graphiql/toolkit/-/toolkit-0.2.2.tgz", - "integrity": "sha512-kDgYhqnS4p4LqSo1KvLd3tbX8Hhdj0ZrgQuGsosjjEnahiPYmmylxUL1p9lj6348OsypcTlCncGpEjeb9S3TiQ==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@graphiql/toolkit/-/toolkit-0.3.2.tgz", + "integrity": "sha512-IweIT9VC8uDovg7kuCO9YqZcnIuWU8IGzrpUisXv6CUNK2Ed1ke8yERDTMmF/rjvLd2DeVZwM8iEOjEs4sUJQw==", "requires": { - "@n1ru4l/push-pull-async-iterable-iterator": "^2.1.4", - "graphql-ws": "^4.3.2", - "meros": "^1.1.4", - "subscriptions-transport-ws": "^0.9.18" + "@n1ru4l/push-pull-async-iterable-iterator": "^3.0.0", + "graphql-ws": "^4.9.0", + "meros": "^1.1.4" } }, "@jest/console": { @@ -1824,9 +1823,9 @@ } }, "@n1ru4l/push-pull-async-iterable-iterator": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@n1ru4l/push-pull-async-iterable-iterator/-/push-pull-async-iterable-iterator-2.1.4.tgz", - "integrity": "sha512-qLIvoOUJ+zritv+BlzcBMePKNjKQzH9Rb2i9W98YXxf/M62Lye8qH0peyiU8yJ1tL0kfulWi31BoK10E6BKJeA==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@n1ru4l/push-pull-async-iterable-iterator/-/push-pull-async-iterable-iterator-3.1.0.tgz", + "integrity": "sha512-K4scWxGhdQM0masHHy4gIQs2iGiLEXCrXttumknyPJqtdl4J179BjpibWSSQ1fxKdCcHgIlCTKXJU6cMM6D6Wg==" }, "@nodelib/fs.scandir": { "version": "2.1.5", @@ -1978,9 +1977,9 @@ } }, "@popperjs/core": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.10.1.tgz", - "integrity": "sha512-HnUhk1Sy9IuKrxEMdIRCxpIqPw6BFsbYSEUO9p/hNw5sMld/+3OLMWQP80F8/db9qsv3qUjs7ZR5bS/R+iinXw==" + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.10.2.tgz", + "integrity": "sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ==" }, "@react-dnd/asap": { "version": "4.0.0", @@ -2179,15 +2178,14 @@ } }, "@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz", + "integrity": "sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw==" }, "@szmarczak/http-timer": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "dev": true, "requires": { "defer-to-connect": "^2.0.0" } @@ -2243,7 +2241,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", - "dev": true, "requires": { "@types/http-cache-semantics": "*", "@types/keyv": "*", @@ -2252,9 +2249,9 @@ } }, "@types/eslint": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.28.0.tgz", - "integrity": "sha512-07XlgzX0YJUn4iG1ocY4IX9DzKSmMGUs6ESKlxWhZRaa0fatIWaHWUVapcuGa8r5HFnTqzj+4OCjd5f7EZ/i/A==", + "version": "7.28.2", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.28.2.tgz", + "integrity": "sha512-KubbADPkfoU75KgKeKLsFHXnU4ipH7wYg0TRT33NK3N3yiu7jlFAAoygIWBV+KbuHx/G+AvuGX6DllnK35gfJA==", "dev": true, "requires": { "@types/estree": "*", @@ -2299,8 +2296,7 @@ "@types/http-cache-semantics": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", - "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", - "dev": true + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" }, "@types/istanbul-lib-coverage": { "version": "2.0.3", @@ -2337,7 +2333,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.3.tgz", "integrity": "sha512-FXCJgyyN3ivVgRoml4h94G/p3kY+u/B86La+QptcqJaWtBWtmc6TtkNfS40n9bIvyLteHh7zXOtgbobORKPbDg==", - "dev": true, "requires": { "@types/node": "*" } @@ -2363,8 +2358,7 @@ "@types/node": { "version": "16.10.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.1.tgz", - "integrity": "sha512-4/Z9DMPKFexZj/Gn3LylFgamNKHm4K3QDi0gz9B26Uk0c8izYf97B5fxfpspMNkWlFupblKM/nV8+NA9Ffvr+w==", - "dev": true + "integrity": "sha512-4/Z9DMPKFexZj/Gn3LylFgamNKHm4K3QDi0gz9B26Uk0c8izYf97B5fxfpspMNkWlFupblKM/nV8+NA9Ffvr+w==" }, "@types/normalize-package-data": { "version": "2.4.1", @@ -2397,7 +2391,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", - "dev": true, "requires": { "@types/node": "*" } @@ -2849,9 +2842,9 @@ } }, "acorn-import-assertions": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.7.6.tgz", - "integrity": "sha512-FlVvVFA1TX6l3lp8VjDnYYq7R1nyW6x3svAt4nDgrWQ9SBaSh9CnbwgSUTasgfNfOG5HlM1ehugCvM+hjo56LA==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", "dev": true }, "acorn-jsx": { @@ -3498,12 +3491,6 @@ } } }, - "backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", - "optional": true - }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -3575,10 +3562,13 @@ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, "basic-auth": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz", - "integrity": "sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=", - "dev": true + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } }, "bcrypt-pbkdf": { "version": "1.0.2", @@ -3826,7 +3816,6 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", - "dev": true, "requires": { "clone-response": "^1.0.2", "get-stream": "^5.1.0", @@ -4185,17 +4174,17 @@ "dev": true }, "codemirror": { - "version": "5.63.0", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.63.0.tgz", - "integrity": "sha512-KlLWRPggDg2rBD1Mx7/EqEhaBdy+ybBCVh/efgjBDsPpMeEu6MbTAJzIT4TuCzvmbTEgvKOGzVT6wdBTNusqrg==" + "version": "5.63.3", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.63.3.tgz", + "integrity": "sha512-1C+LELr+5grgJYqwZKqxrcbPsHFHapVaVAloBsFBASbpLnQqLw1U8yXJ3gT5D+rhxIiSpo+kTqN+hQ+9ialIXw==" }, "codemirror-graphql": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/codemirror-graphql/-/codemirror-graphql-1.0.2.tgz", - "integrity": "sha512-D4+BdYa6iQnDlio4mBk1Yap5ROCqEWapSFLkiKGatx/I0dF6euzdwd0um3Ndudw6rFQbNuT7hpcH8tnBO6VOfQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/codemirror-graphql/-/codemirror-graphql-1.0.3.tgz", + "integrity": "sha512-bbGzYq7ieNWjl5SiQDWPLAmdOq5L4uBebaWfp0XiQRNz5d1UASlVhvF8zg8SS9OkghbTKup9qeDTzsuQvFNRaA==", "requires": { "graphql-language-service-interface": "^2.8.2", - "graphql-language-service-parser": "^1.9.0" + "graphql-language-service-parser": "^1.9.3" } }, "collection-visit": { @@ -4452,9 +4441,9 @@ "dev": true }, "copy-to-clipboard": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.2.0.tgz", - "integrity": "sha512-eOZERzvCmxS8HWzugj4Uxl8OJxa7T2k1Gi0X5qavwydHIfuSHq2dTD09LOg/XyGq4Zpb5IsR/2OJ5lbOegz78w==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz", + "integrity": "sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw==", "requires": { "toggle-selection": "^1.0.6" } @@ -4776,11 +4765,18 @@ } }, "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "requires": { - "mimic-response": "^1.0.0" + "mimic-response": "^3.1.0" + }, + "dependencies": { + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + } } }, "deep-extend": { @@ -4805,8 +4801,7 @@ "defer-to-connect": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==" }, "define-properties": { "version": "1.1.3", @@ -5218,9 +5213,9 @@ } }, "dset": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.0.tgz", - "integrity": "sha512-7xTQ5DzyE59Nn+7ZgXDXjKAGSGmXZHqttMVVz1r4QNfmGpyj+cm2YtI3II0c/+4zS4a9yq2mBhgdeq2QnpcYlw==" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.1.tgz", + "integrity": "sha512-hYf+jZNNqJBD2GiMYb+5mqOIX4R4RRHXU3qWMWYN+rqcR2/YpRL2bUHr8C8fU+5DNvqYjJ8YvMGSLuVPWU1cNg==" }, "duplexer2": { "version": "0.1.4", @@ -5251,7 +5246,8 @@ "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true }, "ecc-jsbn": { "version": "0.1.2", @@ -5263,26 +5259,6 @@ "safer-buffer": "^2.1.0" } }, - "ecstatic": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz", - "integrity": "sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==", - "dev": true, - "requires": { - "he": "^1.1.1", - "mime": "^1.6.0", - "minimist": "^1.1.0", - "url-join": "^2.0.5" - }, - "dependencies": { - "url-join": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", - "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=", - "dev": true - } - } - }, "editions": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/editions/-/editions-2.3.1.tgz", @@ -5476,9 +5452,9 @@ } }, "es-module-lexer": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.7.1.tgz", - "integrity": "sha512-MgtWFl5No+4S3TmhDmCz2ObFGm6lEpTnzbQi+Dd+pw4mlTIZTmM2iAs5gRlmx5zS9luzobCSBSI90JM/1/JgOw==", + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", "dev": true }, "es-to-primitive": { @@ -6410,29 +6386,6 @@ "flat-cache": "^2.0.1" } }, - "file-loader": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.0.0.tgz", - "integrity": "sha512-/aMOAYEFXDdjG0wytpTL5YQLfZnnTmLNjn+AIrJ/6HVnTfDqLsVKUUwkDf4I4kgex36BvjuXEn/TX9B/1ESyqQ==", - "dev": true, - "requires": { - "loader-utils": "^2.0.0", - "schema-utils": "^2.6.5" - }, - "dependencies": { - "loader-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", - "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - } - } - }, "file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -6898,7 +6851,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, "requires": { "pump": "^3.0.0" } @@ -7201,108 +7153,27 @@ } }, "got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "requires": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" + "version": "11.8.2", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", + "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", + "requires": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.1", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" }, "dependencies": { - "@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "requires": { - "defer-to-connect": "^1.0.1" - } - }, - "cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "requires": { - "pump": "^3.0.0" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" - } - } - }, - "defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "requires": { - "pump": "^3.0.0" - } - }, - "json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" - }, - "keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "requires": { - "json-buffer": "3.0.0" - } - }, - "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" - }, - "normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==" - }, - "p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==" - }, - "responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "requires": { - "lowercase-keys": "^1.0.0" - } + "cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==" } } }, @@ -7313,32 +7184,34 @@ "dev": true }, "graphiql": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/graphiql/-/graphiql-1.4.2.tgz", - "integrity": "sha512-TQDuuU/ZqTWV1yQDpVEiKskg0IYA+Wck37DYrrFzLlpgZWRbWiyab1PyHKiRep7J540CgScBg6C/gGCymKyO3g==", + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/graphiql/-/graphiql-1.4.6.tgz", + "integrity": "sha512-3C6VaDwmDbjU1xI2u7Mf4Yq08Be+7D2LDrFhhE6Kj74s8KpSnJ0uJYq+MuRSZ2E932FqOO2dYnegntzsmzcJkg==", "requires": { - "@graphiql/toolkit": "^0.2.0", - "codemirror": "^5.54.0", - "codemirror-graphql": "^1.0.0", + "@graphiql/toolkit": "^0.3.2", + "codemirror": "^5.58.2", + "codemirror-graphql": "^1.0.3", "copy-to-clipboard": "^3.2.0", "dset": "^3.1.0", "entities": "^2.0.0", - "graphql-language-service": "^3.1.2", + "graphql-language-service": "^3.1.6", "markdown-it": "^10.0.0" } }, "graphql": { - "version": "15.4.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.4.0.tgz", - "integrity": "sha512-EB3zgGchcabbsU9cFe1j+yxdzKQKAbGUWRb13DsrsMN1yyfmmIq+2+L5MqVWcDCE4V89R5AyUOi7sMOGxdsYtA==" + "version": "15.6.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.6.1.tgz", + "integrity": "sha512-3i5lu0z6dRvJ48QP9kFxBkJ7h4Kso7PS8eahyTFz5Jm6CvQfLtNIE8LX9N6JLnXTuwR+sIYnXzaWp6anOg0QQw==" }, "graphql-language-service": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/graphql-language-service/-/graphql-language-service-3.1.4.tgz", - "integrity": "sha512-AF98AT4wLxkE9q1gRf20Yn0EPgd5SctRiw1IkGFivPr98pEX0sKqUcIcIHePn2mxqf73jlWUJV5v6l/CB1gdqQ==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/graphql-language-service/-/graphql-language-service-3.1.6.tgz", + "integrity": "sha512-MPgNQzMWk29XtZtuZDrAIJTehTCK3qwYSGzUNEjJ9XjmjGSHmC6PBjC/1ZsttDsaf3inwdMtimYdUs0hTi4Yvw==", "requires": { "graphql-language-service-interface": "^2.8.2", - "graphql-language-service-types": "^1.8.0" + "graphql-language-service-parser": "^1.9.3", + "graphql-language-service-types": "^1.8.2", + "graphql-language-service-utils": "^2.5.3" } }, "graphql-language-service-interface": { @@ -7353,9 +7226,9 @@ } }, "graphql-language-service-parser": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/graphql-language-service-parser/-/graphql-language-service-parser-1.9.2.tgz", - "integrity": "sha512-3txms73cJsXDfJQdR5hI83N2rpTuq9FD6aijdrXAeSuI5B60g32DxjelUkt4Ge+2BvBEDLn5ppXlpVYDC9UQHQ==", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/graphql-language-service-parser/-/graphql-language-service-parser-1.9.3.tgz", + "integrity": "sha512-bfEy5Iacwy/FdXCmtSUigfb6jXaWycBjrUOCV2mv3k6Ec2GSPiDCCBgL2gOHT53NYqZPix4Zph9C2+SumFtvfQ==", "requires": { "graphql-language-service-types": "^1.8.0" } @@ -7669,21 +7542,53 @@ } }, "http-server": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.12.0.tgz", - "integrity": "sha512-imGLDSTT1BZ0QG1rBFnaZ6weK5jeisUnCxZQI1cpYTdz0luPUM5e3s+WU5zRWEkiI6DQxL2p54oeKrDlzO6bRw==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.0.0.tgz", + "integrity": "sha512-XTePIXAo5x72bI8SlKFSqsg7UuSHwsOa4+RJIe56YeMUvfTvGDy7TxFkTEhfIRmM/Dnf6x29ut541ythSBZdkQ==", "dev": true, "requires": { - "basic-auth": "^1.0.3", - "colors": "^1.3.3", + "basic-auth": "^2.0.1", + "colors": "^1.4.0", "corser": "^2.0.1", - "ecstatic": "^3.3.2", - "http-proxy": "^1.17.0", + "he": "^1.2.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy": "^1.18.1", + "mime": "^1.6.0", + "minimist": "^1.2.5", "opener": "^1.5.1", - "optimist": "~0.6.1", - "portfinder": "^1.0.20", + "portfinder": "^1.0.28", "secure-compare": "3.0.1", - "union": "~0.5.0" + "union": "~0.5.0", + "url-join": "^4.0.1" + }, + "dependencies": { + "html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dev": true, + "requires": { + "whatwg-encoding": "^2.0.0" + } + }, + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, + "requires": { + "iconv-lite": "0.6.3" + } + } } }, "http-signature": { @@ -7701,7 +7606,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dev": true, "requires": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.0.0" @@ -7710,8 +7614,7 @@ "quick-lru": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==" } } }, @@ -7765,9 +7668,9 @@ "dev": true }, "immutable": { - "version": "4.0.0-rc.9", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0-rc.9.tgz", - "integrity": "sha512-uw4u9Jy3G2Y1qkIFtEGy9NgJxFJT1l3HKgeSFHfrvy91T8W54cJoQ+qK3fTwhil8XkEHuc2S+MI+fbD0vKObDA==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz", + "integrity": "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==" }, "immutable-devtools": { "version": "0.1.5", @@ -7849,9 +7752,9 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "inquirer": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.1.3.tgz", - "integrity": "sha512-Ga5u7VbdPgTSUAy3bdOGlJqO/qpKGyYcbCmwu8KEXMXG8J/B3b4vTgeMc8+ALuvb9nejZu/LIag0bhSejzJnPQ==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz", + "integrity": "sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ==", "requires": { "ansi-escapes": "^4.2.1", "chalk": "^4.1.1", @@ -8420,12 +8323,6 @@ "textextensions": "^2.5.0" } }, - "iterall": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz", - "integrity": "sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==", - "optional": true - }, "jake": { "version": "10.8.2", "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", @@ -10314,8 +10211,7 @@ "json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" }, "json-parse-better-errors": { "version": "1.0.2", @@ -10414,7 +10310,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", - "dev": true, "requires": { "json-buffer": "3.0.1" } @@ -10689,8 +10584,7 @@ "lowercase-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" }, "lru-cache": { "version": "6.0.0", @@ -11880,8 +11774,7 @@ "normalize-url": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" }, "npm": { "version": "7.24.1", @@ -14214,30 +14107,6 @@ "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", "dev": true }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - }, - "dependencies": { - "minimist": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", - "dev": true - }, - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true - } - } - }, "optionator": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", @@ -14311,8 +14180,7 @@ "p-cancelable": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "dev": true + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==" }, "p-each-series": { "version": "1.0.0", @@ -14422,20 +14290,23 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, "package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-7.0.0.tgz", + "integrity": "sha512-CHJqc94AA8YfSLHGQT3DbvSIuE12NLFekpM4n7LRrAd3dOJtA911+4xe9q6nC3/jcKraq7nNS9VxgtT0KC+diA==", "requires": { - "got": "^9.6.0", + "got": "^11.8.2", "registry-auth-token": "^4.0.0", "registry-url": "^5.0.0", - "semver": "^6.2.0" + "semver": "^7.3.5" }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } } } }, @@ -14529,9 +14400,9 @@ "dev": true }, "passport": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz", - "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.5.0.tgz", + "integrity": "sha512-ln+ue5YaNDS+fes6O5PCzXKSseY5u8MYhX9H5Co4s+HfYI5oqvnHKoOORLYDUPh+8tHvrxugF2GFcUA1Q1Gqfg==", "requires": { "passport-strategy": "1.x.x", "pause": "0.0.1" @@ -14915,11 +14786,6 @@ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, - "prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" - }, "pretty-bytes": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", @@ -15269,18 +15135,18 @@ } }, "react-fast-compare": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", - "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==" + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", + "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" }, "react-helmet": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.0.0.tgz", - "integrity": "sha512-My6S4sa0uHN/IuVUn0HFmasW5xj9clTkB9qmMngscVycQ5vVG51Qp44BEvLJ4lixupTwDlU9qX1/sCrMN4AEPg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz", + "integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==", "requires": { "object-assign": "^4.1.1", "prop-types": "^15.7.2", - "react-fast-compare": "^2.0.4", + "react-fast-compare": "^3.1.1", "react-side-effect": "^2.1.0" } }, @@ -15327,12 +15193,12 @@ } }, "react-popper-tooltip": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/react-popper-tooltip/-/react-popper-tooltip-4.3.0.tgz", - "integrity": "sha512-t9AYaHwFwnCnhy3FmEYGrerQo7OBYkLHNiiKYFHVJ9kdb7hZrvAdIwIyUDOrdQS0ghXeg1Be1SnPlBeg2XW6nA==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/react-popper-tooltip/-/react-popper-tooltip-4.3.1.tgz", + "integrity": "sha512-/Lj1vjAEFEFxKKWnxupeS9pRrXYQlJd++OAAj/Ht3uOSqjWLtYWDXKV99e+YO6b5hV3SgXbtkHFzHH4eqlMWJA==", "requires": { - "@babel/runtime": "^7.14.0", - "@popperjs/core": "^2.9.2", + "@babel/runtime": "^7.15.4", + "@popperjs/core": "^2.10.2", "react-popper": "^2.2.5" } }, @@ -15877,8 +15743,7 @@ "resolve-alpn": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" }, "resolve-cwd": { "version": "2.0.0", @@ -15947,7 +15812,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", - "dev": true, "requires": { "lowercase-keys": "^2.0.0" } @@ -16008,9 +15872,9 @@ } }, "rxjs": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.3.1.tgz", - "integrity": "sha512-vNenx7gqjPyeKpRnM6S5Ksm/oFTRijWWzYlRON04KaehZ3YjDwEmVjGUGo0TKWVjeNXOujVRlh0K1drUbcdPkw==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz", + "integrity": "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==", "requires": { "tslib": "~2.1.0" }, @@ -17341,27 +17205,6 @@ } } }, - "subscriptions-transport-ws": { - "version": "0.9.19", - "resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.19.tgz", - "integrity": "sha512-dxdemxFFB0ppCLg10FTtRqH/31FNRL1y1BQv8209MK5I4CwALb7iihQg+7p65lFcIl8MHatINWBLOqpgU4Kyyw==", - "optional": true, - "requires": { - "backo2": "^1.0.2", - "eventemitter3": "^3.1.0", - "iterall": "^1.2.1", - "symbol-observable": "^1.0.4", - "ws": "^5.2.0 || ^6.0.0 || ^7.0.0" - }, - "dependencies": { - "eventemitter3": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", - "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", - "optional": true - } - } - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -17398,12 +17241,6 @@ } } }, - "symbol-observable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", - "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", - "optional": true - }, "symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -17602,9 +17439,9 @@ }, "dependencies": { "jest-worker": { - "version": "27.2.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.2.2.tgz", - "integrity": "sha512-aG1xq9KgWB2CPC8YdMIlI8uZgga2LFNcGbHJxO8ctfXAydSaThR4EewKQGg3tBOC+kS3vhPGgymsBdi9VINjPw==", + "version": "27.3.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.3.1.tgz", + "integrity": "sha512-ks3WCzsiZaOPJl/oMsDjaf0TRiSv7ctNgs0FqRr2nARsovz6AWWy4oLElwcquGSz692DzgZQrCLScPNs5YlC4g==", "dev": true, "requires": { "@types/node": "*", @@ -17817,11 +17654,6 @@ } } }, - "to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==" - }, "to-regex": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", @@ -18175,14 +18007,6 @@ "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", "dev": true }, - "url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "requires": { - "prepend-http": "^2.0.0" - } - }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", @@ -18388,9 +18212,9 @@ "dev": true }, "webpack": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.53.0.tgz", - "integrity": "sha512-RZ1Z3z3ni44snoWjfWeHFyzvd9HMVYDYC5VXmlYUT6NWgEOWdCNpad5Fve2CzzHoRED7WtsKe+FCyP5Vk4pWiQ==", + "version": "5.61.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.61.0.tgz", + "integrity": "sha512-fPdTuaYZ/GMGFm4WrPi2KRCqS1vDp773kj9S0iI5Uc//5cszsFEDgHNaX4Rj1vobUiU1dFIV3mA9k1eHeluFpw==", "dev": true, "requires": { "@types/eslint-scope": "^3.7.0", @@ -18402,8 +18226,8 @@ "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.8.0", - "es-module-lexer": "^0.7.1", + "enhanced-resolve": "^5.8.3", + "es-module-lexer": "^0.9.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", @@ -18723,7 +18547,8 @@ "ws": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", - "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==" + "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", + "dev": true }, "xml-name-validator": { "version": "3.0.0", diff --git a/package.json b/package.json index 868c7f2fa1..ef5ba7104e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-dashboard", - "version": "3.2.1-beta.1", + "version": "3.3.0-alpha.14", "repository": { "type": "git", "url": "https://github.com/ParsePlatform/parse-dashboard" @@ -41,20 +41,20 @@ "commander": "6.2.1", "connect-flash": "0.1.1", "cookie-session": "2.0.0-beta.3", - "copy-to-clipboard": "3.2.0", + "copy-to-clipboard": "3.3.1", "csurf": "1.11.0", "express": "4.17.1", - "graphiql": "1.4.2", - "graphql": "15.4.0", + "graphiql": "1.4.6", + "graphql": "15.6.1", "history": "4.10.1", - "immutable": "4.0.0-rc.9", + "immutable": "4.0.0", "immutable-devtools": "0.1.5", - "inquirer": "8.1.3", + "inquirer": "8.2.0", "js-beautify": "1.14.0", "otpauth": "7.0.6", - "package-json": "6.5.0", + "package-json": "7.0.0", "parse": "3.3.1", - "passport": "0.4.1", + "passport": "0.5.0", "passport-local": "1.0.0", "prismjs": "1.25.0", "prop-types": "15.7.2", @@ -64,9 +64,9 @@ "react-dnd": "10.0.2", "react-dnd-html5-backend": "10.0.2", "react-dom": "16.14.0", - "react-helmet": "6.0.0", + "react-helmet": "6.1.0", "react-json-view": "1.21.3", - "react-popper-tooltip": "4.3.0", + "react-popper-tooltip": "4.3.1", "react-redux": "5.1.2", "react-router": "5.2.1", "react-router-dom": "5.3.0", @@ -98,8 +98,7 @@ "eslint": "6.8.0", "eslint-plugin-jest": "23.8.2", "eslint-plugin-react": "7.19.0", - "file-loader": "6.0.0", - "http-server": "0.12.0", + "http-server": "14.0.0", "jest": "24.8.0", "madge": "5.0.1", "marked": "0.8.2", @@ -114,7 +113,7 @@ "semantic-release": "17.4.6", "style-loader": "1.1.2", "svg-prep": "1.0.4", - "webpack": "5.53.0", + "webpack": "5.61.0", "webpack-cli": "4.0.0", "yaml": "1.10.0" }, @@ -125,7 +124,7 @@ "dashboard": "node ./Parse-Dashboard/index.js & webpack --config webpack/build.config.js --progress --watch", "pig": "http-server ./PIG -p 4041 -s & webpack --config webpack/PIG.config.js --progress --watch", "build": "cross-env NODE_ENV=production webpack --config webpack/production.config.js && webpack --config webpack/PIG.config.js", - "test": "cross-env NODE_PATH=./node_modules jest", + "test": "jest", "lint": "eslint . --ignore-path .gitignore --cache", "pretest": "npm run lint", "generate": "node scripts/generate.js", diff --git a/release.config.js b/release.config.js index 92053dc112..b59ac7fa11 100644 --- a/release.config.js +++ b/release.config.js @@ -107,7 +107,7 @@ async function readFile(filePath) { function getReleaseComment() { const url = repositoryUrl + '/releases/tag/${nextRelease.gitTag}'; - let comment = '🎉 This pull request has been released in version [${nextRelease.version}](' + url + ')'; + let comment = '🎉 This change has been released in version [${nextRelease.version}](' + url + ')'; return comment; } diff --git a/src/components/BooleanEditor/BooleanEditor.react.js b/src/components/BooleanEditor/BooleanEditor.react.js index b68316f7ad..38606d2286 100644 --- a/src/components/BooleanEditor/BooleanEditor.react.js +++ b/src/components/BooleanEditor/BooleanEditor.react.js @@ -20,6 +20,7 @@ export default class BooleanEditor extends React.Component { this.checkExternalClick = this.checkExternalClick.bind(this); this.handleKey = this.handleKey.bind(this); + this.inputRef = React.createRef(); } componentDidMount() { @@ -33,7 +34,7 @@ export default class BooleanEditor extends React.Component { } checkExternalClick(e) { - if (!hasAncestor(e.target, this.refs.input)) { + if (!hasAncestor(e.target, this.inputRef.current)) { this.props.onCommit(this.state.value); } } @@ -46,7 +47,7 @@ export default class BooleanEditor extends React.Component { render() { return ( -
+
 ; + classes.push(styles.empty); + } else if (this.props.type === 'Pointer') { + const defaultPointerKey = ColumnPreferences.getPointerDefaultKey(this.props.appId, this.props.value.className); + let dataValue = this.props.value.id; + if( defaultPointerKey !== 'objectId' ) { + dataValue = this.props.value.get(defaultPointerKey); + if ( dataValue && typeof dataValue === 'object' ){ + if ( dataValue instanceof Date ) { + dataValue = dataValue.toLocaleString(); + } + else { + if ( !this.props.value.id ) { + dataValue = this.props.value.id; + } else { + dataValue = '(undefined)'; + } + } + } + if ( !dataValue ) { + if ( this.props.value.id ) { + dataValue = this.props.value.id; + } else { + dataValue = '(undefined)'; + } + } + } + + if (this.props.value && this.props.value.__type) { + const object = new Parse.Object(this.props.value.className); + object.id = this.props.value.objectId; + this.props.value = object; + } + + content = this.props.onPointerClick ? ( + + ) : ( + dataValue + ); + + this.copyableValue = this.props.value.id; + } + else if (this.props.type === 'Array') { + if ( this.props.value[0] && typeof this.props.value[0] === 'object' && this.props.value[0].__type === 'Pointer' ) { + const array = []; + this.props.value.map( (v, i) => { + if ( typeof v !== 'object' || v.__type !== 'Pointer' ) { + throw new Error('Invalid type found in pointer array'); + } + const object = new Parse.Object(v.className); + object.id = v.objectId; + array.push( + + ); + }); + this.copyableValue = content =
    + { array.map( a =>
  • {a}
  • ) } +
+ if ( array.length > 1 ) { + classes.push(styles.hasMore); + } + } + else { + this.copyableValue = content = JSON.stringify(this.props.value); + } + } + else if (this.props.type === 'Date') { + if (typeof value === 'object' && this.props.value.__type) { + this.props.value = new Date(this.props.value.iso); + } else if (typeof value === 'string') { + this.props.value = new Date(this.props.value); + } + this.copyableValue = content = dateStringUTC(this.props.value); + } else if (this.props.type === 'Boolean') { + this.copyableValue = content = this.props.value ? 'True' : 'False'; + } else if (this.props.type === 'Object' || this.props.type === 'Bytes') { + this.copyableValue = content = JSON.stringify(this.props.value); + } else if (this.props.type === 'File') { + const fileName = this.props.value.url() ? getFileName(this.props.value) : 'Uploading\u2026'; + content = ; + this.copyableValue = fileName; + } else if (this.props.type === 'ACL') { + let pieces = []; + let json = this.props.value.toJSON(); + if (Object.prototype.hasOwnProperty.call(json, '*')) { + if (json['*'].read && json['*'].write) { + pieces.push('Public Read + Write'); + } else if (json['*'].read) { + pieces.push('Public Read'); + } else if (json['*'].write) { + pieces.push('Public Write'); + } + } + for (let role in json) { + if (role !== '*') { + pieces.push(role); + } + } + if (pieces.length === 0) { + pieces.push('Master Key Only'); + } + this.copyableValue = content = pieces.join(', '); + } else if (this.props.type === 'GeoPoint') { + this.copyableValue = content = `(${this.props.value.latitude}, ${this.props.value.longitude})`; + } else if (this.props.type === 'Polygon') { + this.copyableValue = content = this.props.value.coordinates.map(coord => `(${coord})`) + } else if (this.props.type === 'Relation') { + content = this.props.setRelation ? ( +
+ this.props.setRelation(this.props.value)} value='View relation' followClick={true} shrinkablePill /> +
+ ) : ( + 'Relation' + ); + this.copyableValue = undefined; } this.onContextMenu = this.onContextMenu.bind(this); + if (this.props.markRequiredField && this.props.isRequired && !this.props.value) { + classes.push(styles.required); + } + + this.setState({ ...this.state, content, classes }) } componentDidUpdate(prevProps) { + if ( this.props.value !== prevProps.value ) { + this.renderCellContent(); + } if (this.props.current) { const node = this.cellRef.current; const { setRelation } = this.props; @@ -58,7 +207,7 @@ export default class BrowserCell extends Component { } shouldComponentUpdate(nextProps, nextState) { - if (nextState.showTooltip !== this.state.showTooltip) { + if (nextState.showTooltip !== this.state.showTooltip || nextState.content !== this.state.content ) { return true; } const shallowVerifyProps = [...new Set(Object.keys(this.props).concat(Object.keys(nextProps)))] @@ -225,139 +374,27 @@ export default class BrowserCell extends Component { }))); } + componentDidMount(){ + this.renderCellContent(); + } + //#endregion render() { - let { type, value, hidden, width, current, onSelect, onEditChange, setCopyableValue, setRelation, onPointerClick, onPointerCmdClick, row, col, field, onEditSelectedRow, readonly, isRequired, markRequiredFieldRow } = this.props; - let content = value; + let { type, value, hidden, width, current, onSelect, onEditChange, setCopyableValue, onPointerCmdClick, row, col, field, onEditSelectedRow, readonly, isRequired, markRequiredFieldRow } = this.props; let isNewRow = row < 0; - this.copyableValue = content; - let classes = [styles.cell, unselectable]; - if (hidden) { - content = value !== undefined || !isNewRow ? '(hidden)' : isRequired ? '(required)' : '(undefined)'; - classes.push(styles.empty); - } else if (value === undefined) { - if (type === 'ACL') { - this.copyableValue = content = 'Public Read + Write'; - } else { - this.copyableValue = content = '(undefined)'; - classes.push(styles.empty); - } - content = isNewRow && isRequired && value === undefined ? '(required)' : content; - } else if (value === null) { - this.copyableValue = content = '(null)'; - classes.push(styles.empty); - } else if (value === '') { - content =  ; - classes.push(styles.empty); - } else if (type === 'Pointer') { - if (value && value.__type) { - const object = new Parse.Object(value.className); - object.id = value.objectId; - value = object; - } - content = onPointerClick ? ( - - ) : ( - value.id - ); - this.copyableValue = value.id; - } - else if (type === 'Array') { - if (value[0] && typeof value[0] === 'object' && value[0].__type === 'Pointer') { - const array = []; - value.map((v, i) => { - if (typeof v !== 'object' || v.__type !== 'Pointer') { - throw new Error('Invalid type found in pointer array'); - } - const object = new Parse.Object(v.className); - object.id = v.objectId; - array.push( - - ); - }); - content =
    - {array.map(a =>
  • {a}
  • )} -
- this.copyableValue = JSON.stringify(value); - if (array.length > 1) { - classes.push(styles.removePadding); - } - } - else { - this.copyableValue = content = JSON.stringify(value); - } - } - else if (type === 'Date') { - if (typeof value === 'object' && value.__type) { - value = new Date(value.iso); - } else if (typeof value === 'string') { - value = new Date(value); - } - this.copyableValue = content = dateStringUTC(value); - } else if (type === 'Boolean') { - this.copyableValue = content = value ? 'True' : 'False'; - } else if (type === 'Object' || type === 'Bytes') { - this.copyableValue = content = JSON.stringify(value); - } else if (type === 'File') { - const fileName = value.url() ? getFileName(value) : 'Uploading\u2026'; - content = ; - this.copyableValue = fileName; - } else if (type === 'ACL') { - let pieces = []; - let json = value.toJSON(); - if (Object.prototype.hasOwnProperty.call(json, '*')) { - if (json['*'].read && json['*'].write) { - pieces.push('Public Read + Write'); - } else if (json['*'].read) { - pieces.push('Public Read'); - } else if (json['*'].write) { - pieces.push('Public Write'); - } - } - for (let role in json) { - if (role !== '*') { - pieces.push(role); - } - } - if (pieces.length === 0) { - pieces.push('Master Key Only'); - } - this.copyableValue = content = pieces.join(', '); - } else if (type === 'GeoPoint') { - this.copyableValue = content = `(${value.latitude}, ${value.longitude})`; - } else if (type === 'Polygon') { - this.copyableValue = content = value.coordinates.map(coord => `(${coord})`) - } else if (type === 'Relation') { - content = setRelation ? ( -
- setRelation(value)} value='View relation' followClick={true} /> -
- ) : ( - 'Relation' - ); - this.copyableValue = undefined; - } - if (current) { + let classes = [...this.state.classes]; + + if ( current ) { classes.push(styles.current); } - if (markRequiredFieldRow === row && isRequired && !value) { classes.push(styles.required); } return readonly ? ( - + - {isNewRow ? '(auto)' : content} + {row < 0 || isNewRow ? '(auto)' : this.state.content} ) : ( @@ -413,13 +450,11 @@ export default class BrowserCell extends Component { if (['ACL', 'Boolean', 'File'].includes(type)) { e.preventDefault(); } - onEditChange(true); - } - }} - onContextMenu={this.onContextMenu} - > - {content} - + }}} + onContextMenu={this.onContextMenu.bind(this)} + > + {this.state.content} + ); } } diff --git a/src/components/BrowserFilter/BrowserFilter.react.js b/src/components/BrowserFilter/BrowserFilter.react.js index c474bc5566..0e90cbcedf 100644 --- a/src/components/BrowserFilter/BrowserFilter.react.js +++ b/src/components/BrowserFilter/BrowserFilter.react.js @@ -105,6 +105,7 @@ export default class BrowserFilter extends React.Component {
+
{this.props.categories.map((c) => { let id = c.id || c.name; + if (c.type === 'separator') { + return
; + } let count = c.count; let className = id === this.props.current ? styles.active : ''; let link = this.context.generatePath( diff --git a/src/components/CategoryList/CategoryList.scss b/src/components/CategoryList/CategoryList.scss index 168540b28a..f24bd69580 100644 --- a/src/components/CategoryList/CategoryList.scss +++ b/src/components/CategoryList/CategoryList.scss @@ -10,13 +10,13 @@ .class_list { position: relative; margin-bottom: 5px; + border-left: 1px solid #3e87b2; a { display: block; padding-left: 12px; height: 20px; line-height: 20px; - border-left: 1px solid #3e87b2; color: #8fb9cf; font-size: 12px; @@ -55,3 +55,10 @@ background: white; transition: top 0.2s cubic-bezier(1, 0, 0, 1); } + +.separator { + margin: 6px 0 6px 12px; + background-color: #3e87b2; + border: 0; + height: 1px; +} diff --git a/src/components/CodeSnippet/CodeSnippet.react.js b/src/components/CodeSnippet/CodeSnippet.react.js index 605d13058e..85b57bbe89 100644 --- a/src/components/CodeSnippet/CodeSnippet.react.js +++ b/src/components/CodeSnippet/CodeSnippet.react.js @@ -13,6 +13,11 @@ import './CodeSnippet.css'; import 'prismjs/plugins/line-numbers/prism-line-numbers'; export default class CodeSnippet extends React.Component { + constructor() { + super(); + this.codeRef = React.createRef(); + } + componentDidMount() { this._highlight(); } @@ -22,7 +27,7 @@ export default class CodeSnippet extends React.Component { } _highlight() { - Prism.highlightElement(this.refs.code); + Prism.highlightElement(this.codeRef.current); } render() { @@ -34,7 +39,7 @@ export default class CodeSnippet extends React.Component { let pageStyle = fullPage ? { minHeight: 'calc(100vh - 96px)'} : {}; return (
-        {this.props.source}
+        {this.props.source}
       
); } diff --git a/src/components/ColumnsConfiguration/ColumnConfigurationItem.react.js b/src/components/ColumnsConfiguration/ColumnConfigurationItem.react.js index a681b5d0f6..087e88b385 100644 --- a/src/components/ColumnsConfiguration/ColumnConfigurationItem.react.js +++ b/src/components/ColumnsConfiguration/ColumnConfigurationItem.react.js @@ -40,4 +40,4 @@ export default ({ name, handleColumnDragDrop, index, onChangeVisible, visible })
)); -}; \ No newline at end of file +}; diff --git a/src/components/DateTimeEditor/DateTimeEditor.react.js b/src/components/DateTimeEditor/DateTimeEditor.react.js index 79ad194a22..f2af5dc61c 100644 --- a/src/components/DateTimeEditor/DateTimeEditor.react.js +++ b/src/components/DateTimeEditor/DateTimeEditor.react.js @@ -23,6 +23,8 @@ export default class DateTimeEditor extends React.Component { this.checkExternalClick = this.checkExternalClick.bind(this); this.handleKey = this.handleKey.bind(this); + this.inputRef = React.createRef(); + this.editorRef = React.createRef(); } componentWillReceiveProps(props) { @@ -31,16 +33,16 @@ export default class DateTimeEditor extends React.Component { componentDidMount() { document.body.addEventListener('click', this.checkExternalClick); - this.refs.input.addEventListener('keypress', this.handleKey); + this.inputRef.current.addEventListener('keypress', this.handleKey); } componentWillUnmount() { document.body.removeEventListener('click', this.checkExternalClick); - this.refs.input.removeEventListener('keypress', this.handleKey); + this.inputRef.current.removeEventListener('keypress', this.handleKey); } checkExternalClick(e) { - if (!hasAncestor(e.target, this.refs.editor)) { + if (!hasAncestor(e.target, this.editorRef.current)) { this.props.onCommit(this.state.value); } } @@ -100,11 +102,11 @@ export default class DateTimeEditor extends React.Component { } return ( -
+
e.target.select()} onClick={this.toggle.bind(this)} diff --git a/src/components/FileEditor/FileEditor.react.js b/src/components/FileEditor/FileEditor.react.js index 7e438a995a..5c2b507026 100644 --- a/src/components/FileEditor/FileEditor.react.js +++ b/src/components/FileEditor/FileEditor.react.js @@ -21,6 +21,8 @@ export default class FileEditor extends React.Component { this.checkExternalClick = this.checkExternalClick.bind(this); this.handleKey = this.handleKey.bind(this); this.removeFile = this.removeFile.bind(this); + this.inputRef = React.createRef(); + this.fileInputRef = React.createRef(); } componentDidMount() { @@ -31,7 +33,7 @@ export default class FileEditor extends React.Component { fileInputElement.click(); } } - + componentWillUnmount() { document.body.removeEventListener('click', this.checkExternalClick); document.body.removeEventListener('keypress', this.handleKey); @@ -39,7 +41,7 @@ export default class FileEditor extends React.Component { checkExternalClick(e) { const { onCancel } = this.props; - if (!hasAncestor(e.target, this.refs.input) && onCancel) { + if (!hasAncestor(e.target, this.inputRef.current) && onCancel) { onCancel(); } } @@ -61,7 +63,7 @@ export default class FileEditor extends React.Component { } removeFile() { - this.refs.fileInput.value = ''; + this.fileInputRef.current.value = ''; this.props.onCommit(undefined); } @@ -76,9 +78,9 @@ export default class FileEditor extends React.Component { render() { const file = this.props.value; return ( -
+ diff --git a/src/components/FileInput/FileInput.react.js b/src/components/FileInput/FileInput.react.js index 1d59b78d23..cff626fd95 100644 --- a/src/components/FileInput/FileInput.react.js +++ b/src/components/FileInput/FileInput.react.js @@ -58,7 +58,7 @@ export default class FileInput extends React.Component { return (
-
+
{this.props.uploading ? (
) : label ? ( diff --git a/src/components/Filter/Filter.react.js b/src/components/Filter/Filter.react.js index af8a8b7877..f6c5c60ff1 100644 --- a/src/components/Filter/Filter.react.js +++ b/src/components/Filter/Filter.react.js @@ -9,6 +9,8 @@ import * as Filters from 'lib/Filters'; import { List, Map } from 'immutable'; import PropTypes from 'lib/PropTypes'; import React from 'react'; +import stringCompare from 'lib/stringCompare'; +import ParseApp from 'lib/ParseApp'; function changeField(schema, filters, index, newField) { let newFilter = new Map({ @@ -42,7 +44,7 @@ function deleteRow(filters, index) { return filters.delete(index); } -let Filter = ({ schema, filters, renderRow, onChange, blacklist }) => { +let Filter = ({ schema, filters, renderRow, onChange, blacklist, className }, context) => { blacklist = blacklist || []; let available = Filters.availableFilters(schema, filters); return ( @@ -56,7 +58,37 @@ let Filter = ({ schema, filters, renderRow, onChange, blacklist }) => { if (fields.indexOf(field) < 0) { fields.push(field); } - fields.sort(); + + // Get the column preference of the current class. + const currentColumnPreference = context.currentApp.columnPreference[className]; + + // Check if the preference exists. + if (currentColumnPreference) { + const fieldsToSortToTop = currentColumnPreference + .filter(item => item.filterSortToTop) + .map(item => item.name); + // Sort the fields. + fields.sort((a, b) => { + // Only "a" should sorted to the top. + if (fieldsToSortToTop.includes(a) && !fieldsToSortToTop.includes(b)) { + return -1 + } + // Only "b" should sorted to the top. + if (!fieldsToSortToTop.includes(a) && fieldsToSortToTop.includes(b)) { + return 1; + } + // Both should sorted to the top -> they should be sorted to the same order as in the "fieldsToSortToTop" array. + if (fieldsToSortToTop.includes(a) && fieldsToSortToTop.includes(b)) { + return fieldsToSortToTop.indexOf(a) - fieldsToSortToTop.indexOf(b); + } + return stringCompare(a, b); + }); + } + // If there's no preference: Use the default sort function. + else { + fields.sort(); + } + let constraints = Filters.FieldConstraints[schema[field].type].filter((c) => blacklist.indexOf(c) < 0); let compareType = schema[field].type; if (Object.prototype.hasOwnProperty.call(Filters.Constraints[constraint], 'field')) { @@ -105,3 +137,7 @@ Filter.propTypes = { 'A function for rendering a row of a filter.' ) }; + +Filter.contextTypes = { + currentApp: PropTypes.instanceOf(ParseApp) +}; diff --git a/src/components/GeoPointEditor/GeoPointEditor.react.js b/src/components/GeoPointEditor/GeoPointEditor.react.js index a91c708cb5..597bc529ee 100644 --- a/src/components/GeoPointEditor/GeoPointEditor.react.js +++ b/src/components/GeoPointEditor/GeoPointEditor.react.js @@ -22,15 +22,18 @@ export default class GeoPointEditor extends React.Component { this.checkExternalClick = this.checkExternalClick.bind(this); this.handleKeyLatitude = this.handleKeyLatitude.bind(this); this.handleKeyLongitude = this.handleKeyLongitude.bind(this); + + this.latitudeRef = React.createRef(); + this.longitudeRef = React.createRef(); } componentDidMount() { if (!this.props.disableAutoFocus) { - this.refs.latitude.focus(); + this.latitudeRef.current.focus(); } - this.refs.latitude.setSelectionRange(0, String(this.state.latitude).length); - this.refs.latitude.addEventListener('keypress', this.handleKeyLatitude); - this.refs.longitude.addEventListener('keypress', this.handleKeyLongitude); + this.latitudeRef.current.setSelectionRange(0, String(this.state.latitude).length); + this.latitudeRef.current.addEventListener('keypress', this.handleKeyLatitude); + this.longitudeRef.current.addEventListener('keypress', this.handleKeyLongitude); } componentWillReceiveProps(props) { @@ -45,8 +48,8 @@ export default class GeoPointEditor extends React.Component { } componentWillUnmount() { - this.refs.latitude.removeEventListener('keypress', this.handleKeyLatitude); - this.refs.longitude.removeEventListener('keypress', this.handleKeyLongitude); + this.latitudeRef.current.removeEventListener('keypress', this.handleKeyLatitude); + this.longitudeRef.current.removeEventListener('keypress', this.handleKeyLongitude); } checkExternalClick() { @@ -55,8 +58,8 @@ export default class GeoPointEditor extends React.Component { // check if activeElement is something else from input fields, // to avoid commiting new value on every switch of focus beetween latitude and longitude fields if ( - document.activeElement !== this.refs.latitude && - document.activeElement !== this.refs.longitude + document.activeElement !== this.latitudeRef.current && + document.activeElement !== this.longitudeRef.current ) { this.commitValue(); } @@ -65,8 +68,8 @@ export default class GeoPointEditor extends React.Component { handleKeyLatitude(e) { if (e.keyCode === 13 || e.keyCode === 44) { - this.refs.longitude.focus(); - this.refs.longitude.setSelectionRange(0, String(this.state.longitude).length); + this.longitudeRef.current.focus(); + this.longitudeRef.current.setSelectionRange(0, String(this.state.longitude).length); } } @@ -112,15 +115,15 @@ export default class GeoPointEditor extends React.Component { if (values[1].length <= 0 || !validateNumeric(values[1])) { this.setState({ latitude: values[0] }); - this.refs.longitude.focus(); - this.refs.longitude.setSelectionRange(0, String(this.state.longitude).length); + this.longitudeRef.current.focus(); + this.longitudeRef.current.setSelectionRange(0, String(this.state.longitude).length); return; } if (validateNumeric(values[1])) { this.setState({ latitude: values[0] }); this.setState({ longitude: values[1] }); - this.refs.longitude.focus(); + this.longitudeRef.current.focus(); return; } } @@ -130,14 +133,14 @@ export default class GeoPointEditor extends React.Component { this.setState({ [target]: validateNumeric(value) ? value : this.state[target] }); }; return ( -
+
diff --git a/src/components/GeoPointInput/GeoPointInput.react.js b/src/components/GeoPointInput/GeoPointInput.react.js index 8711301e18..c80484519b 100644 --- a/src/components/GeoPointInput/GeoPointInput.react.js +++ b/src/components/GeoPointInput/GeoPointInput.react.js @@ -52,4 +52,4 @@ export default class GeoPointInput extends React.Component {
); } -} \ No newline at end of file +} diff --git a/src/components/IntervalInput/IntervalInput.react.js b/src/components/IntervalInput/IntervalInput.react.js index 5e4fbe8cf6..97afccbe7b 100644 --- a/src/components/IntervalInput/IntervalInput.react.js +++ b/src/components/IntervalInput/IntervalInput.react.js @@ -45,4 +45,4 @@ IntervalInput.propTypes = { count: PropTypes.number.isRequired, unit: PropTypes.oneOf(['minute', 'hour']), onChange: PropTypes.func.isRequired -}; \ No newline at end of file +}; diff --git a/src/components/Loader/Loader.react.js b/src/components/Loader/Loader.react.js index 9159838ddd..277972f68f 100644 --- a/src/components/Loader/Loader.react.js +++ b/src/components/Loader/Loader.react.js @@ -52,6 +52,13 @@ function getPosition(t) { } export default class Loader extends React.Component { + constructor() { + super(); + this.dot0Ref = React.createRef(); + this.dot1Ref = React.createRef(); + this.dot2Ref = React.createRef(); + } + componentDidMount() { this.mounted = true; this.mountTime = new Date().getTime(); @@ -69,21 +76,21 @@ export default class Loader extends React.Component { let delta = new Date() - this.mountTime; let t = (delta / DURATION) % 1; let pos = getPosition(t); - let style = this.refs.dot0.style; + let style = this.dot0Ref.current.style; style.left = pos.x + 'px'; style.top = pos.y + 'px'; style.width = style.height = getRadius(t) + 'px'; t = (delta / DURATION + 0.4) % 1; pos = getPosition(t); - style = this.refs.dot1.style; + style = this.dot1Ref.current.style; style.left = pos.x + 'px'; style.top = pos.y + 'px'; style.width = style.height = getRadius(t) + 'px'; t = (delta / DURATION + 0.8) % 1; pos = getPosition(t); - style = this.refs.dot2.style; + style = this.dot2Ref.current.style; style.left = pos.x + 'px'; style.top = pos.y + 'px'; style.width = style.height = getRadius(t) + 'px'; @@ -98,9 +105,9 @@ export default class Loader extends React.Component { } return (
-
-
-
+
+
+
); } diff --git a/src/components/LoginForm/LoginForm.react.js b/src/components/LoginForm/LoginForm.react.js index e651658ff1..df824a4b11 100644 --- a/src/components/LoginForm/LoginForm.react.js +++ b/src/components/LoginForm/LoginForm.react.js @@ -13,11 +13,15 @@ import { verticalCenter } from 'stylesheets/base.scss'; // Class-style component, because we need refs export default class LoginForm extends React.Component { + constructor() { + super(); + this.formRef = React.createRef(); + } render() { return (
-
+
{this.props.header}
{this.props.children} @@ -34,7 +38,7 @@ export default class LoginForm extends React.Component { return; } this.props.formSubmit(); - this.refs.form.submit() + this.formRef.current.submit() }} className={styles.submit} value={this.props.action} /> diff --git a/src/components/NumberEditor/NumberEditor.react.js b/src/components/NumberEditor/NumberEditor.react.js index 1f3b579e91..0a63275272 100644 --- a/src/components/NumberEditor/NumberEditor.react.js +++ b/src/components/NumberEditor/NumberEditor.react.js @@ -19,10 +19,11 @@ export default class NumberEditor extends React.Component { this.checkExternalClick = this.checkExternalClick.bind(this); this.handleKey = this.handleKey.bind(this); + this.inputRef = React.createRef(); } componentDidMount() { - this.refs.input.setSelectionRange(0, String(this.state.value).length); + this.inputRef.current.setSelectionRange(0, String(this.state.value).length); document.body.addEventListener('click', this.checkExternalClick); document.body.addEventListener('keypress', this.handleKey); } @@ -33,7 +34,7 @@ export default class NumberEditor extends React.Component { } checkExternalClick(e) { - if (e.target !== this.refs.input) { + if (e.target !== this.inputRef.current) { this.commitValue() } } @@ -64,7 +65,7 @@ export default class NumberEditor extends React.Component { return (
diff --git a/src/components/Pill/Pill.react.js b/src/components/Pill/Pill.react.js index 45c6aa9d5a..81d7fe5818 100644 --- a/src/components/Pill/Pill.react.js +++ b/src/components/Pill/Pill.react.js @@ -10,7 +10,7 @@ import styles from 'components/Pill/Pill.scss'; import Icon from "components/Icon/Icon.react"; //TODO: refactor, may want to move onClick outside or need to make onClick able to handle link/button a11y -let Pill = ({ value, onClick, fileDownloadLink, followClick = false }) => ( +let Pill = ({ value, onClick, fileDownloadLink, followClick = false, shrinkablePill = false }) => ( ( ].join(" ")} onClick={!followClick && onClick ? onClick : null} > - {value} + {value} {followClick && ( !e.metaKey && onClick()}> diff --git a/src/components/Pill/Pill.scss b/src/components/Pill/Pill.scss index 95987e52a6..91744f68d1 100644 --- a/src/components/Pill/Pill.scss +++ b/src/components/Pill/Pill.scss @@ -9,9 +9,8 @@ .pill { @include MonospaceFont; - display: flex; - justify-content: space-between; - align-items: center; + position: relative; + display: inline-block; color: #0E69A1; height: 20px; line-height: 20px; @@ -22,6 +21,8 @@ text-overflow: ellipsis; white-space: nowrap; & a { + position: absolute; + right: 0; height: 20px; width: 20px; background: #d6e5f2; @@ -31,6 +32,14 @@ transform: rotate(316deg); } } + & .pillText { + position: absolute; + left: 0; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + width: 75%; + } } .content { diff --git a/src/components/PushCerts/PushCerts.react.js b/src/components/PushCerts/PushCerts.react.js index 20a3aaedc4..fcff72e3fb 100644 --- a/src/components/PushCerts/PushCerts.react.js +++ b/src/components/PushCerts/PushCerts.react.js @@ -59,4 +59,4 @@ PushCerts.propTypes = { ), }; -export default PushCerts; \ No newline at end of file +export default PushCerts; diff --git a/src/components/Range/Range.react.js b/src/components/Range/Range.react.js index ee9b3d3e2a..c1e6b3833f 100644 --- a/src/components/Range/Range.react.js +++ b/src/components/Range/Range.react.js @@ -16,11 +16,12 @@ export default class Range extends React.Component { constructor(props) { super(); this.state = { width: props.width }; + this.metricsRef = React.createRef(); } componentDidMount() { if (!this.props.width) { - this.setState({ width: this.refs.metrics.clientWidth }); + this.setState({ width: this.metricsRef.current.clientWidth }); } } @@ -64,7 +65,7 @@ export default class Range extends React.Component { return (
{tracker} (
); -export default AppName; \ No newline at end of file +export default AppName; diff --git a/src/components/Sidebar/FooterMenu.react.js b/src/components/Sidebar/FooterMenu.react.js index 594bc0b8f5..af09f3abf0 100644 --- a/src/components/Sidebar/FooterMenu.react.js +++ b/src/components/Sidebar/FooterMenu.react.js @@ -21,10 +21,11 @@ export default class FooterMenu extends React.Component { show: false, position: null, }; + this.moreRef = React.createRef(); } toggle() { - let pos = Position.inWindow(this.refs.more); + let pos = Position.inWindow(this.moreRef.current); pos.x += 24; this.setState({ show: true, @@ -59,7 +60,7 @@ export default class FooterMenu extends React.Component { ); } return ( -
+ {content} diff --git a/src/components/StringEditor/StringEditor.react.js b/src/components/StringEditor/StringEditor.react.js index d4859082a3..58ccda18e2 100644 --- a/src/components/StringEditor/StringEditor.react.js +++ b/src/components/StringEditor/StringEditor.react.js @@ -18,10 +18,11 @@ export default class StringEditor extends React.Component { this.checkExternalClick = this.checkExternalClick.bind(this); this.handleKey = this.handleKey.bind(this); + this.inputRef = React.createRef(); } componentDidMount() { - this.refs.input.setSelectionRange(0, this.state.value.length); + this.inputRef.current.setSelectionRange(0, this.state.value.length); document.body.addEventListener('click', this.checkExternalClick); document.body.addEventListener('keypress', this.handleKey); } @@ -32,7 +33,7 @@ export default class StringEditor extends React.Component { } checkExternalClick(e) { - if (e.target !== this.refs.input) { + if (e.target !== this.inputRef.current) { this.props.onCommit(this.state.value); } } @@ -57,7 +58,7 @@ export default class StringEditor extends React.Component { return (