From 47a24f93dcd3449596635a4fc8fe4f384d7f8016 Mon Sep 17 00:00:00 2001 From: Luka Fontanilla Date: Fri, 15 Apr 2022 14:34:45 -0700 Subject: [PATCH 1/2] feat[adding extension for the merge query site] --- .../typescript/explore-query-merge/.gitignore | 8 + .../typescript/explore-query-merge/README.md | 85 +++++++++ .../explore-query-merge/babel.config.js | 58 +++++++ .../explore-query-merge/manifest.lkml | 11 ++ .../explore-query-merge/package.json | 83 +++++++++ .../explore-query-merge/src/App.tsx | 30 ++++ .../explore-query-merge/src/MergeMain.tsx | 162 ++++++++++++++++++ .../src/components/DrawerContent.tsx | 30 ++++ .../src/components/MergeInputs.tsx | 42 +++++ .../explore-query-merge/src/index.tsx | 23 +++ .../explore-query-merge/src/utils/helpers.ts | 20 +++ .../explore-query-merge/tsconfig.json | 10 ++ .../explore-query-merge/webpack.config.js | 61 +++++++ .../explore-query-merge/webpack.develop.js | 44 +++++ .../explore-query-merge/webpack.prod.js | 23 +++ 15 files changed, 690 insertions(+) create mode 100644 react/typescript/explore-query-merge/.gitignore create mode 100644 react/typescript/explore-query-merge/README.md create mode 100644 react/typescript/explore-query-merge/babel.config.js create mode 100644 react/typescript/explore-query-merge/manifest.lkml create mode 100644 react/typescript/explore-query-merge/package.json create mode 100644 react/typescript/explore-query-merge/src/App.tsx create mode 100644 react/typescript/explore-query-merge/src/MergeMain.tsx create mode 100644 react/typescript/explore-query-merge/src/components/DrawerContent.tsx create mode 100644 react/typescript/explore-query-merge/src/components/MergeInputs.tsx create mode 100644 react/typescript/explore-query-merge/src/index.tsx create mode 100644 react/typescript/explore-query-merge/src/utils/helpers.ts create mode 100644 react/typescript/explore-query-merge/tsconfig.json create mode 100644 react/typescript/explore-query-merge/webpack.config.js create mode 100644 react/typescript/explore-query-merge/webpack.develop.js create mode 100644 react/typescript/explore-query-merge/webpack.prod.js diff --git a/react/typescript/explore-query-merge/.gitignore b/react/typescript/explore-query-merge/.gitignore new file mode 100644 index 0000000..48f9201 --- /dev/null +++ b/react/typescript/explore-query-merge/.gitignore @@ -0,0 +1,8 @@ +node_modules/ +.npm +.eslintcache +npm-debug.log* +yarn-debug.log* +yarn-error.log* +yarn.lock +node_modules diff --git a/react/typescript/explore-query-merge/README.md b/react/typescript/explore-query-merge/README.md new file mode 100644 index 0000000..058bab5 --- /dev/null +++ b/react/typescript/explore-query-merge/README.md @@ -0,0 +1,85 @@ +# Looker Extension explore-query-merge + +explore-query-merge is a Looker extension using React and TypeScript. + +## Getting Started for Development + +1. Install the dependencies with [Yarn](https://yarnpkg.com/). + + ```sh + yarn install + ``` + +2. Build the project + + ```sh + yarn build + ``` + +3. Start the development server + + ```sh + yarn develop + ``` + + The development server is now running and serving the JavaScript at http://localhost:8080/bundle.js. + +4. Now log in to Looker and create a new project. + + Depending on the version of Looker, a new project can be created under: + + - **Develop** => **Manage LookML Projects** => **New LookML Project**, or + - **Develop** => **Projects** => **New LookML Project** + + Select "Blank Project" as the "Starting Point". This creates a new LookML project with no files. + +5. Create a `manifest` file + + Either drag and upload the `manifest.lkml` file in this directory into your Looker project, or create a `manifest.lkml` with the same content. Change the `id`, `label`, or `url` as needed. + + ``` + project_name: "explore-query-merge" + application: explore-query-merge { + label: "explore-query-merge React/TypeScript extension" + url: "http://localhost:8080/bundle.js" + entitlements: { + core_api_methods: ["me"] + } + } + ``` + +6. Create a `model` LookML file in your project. + + Typically, the model is named the same as the extension project. The model is used to control access to the extension. + + - [Configure the model you created](https://docs.looker.com/data-modeling/getting-started/create-projects#configuring_a_model) so that it has access to some connection (any connection). + +7. Connect the new project to Git. + + - Create a new repository on GitHub or a similar service, and follow the instructions to [connect your project to Git](https://docs.looker.com/data-modeling/getting-started/setting-up-git-connection) + +8. Commit the changes and deploy them to production through the Project UI. + +9. Reload the page and click the `Browse` dropdown menu. You should see the extension label in the list. + + - The extension will load the JavaScript from the `url` you provided in the `application` definition. By default, this is `http://localhost:8080/bundle.js`. If you change the port your server runs on in the `package.json`, you will need to also update it in the `manifest.lkml`. + - Reloading the extension page will bring in any new code changes from the extension template. + +## Deploying the extension + +To allow other people to use the extension, build the JavaScript bundle file and directly include it in the project. + +1. Build the extension with `yarn build` in the extension project directory on your development machine. +2. Drag and drop the generated `dist/bundle.js` file into the Looker project interface +3. Modify your `manifest.lkml` to use `file` instead of `url`: + + ``` + project_name: "explore-query-merge" + application: explore-query-merge { + label: "A Looker React/TypeScript extension" + file: "bundle.js" + entitlements: { + core_api_methods: ["me"] + } + } + ``` diff --git a/react/typescript/explore-query-merge/babel.config.js b/react/typescript/explore-query-merge/babel.config.js new file mode 100644 index 0000000..3bb643b --- /dev/null +++ b/react/typescript/explore-query-merge/babel.config.js @@ -0,0 +1,58 @@ +// Copyright 2021 Google LLC + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// https://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License 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. + +module.exports = (api) => { + api.cache(true) + + return { + presets: [ + [ + '@babel/env', + { + targets: { + esmodules: true, + }, + modules: false, + }, + ], + [ + '@babel/preset-react', + { + development: process.env.BABEL_ENV !== 'build', + }, + ], + '@babel/preset-typescript', + ], + env: { + build: { + ignore: [ + '**/*.d.ts', + '**/*.test.js', + '**/*.test.jsx', + '**/*.test.ts', + '**/*.test.tsx', + '__snapshots__', + '__tests__', + ], + }, + }, + ignore: ['node_modules'], + plugins: [ + '@babel/plugin-proposal-class-properties', + '@babel/plugin-proposal-object-rest-spread', + '@babel/plugin-transform-runtime', + 'babel-plugin-styled-components', + ], + } +} diff --git a/react/typescript/explore-query-merge/manifest.lkml b/react/typescript/explore-query-merge/manifest.lkml new file mode 100644 index 0000000..5d76f0e --- /dev/null +++ b/react/typescript/explore-query-merge/manifest.lkml @@ -0,0 +1,11 @@ + +project_name: "explore-query-merge" + +application: explore-query-merge { + label: "explore-query-merge" + url: "http://localhost:8080/bundle.js" + # file: "bundle.js + entitlements: { + core_api_methods: ["me"] #Add more entitlements here as you develop new functionality + } +} diff --git a/react/typescript/explore-query-merge/package.json b/react/typescript/explore-query-merge/package.json new file mode 100644 index 0000000..cbc4d58 --- /dev/null +++ b/react/typescript/explore-query-merge/package.json @@ -0,0 +1,83 @@ +{ + "name": "explore-query-merge", + "version": "0.0.1", + "description": "Bootstrapped Looker Extension with React and Typescript", + "main": "dist/bundle.js", + "author": "yournamehere", + "license": "Apache-2.0", + "scripts": { + "analyze": "export ANALYZE_MODE=static && yarn build", + "build": "export BABEL_ENV=build && webpack --config webpack.prod.js", + "clean": "rm -rf dist", + "develop": "webpack serve --hot --port 8080 --disable-host-check --config webpack.develop.js", + "prebuild": "yarn clean" + }, + "dependencies": { + "@looker/components": "^2.8.9", + "@looker/icons": "^1.5.9", + "@looker/embed-sdk": "^1.6.1", + "@looker/extension-sdk": "^21.18.1", + "@looker/extension-sdk-react": "^21.18.1", + "@looker/sdk": "^21.18.1", + "@looker/sdk-rtl": "^21.1.1", + "@styled-icons/material": "10.34.0", + "@styled-icons/material-outlined": "10.34.0", + "@styled-icons/material-rounded": "10.34.0", + "date-fns": "^2.25.0", + "lodash": "^4.17.21", + "react": "^16.14.0", + "react-dom": "^16.14.0", + "react-is": "^16.13.1", + "react-router-dom": "^5.3.0", + "semver": "^7.3.5", + "styled-components": "^5.3.3" + }, + "devDependencies": { + "@babel/cli": "^7.16.0", + "@babel/core": "^7.16.0", + "@babel/plugin-proposal-class-properties": "^7.16.0", + "@babel/plugin-proposal-object-rest-spread": "^7.16.0", + "@babel/plugin-transform-react-jsx": "^7.16.0", + "@babel/plugin-transform-runtime": "^7.16.0", + "@babel/preset-env": "^7.16.0", + "@babel/preset-react": "^7.16.0", + "@babel/preset-typescript": "^7.16.0", + "@babel/runtime": "^7.16.0", + "@types/lodash": "^4.14.176", + "@types/node": "^14.14.12", + "@types/react": "^16.14.2", + "@types/react-dom": "^16.9.10", + "@types/react-router-dom": "^5.1.5", + "@types/readable-stream": "^2.3.5", + "@types/semver": "^7.3.1", + "@types/styled-components": "5.1.5", + "babel-loader": "^8.2.3", + "babel-loader-exclude-node-modules-except": "^1.2.1", + "babel-preset-nano-react-app": "^0.1.0", + "minimist": "^1.2.5", + "nodemon": "^2.0.14", + "npm-run-all": "^4.1.5", + "react-hot-loader": "^4.13.0", + "typescript": "4.4.4", + "webpack": "^5.10.0", + "webpack-bundle-analyzer": "^4.5.0", + "webpack-cli": "^4.9.1", + "webpack-dev-server": "^3.11.2" + }, + "babel": { + "presets": [ + "nano-react-app" + ], + "plugins": [ + [ + "@babel/plugin-proposal-class-properties" + ], + [ + "@babel/plugin-transform-react-jsx", + { + "pragmaFrag": "React.Fragment" + } + ] + ] + } +} \ No newline at end of file diff --git a/react/typescript/explore-query-merge/src/App.tsx b/react/typescript/explore-query-merge/src/App.tsx new file mode 100644 index 0000000..1878ecc --- /dev/null +++ b/react/typescript/explore-query-merge/src/App.tsx @@ -0,0 +1,30 @@ +// Copyright 2021 Google LLC + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// https://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License 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. + +/** + * This is a sample Looker Extension written in typescript and React. It imports one component, . + * HelloWorld makes a simple call to the Looker API using the Extension Framework's built in authentication, + * and returns the logged in user. +*/ +import React from 'react' +import { ExtensionProvider } from '@looker/extension-sdk-react' +import { hot } from 'react-hot-loader/root' + +import { MergeMain } from './MergeMain' + +export const App = hot(() => ( + + + +)) diff --git a/react/typescript/explore-query-merge/src/MergeMain.tsx b/react/typescript/explore-query-merge/src/MergeMain.tsx new file mode 100644 index 0000000..d1a8f8a --- /dev/null +++ b/react/typescript/explore-query-merge/src/MergeMain.tsx @@ -0,0 +1,162 @@ +// Copyright 2021 Google LLC + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// https://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License 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, { useContext, useEffect, useState} from 'react' +import { ComponentsProvider, Space, Span, SpaceVertical, Form, Link, Button, ButtonTransparent, Slider, MessageBar, Card, CardContent, Paragraph, Heading, Grid, Drawer} from '@looker/components' +import { ExtensionContext } from '@looker/extension-sdk-react' +import {getHostname, getQID, Range} from './utils/helpers' +import { MergeInputs } from './components/MergeInputs' +import {DrawerContent} from './components/DrawerContent' + +export const MergeMain: React.FC = () => { + const { core40SDK } = useContext(ExtensionContext) + const [message, setMessage] = useState('') + const [merge, setMerge] = useState() + const [error, setError] = useState('') + const [url, setUrl] = useState('') + const [inputs, setInputs] = useState(2) + + interface MergeTypes { + hostname: Array, + qID: Array + } + + useEffect(() => { + const getMe = async () => { + try { + const me = await core40SDK.ok(core40SDK.me()) + setMessage(`Hello, ${me.display_name}`) + } catch (error) { + console.error(error) + setMessage('An error occurred while getting information about me!') + } + } + getMe() + }, []) + + useEffect(() => { + if(merge) createMergeQuery(merge) + },[merge]) + + const extractMergeInfo = (url: string) => { + if(url) { + const hostname = getHostname(url) + const qID = getQID(url) + return [hostname, qID] + } else { + throw new Error('No url supplied.') + } + } + + const handleClearForm = (e: any) => { + e.preventDefault(); + setUrl('') + setMerge(undefined) + if(error) setError(''); + // only grab unique inputs + const uniqueInputs = new Set(document.getElementsByTagName('INPUT') as any as Array) + uniqueInputs.forEach((elem) => (elem as HTMLInputElement).value = '') + } + + const handleClick = (e:any) => { + const hostnames = new Array() + const qIDs = new Array() + e.preventDefault(); + const mergeRange = Range(inputs) + const merges = mergeRange.map((merge) => (document.getElementsByName(`merge${merge}`)[0] as HTMLInputElement).value) + merges.forEach((m:string) => { + const [hostname, qID] = extractMergeInfo(m) + if(hostname) hostnames.push(hostname) + if(qID) qIDs.push(qID) + }) + setMerge({hostname:hostnames,qID:qIDs}); + } + + const createMergeQuery = (merge: MergeTypes) => { + // this should be handled by form input but if not + if(merge?.qID?.length <= 1) setError('At least two explore query urls need to be specified') + if(merge?.qID.includes("URL_ERROR")) setError('There was an error parsing the query id from the url. Check the explore query urls and try again.') + if(merge.hostname.every((val, i, arr: Array) => val === arr[0])) { + const url = `${merge.hostname[0]}merge?qids%5B%5D=${merge.qID.join('&qids%5B%5D=')}` + console.log(url) + setUrl(url) + } else { + setError('The hostnames of the inputted explore queries dont match. Please check that both urls come from the same Looker instance.') + } + } + + return ( + +
+ + + + {message}, welcome to Merge Explore Query! + + where queries become one. + + + + + What is Merge Explore Query? + + The Merge Explore Query Extension was inspired by this site, and provides a UI + to merge explore queries together. + + + Explore Merge + + + + + + How to use Merge Explore Query? + + Using Merge Explore Query, please select firstly the amount of queries you'd like to merge. Then input the explore urls with the first input being the base explore. + After submitting the merge query url will be outputted for you below. + + }> + + Please See Pre-Reqs before using. + + + + + + {error && Error with merged queries: {error}} +
+ + + + + {!url && !error + ? + + + setInputs(e.currentTarget.value as any as number)} + value={inputs} + /> + + : + + } + +
+ {url && !error && Access Link Here} +
+
+
+ ) +} diff --git a/react/typescript/explore-query-merge/src/components/DrawerContent.tsx b/react/typescript/explore-query-merge/src/components/DrawerContent.tsx new file mode 100644 index 0000000..6e86c01 --- /dev/null +++ b/react/typescript/explore-query-merge/src/components/DrawerContent.tsx @@ -0,0 +1,30 @@ +import React, {} from "react" +import {SpaceVertical, Heading, UnorderedList, Code, Card, CardContent} from "@looker/components" + +export const DrawerContent = () => { + return ( + <> + + + + Merge Explore Query Pre-Requisites + +
  • The url's inputted must be explore urls.
  • +
  • The explore url's must contain a qid= or query id in the url itself.
  • +
  • Merge Monster expects a normal explore url and not an expanded explore url (which is the url received when clicking "Share" in the Explore and grabbing + expanded url.)
  • +
  • All explore queries inputted must have a common dimension key (or shared table calc column) to be joined on otherwise you will get an error/warning in the resulting merge that no common key is + shared and that the merge failed. +
  • +
  • Your explore queries must not contain any pivots.
  • +
  • Merge queries don't support specifying a join condition, as such all queries will be left joined to the first merge input (so make sure the base query/base merge + is at the most granular level you are trying to show. +
  • +
  • Merge Queries can be expensive computations, as such we limit the amount of queries that can be merged to 5-6.
  • +
    +
    +
    +
    + + ) +} \ No newline at end of file diff --git a/react/typescript/explore-query-merge/src/components/MergeInputs.tsx b/react/typescript/explore-query-merge/src/components/MergeInputs.tsx new file mode 100644 index 0000000..69b6389 --- /dev/null +++ b/react/typescript/explore-query-merge/src/components/MergeInputs.tsx @@ -0,0 +1,42 @@ +// Copyright 2021 Google LLC + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// https://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License 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, { useEffect, useState} from 'react' +import { FieldText, Grid} from '@looker/components' +import { Range } from '../utils/helpers' + +interface InputProps { + inputs: number +} +export const MergeInputs = ({inputs}: InputProps) => { + const [range, setRange] = useState([0,1]) + + useEffect(() => { + console.log(Array.from(Array(inputs).keys())) + console.log('the inputs: ' + inputs) + setRange((Range(inputs))) + },[inputs]) + + return ( + // creating array range to loop over + <> + + {range.map((input, key) => ( + + ) + )} + + + ) +} \ No newline at end of file diff --git a/react/typescript/explore-query-merge/src/index.tsx b/react/typescript/explore-query-merge/src/index.tsx new file mode 100644 index 0000000..a36f78b --- /dev/null +++ b/react/typescript/explore-query-merge/src/index.tsx @@ -0,0 +1,23 @@ +// Copyright 2021 Google LLC + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// https://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License 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' +import ReactDOM from 'react-dom' +import { App } from './App' + +window.addEventListener('DOMContentLoaded', (_) => { + const root = document.createElement('div') + document.body.appendChild(root) + ReactDOM.render(, root) +}) diff --git a/react/typescript/explore-query-merge/src/utils/helpers.ts b/react/typescript/explore-query-merge/src/utils/helpers.ts new file mode 100644 index 0000000..acaafb8 --- /dev/null +++ b/react/typescript/explore-query-merge/src/utils/helpers.ts @@ -0,0 +1,20 @@ +export const getHostname = (url:string) => { + var matches = url.match(/^https?\:\/\/([^\/?#]+)(?:[\/?#]|$)/i); + var hostname = matches && matches[0]; + return hostname; +} + +export const getQID = (url:string) => { + if(url.includes("qid=")) { + const qid = url.split("qid=")[1].split("&")[0].replace(/\s+/g, ''); + if(/[~`!#$%\^&*+=\-\[\]\\';,/{}|\\":<>\?]/g.test(qid)) { + return "URL_ERROR" + } else { + return qid + } + } else { + return "URL_ERROR" + } +} + +export const Range = (n: number) => Array.from({length: n}, (value, key) => key) \ No newline at end of file diff --git a/react/typescript/explore-query-merge/tsconfig.json b/react/typescript/explore-query-merge/tsconfig.json new file mode 100644 index 0000000..ee9e935 --- /dev/null +++ b/react/typescript/explore-query-merge/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "jsx": "react", + "lib": ["dom", "es2015"], + "sourceMap": true, + "strict": true, + "esModuleInterop": true + }, + "exclude": ["node_modules"] +} \ No newline at end of file diff --git a/react/typescript/explore-query-merge/webpack.config.js b/react/typescript/explore-query-merge/webpack.config.js new file mode 100644 index 0000000..d522b1d --- /dev/null +++ b/react/typescript/explore-query-merge/webpack.config.js @@ -0,0 +1,61 @@ +// Copyright 2021 Google LLC + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// https://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License 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 fs = require("fs"); +const path = require("path"); + +const BundleAnalyzerPlugin = require("webpack-bundle-analyzer") + .BundleAnalyzerPlugin; +if (!process.env.POSTS_SERVER_URL) { + // webpack 5 is stricter about environment variables. The POSTS_SERVER_URL + // environment variable was not mentioned in the README so default it for + // those developers who may have created a .env file without the variable. + process.env.POSTS_SERVER_URL = "http://127.0.0.1:3000"; +} + +const PATHS = { + app: path.join(__dirname, "src/index.tsx"), +}; + +module.exports = { + entry: { + app: PATHS.app, + }, + output: { + path: __dirname + "/dist", + filename: "bundle.js", + }, + module: { + rules: [ + { + test: /\.(js|jsx|ts|tsx)$/, + loader: "babel-loader", + exclude: /node_modules/, + include: /src/, + sideEffects: false, + }, + ], + }, + resolve: { + extensions: [".tsx", ".ts", ".js"], + fallback: { buffer: false }, + }, + devtool: "source-map", + plugins: [ + new BundleAnalyzerPlugin({ + analyzerMode: process.env.ANALYZE_MODE || "disabled", + }), + ], +}; + diff --git a/react/typescript/explore-query-merge/webpack.develop.js b/react/typescript/explore-query-merge/webpack.develop.js new file mode 100644 index 0000000..1602b3d --- /dev/null +++ b/react/typescript/explore-query-merge/webpack.develop.js @@ -0,0 +1,44 @@ +// Copyright 2021 Google LLC + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// https://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License 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 commonConfig = require('./webpack.config') + +module.exports = { + ...commonConfig, + output: { + ...commonConfig.output, + publicPath: 'http://localhost:8080/', + }, + mode: 'development', + module: { + rules: [ + ...commonConfig.module.rules, + { + test: /\.(js|jsx|ts|tsx)?$/, + use: 'react-hot-loader/webpack', + include: /node_modules/, + }, + ], + }, + devServer: { + index: 'index.html', + headers: { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS', + 'Access-Control-Allow-Headers': + 'X-Requested-With, content-type, Authorization', + }, + }, + plugins: [...commonConfig.plugins], +} diff --git a/react/typescript/explore-query-merge/webpack.prod.js b/react/typescript/explore-query-merge/webpack.prod.js new file mode 100644 index 0000000..35d9b44 --- /dev/null +++ b/react/typescript/explore-query-merge/webpack.prod.js @@ -0,0 +1,23 @@ +// Copyright 2021 Google LLC + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// https://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License 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 commonConfig = require("./webpack.config"); + +module.exports = { + ...commonConfig, + mode: "production", + optimization: { + chunkIds: "named", + }, +}; From 8e49026df1b32f918317557ac4725b03e5cb699d Mon Sep 17 00:00:00 2001 From: Luka Fontanilla Date: Fri, 15 Apr 2022 15:09:24 -0700 Subject: [PATCH 2/2] adding dev command for new extension example in root package.json --- package.json | 1 + react/typescript/explore-query-merge/.prettierrc.json | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 react/typescript/explore-query-merge/.prettierrc.json diff --git a/package.json b/package.json index b3bb500..c1c317d 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "dev:map-iframe": "yarn workspace map-iframe develop", "dev:access-key-demo": "cd react/typescript/access-key-demo && yarn develop", "dev:access-key-demo-server": "cd react/typescript/access-key-demo && yarn start-server", + "dev:explore-query-merge": "cd react/typescript/explore-query-merge && yarn develop", "dev:helloworld-ts": "cd react/typescript/helloworld-ts && yarn develop", "dev:kitchensink": "cd react/typescript/kitchensink && yarn develop", "dev:looks-query": "cd react/typescript/looks-query-redux && yarn develop", diff --git a/react/typescript/explore-query-merge/.prettierrc.json b/react/typescript/explore-query-merge/.prettierrc.json new file mode 100644 index 0000000..36301bc --- /dev/null +++ b/react/typescript/explore-query-merge/.prettierrc.json @@ -0,0 +1,5 @@ +{ + "semi": false, + "singleQuote": true, + "trailingComma": "es5" +}