From d8c7b15ccc054fff6990824c9f9d41b3185fbf13 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Jul 2022 06:17:13 +0000 Subject: [PATCH 01/36] Bump terser from 5.12.1 to 5.14.2 Bumps [terser](https://github.com/terser/terser) from 5.12.1 to 5.14.2. - [Release notes](https://github.com/terser/terser/releases) - [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md) - [Commits](https://github.com/terser/terser/commits) --- updated-dependencies: - dependency-name: terser dependency-type: indirect ... Signed-off-by: dependabot[bot] --- yarn.lock | 74 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 26 deletions(-) diff --git a/yarn.lock b/yarn.lock index b6d9a423..fa729f4e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2822,15 +2822,37 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" +"@jridgewell/gen-mapping@^0.3.0": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/resolve-uri@^3.0.3": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz#68eb521368db76d040a6315cdb24bf2483037b9c" - integrity sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew== + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/source-map@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" + integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" "@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.11" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz#771a1d8d744eeb71b6adb35808e1a6c7b9b8c8ec" - integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg== + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== "@jridgewell/trace-mapping@^0.3.0": version "0.3.4" @@ -2840,6 +2862,14 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" +"@jridgewell/trace-mapping@^0.3.9": + version "0.3.14" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed" + integrity sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@leichtgewicht/ip-codec@^2.0.1": version "2.0.3" resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.3.tgz#0300943770e04231041a51bd39f0439b5c7ab4f0" @@ -4404,9 +4434,9 @@ acorn@^7.0.0, acorn@^7.1.1: integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== acorn@^8.2.4, acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.0: - version "8.7.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" - integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== + version "8.7.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30" + integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== address@^1.0.1, address@^1.1.2: version "1.1.2" @@ -5062,9 +5092,9 @@ buffer-equal@0.0.1: integrity sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs= buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== buffer@^6.0.3: version "6.0.3" @@ -12373,15 +12403,7 @@ source-map-resolve@^0.6.0: atob "^2.1.2" decode-uri-component "^0.2.0" -source-map-support@^0.5.6: - version "0.5.19" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" - integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-support@~0.5.20: +source-map-support@^0.5.6, source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== @@ -12399,7 +12421,7 @@ source-map@^0.5.0, source-map@^0.5.6, source-map@^0.5.7: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= -source-map@^0.7.3, source-map@~0.7.2: +source-map@^0.7.3: version "0.7.3" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== @@ -12890,13 +12912,13 @@ terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.2.5: terser "^5.7.2" terser@^5.0.0, terser@^5.10.0, terser@^5.7.2: - version "5.12.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.12.1.tgz#4cf2ebed1f5bceef5c83b9f60104ac4a78b49e9c" - integrity sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ== + version "5.14.2" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.14.2.tgz#9ac9f22b06994d736174f4091aa368db896f1c10" + integrity sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA== dependencies: + "@jridgewell/source-map" "^0.3.2" acorn "^8.5.0" commander "^2.20.0" - source-map "~0.7.2" source-map-support "~0.5.20" test-exclude@^6.0.0: From 688052dcc134f6b76f6ef40d84afe234bacb6cec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Aug 2022 10:19:36 +0000 Subject: [PATCH 02/36] Bump async from 2.6.3 to 2.6.4 Bumps [async](https://github.com/caolan/async) from 2.6.3 to 2.6.4. - [Release notes](https://github.com/caolan/async/releases) - [Changelog](https://github.com/caolan/async/blob/v2.6.4/CHANGELOG.md) - [Commits](https://github.com/caolan/async/compare/v2.6.3...v2.6.4) --- updated-dependencies: - dependency-name: async dependency-type: indirect ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index da7f9913..503d0c59 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4672,9 +4672,9 @@ astral-regex@^2.0.0: integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== async@^2.6.2: - version "2.6.3" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" - integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== + version "2.6.4" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" + integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== dependencies: lodash "^4.17.14" From a0b0631a718a6ca6a04a6d8b7e4c73abc82469ff Mon Sep 17 00:00:00 2001 From: Harini Janakiraman Date: Fri, 19 Aug 2022 15:32:04 +1000 Subject: [PATCH 03/36] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5f1fa589..b84719b8 100644 --- a/README.md +++ b/README.md @@ -36,9 +36,9 @@ Connect to your database, manage data in table-UI with role based access control Set up Rowy on your Google Cloud Platform project with this easy deploy button. -[![Run on Google Cloud](https://deploy.cloud.run/button.svg)](https://deploy.rowy.app/) +[Guided quick start button](https://rowy.app/) -https://deploy.rowy.app/ +https://rowy.app ## Documentation @@ -91,7 +91,7 @@ https://user-images.githubusercontent.com/307298/157185793-f67511cd-7b7b-4229-95 Set up Rowy on your Google Cloud project with this one-click deploy button. Your data and cloud functions stay on your own Firestore/GCP. -[![Run on Google Cloud](https://deploy.cloud.run/button.svg)](https://deploy.rowy.app/) +[![Run on Google Cloud](https://deploy.cloud.run/button.svg)](https://rowy.app/) The one-click deploy makes the process of setting up easy with a step by step guide and ensures your project is setup correctly. From bafc415a16a1c6f7dd50f89450ffb37f53fcddc5 Mon Sep 17 00:00:00 2001 From: Bhavya Verma Date: Fri, 16 Sep 2022 13:35:10 +0530 Subject: [PATCH 04/36] Added confirmation for Duplicate Row button --- .../Table/ContextMenu/MenuContents.tsx | 35 +++++++++++++++---- .../Table/formatters/FinalColumn.tsx | 33 ++++++++++++++--- 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/src/components/Table/ContextMenu/MenuContents.tsx b/src/components/Table/ContextMenu/MenuContents.tsx index ae53a4a0..52b2d3d3 100644 --- a/src/components/Table/ContextMenu/MenuContents.tsx +++ b/src/components/Table/ContextMenu/MenuContents.tsx @@ -137,6 +137,12 @@ export default function MenuContents({ onClose }: IMenuContentsProps) { // Row actions if (row) { + const handleDuplicate = () => { + addRow({ + row, + setId: addRowIdType === "custom" ? "decrement" : addRowIdType, + }); + }; const handleDelete = () => deleteRow(row._rowy_ref.path); const rowActions = [ { @@ -179,13 +185,28 @@ export default function MenuContents({ onClose }: IMenuContentsProps) { disabled: tableSettings.tableType === "collectionGroup" || (!userRoles.includes("ADMIN") && tableSettings.readOnly), - onClick: () => { - addRow({ - row, - setId: addRowIdType === "custom" ? "decrement" : addRowIdType, - }); - onClose(); - }, + onClick: altPress + ? handleDuplicate + : () => { + confirm({ + title: "Duplicate row?", + body: ( + <> + Row path: +
+ + {row._rowy_ref.path} + + + ), + confirm: "Duplicate", + confirmColor: "success", + handleConfirm: handleDuplicate, + }); + onClose(); + }, }, { label: altPress ? "Delete" : "Delete…", diff --git a/src/components/Table/formatters/FinalColumn.tsx b/src/components/Table/formatters/FinalColumn.tsx index d5d57934..73f1c7b1 100644 --- a/src/components/Table/formatters/FinalColumn.tsx +++ b/src/components/Table/formatters/FinalColumn.tsx @@ -31,6 +31,12 @@ export default function FinalColumn({ row }: FormatterProps) { const [altPress] = useAtom(altPressAtom, projectScope); const handleDelete = () => deleteRow(row._rowy_ref.path); + const handleDuplicate = () => { + addRow({ + row, + setId: addRowIdType === "custom" ? "decrement" : addRowIdType, + }); + }; if (!userRoles.includes("ADMIN") && tableSettings.readOnly === true) return null; @@ -42,11 +48,28 @@ export default function FinalColumn({ row }: FormatterProps) { size="small" color="inherit" disabled={tableSettings.tableType === "collectionGroup"} - onClick={() => - addRow({ - row, - setId: addRowIdType === "custom" ? "decrement" : addRowIdType, - }) + onClick={ + altPress + ? handleDuplicate + : () => { + confirm({ + title: "Duplicate row?", + body: ( + <> + Row path: +
+ + {row._rowy_ref.path} + + + ), + confirm: "Duplicate", + confirmColor: "success", + handleConfirm: handleDuplicate, + }); + } } aria-label="Duplicate row" className="row-hover-iconButton" From fccad0bc1be7cef60a1786a2f75b89b6eae043df Mon Sep 17 00:00:00 2001 From: Han Tuerker Date: Fri, 16 Sep 2022 18:17:43 +0300 Subject: [PATCH 05/36] fix(airtable-import): fix columns step issues, ui improvements exact same as csv import --- .../ImportAirtableWizard/Step1Columns.tsx | 52 +++++++++++++------ 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/src/components/TableModals/ImportAirtableWizard/Step1Columns.tsx b/src/components/TableModals/ImportAirtableWizard/Step1Columns.tsx index d3500605..ea86e2c4 100644 --- a/src/components/TableModals/ImportAirtableWizard/Step1Columns.tsx +++ b/src/components/TableModals/ImportAirtableWizard/Step1Columns.tsx @@ -13,14 +13,17 @@ import { FormControl, RadioGroup, Radio, + Stack, + Box, } from "@mui/material"; import ArrowIcon from "@mui/icons-material/ArrowForward"; +import { TableColumn as TableColumnIcon } from "@src/assets/icons"; import { IStepProps } from "."; -import { AirtableConfig } from "./ImportAirtableWizard"; +import { AirtableConfig } from "@src/components/TableModals/ImportAirtableWizard"; import FadeList from "@src/components/TableModals/ScrollableList"; import Column, { COLUMN_HEADER_HEIGHT } from "@src/components/Table/Column"; -import MultiSelect from "@rowy/multiselect"; +import ColumnSelect from "@src/components/Table/ColumnSelect"; import { tableScope, @@ -28,7 +31,8 @@ import { tableColumnsOrderedAtom, } from "@src/atoms/tableScope"; import { FieldType } from "@src/constants/fields"; -import { suggestType } from "./utils"; +import { getFieldProp } from "@src/components/fields"; +import { suggestType } from "@src/components/TableModals/ImportAirtableWizard/utils"; export default function Step1Columns({ airtableData, @@ -51,6 +55,7 @@ export default function Step1Columns({ config.pairs.map((pair) => pair.fieldKey) ); + // When a field is selected to be imported const handleSelect = (field: string) => (e: React.ChangeEvent) => { const checked = e.target.checked; @@ -98,7 +103,7 @@ export default function Step1Columns({ // Delete matching newColumn if it was created if (configPair) { const newColumnIndex = findIndex(config.newColumns, { - key: configPair.fieldKey, + key: configPair.columnKey, }); if (newColumnIndex > -1) { const newColumns = [...config.newColumns]; @@ -116,14 +121,17 @@ export default function Step1Columns({ } }; + // When a field is mapped to a new column const handleChange = (fieldKey: string) => (value: string) => { if (!value) return; const columnKey = !!tableSchema.columns?.[value] ? value : camelCase(value); + if (columnKey === "") return; // Check if this pair already exists in config const configIndex = findIndex(config.pairs, { fieldKey }); + console.log(columnKey, configIndex); if (configIndex > -1) { const pairs = [...config.pairs]; - pairs[configIndex].fieldKey = columnKey; + pairs[configIndex].columnKey = columnKey; setConfig((config) => ({ ...config, pairs })); } else { updateConfig({ @@ -217,9 +225,8 @@ export default function Step1Columns({ {selected && ( - + + + {!isNewColumn ? ( + getFieldProp("icon", matchingColumn?.type) + ) : ( + + )} + {matchingColumn?.name} {isNewColumn && ( - theme.spacing(1) + " !important", - backgroundColor: "action.focus", + variant="outlined" + style={{ + marginLeft: "auto", pointerEvents: "none", + height: 24, + fontWeight: "normal", }} /> )} - + ); }, sx: [ @@ -274,14 +294,14 @@ export default function Step1Columns({ !columnKey && { color: "text.disabled" }, ], }, + sx: { "& .MuiInputLabel-root": { display: "none" } }, }} clearable={false} displayEmpty - labelPlural="columns" freeText - AddButtonProps={{ children: "Add new column…" }} + AddButtonProps={{ children: "Create column…" }} AddDialogProps={{ - title: "Add new column", + title: "Create column", textFieldLabel: "Column name", }} /> From 4deae4866d9e8f2a9db53e1d050abb1916db07d7 Mon Sep 17 00:00:00 2001 From: Han Tuerker Date: Fri, 16 Sep 2022 19:22:03 +0300 Subject: [PATCH 06/36] feat(airtable-import): add doc links --- .../ImportData/ImportFromAirtable.tsx | 51 +++++++++++++++++-- src/constants/externalLinks.ts | 4 ++ 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/components/TableToolbar/ImportData/ImportFromAirtable.tsx b/src/components/TableToolbar/ImportData/ImportFromAirtable.tsx index 21bdb405..f5ed3aa9 100644 --- a/src/components/TableToolbar/ImportData/ImportFromAirtable.tsx +++ b/src/components/TableToolbar/ImportData/ImportFromAirtable.tsx @@ -1,7 +1,14 @@ import { useState, useEffect } from "react"; import { useAtom, useSetAtom } from "jotai"; -import { Button, Typography, TextField } from "@mui/material"; +import { + Button, + Typography, + TextField, + IconButton, + Stack, + InputLabel, +} from "@mui/material"; import { tableModalAtom, @@ -11,6 +18,9 @@ import { import { analytics, logEvent } from "@src/analytics"; import { find } from "lodash-es"; +import { WIKI_LINKS } from "@src/constants/externalLinks"; +import DocsIcon from "@mui/icons-material/ArrowUpward"; + export default function ImportFromAirtable() { const [{ baseId, tableId, apiKey }, setImportAirtable] = useAtom( importAirtableAtom, @@ -108,10 +118,28 @@ export default function ImportFromAirtable() { manage with Rowy. + Airtable API Key + + API Key + + + } placeholder="Insert your API key here" value={apiKey} onChange={(e) => @@ -126,7 +154,24 @@ export default function ImportFromAirtable() { + Airtable Table URL + + Table URL + + + } placeholder="Insert your Table URL here" value={tableUrl} onChange={(e) => { diff --git a/src/constants/externalLinks.ts b/src/constants/externalLinks.ts index 10538e14..84035a12 100644 --- a/src/constants/externalLinks.ts +++ b/src/constants/externalLinks.ts @@ -55,6 +55,10 @@ const WIKI_PATHS = { extensionsSendgridEmail: "/extensions/sendgrid-email", extensionsTwilioMessage: "/extensions/twilio-message", webhooks: "/webhooks", + + importAirtable: "/import-export-data/import-airtable", + importAirtableApiKey: "/import-export-data/import-airtable#api-key", + importAirtableTableUrl: "/import-export-data/import-airtable#table-url", }; export const WIKI_LINKS = mapValues( WIKI_PATHS, From 33dd82ac6bdb21bb9f8c8b1ed0cbac3c350ab18e Mon Sep 17 00:00:00 2001 From: Miriam Shams-Rainey Date: Fri, 16 Sep 2022 23:44:49 -0400 Subject: [PATCH 07/36] #816: Fixed Logic for Custom Icons in Action Field --- src/components/fields/Action/ActionFab.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/components/fields/Action/ActionFab.tsx b/src/components/fields/Action/ActionFab.tsx index 67f00847..0e4db6cd 100644 --- a/src/components/fields/Action/ActionFab.tsx +++ b/src/components/fields/Action/ActionFab.tsx @@ -28,6 +28,16 @@ const replacer = (data: any) => (m: string, key: string) => { }; const getStateIcon = (actionState: "undo" | "redo" | string, config: any) => { + if (!get(config, "customIcons.enabled", false)) { + switch (actionState) { + case "undo": + return ; + case "redo": + return ; + default: + return ; + } + } switch (actionState) { case "undo": return get(config, "customIcons.undo") || ; From 37887b3826048d0874e75e565f2738a9c1becdfd Mon Sep 17 00:00:00 2001 From: shamsmosowi Date: Sat, 17 Sep 2022 16:33:20 +0200 Subject: [PATCH 08/36] implement cell copy/paste for json field --- .../fields/Json/ContextMenuActions.tsx | 75 +++++++++++++++++++ src/components/fields/Json/index.tsx | 2 + 2 files changed, 77 insertions(+) create mode 100644 src/components/fields/Json/ContextMenuActions.tsx diff --git a/src/components/fields/Json/ContextMenuActions.tsx b/src/components/fields/Json/ContextMenuActions.tsx new file mode 100644 index 00000000..de0555e3 --- /dev/null +++ b/src/components/fields/Json/ContextMenuActions.tsx @@ -0,0 +1,75 @@ +import { useAtom, useSetAtom } from "jotai"; +import { find, get } from "lodash-es"; +import { useSnackbar } from "notistack"; +import { Copy } from "@src/assets/icons"; +import Paste from "@mui/icons-material/ContentPaste"; + +import { + tableScope, + tableSchemaAtom, + tableRowsAtom, + updateFieldAtom, +} from "@src/atoms/tableScope"; +import { IFieldConfig } from "@src/components/fields/types"; + +export interface IContextMenuActions { + label: string; + icon: React.ReactNode; + onClick: () => void; +} + +export const ContextMenuActions: IFieldConfig["contextMenuActions"] = ( + selectedCell, + reset +) => { + const [tableSchema] = useAtom(tableSchemaAtom, tableScope); + const [tableRows] = useAtom(tableRowsAtom, tableScope); + const { enqueueSnackbar } = useSnackbar(); + const updateField = useSetAtom(updateFieldAtom, tableScope); + const selectedCol = tableSchema.columns?.[selectedCell.columnKey]; + if (!selectedCol) return []; + + const selectedRow = find(tableRows, ["_rowy_ref.path", selectedCell.path]); + const cellValue = get(selectedRow, selectedCol.fieldName) || []; + + const isEmpty = + cellValue === "" || + cellValue === null || + cellValue === undefined || + cellValue.length === 0; + + return [ + { + label: "Copy", + icon: , + onClick: () => { + try { + navigator.clipboard.writeText(JSON.stringify(cellValue)); + enqueueSnackbar("Copied"); + } catch (error) { + enqueueSnackbar(`Failed to copy: ${error}`, { variant: "error" }); + } + }, + disabled: isEmpty, + }, + { + label: "Paste", + icon: , + onClick: async () => { + try { + const text = await navigator.clipboard.readText(); + const parsed = JSON.parse(text); + updateField({ + path: selectedCell.path, + fieldName: selectedCol.fieldName, + value: parsed, + }); + } catch (error) { + enqueueSnackbar(`Failed to paste: ${error}`, { variant: "error" }); + } + }, + }, + ]; +}; + +export default ContextMenuActions; diff --git a/src/components/fields/Json/index.tsx b/src/components/fields/Json/index.tsx index e4587c17..8981d877 100644 --- a/src/components/fields/Json/index.tsx +++ b/src/components/fields/Json/index.tsx @@ -5,6 +5,7 @@ import withBasicCell from "@src/components/fields/_withTableCell/withBasicCell"; import { Json as JsonIcon } from "@src/assets/icons"; import BasicCell from "./BasicCell"; import withSideDrawerEditor from "@src/components/Table/editors/withSideDrawerEditor"; +import ContextMenuActions from "./ContextMenuActions"; const SideDrawerField = lazy( () => @@ -35,5 +36,6 @@ export const config: IFieldConfig = { }, SideDrawerField, settings: Settings, + contextMenuActions: ContextMenuActions, }; export default config; From 9105c167800426a81026fdad918cc2861523057d Mon Sep 17 00:00:00 2001 From: Sidney Alcantara Date: Mon, 19 Sep 2022 16:24:51 +1000 Subject: [PATCH 09/36] sync EmojiAvatar updates --- src/components/EmojiAvatar.tsx | 35 ++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/components/EmojiAvatar.tsx b/src/components/EmojiAvatar.tsx index ea11a4b2..0f089e6c 100644 --- a/src/components/EmojiAvatar.tsx +++ b/src/components/EmojiAvatar.tsx @@ -4,17 +4,28 @@ import { colord } from "colord"; import { useTheme, Avatar, AvatarProps } from "@mui/material"; import { spreadSx } from "@src/utils/ui"; +// https://www.stefanjudis.com/snippets/how-to-detect-emojis-in-javascript-strings/ +const emojiRegex = /\p{Emoji}/u; + +export const EMOJI_AVATAR_L_LIGHT = 90; +export const EMOJI_AVATAR_L_DARK = 30; +export const EMOJI_AVATAR_C_LIGHT = 15; +export const EMOJI_AVATAR_C_DARK = 20; + export interface IEmojiAvatarProps extends Partial { + /** CSS color string or a number (as a string). If number, used as hue */ bgColor?: string; emoji?: string; fallback: string; + uid?: string; size?: number; } export default function EmojiAvatar({ - bgColor, + bgColor: bgColorProp, emoji, fallback, + uid, children, size = 40, ...props @@ -22,7 +33,19 @@ export default function EmojiAvatar({ const theme = useTheme(); const darkMode = theme.palette.mode === "dark"; - const bgcolor = bgColor || generateRandomColor(fallback, darkMode); + let bgcolor: string; + if (bgColorProp && !Number.isNaN(Number(bgColorProp))) { + bgcolor = colord({ + l: darkMode ? EMOJI_AVATAR_L_DARK : EMOJI_AVATAR_L_LIGHT, + c: darkMode ? EMOJI_AVATAR_C_DARK : EMOJI_AVATAR_C_LIGHT, + h: Number(bgColorProp), + }).toHslString(); + } else if (bgColorProp) { + bgcolor = bgColorProp; + } else { + bgcolor = generateRandomColor(`${fallback}__${uid}`, darkMode); + } + const bgcolorLch = colord(bgcolor).toLch(); const textColor = colord({ l: @@ -42,7 +65,7 @@ export default function EmojiAvatar({ color: textColor, width: size, height: size, - fontSize: size * 0.45, + fontSize: size * (emojiRegex.test(emoji || "") ? 0.67 : 0.45), }, props.variant === "rounded" && { borderRadius: size / 40 }, ...spreadSx(props.sx), @@ -61,6 +84,10 @@ export default function EmojiAvatar({ const generateRandomColor = (seed: string, darkMode: boolean) => { const rng = seedrandom(seed); - const color = colord({ l: darkMode ? 30 : 90, c: 15, h: rng() * 360 }); + const color = colord({ + l: darkMode ? EMOJI_AVATAR_L_DARK : EMOJI_AVATAR_L_LIGHT, + c: darkMode ? EMOJI_AVATAR_C_DARK : EMOJI_AVATAR_C_LIGHT, + h: rng() * 360, + }); return color.toHslString(); }; From 067885b8dd51304b8ace9c9f8169154335d8d7c4 Mon Sep 17 00:00:00 2001 From: Sidney Alcantara Date: Mon, 19 Sep 2022 19:48:20 +1000 Subject: [PATCH 10/36] ConfirmDialog: fix confirm command persisting after close --- src/components/ConfirmDialog.tsx | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/components/ConfirmDialog.tsx b/src/components/ConfirmDialog.tsx index dd37b76d..e867dec0 100644 --- a/src/components/ConfirmDialog.tsx +++ b/src/components/ConfirmDialog.tsx @@ -1,5 +1,6 @@ import { useState } from "react"; import { useAtom } from "jotai"; +import { Scope } from "jotai/core/atom"; import { Dialog, @@ -14,11 +15,17 @@ import { import { SlideTransitionMui } from "@src/components/Modal/SlideTransition"; import { projectScope, confirmDialogAtom } from "@src/atoms/projectScope"; +export interface IConfirmDialogProps { + scope?: Scope; +} + /** * Display a confirm dialog using `confirmDialogAtom` in `globalState` * @see {@link confirmDialogAtom | Usage example} */ -export default function ConfirmDialog() { +export default function ConfirmDialog({ + scope = projectScope, +}: IConfirmDialogProps) { const [ { open, @@ -39,8 +46,12 @@ export default function ConfirmDialog() { buttonLayout = "horizontal", }, setState, - ] = useAtom(confirmDialogAtom, projectScope); - const handleClose = () => setState({ open: false }); + ] = useAtom(confirmDialogAtom, scope); + + const handleClose = () => { + setState({ open: false }); + setDryText(""); + }; const [dryText, setDryText] = useState(""); @@ -68,7 +79,7 @@ export default function ConfirmDialog() { value={dryText} onChange={(e) => setDryText(e.target.value)} autoFocus - label={`Type ${confirmationCommand} below to continue:`} + label={`Type “${confirmationCommand}” below to continue:`} placeholder={confirmationCommand} fullWidth id="dryText" From e64b8ad7136c1a414b178b3b9f133940c47c7e91 Mon Sep 17 00:00:00 2001 From: Sidney Alcantara Date: Tue, 20 Sep 2022 15:22:01 +1000 Subject: [PATCH 11/36] ref field: fix crashing when invalid path is typed --- .../fields/Reference/EditorCell.tsx | 18 +++++++--- .../fields/Reference/SideDrawerField.tsx | 34 ++++++++++++++----- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/components/fields/Reference/EditorCell.tsx b/src/components/fields/Reference/EditorCell.tsx index 824a8585..12c5e6b2 100644 --- a/src/components/fields/Reference/EditorCell.tsx +++ b/src/components/fields/Reference/EditorCell.tsx @@ -2,6 +2,7 @@ import { useRef, useLayoutEffect } from "react"; import { useAtom, useSetAtom } from "jotai"; import { EditorProps } from "react-data-grid"; import { get } from "lodash-es"; +import { useSnackbar } from "notistack"; import { TextField } from "@mui/material"; @@ -14,6 +15,7 @@ import { doc, deleteField } from "firebase/firestore"; export default function TextEditor({ row, column }: EditorProps) { const [firebaseDb] = useAtom(firebaseDbAtom, projectScope); const updateField = useSetAtom(updateFieldAtom, tableScope); + const { enqueueSnackbar } = useSnackbar(); const inputRef = useRef(null); @@ -23,11 +25,17 @@ export default function TextEditor({ row, column }: EditorProps) { return () => { const newValue = inputElement?.value; if (newValue !== undefined && newValue !== "") { - updateField({ - path: row._rowy_ref.path, - fieldName: column.key, - value: doc(firebaseDb, newValue), - }); + try { + const refValue = doc(firebaseDb, newValue); + + updateField({ + path: row._rowy_ref.path, + fieldName: column.key, + value: refValue, + }); + } catch (e: any) { + enqueueSnackbar(`Invalid path: ${e.message}`, { variant: "error" }); + } } else { updateField({ path: row._rowy_ref.path, diff --git a/src/components/fields/Reference/SideDrawerField.tsx b/src/components/fields/Reference/SideDrawerField.tsx index 2c13b345..677de82e 100644 --- a/src/components/fields/Reference/SideDrawerField.tsx +++ b/src/components/fields/Reference/SideDrawerField.tsx @@ -1,3 +1,4 @@ +import { useState } from "react"; import { useAtom } from "jotai"; import { doc } from "firebase/firestore"; import { ISideDrawerFieldProps } from "@src/components/fields/types"; @@ -19,20 +20,37 @@ export default function Reference({ const [projectId] = useAtom(projectIdAtom, projectScope); const [firebaseDb] = useAtom(firebaseDbAtom, projectScope); - const transformedValue = + const [localValue, setLocalValue] = useState( Boolean(value) && "path" in value && typeof value.path === "string" ? value.path - : ""; + : "" + ); + const [error, setError] = useState(""); return ( - + onChange(doc(firebaseDb, e.target.value))} - onBlur={onSubmit} - value={transformedValue} + onChange={(e) => { + try { + doc(firebaseDb, e.target.value); + setError(""); + } catch (e: any) { + setError(e.message); + } + setLocalValue(e.target.value); + }} + onBlur={() => { + if (!error) { + onChange(doc(firebaseDb, localValue)); + onSubmit(); + } + }} + value={localValue} + error={Boolean(error)} + helperText={error} id={getFieldId(column.key)} label="" hiddenLabel @@ -41,14 +59,14 @@ export default function Reference({ From 422aebdfba8584e7029aeabf4ce9e2efffe597c2 Mon Sep 17 00:00:00 2001 From: Bobby Wang Date: Wed, 21 Sep 2022 02:34:52 +0800 Subject: [PATCH 12/36] Fix the crash issue when pasting into action field input form --- src/components/fields/Action/Settings.tsx | 38 ++++++++++++----------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/components/fields/Action/Settings.tsx b/src/components/fields/Action/Settings.tsx index bf5fce43..3c5c26b8 100644 --- a/src/components/fields/Action/Settings.tsx +++ b/src/components/fields/Action/Settings.tsx @@ -88,7 +88,7 @@ const Settings = ({ config, onChange, fieldName }: ISettingsProps) => { Array.isArray(config.params) ? config.params : [], { space: 2 } ); - const [codeValid, setCodeValid] = useState(true); + const [codeErrorMessage, setCodeErrorMessage] = useState(null); const scriptExtraLibs = [ [ @@ -96,14 +96,16 @@ const Settings = ({ config, onChange, fieldName }: ISettingsProps) => { " /**", " * actionParams are provided by dialog popup form", " */", - (config.params ?? []).filter(Boolean).map((param: any) => { - const validationKeys = Object.keys(param.validation ?? {}); - if (validationKeys.includes("string")) { - return `static ${param.name}: string`; - } else if (validationKeys.includes("array")) { - return `static ${param.name}: any[]`; - } else return `static ${param.name}: any`; - }), + (Array.isArray(config.params) ? config.params : []) + .filter(Boolean) + .map((param: any) => { + const validationKeys = Object.keys(param.validation ?? {}); + if (validationKeys.includes("string")) { + return `static ${param.name}: string`; + } else if (validationKeys.includes("array")) { + return `static ${param.name}: any[]`; + } else return `static ${param.name}: any`; + }), "}", ].join("\n"), actionDefs, @@ -256,25 +258,25 @@ const Settings = ({ config, onChange, fieldName }: ISettingsProps) => { value={formattedParamsJson} onChange={(v) => { try { - if (v) { - const parsed = JSON.parse(v); + const parsed = JSON.parse(v ?? ""); + if (Array.isArray(parsed)) { onChange("params")(parsed); + setCodeErrorMessage(null); + } else { + setCodeErrorMessage("Form fields must be array"); } } catch (e) { console.log(`Failed to parse JSON: ${e}`); - setCodeValid(false); + setCodeErrorMessage("Invalid JSON"); } }} - onValidStatusUpdate={({ isValid }) => - setCodeValid(isValid) - } - error={!codeValid} + error={!!codeErrorMessage} /> - {!codeValid && ( + {codeErrorMessage && ( - Invalid JSON + {codeErrorMessage} )} From 44b82cc2e255040e0440cf1a3e623791f098bd19 Mon Sep 17 00:00:00 2001 From: Sidney Alcantara Date: Thu, 22 Sep 2022 13:38:22 +1000 Subject: [PATCH 13/36] Modal: use M3 FadeTransition --- src/components/ConfirmDialog.tsx | 4 ++-- src/components/Modal/Modal.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/ConfirmDialog.tsx b/src/components/ConfirmDialog.tsx index e867dec0..5819b169 100644 --- a/src/components/ConfirmDialog.tsx +++ b/src/components/ConfirmDialog.tsx @@ -12,7 +12,7 @@ import { Button, } from "@mui/material"; -import { SlideTransitionMui } from "@src/components/Modal/SlideTransition"; +import { FadeTransitionMui } from "@src/components/Modal/FadeTransition"; import { projectScope, confirmDialogAtom } from "@src/atoms/projectScope"; export interface IConfirmDialogProps { @@ -63,7 +63,7 @@ export default function ConfirmDialog({ else handleClose(); }} maxWidth={maxWidth} - TransitionComponent={SlideTransitionMui} + TransitionComponent={FadeTransitionMui} sx={{ cursor: "default", zIndex: (theme) => theme.zIndex.modal + 50 }} > {title} diff --git a/src/components/Modal/Modal.tsx b/src/components/Modal/Modal.tsx index 475ae796..fa9a9baa 100644 --- a/src/components/Modal/Modal.tsx +++ b/src/components/Modal/Modal.tsx @@ -16,7 +16,7 @@ import { import LoadingButton, { LoadingButtonProps } from "@mui/lab/LoadingButton"; import CloseIcon from "@mui/icons-material/Close"; -import { SlideTransitionMui } from "./SlideTransition"; +import { FadeTransitionMui } from "./FadeTransition"; import ScrollableDialogContent, { IScrollableDialogContentProps, } from "./ScrollableDialogContent"; @@ -86,7 +86,7 @@ export default function Modal({ onClose={handleClose} fullWidth fullScreen={fullScreen} - TransitionComponent={fullScreen ? Slide : SlideTransitionMui} + TransitionComponent={fullScreen ? Slide : FadeTransitionMui} TransitionProps={fullScreen ? ({ direction: "up" } as any) : undefined} aria-labelledby="modal-title" {...props} From 3353978243d892036a80c06c0e816a7e32ea99c0 Mon Sep 17 00:00:00 2001 From: Sidney Alcantara Date: Thu, 22 Sep 2022 13:38:29 +1000 Subject: [PATCH 14/36] upgrade jotai to latest --- package.json | 2 +- src/atoms/utils.ts | 3 +-- src/components/ConfirmDialog.tsx | 3 +-- src/hooks/useBeforeUnload.ts | 6 ++++-- src/hooks/useFirestoreCollectionWithAtom.ts | 3 +-- src/hooks/useFirestoreDocWithAtom.ts | 3 +-- src/hooks/useKeyPressWithAtom.ts | 5 ++--- src/layouts/RequireAuth.tsx | 12 +++++++++--- yarn.lock | 8 ++++---- 9 files changed, 24 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index f6e3055d..721396ac 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "file-saver": "^2.0.5", "firebase": "^9.6.11", "firebaseui": "^6.0.1", - "jotai": "^1.7.2", + "jotai": "^1.8.4", "json-stable-stringify-without-jsonify": "^1.0.1", "json2csv": "^5.0.7", "jszip": "^3.10.0", diff --git a/src/atoms/utils.ts b/src/atoms/utils.ts index 7903ca86..2c1458ab 100644 --- a/src/atoms/utils.ts +++ b/src/atoms/utils.ts @@ -1,8 +1,7 @@ -import { Scope } from "jotai/core/atom"; import { useAtomsDebugValue } from "jotai/devtools"; export function DebugAtoms( - options: { scope: Scope } & Parameters[0] + options: NonNullable[0]> ) { useAtomsDebugValue(options); return null; diff --git a/src/components/ConfirmDialog.tsx b/src/components/ConfirmDialog.tsx index 5819b169..ef2549f8 100644 --- a/src/components/ConfirmDialog.tsx +++ b/src/components/ConfirmDialog.tsx @@ -1,6 +1,5 @@ import { useState } from "react"; import { useAtom } from "jotai"; -import { Scope } from "jotai/core/atom"; import { Dialog, @@ -16,7 +15,7 @@ import { FadeTransitionMui } from "@src/components/Modal/FadeTransition"; import { projectScope, confirmDialogAtom } from "@src/atoms/projectScope"; export interface IConfirmDialogProps { - scope?: Scope; + scope?: Parameters[1]; } /** diff --git a/src/hooks/useBeforeUnload.ts b/src/hooks/useBeforeUnload.ts index 9a42ba66..98438a5f 100644 --- a/src/hooks/useBeforeUnload.ts +++ b/src/hooks/useBeforeUnload.ts @@ -1,6 +1,5 @@ import { useEffect } from "react"; import { useAtom, Atom } from "jotai"; -import { Scope } from "jotai/core/atom"; function beforeUnloadHandler(event: BeforeUnloadEvent) { event.preventDefault(); @@ -14,7 +13,10 @@ function beforeUnloadHandler(event: BeforeUnloadEvent) { * @param atom - The atom’s value to listen to * @param scope - The atom scope */ -export default function useBeforeUnload(atom: Atom, scope: Scope) { +export default function useBeforeUnload( + atom: Atom, + scope: NonNullable[1]> +) { const [atomValue] = useAtom(atom, scope); const atomValueFalsy = !atomValue; diff --git a/src/hooks/useFirestoreCollectionWithAtom.ts b/src/hooks/useFirestoreCollectionWithAtom.ts index 23bc2ce5..43f7165a 100644 --- a/src/hooks/useFirestoreCollectionWithAtom.ts +++ b/src/hooks/useFirestoreCollectionWithAtom.ts @@ -1,7 +1,6 @@ import { useState, useEffect } from "react"; import useMemoValue from "use-memo-value"; import { useAtom, PrimitiveAtom, useSetAtom, SetStateAction } from "jotai"; -import { Scope } from "jotai/core/atom"; import { set } from "lodash-es"; import { Firestore, @@ -77,7 +76,7 @@ interface IUseFirestoreCollectionWithAtomOptions { */ export function useFirestoreCollectionWithAtom( dataAtom: PrimitiveAtom, - dataScope: Scope | undefined, + dataScope: Parameters[1] | undefined, path: string | undefined, options?: IUseFirestoreCollectionWithAtomOptions ) { diff --git a/src/hooks/useFirestoreDocWithAtom.ts b/src/hooks/useFirestoreDocWithAtom.ts index e7691155..007061ac 100644 --- a/src/hooks/useFirestoreDocWithAtom.ts +++ b/src/hooks/useFirestoreDocWithAtom.ts @@ -1,7 +1,6 @@ import { useEffect } from "react"; import useMemoValue from "use-memo-value"; import { useAtom, PrimitiveAtom, useSetAtom } from "jotai"; -import { Scope } from "jotai/core/atom"; import { set } from "lodash-es"; import { Firestore, @@ -45,7 +44,7 @@ interface IUseFirestoreDocWithAtomOptions { */ export function useFirestoreDocWithAtom( dataAtom: PrimitiveAtom, - dataScope: Scope | undefined, + dataScope: Parameters[1] | undefined, path: string | undefined, options?: IUseFirestoreDocWithAtomOptions ) { diff --git a/src/hooks/useKeyPressWithAtom.ts b/src/hooks/useKeyPressWithAtom.ts index 78d23286..e51b1dd0 100644 --- a/src/hooks/useKeyPressWithAtom.ts +++ b/src/hooks/useKeyPressWithAtom.ts @@ -1,6 +1,5 @@ import { useEffect } from "react"; import { useSetAtom } from "jotai"; -import { PrimitiveAtom, Scope } from "jotai/core/atom"; /** * A hook that listens to when the target key is pressed @@ -11,8 +10,8 @@ import { PrimitiveAtom, Scope } from "jotai/core/atom"; */ export default function useKeyPressWithAtom( targetKey: string, - atom: PrimitiveAtom, - scope: Scope + atom: Parameters[0], + scope: Parameters[1] ) { const setAtom = useSetAtom(atom, scope); diff --git a/src/layouts/RequireAuth.tsx b/src/layouts/RequireAuth.tsx index f568b23a..bd5d7b09 100644 --- a/src/layouts/RequireAuth.tsx +++ b/src/layouts/RequireAuth.tsx @@ -1,4 +1,4 @@ -import { useAtom } from "jotai"; +import { useAtom, Atom } from "jotai"; import { useLocation, Navigate } from "react-router-dom"; import Loading from "@src/components/Loading"; @@ -8,10 +8,16 @@ import { ROUTES } from "@src/constants/routes"; export interface IRequireAuthProps { children: React.ReactElement; + atom?: Atom; + scope?: Parameters[1]; } -export default function RequireAuth({ children }: IRequireAuthProps) { - const [currentUser] = useAtom(currentUserAtom, projectScope); +export default function RequireAuth({ + children, + atom = currentUserAtom, + scope = projectScope, +}: IRequireAuthProps) { + const [currentUser] = useAtom(atom, scope); const location = useLocation(); if (currentUser === undefined) diff --git a/yarn.lock b/yarn.lock index 3dbe40a8..3e2592d4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8745,10 +8745,10 @@ jju@~1.4.0: resolved "https://registry.yarnpkg.com/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a" integrity sha1-o6vicYryQaKykE+EpiWXDzia4yo= -jotai@^1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/jotai/-/jotai-1.7.2.tgz#80587cf10f51a614c2028688e12d2abc6ac0b00c" - integrity sha512-ksvpW1Wu+/HwW1iDYq23PpXLu2df5Vv+eWw70jRAx7IEY4c+qRsORULnqPFurSy/X8LSoPcRhVDJx/cyf8jjMg== +jotai@^1.8.4: + version "1.8.4" + resolved "https://registry.yarnpkg.com/jotai/-/jotai-1.8.4.tgz#e188bff3cc790c758d25646f6f5daf9854c98eef" + integrity sha512-bkHDHNxm7bU4+bJL4z96fTlJYN34UDRTu3ghEajJrDepayON9YEaxPrXr7xhLnIRntoFC6eDYYhMNA/ilbj2RQ== js-base64@^2.4.3: version "2.6.4" From 67c2a3b6638fd69d88b15a435c4531dc8a5ca3ca Mon Sep 17 00:00:00 2001 From: Sidney Alcantara Date: Fri, 23 Sep 2022 11:53:00 +1000 Subject: [PATCH 15/36] ROWY-684: set table auditing to off by default --- src/components/TableSettingsDialog/form.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/TableSettingsDialog/form.tsx b/src/components/TableSettingsDialog/form.tsx index 11942034..d26e83d8 100644 --- a/src/components/TableSettingsDialog/form.tsx +++ b/src/components/TableSettingsDialog/form.tsx @@ -300,7 +300,7 @@ export const tableSettings = ( type: FieldType.checkbox, name: "audit", label: "Enable auditing for this table", - defaultValue: true, + defaultValue: false, }, { step: "auditing", From 0acca9d8599b71c7dc04e866a055d4b439d024e1 Mon Sep 17 00:00:00 2001 From: Sidney Alcantara Date: Fri, 23 Sep 2022 12:05:36 +1000 Subject: [PATCH 16/36] useBasicSearch: stricter search criteria --- src/hooks/useBasicSearch.ts | 6 ++++-- src/pages/TablesPage.tsx | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hooks/useBasicSearch.ts b/src/hooks/useBasicSearch.ts index cb61aebc..20c0ff48 100644 --- a/src/hooks/useBasicSearch.ts +++ b/src/hooks/useBasicSearch.ts @@ -1,6 +1,6 @@ import { useState } from "react"; import { useDebouncedCallback } from "use-debounce"; -import { matchSorter } from "match-sorter"; +import { matchSorter, rankings } from "match-sorter"; export function useBasicSearch( list: T[], @@ -10,7 +10,9 @@ export function useBasicSearch( const [query, setQuery] = useState(""); const handleQuery = useDebouncedCallback(setQuery, debounce); - const results = query ? matchSorter(list, query, { keys }) : list; + const results = query + ? matchSorter(list, query, { keys, threshold: rankings.ACRONYM }) + : list; return [results, query, handleQuery] as const; } diff --git a/src/pages/TablesPage.tsx b/src/pages/TablesPage.tsx index 4c914754..378f04a4 100644 --- a/src/pages/TablesPage.tsx +++ b/src/pages/TablesPage.tsx @@ -44,7 +44,7 @@ import { useScrollToHash } from "@src/hooks/useScrollToHash"; const SEARCH_KEYS = ["id", "name", "section", "description"]; -export default function HomePage() { +export default function TablesPage() { const [userRoles] = useAtom(userRolesAtom, projectScope); const [userSettings] = useAtom(userSettingsAtom, projectScope); const [updateUserSettings] = useAtom(updateUserSettingsAtom, projectScope); From c33484fbba4b3682d5f095faf26001e3e4ce94e8 Mon Sep 17 00:00:00 2001 From: Sidney Alcantara Date: Fri, 23 Sep 2022 12:13:27 +1000 Subject: [PATCH 17/36] ROWY-647: fix import wizard suggesting URLs should be a phone number column --- src/components/TableModals/ImportExistingWizard/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/TableModals/ImportExistingWizard/utils.ts b/src/components/TableModals/ImportExistingWizard/utils.ts index 98ec10e0..45750420 100644 --- a/src/components/TableModals/ImportExistingWizard/utils.ts +++ b/src/components/TableModals/ImportExistingWizard/utils.ts @@ -58,8 +58,8 @@ const inferTypeFromValue = (value: any) => { if (typeof value === "string") { if (REGEX_EMAIL.test(value)) return FieldType.email; - if (REGEX_PHONE.test(value)) return FieldType.phone; if (REGEX_URL.test(value)) return FieldType.url; + if (REGEX_PHONE.test(value)) return FieldType.phone; if (REGEX_HTML.test(value)) return FieldType.richText; if (value.length >= 50) return FieldType.longText; return FieldType.shortText; From 9aa2ad8540b0de735177b9d2b6a5b882ccb107d4 Mon Sep 17 00:00:00 2001 From: Bobby Wang Date: Mon, 26 Sep 2022 06:54:51 +0800 Subject: [PATCH 18/36] Add stripe webhook --- .../WebhooksModal/Schemas/basic.tsx | 9 -- .../WebhooksModal/Schemas/index.ts | 3 +- .../WebhooksModal/Schemas/stripe.tsx | 95 +++++++++++++++++++ .../TableModals/WebhooksModal/utils.tsx | 8 +- 4 files changed, 102 insertions(+), 13 deletions(-) create mode 100644 src/components/TableModals/WebhooksModal/Schemas/stripe.tsx diff --git a/src/components/TableModals/WebhooksModal/Schemas/basic.tsx b/src/components/TableModals/WebhooksModal/Schemas/basic.tsx index 616e6528..d9f81121 100644 --- a/src/components/TableModals/WebhooksModal/Schemas/basic.tsx +++ b/src/components/TableModals/WebhooksModal/Schemas/basic.tsx @@ -3,15 +3,6 @@ import WarningIcon from "@mui/icons-material/WarningAmber"; import { TableSettings } from "@src/types/table"; import { IWebhook } from "@src/components/TableModals/WebhooksModal/utils"; -export const webhookTypes = [ - "basic", - "typeform", - "sendgrid", - //"shopify", - //"twitter", - //"stripe", -] as const; - const requestType = [ "declare type WebHookRequest {", " /**", diff --git a/src/components/TableModals/WebhooksModal/Schemas/index.ts b/src/components/TableModals/WebhooksModal/Schemas/index.ts index 15ea2a1a..fff6341f 100644 --- a/src/components/TableModals/WebhooksModal/Schemas/index.ts +++ b/src/components/TableModals/WebhooksModal/Schemas/index.ts @@ -2,5 +2,6 @@ import basic from "./basic"; import typeform from "./typeform"; import sendgrid from "./sendgrid"; import webform from "./webform"; +import stripe from "./stripe"; -export { basic, typeform, sendgrid, webform }; +export { basic, typeform, sendgrid, webform, stripe }; diff --git a/src/components/TableModals/WebhooksModal/Schemas/stripe.tsx b/src/components/TableModals/WebhooksModal/Schemas/stripe.tsx new file mode 100644 index 00000000..77a78536 --- /dev/null +++ b/src/components/TableModals/WebhooksModal/Schemas/stripe.tsx @@ -0,0 +1,95 @@ +import { Typography, Link, TextField } from "@mui/material"; +import InlineOpenInNewIcon from "@src/components/InlineOpenInNewIcon"; +import { TableSettings } from "@src/types/table"; +import { IWebhook } from "@src/components/TableModals/WebhooksModal/utils"; + +export const webhookStripe = { + name: "Stripe", + parser: { + additionalVariables: null, + extraLibs: null, + template: ( + table: TableSettings + ) => `const sendgridParser: Parser = async ({ req, db, ref }) => { + const event = req.body + switch (event.type) { + case "payment_intent.succeeded": + break; + case "payment_intent.payment_failed": + break; + default: + // all other types + } +};`, + }, + condition: { + additionalVariables: null, + extraLibs: null, + template: ( + table: TableSettings + ) => `const condition: Condition = async({ref,req,db}) => { + // feel free to add your own code logic here + return true; +}`, + }, + auth: (webhookObject: IWebhook, setWebhookObject: (w: IWebhook) => void) => { + return ( + <> + + Get your{" "} + + secret key + + {" "} + and{" "} + + signing key + + {" "} + from Stripe dashboard. +
+ Then add the secret below. +
+ + { + setWebhookObject({ + ...webhookObject, + auth: { ...webhookObject.auth, secretKey: e.target.value }, + }); + }} + /> + { + setWebhookObject({ + ...webhookObject, + auth: { ...webhookObject.auth, signingSecret: e.target.value }, + }); + }} + /> + + ); + }, +}; + +export default webhookStripe; diff --git a/src/components/TableModals/WebhooksModal/utils.tsx b/src/components/TableModals/WebhooksModal/utils.tsx index db833809..c9cdccf1 100644 --- a/src/components/TableModals/WebhooksModal/utils.tsx +++ b/src/components/TableModals/WebhooksModal/utils.tsx @@ -1,6 +1,7 @@ import { TableSettings } from "@src/types/table"; import { generateId } from "@src/utils/table"; -import { typeform, basic, sendgrid, webform } from "./Schemas"; +import { typeform, basic, sendgrid, webform, stripe } from "./Schemas"; + export const webhookTypes = [ "basic", "typeform", @@ -8,7 +9,7 @@ export const webhookTypes = [ "webform", //"shopify", //"twitter", - //"stripe", + "stripe", ] as const; const requestType = [ @@ -53,7 +54,7 @@ export const webhookNames: Record = { //github:"GitHub", // shopify: "Shopify", // twitter: "Twitter", - // stripe: "Stripe", + stripe: "Stripe", basic: "Basic", webform: "Web form", }; @@ -82,6 +83,7 @@ export const webhookSchemas = { typeform, sendgrid, webform, + stripe, }; export function emptyWebhookObject( From 8a3632e4f99231cc6d701c4b68e4e6427422c672 Mon Sep 17 00:00:00 2001 From: Sidney Alcantara Date: Mon, 26 Sep 2022 12:53:11 +1000 Subject: [PATCH 19/36] NavDrawer: update Help, Learning menus --- src/constants/externalLinks.ts | 6 ++ src/layouts/Navigation/NavDrawer/HelpMenu.tsx | 58 ++++++------- .../Navigation/NavDrawer/LearningMenu.tsx | 86 +++++++++++++++++++ .../Navigation/NavDrawer/NavDrawer.tsx | 21 ++++- 4 files changed, 136 insertions(+), 35 deletions(-) create mode 100644 src/layouts/Navigation/NavDrawer/LearningMenu.tsx diff --git a/src/constants/externalLinks.ts b/src/constants/externalLinks.ts index 84035a12..bf2f41ab 100644 --- a/src/constants/externalLinks.ts +++ b/src/constants/externalLinks.ts @@ -23,6 +23,9 @@ export const EXTERNAL_LINKS = { rowyAppHostName: "rowy.app", dateFormat: "https://date-fns.org/v2.24.0/docs/format", + + welcomeVideo: + "https://www.youtube.com/watch?v=rJWASZW2ivg&list=PLow2dGbF6XclrTSvW3ug1pRxbGwsIgcWJ&index=1", } as const; const WIKI_PATHS = { @@ -38,6 +41,9 @@ const WIKI_PATHS = { howToDefaultValues: "/how-to/default-values", howToCustomViews: "/how-to/custom-views", + faqs: "/category/faqs", + faqsAccess: "/faqs/access", + fieldTypesSupportedFields: "/field-types/supported-fields", fieldTypesDerivative: "/field-types/derivative", fieldTypesConnectTable: "/field-types/connect-table", diff --git a/src/layouts/Navigation/NavDrawer/HelpMenu.tsx b/src/layouts/Navigation/NavDrawer/HelpMenu.tsx index 5ec00f04..75b7a5d4 100644 --- a/src/layouts/Navigation/NavDrawer/HelpMenu.tsx +++ b/src/layouts/Navigation/NavDrawer/HelpMenu.tsx @@ -3,16 +3,15 @@ import { useEffect } from "react"; import { Menu, MenuProps, - ListSubheader, MenuItem, - ListItemIcon, ListItemSecondaryAction, Divider, + ListItem, + ListItemText, } from "@mui/material"; import InlineOpenInNewIcon from "@src/components/InlineOpenInNewIcon"; -import SocialLogo from "@src/components/SocialLogo"; -import { EXTERNAL_LINKS } from "@src/constants/externalLinks"; +import { EXTERNAL_LINKS, WIKI_LINKS } from "@src/constants/externalLinks"; import { logEvent, analytics } from "analytics"; export default function HelpMenu({ @@ -46,28 +45,9 @@ export default function HelpMenu({ id="help-menu" anchorOrigin={{ vertical: "bottom", horizontal: "right" }} transformOrigin={{ vertical: "bottom", horizontal: "left" }} - sx={{ "& .MuiPaper-root": { mt: 1.5, py: 1 } }} + sx={{ "& .MuiPaper-root": { mt: 1.5 } }} PaperProps={{ elevation: 12 }} > - - Get support - - - Reach out for help and find FAQs on GitHub Discussions - - - - - - GitHub Discussions + Get support {externalLinkIcon} - + + FAQs + {externalLinkIcon} + - - - - Feature request + Feature requests {externalLinkIcon} + + + + + + ); } diff --git a/src/layouts/Navigation/NavDrawer/LearningMenu.tsx b/src/layouts/Navigation/NavDrawer/LearningMenu.tsx new file mode 100644 index 00000000..7aa65d14 --- /dev/null +++ b/src/layouts/Navigation/NavDrawer/LearningMenu.tsx @@ -0,0 +1,86 @@ +import { useEffect } from "react"; +import { Link } from "react-router-dom"; + +import { + Menu, + MenuProps, + MenuItem, + ListItemSecondaryAction, +} from "@mui/material"; +import InlineOpenInNewIcon from "@src/components/InlineOpenInNewIcon"; +import { ChevronRight as ChevronRightIcon } from "@src/assets/icons"; + +import { EXTERNAL_LINKS, WIKI_LINKS } from "@src/constants/externalLinks"; +import { ROUTES } from "@src/constants/routes"; +import { logEvent, analytics } from "analytics"; + +export default function LearningMenu({ + anchorEl, + onClose, +}: Pick) { + const open = Boolean(anchorEl); + useEffect(() => { + if (open) logEvent(analytics, "open_learning_menu"); + }, [open]); + + const externalLinkIcon = ( + + + + ); + + return ( + + + How-to guides + {externalLinkIcon} + + + + Table tutorial + + + + + + + Video tutorials + {externalLinkIcon} + + + ); +} diff --git a/src/layouts/Navigation/NavDrawer/NavDrawer.tsx b/src/layouts/Navigation/NavDrawer/NavDrawer.tsx index 769a0667..118ab4c5 100644 --- a/src/layouts/Navigation/NavDrawer/NavDrawer.tsx +++ b/src/layouts/Navigation/NavDrawer/NavDrawer.tsx @@ -30,6 +30,7 @@ import { import Logo from "@src/assets/Logo"; import NavItem from "./NavItem"; import GetStartedProgress from "@src/components/GetStartedChecklist/GetStartedProgress"; +import LearningMenu from "./LearningMenu"; import CommunityMenu from "./CommunityMenu"; import HelpMenu from "./HelpMenu"; import { INavDrawerContentsProps } from "./NavDrawerContents"; @@ -73,6 +74,8 @@ export default function NavDrawer({ const [getStartedCompleted, getStartedCompletionCount] = useGetStartedCompletion(); + const [learningMenuAnchorEl, setLearningMenuAnchorEl] = + useState(null); const [communityMenuAnchorEl, setCommunityMenuAnchorEl] = useState(null); const [helpMenuAnchorEl, setHelpMenuAnchorEl] = @@ -300,13 +303,27 @@ export default function NavDrawer({
  • - + { + setLearningMenuAnchorEl(e.currentTarget); + setHover("persist"); + }} + > - {externalLinkIcon} + + + + { + setLearningMenuAnchorEl(null); + setHover(false); + }} + />
  • From d801c5ecc963aedd9953d698c93d5a23604d1859 Mon Sep 17 00:00:00 2001 From: Sidney Alcantara Date: Mon, 26 Sep 2022 12:54:05 +1000 Subject: [PATCH 20/36] fix missing import --- src/layouts/Navigation/NavDrawer/HelpMenu.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/layouts/Navigation/NavDrawer/HelpMenu.tsx b/src/layouts/Navigation/NavDrawer/HelpMenu.tsx index 75b7a5d4..1ecdf03d 100644 --- a/src/layouts/Navigation/NavDrawer/HelpMenu.tsx +++ b/src/layouts/Navigation/NavDrawer/HelpMenu.tsx @@ -13,6 +13,7 @@ import InlineOpenInNewIcon from "@src/components/InlineOpenInNewIcon"; import { EXTERNAL_LINKS, WIKI_LINKS } from "@src/constants/externalLinks"; import { logEvent, analytics } from "analytics"; +import meta from "@root/package.json"; export default function HelpMenu({ anchorEl, From 83ee0e10a81606ff1cb48ccd543c8629850b9092 Mon Sep 17 00:00:00 2001 From: Sidney Alcantara Date: Mon, 26 Sep 2022 16:22:21 +1000 Subject: [PATCH 21/36] show rowy run popup for connector and action fields --- src/components/fields/Action/Settings.tsx | 8 +++++++- src/components/fields/Connector/Settings.tsx | 17 ++++++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/components/fields/Action/Settings.tsx b/src/components/fields/Action/Settings.tsx index 3c5c26b8..bc762c82 100644 --- a/src/components/fields/Action/Settings.tsx +++ b/src/components/fields/Action/Settings.tsx @@ -1,4 +1,4 @@ -import { lazy, Suspense, useState } from "react"; +import { lazy, Suspense, useState, useEffect } from "react"; import { get } from "lodash-es"; import stringify from "json-stable-stringify-without-jsonify"; import { Link } from "react-router-dom"; @@ -37,6 +37,7 @@ import { projectRolesAtom, projectSettingsAtom, compatibleRowyRunVersionAtom, + rowyRunModalAtom, } from "@src/atoms/projectScope"; import { tableScope, tableColumnsOrderedAtom } from "@src/atoms/tableScope"; import { WIKI_LINKS } from "@src/constants/externalLinks"; @@ -68,6 +69,11 @@ const Settings = ({ config, onChange, fieldName }: ISettingsProps) => { ); const [tableColumnsOrdered] = useAtom(tableColumnsOrderedAtom, tableScope); + const openRowyRunModal = useSetAtom(rowyRunModalAtom, projectScope); + useEffect(() => { + if (!settings.rowyRunUrl) openRowyRunModal({ feature: "Action fields" }); + }, [settings.rowyRunUrl]); + // const [activeStep, setActiveStep] = useState< // "requirements" | "friction" | "action" | "undo" | "customization" // >("requirements"); diff --git a/src/components/fields/Connector/Settings.tsx b/src/components/fields/Connector/Settings.tsx index a2c77c57..36548d03 100644 --- a/src/components/fields/Connector/Settings.tsx +++ b/src/components/fields/Connector/Settings.tsx @@ -1,5 +1,5 @@ -import { lazy, Suspense, useState } from "react"; -import { get } from "lodash-es"; +import { lazy, Suspense, useEffect } from "react"; +import { useAtom, useSetAtom } from "jotai"; import { Grid, @@ -11,7 +11,6 @@ import { Link, } from "@mui/material"; -import SteppedAccordion from "@src/components/SteppedAccordion"; import FieldSkeleton from "@src/components/SideDrawer/FieldSkeleton"; import CodeEditorHelper from "@src/components/CodeEditor/CodeEditorHelper"; import InlineOpenInNewIcon from "@src/components/InlineOpenInNewIcon"; @@ -21,6 +20,11 @@ import connectorDefs from "!!raw-loader!./connector.d.ts"; import { WIKI_LINKS } from "@src/constants/externalLinks"; import { baseFunction } from "./utils"; import { ISettingsProps } from "@src/components/fields/types"; +import { + projectScope, + projectSettingsAtom, + rowyRunModalAtom, +} from "@src/atoms/projectScope"; //import typeDefs from "!!raw-loader!./types.d.ts"; const CodeEditor = lazy( @@ -46,6 +50,13 @@ const diagnosticsOptions = { }; export default function Settings({ config, onChange }: ISettingsProps) { + const [projectSettings] = useAtom(projectSettingsAtom, projectScope); + const openRowyRunModal = useSetAtom(rowyRunModalAtom, projectScope); + useEffect(() => { + if (!projectSettings.rowyRunUrl) + openRowyRunModal({ feature: "Connector fields" }); + }, [projectSettings.rowyRunUrl]); + return ( <>
    From ae77fb066493eda54e017ce6b4a80ce1ec6c082a Mon Sep 17 00:00:00 2001 From: rohitb Date: Wed, 21 Sep 2022 14:45:56 +0530 Subject: [PATCH 22/36] Copy Document Path to Clipboard --- src/components/SideDrawer/FieldWrapper.tsx | 29 ++++++++++++++++------ src/constants/externalLinks.ts | 1 + src/utils/ui.ts | 4 +++ 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/components/SideDrawer/FieldWrapper.tsx b/src/components/SideDrawer/FieldWrapper.tsx index 620cf60d..d9214b84 100644 --- a/src/components/SideDrawer/FieldWrapper.tsx +++ b/src/components/SideDrawer/FieldWrapper.tsx @@ -11,6 +11,7 @@ import { } from "@mui/material"; import { DocumentPath as DocumentPathIcon } from "@src/assets/icons"; import LaunchIcon from "@mui/icons-material/Launch"; +import ContentCopyIcon from "@mui/icons-material/ContentCopy"; import LockIcon from "@mui/icons-material/LockOutlined"; import VisibilityOffIcon from "@mui/icons-material/VisibilityOffOutlined"; @@ -25,6 +26,9 @@ import { import { FieldType } from "@src/constants/fields"; import { getFieldProp } from "@src/components/fields"; import { getLabelId, getFieldId } from "./utils"; +import { EXTERNAL_LINKS } from "@src/constants/externalLinks"; +import { useSnackbar } from "notistack"; +import { copyToClipboard } from "@src/utils/ui"; export interface IFieldWrapperProps { children?: React.ReactNode; @@ -47,9 +51,15 @@ export default function FieldWrapper({ hidden, index, }: IFieldWrapperProps) { - const [projectId] = useAtom(projectIdAtom, projectScope); - const [altPress] = useAtom(altPressAtom, projectScope); - + const [projectId] = useAtom(projectIdAtom, globalScope); + const [altPress] = useAtom(altPressAtom, globalScope); + const { enqueueSnackbar } = useSnackbar(); + const documentPath = `${ + EXTERNAL_LINKS.firebaseProjectbasePath + }/${projectId}/firestore/data/~2F${(debugText as string)?.replace( + /\//g, + "~2F" + )}`; return (
    {debugText} - { + copyToClipboard(documentPath); + enqueueSnackbar("Copied!"); + }} + > + + + { export const spreadSx = (sx?: SxProps) => Array.isArray(sx) ? sx : sx ? [sx] : []; + +export const copyToClipboard = (text: string) => { + navigator.clipboard.writeText(text); +}; From c31b9e38c4f564128192968060abf96e1e8b57a6 Mon Sep 17 00:00:00 2001 From: rohitb Date: Mon, 26 Sep 2022 16:07:56 +0530 Subject: [PATCH 23/36] Fixed merge issue --- src/components/SideDrawer/FieldWrapper.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/SideDrawer/FieldWrapper.tsx b/src/components/SideDrawer/FieldWrapper.tsx index d9214b84..3ee90927 100644 --- a/src/components/SideDrawer/FieldWrapper.tsx +++ b/src/components/SideDrawer/FieldWrapper.tsx @@ -51,8 +51,8 @@ export default function FieldWrapper({ hidden, index, }: IFieldWrapperProps) { - const [projectId] = useAtom(projectIdAtom, globalScope); - const [altPress] = useAtom(altPressAtom, globalScope); + const [projectId] = useAtom(projectIdAtom, projectScope); + const [altPress] = useAtom(altPressAtom, projectScope); const { enqueueSnackbar } = useSnackbar(); const documentPath = `${ EXTERNAL_LINKS.firebaseProjectbasePath From 0cc440c3539e2d8482c6b38ac003e2f7d1041b6c Mon Sep 17 00:00:00 2001 From: Sidney Alcantara Date: Tue, 27 Sep 2022 16:17:44 +1000 Subject: [PATCH 24/36] lock settings routes to admin only --- src/App.tsx | 23 ++++++------- src/components/AccessDenied.tsx | 4 +-- src/components/CircularProgressTimed.tsx | 1 + src/layouts/AdminRoute.tsx | 44 ++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 14 deletions(-) create mode 100644 src/layouts/AdminRoute.tsx diff --git a/src/App.tsx b/src/App.tsx index 97209c9e..2890beba 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -9,6 +9,7 @@ import ConfirmDialog from "@src/components/ConfirmDialog"; import RowyRunModal from "@src/components/RowyRunModal"; import NotFound from "@src/pages/NotFoundPage"; import RequireAuth from "@src/layouts/RequireAuth"; +import AdminRoute from "@src/layouts/AdminRoute"; import { projectScope, @@ -20,7 +21,6 @@ import { ROUTES } from "@src/constants/routes"; import useKeyPressWithAtom from "@src/hooks/useKeyPressWithAtom"; import TableGroupRedirectPage from "./pages/TableGroupRedirectPage"; -import JotaiTestPage from "@src/pages/Test/JotaiTestPage"; import SignOutPage from "@src/pages/Auth/SignOutPage"; // prettier-ignore @@ -60,10 +60,6 @@ const MembersPage = lazy(() => import("@src/pages/Settings/MembersPage" /* webpa // prettier-ignore const DebugSettingsPage = lazy(() => import("@src/pages/Settings/DebugSettingsPage" /* webpackChunkName: "DebugSettingsPage" */)); -// prettier-ignore -const ThemeTestPage = lazy(() => import("@src/pages/Test/ThemeTestPage" /* webpackChunkName: "ThemeTestPage" */)); -// const RowyRunTestPage = lazy(() => import("@src/pages/RowyRunTestPage" /* webpackChunkName: "RowyRunTestPage" */)); - export default function App() { const [currentUser] = useAtom(currentUserAtom, projectScope); const [userRoles] = useAtom(userRolesAtom, projectScope); @@ -150,19 +146,22 @@ export default function App() { } /> } + element={ + + + + } /> } /> } + element={ + + + + } /> - {/* } /> */} - - } /> - - } /> )} diff --git a/src/components/AccessDenied.tsx b/src/components/AccessDenied.tsx index 792e9af3..7d068602 100644 --- a/src/components/AccessDenied.tsx +++ b/src/components/AccessDenied.tsx @@ -11,7 +11,7 @@ import { Link as MuiLink, Button, } from "@mui/material"; -import SecurityIcon from "@mui/icons-material/SecurityOutlined"; +import LockIcon from "@mui/icons-material/LockOutlined"; import EmptyState from "@src/components/EmptyState"; @@ -33,7 +33,7 @@ export default function AccessDenied({ resetErrorBoundary }: FallbackProps) { diff --git a/src/components/CircularProgressTimed.tsx b/src/components/CircularProgressTimed.tsx index 12c62862..11959f37 100644 --- a/src/components/CircularProgressTimed.tsx +++ b/src/components/CircularProgressTimed.tsx @@ -7,6 +7,7 @@ import { Box } from "@mui/material"; export interface ICircularProgressTimedProps extends ICircularProgressOpticalProps { + /** Duration in seconds */ duration: number; complete: boolean; } diff --git a/src/layouts/AdminRoute.tsx b/src/layouts/AdminRoute.tsx new file mode 100644 index 00000000..79cf2bcf --- /dev/null +++ b/src/layouts/AdminRoute.tsx @@ -0,0 +1,44 @@ +import { PropsWithChildren } from "react"; +import { useAtom } from "jotai"; +import { Link } from "react-router-dom"; + +import { Typography, Button } from "@mui/material"; +import LockIcon from "@mui/icons-material/LockOutlined"; +import HomeIcon from "@mui/icons-material/HomeOutlined"; + +import EmptyState from "@src/components/EmptyState"; + +import { projectScope, userRolesAtom } from "@src/atoms/projectScope"; +import { ROUTES } from "@src/constants/routes"; +import { TOP_BAR_HEIGHT } from "@src/layouts/Navigation/TopBar"; + +/** + * Lock pages for admins only + */ +export default function AdminRoute({ children }: PropsWithChildren<{}>) { + const [userRoles] = useAtom(userRolesAtom, projectScope); + + if (!userRoles.includes("ADMIN")) + return ( + + + You must be an admin of this workspace to access this page. + + + + + } + style={{ marginTop: -TOP_BAR_HEIGHT, marginBottom: -TOP_BAR_HEIGHT }} + /> + ); + + return children as JSX.Element; +} From b2102fd88a33dce12f9dc12eac8e669edf6cfb26 Mon Sep 17 00:00:00 2001 From: shamsmosowi Date: Tue, 27 Sep 2022 17:31:02 +0200 Subject: [PATCH 25/36] fix confirmation label --- src/components/ColumnMenu/ColumnMenu.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/ColumnMenu/ColumnMenu.tsx b/src/components/ColumnMenu/ColumnMenu.tsx index 9a4886bd..4884a75a 100644 --- a/src/components/ColumnMenu/ColumnMenu.tsx +++ b/src/components/ColumnMenu/ColumnMenu.tsx @@ -329,6 +329,7 @@ export default function ColumnMenu() { ), handleConfirm: handleEvaluateAll, + confirm: "Evaluate", }), }, ]; From c5730d6abe4e29227a044f934407a8b051c0e981 Mon Sep 17 00:00:00 2001 From: Sidney Alcantara Date: Wed, 28 Sep 2022 10:30:55 +1000 Subject: [PATCH 26/36] fix tables not loading from URL --- src/pages/Table/ProvidedTablePage.tsx | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/pages/Table/ProvidedTablePage.tsx b/src/pages/Table/ProvidedTablePage.tsx index 777b59e5..f609ac4c 100644 --- a/src/pages/Table/ProvidedTablePage.tsx +++ b/src/pages/Table/ProvidedTablePage.tsx @@ -3,7 +3,7 @@ import { useAtom, Provider } from "jotai"; import { DebugAtoms } from "@src/atoms/utils"; import { useParams, useOutlet } from "react-router-dom"; import { ErrorBoundary } from "react-error-boundary"; -import { find } from "lodash-es"; +import { find, isEmpty } from "lodash-es"; import ErrorFallback, { ERROR_TABLE_NOT_FOUND, @@ -16,6 +16,7 @@ import TableSkeleton from "@src/components/Table/TableSkeleton"; import { projectScope, currentUserAtom, + projectSettingsAtom, tablesAtom, } from "@src/atoms/projectScope"; import { @@ -32,10 +33,22 @@ export default function ProvidedTablePage() { const { id } = useParams(); const outlet = useOutlet(); const [currentUser] = useAtom(currentUserAtom, projectScope); + const [projectSettings] = useAtom(projectSettingsAtom, projectScope); const [tables] = useAtom(tablesAtom, projectScope); const tableSettings = useMemo(() => find(tables, ["id", id]), [tables, id]); - if (!tableSettings) throw new Error(ERROR_TABLE_NOT_FOUND + ": " + id); + if (!tableSettings) { + if (isEmpty(projectSettings)) { + return ( + <> + + + + ); + } else { + throw new Error(ERROR_TABLE_NOT_FOUND + ": " + id); + } + } return ( From 5c4f732e982e8abad1319f915f128fdc13dab35f Mon Sep 17 00:00:00 2001 From: shamsmosowi Date: Wed, 28 Sep 2022 23:25:25 +0100 Subject: [PATCH 27/36] change row and ref to be additional variable --- .../CodeEditor/CodeEditorHelper.tsx | 10 +-------- .../ColumnConfigModal/DefaultValueInput.tsx | 14 +++++++++++- .../ExtensionsModal/Step3Conditions.tsx | 8 +++++++ .../TableModals/ExtensionsModal/Step4Body.tsx | 8 +++++++ .../TableModals/WebhooksModal/Step3Parser.tsx | 4 ++++ src/components/fields/Action/Settings.tsx | 22 +++++++++++++++++-- src/components/fields/Connector/Settings.tsx | 11 +++++++++- src/components/fields/Derivative/Settings.tsx | 14 +++++++++++- 8 files changed, 77 insertions(+), 14 deletions(-) diff --git a/src/components/CodeEditor/CodeEditorHelper.tsx b/src/components/CodeEditor/CodeEditorHelper.tsx index 0b816c36..299c2134 100644 --- a/src/components/CodeEditor/CodeEditorHelper.tsx +++ b/src/components/CodeEditor/CodeEditorHelper.tsx @@ -22,18 +22,10 @@ export default function CodeEditorHelper({ const [projectId] = useAtom(projectIdAtom, projectScope); const availableVariables = [ - { - key: "row", - description: `row has the value of doc.data() it has type definitions using this table's schema, but you can access any field in the document.`, - }, { key: "db", description: `db object provides access to firestore database instance of this project. giving you access to any collection or document in this firestore instance`, }, - { - key: "ref", - description: `ref object that represents the reference to the current row in firestore db (ie: doc.ref).`, - }, { key: "auth", description: `auth provides access to a firebase auth instance, can be used to manage auth users or generate tokens.`, @@ -44,7 +36,7 @@ export default function CodeEditorHelper({ }, { key: "rowy", - description: `rowy provides a set of functions that are commonly used, such as easy access to GCP Secret Manager`, + description: `rowy provides a set of functions that are commonly used, such as easy file uploads & access to GCP Secret Manager`, }, ]; diff --git a/src/components/ColumnModals/ColumnConfigModal/DefaultValueInput.tsx b/src/components/ColumnModals/ColumnConfigModal/DefaultValueInput.tsx index 52ff712a..5213eb8a 100644 --- a/src/components/ColumnModals/ColumnConfigModal/DefaultValueInput.tsx +++ b/src/components/ColumnModals/ColumnConfigModal/DefaultValueInput.tsx @@ -204,7 +204,19 @@ export default function DefaultValueInput({ {column.config?.defaultValue?.type === "dynamic" && ( <> - + }> { @@ -530,7 +539,16 @@ const Settings = ({ config, onChange, fieldName }: ISettingsProps) => { diff --git a/src/components/fields/Connector/Settings.tsx b/src/components/fields/Connector/Settings.tsx index 36548d03..fc20de5a 100644 --- a/src/components/fields/Connector/Settings.tsx +++ b/src/components/fields/Connector/Settings.tsx @@ -72,7 +72,16 @@ export default function Settings({ config, onChange }: ISettingsProps) {
    diff --git a/src/components/fields/Derivative/Settings.tsx b/src/components/fields/Derivative/Settings.tsx index e084bc32..32ce65dc 100644 --- a/src/components/fields/Derivative/Settings.tsx +++ b/src/components/fields/Derivative/Settings.tsx @@ -135,7 +135,19 @@ export default function Settings({
    Derivative script - + }> Date: Thu, 29 Sep 2022 14:44:47 +1000 Subject: [PATCH 28/36] TablesPage: sort sections by name --- src/atoms/tableScope/table.ts | 2 +- src/pages/TablesPage.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/atoms/tableScope/table.ts b/src/atoms/tableScope/table.ts index 29bc400e..971601e6 100644 --- a/src/atoms/tableScope/table.ts +++ b/src/atoms/tableScope/table.ts @@ -1,6 +1,6 @@ import { atom } from "jotai"; import { atomWithReducer, atomWithHash } from "jotai/utils"; -import { uniqBy, findIndex, cloneDeep, unset, orderBy } from "lodash-es"; +import { findIndex, cloneDeep, unset, orderBy } from "lodash-es"; import { TableSettings, diff --git a/src/pages/TablesPage.tsx b/src/pages/TablesPage.tsx index 378f04a4..060e46e5 100644 --- a/src/pages/TablesPage.tsx +++ b/src/pages/TablesPage.tsx @@ -1,5 +1,5 @@ import { useAtom, useSetAtom } from "jotai"; -import { find, groupBy } from "lodash-es"; +import { find, groupBy, sortBy } from "lodash-es"; import { Container, @@ -67,7 +67,7 @@ export default function TablesPage() { : []; const sections: Record = { Favorites: favorites.map((id) => find(results, { id })) as TableSettings[], - ...groupBy(results, "section"), + ...groupBy(sortBy(results, ["section", "name"]), "section"), }; if (!Array.isArray(tables)) From 3b7c142a0c66bfe5a36fbf69d5dcbe035ae85dde Mon Sep 17 00:00:00 2001 From: Sidney Alcantara Date: Thu, 29 Sep 2022 14:45:02 +1000 Subject: [PATCH 29/36] auth redirect preserves location state --- src/layouts/RequireAuth.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/layouts/RequireAuth.tsx b/src/layouts/RequireAuth.tsx index bd5d7b09..ebe35e99 100644 --- a/src/layouts/RequireAuth.tsx +++ b/src/layouts/RequireAuth.tsx @@ -31,6 +31,7 @@ export default function RequireAuth({ ); From f136677ec85fb7bf75d897386f0af5b131146303 Mon Sep 17 00:00:00 2001 From: Sidney Alcantara Date: Fri, 30 Sep 2022 13:16:32 +1000 Subject: [PATCH 30/36] Modal: add MemoizedText component --- src/components/Modal/MemoizedText.tsx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/components/Modal/MemoizedText.tsx diff --git a/src/components/Modal/MemoizedText.tsx b/src/components/Modal/MemoizedText.tsx new file mode 100644 index 00000000..1b77485b --- /dev/null +++ b/src/components/Modal/MemoizedText.tsx @@ -0,0 +1,14 @@ +import { memo } from "react"; + +/** + * Used for global Modals that can have customizable text + * so that the default text doesn’t appear as the modal closes. + */ +const MemoizedText = memo( + function MemoizedTextComponent({ text }: { text: React.ReactNode }) { + return <>{text}; + }, + () => true +); + +export default MemoizedText; From 3bff1fbbd5374cc0e36ff766ff04f813039930f2 Mon Sep 17 00:00:00 2001 From: rohitb Date: Sun, 2 Oct 2022 22:59:14 +0530 Subject: [PATCH 31/36] Fixed review comments issue --- src/components/SideDrawer/FieldWrapper.tsx | 13 ++++--------- src/constants/externalLinks.ts | 1 - 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/components/SideDrawer/FieldWrapper.tsx b/src/components/SideDrawer/FieldWrapper.tsx index 3ee90927..ffedd66b 100644 --- a/src/components/SideDrawer/FieldWrapper.tsx +++ b/src/components/SideDrawer/FieldWrapper.tsx @@ -26,7 +26,6 @@ import { import { FieldType } from "@src/constants/fields"; import { getFieldProp } from "@src/components/fields"; import { getLabelId, getFieldId } from "./utils"; -import { EXTERNAL_LINKS } from "@src/constants/externalLinks"; import { useSnackbar } from "notistack"; import { copyToClipboard } from "@src/utils/ui"; @@ -54,12 +53,6 @@ export default function FieldWrapper({ const [projectId] = useAtom(projectIdAtom, projectScope); const [altPress] = useAtom(altPressAtom, projectScope); const { enqueueSnackbar } = useSnackbar(); - const documentPath = `${ - EXTERNAL_LINKS.firebaseProjectbasePath - }/${projectId}/firestore/data/~2F${(debugText as string)?.replace( - /\//g, - "~2F" - )}`; return (
    { - copyToClipboard(documentPath); + copyToClipboard((debugText as string).replace(/\//g, "~2F")); enqueueSnackbar("Copied!"); }} > Date: Mon, 3 Oct 2022 10:50:27 +1100 Subject: [PATCH 32/36] Remove replacement of `/` with `2F` in copy button --- src/components/SideDrawer/FieldWrapper.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SideDrawer/FieldWrapper.tsx b/src/components/SideDrawer/FieldWrapper.tsx index ffedd66b..c6a352cd 100644 --- a/src/components/SideDrawer/FieldWrapper.tsx +++ b/src/components/SideDrawer/FieldWrapper.tsx @@ -131,7 +131,7 @@ export default function FieldWrapper({ { - copyToClipboard((debugText as string).replace(/\//g, "~2F")); + copyToClipboard(debugText as string); enqueueSnackbar("Copied!"); }} > From b346b892a018e7d94c4d4470b17d044f09a2de65 Mon Sep 17 00:00:00 2001 From: Miriam Shams-Rainey Date: Mon, 3 Oct 2022 01:25:28 -0400 Subject: [PATCH 33/36] #513: Added Customizable Icons for Ratings Field (#817) * Update README.md * #513: Added Customizable Icons for Ratings Field * #513: Customizable Rating Icons Side Drawer Also updated formatting of custom rating icons to match default star sz * #513: Rating customization preview uses MUIRatings * #513: Using star icon outline for visibility Co-authored-by: Harini Janakiraman --- src/components/fields/Rating/Settings.tsx | 127 ++++++++++++------ .../fields/Rating/SideDrawerField.tsx | 9 +- src/components/fields/Rating/TableCell.tsx | 20 ++- 3 files changed, 110 insertions(+), 46 deletions(-) diff --git a/src/components/fields/Rating/Settings.tsx b/src/components/fields/Rating/Settings.tsx index 5504bd08..6134b530 100644 --- a/src/components/fields/Rating/Settings.tsx +++ b/src/components/fields/Rating/Settings.tsx @@ -1,48 +1,95 @@ import { ISettingsProps } from "@src/components/fields/types"; - -import { Slider, InputLabel, TextField, Grid } from "@mui/material"; +import RatingIcon from "@mui/icons-material/Star"; +import RatingOutlineIcon from "@mui/icons-material/StarBorder" +import { InputLabel, TextField, Grid, FormControlLabel, Checkbox, Stack } from "@mui/material"; import ToggleButton from "@mui/material/ToggleButton"; import ToggleButtonGroup from "@mui/material/ToggleButtonGroup"; +import MuiRating from "@mui/material/Rating"; +import { get } from "lodash-es"; export default function Settings({ onChange, config }: ISettingsProps) { return ( - <> - - - { - onChange("max")(parseInt(e.target.value)); - }} - inputProps={{ min: 1, max: 20 }} - /> - - - Star fraction - { - onChange("precision")(value); - }} - aria-label="text alignment" - > - - 1/4 - - - 1/2 - - - 1 - - - + + + { + let input = parseInt(e.target.value) || 0 + if (input > 20) { input = 20 } + onChange("max")(input); + }} + /> - + + Rating fraction + { + onChange("precision")(value); + }} + aria-label="text alignment" + sx={{ pt: 0.5 }} + > + + 1/4 + + + 1/2 + + + 1 + + + + + + onChange("customIcons.enabled")(e.target.checked) + } + name="customIcons.enabled" + /> + } + label="Customize ratings with emoji" + style={{ marginLeft: -11 }} + /> + + {config.customIcons?.enabled && ( + + + + onChange("customIcons.rating")(e.target.value) + } + label="Custom icon preview:" + className="labelHorizontal" + inputProps={{ style: { width: "2ch" } }} + /> + + e.stopPropagation()} + icon={get(config, "customIcons.rating") || } + size="small" + emptyIcon={get(config, "customIcons.rating") || } + max={get(config, "max")} + precision={get(config, "precision")} + sx={{ pt: 0.5 }} + /> + + + + )} + ); -} +} \ No newline at end of file diff --git a/src/components/fields/Rating/SideDrawerField.tsx b/src/components/fields/Rating/SideDrawerField.tsx index d3e4ffcb..eb117dd4 100644 --- a/src/components/fields/Rating/SideDrawerField.tsx +++ b/src/components/fields/Rating/SideDrawerField.tsx @@ -3,9 +3,8 @@ import { ISideDrawerFieldProps } from "@src/components/fields/types"; import { Grid } from "@mui/material"; import { Rating as MuiRating } from "@mui/material"; import "@mui/lab"; -import StarBorderIcon from "@mui/icons-material/StarBorder"; - -import { fieldSx, getFieldId } from "@src/components/SideDrawer/utils"; +import { getStateIcon, getStateOutline } from "./TableCell"; +import { fieldSx } from "@src/components/SideDrawer/utils"; export default function Rating({ column, @@ -29,7 +28,9 @@ export default function Rating({ onChange(newValue); onSubmit(); }} - emptyIcon={} + icon={getStateIcon(column.config)} + emptyIcon={getStateOutline(column.config)} + size="small" max={max} precision={precision} sx={{ ml: -0.5 }} diff --git a/src/components/fields/Rating/TableCell.tsx b/src/components/fields/Rating/TableCell.tsx index 34da84cf..2e7aee52 100644 --- a/src/components/fields/Rating/TableCell.tsx +++ b/src/components/fields/Rating/TableCell.tsx @@ -1,7 +1,21 @@ import { IHeavyCellProps } from "@src/components/fields/types"; import MuiRating from "@mui/material/Rating"; -import StarBorderIcon from "@mui/icons-material/StarBorder"; +import RatingIcon from "@mui/icons-material/Star"; +import RatingOutlineIcon from "@mui/icons-material/StarBorder" +import { get } from "lodash-es"; + + +export const getStateIcon = (config: any) => { + // only use the config to get the custom rating icon if enabled via toggle + if (!get(config, "customIcons.enabled")) { return } + return get(config, "customIcons.rating") || ; +}; + +export const getStateOutline = (config: any) => { + if (!get(config, "customIcons.enabled")) { return } + return get(config, "customIcons.rating") || ; +} export default function Rating({ row, @@ -28,9 +42,11 @@ export default function Rating({ name={`${row.id}-${column.key}`} value={typeof value === "number" ? value : 0} onClick={(e) => e.stopPropagation()} + icon={getStateIcon(column.config)} + size="small" disabled={disabled} onChange={(_, newValue) => onSubmit(newValue)} - emptyIcon={} + emptyIcon={getStateOutline(column.config)} max={max} precision={precision} sx={{ mx: -0.25 }} From da81271ba797c8b04ae986023d6031b8b01758a2 Mon Sep 17 00:00:00 2001 From: Bobby Wang Date: Mon, 3 Oct 2022 16:27:46 +1100 Subject: [PATCH 34/36] fix code editor type declarations not found error for dynamic import --- src/components/CodeEditor/useMonacoCustomizations.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/CodeEditor/useMonacoCustomizations.ts b/src/components/CodeEditor/useMonacoCustomizations.ts index f16f621b..e6d55533 100644 --- a/src/components/CodeEditor/useMonacoCustomizations.ts +++ b/src/components/CodeEditor/useMonacoCustomizations.ts @@ -78,6 +78,8 @@ export default function useMonacoCustomizations({ try { monaco.languages.typescript.javascriptDefaults.setCompilerOptions({ + moduleResolution: + monaco.languages.typescript.ModuleResolutionKind.NodeJs, target: monaco.languages.typescript.ScriptTarget.ES2020, allowNonTsExtensions: true, }); @@ -125,6 +127,7 @@ export default function useMonacoCustomizations({ ...JSON.parse(stringifiedDiagnosticsOptions), diagnosticCodesToIgnore: [ 1323, // remove dynamic import error + 2307, // silence type declarations not found for dynamic import ], }); } catch (error) { From c158adb4dd154588d8f84c87ebea296cfc518c5d Mon Sep 17 00:00:00 2001 From: Raj Gaurav Maurya Date: Mon, 3 Oct 2022 11:10:31 +0530 Subject: [PATCH 35/36] Feat: Customization options added to long text field (#821) * Update README.md * Update config.yml * Feat: Customization options added to long text field Signed-off-by: Raj Gaurav Maurya * Bug:LongText working Signed-off-by: Raj Gaurav Maurya --- .github/ISSUE_TEMPLATE/config.yml | 6 ++-- src/components/fields/LongText/Filter.tsx | 12 ++++++++ src/components/fields/LongText/Settings.tsx | 31 +++++++++++++++++++++ src/components/fields/LongText/index.tsx | 8 +++++- src/components/fields/ShortText/index.tsx | 1 + 5 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 src/components/fields/LongText/Filter.tsx create mode 100644 src/components/fields/LongText/Settings.tsx diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 35aaf69b..4aeb6a48 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,8 +1,8 @@ blank_issues_enabled: false contact_links: - - name: 🤔 Support & questions - url: https://discord.com/invite/fjBugmvzZP - about: Chat with us for live support on discord. + - name: 🤔 Need support / Q&A + url: https://github.com/rowyio/rowy/discussions/categories/support-q-a + about: Raise a support query on Github Discussion - name: 🙌 Want to join our team? url: https://www.rowy.io/jobs about: Get in touch to contribute & work with Rowy diff --git a/src/components/fields/LongText/Filter.tsx b/src/components/fields/LongText/Filter.tsx new file mode 100644 index 00000000..1fbbbdf7 --- /dev/null +++ b/src/components/fields/LongText/Filter.tsx @@ -0,0 +1,12 @@ +import { IFilterOperator } from "@src/components/fields/types"; + +export const filterOperators: IFilterOperator[] = [ + { + label: "equals", + value: "==", + }, + { + label: "not equals", + value: "!=", + }, +]; diff --git a/src/components/fields/LongText/Settings.tsx b/src/components/fields/LongText/Settings.tsx new file mode 100644 index 00000000..77cc58f9 --- /dev/null +++ b/src/components/fields/LongText/Settings.tsx @@ -0,0 +1,31 @@ +import { ISettingsProps } from "@src/components/fields/types"; +import { TextField } from "@mui/material"; + +export default function Settings({ onChange, config }: ISettingsProps) { + return ( + <> + { + if (e.target.value === "0") onChange("maxLength")(null); + else onChange("maxLength")(e.target.value); + }} + /> + { + if (e.target.value === "") onChange("validationRegex")(null); + else onChange("validationRegex")(e.target.value); + }} + /> + + ); +} diff --git a/src/components/fields/LongText/index.tsx b/src/components/fields/LongText/index.tsx index 2c501ce6..c4cec831 100644 --- a/src/components/fields/LongText/index.tsx +++ b/src/components/fields/LongText/index.tsx @@ -5,7 +5,8 @@ import withBasicCell from "@src/components/fields/_withTableCell/withBasicCell"; import LongTextIcon from "@mui/icons-material/Notes"; import BasicCell from "./BasicCell"; import TextEditor from "@src/components/Table/editors/TextEditor"; -import { filterOperators } from "@src/components/fields/ShortText/Filter"; + +import { filterOperators } from "./Filter"; import BasicContextMenuActions from "@src/components/fields/_BasicCell/BasicCellContextMenuActions"; const SideDrawerField = lazy( @@ -15,6 +16,10 @@ const SideDrawerField = lazy( ) ); +const Settings = lazy( + () => import("./Settings" /* webpackChunkName: "Settings-LongText" */) +); + export const config: IFieldConfig = { type: FieldType.longText, name: "Long Text", @@ -28,6 +33,7 @@ export const config: IFieldConfig = { TableCell: withBasicCell(BasicCell), TableEditor: TextEditor, SideDrawerField, + settings: Settings, filter: { operators: filterOperators, }, diff --git a/src/components/fields/ShortText/index.tsx b/src/components/fields/ShortText/index.tsx index aa288624..88ef7a20 100644 --- a/src/components/fields/ShortText/index.tsx +++ b/src/components/fields/ShortText/index.tsx @@ -15,6 +15,7 @@ const SideDrawerField = lazy( "./SideDrawerField" /* webpackChunkName: "SideDrawerField-ShortText" */ ) ); + const Settings = lazy( () => import("./Settings" /* webpackChunkName: "Settings-ShortText" */) ); From 5344d0c4085e5b5f0fbbe21d207ea8a02e739d04 Mon Sep 17 00:00:00 2001 From: shamsmosowi Date: Mon, 3 Oct 2022 07:58:06 +0200 Subject: [PATCH 36/36] remove max column width --- src/components/Table/Table.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/components/Table/Table.tsx b/src/components/Table/Table.tsx index cf3a3dff..73f910af 100644 --- a/src/components/Table/Table.tsx +++ b/src/components/Table/Table.tsx @@ -114,11 +114,7 @@ export default function Table({ tableSettings.readOnly && !userRoles.includes("ADMIN") ? false : column.editable ?? true, - width: (column.width as number) - ? (column.width as number) > MAX_COL_WIDTH - ? MAX_COL_WIDTH - : (column.width as number) - : DEFAULT_COL_WIDTH, + width: column.width ?? 100, })); if (userRoles.includes("ADMIN") || !tableSettings.readOnly) {