From 154be1ea33f47102df29f5ca61a3df478b6f85a2 Mon Sep 17 00:00:00 2001 From: Shams mosowi Date: Mon, 5 Jul 2021 12:40:47 +1000 Subject: [PATCH 1/7] expose dataset location option for BQ spark --- ft_build/sparksLib/bigqueryIndex.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ft_build/sparksLib/bigqueryIndex.ts b/ft_build/sparksLib/bigqueryIndex.ts index 9341a5898..c5539ab81 100644 --- a/ft_build/sparksLib/bigqueryIndex.ts +++ b/ft_build/sparksLib/bigqueryIndex.ts @@ -163,7 +163,7 @@ const transformToSQLType = (ftType: string) => { }; const bigqueryIndex = async (payload, sparkContext) => { - const { objectID, index, fieldsToSync, projectID } = payload; + const { objectID, index, fieldsToSync, projectID, datasetLocation } = payload; const { triggerType, change, fieldTypes } = sparkContext; const record = rowReducer(fieldsToSync, sparkContext.row); @@ -178,7 +178,9 @@ const bigqueryIndex = async (payload, sparkContext) => { // create dataset with exact name "firetable" if not exists async function preprocessDataset() { - const dataset = bigquery.dataset("firetable"); + const dataset = bigquery.dataset("firetable", { + location: datasetLocation ?? "US", + }); const res = await dataset.exists(); const exists = res[0]; if (!exists) { From 19aff5f9fdbbf5fbcf7cc8879811719374a27498 Mon Sep 17 00:00:00 2001 From: Sidney Alcantara Date: Mon, 5 Jul 2021 16:18:28 +1000 Subject: [PATCH 2/7] TextEditor: fix values not saving in react 17 (thanks @oliviertassinari ) https://github.com/mui-org/material-ui/issues/25560#issuecomment-811465881 https://github.com/facebook/react/pull/17925 --- www/src/components/Table/editors/TextEditor.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/www/src/components/Table/editors/TextEditor.tsx b/www/src/components/Table/editors/TextEditor.tsx index 97207e6df..ff64bbf95 100644 --- a/www/src/components/Table/editors/TextEditor.tsx +++ b/www/src/components/Table/editors/TextEditor.tsx @@ -1,4 +1,4 @@ -import { useRef, useEffect } from "react"; +import { useRef, useLayoutEffect } from "react"; import { EditorProps } from "react-data-grid"; import { makeStyles, createStyles, TextField } from "@material-ui/core"; @@ -47,7 +47,7 @@ export default function TextEditor({ row, column }: EditorProps) { const inputRef = useRef(null); - useEffect(() => { + useLayoutEffect(() => { return () => { const newValue = inputRef.current?.value; if (newValue !== undefined && updateCell) { From d43f4e684b0b8d84ce8a33bb1d1121b2e916e380 Mon Sep 17 00:00:00 2001 From: Sidney Alcantara Date: Mon, 12 Jul 2021 00:49:37 +1000 Subject: [PATCH 3/7] fix TableSettings multiSelects --- www/src/components/TableSettings/form.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/www/src/components/TableSettings/form.tsx b/www/src/components/TableSettings/form.tsx index 8a0c16fd5..b22e6330b 100644 --- a/www/src/components/TableSettings/form.tsx +++ b/www/src/components/TableSettings/form.tsx @@ -93,9 +93,8 @@ export const tableSettings = ( ) as any, }, { - type: FieldType.multiSelect, + type: FieldType.singleSelect, name: "section", - multiple: false, label: "Section", freeText: true, options: sections, @@ -171,12 +170,11 @@ export const tableSettings = ( }, mode === TableSettingsDialogModes.create && tables && tables?.length !== 0 ? { - type: FieldType.multiSelect, + type: FieldType.singleSelect, name: "schemaSource", label: "Copy column config from existing table", labelPlural: "Tables", options: tables, - multiple: false, freeText: false, itemRenderer: (option: { value: string; label: string }) => ( From 6ef23072e1383c761d39fcb70e4e4a31ea655dca Mon Sep 17 00:00:00 2001 From: Bobby Wang Date: Mon, 12 Jul 2021 12:31:51 +1000 Subject: [PATCH 4/7] default signInOptions to google if signInOptions doc is missing --- www/src/components/Auth/FirebaseUi.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/www/src/components/Auth/FirebaseUi.tsx b/www/src/components/Auth/FirebaseUi.tsx index ac22c6421..5ad178661 100644 --- a/www/src/components/Auth/FirebaseUi.tsx +++ b/www/src/components/Auth/FirebaseUi.tsx @@ -187,7 +187,14 @@ export default function FirebaseUi(props: Partial) { useEffect(() => { db.doc("/_FIRETABLE_/publicSettings") .get() - .then((doc) => setSignInOptions(doc?.get("signInOptions"))) + .then((doc) => { + const options = doc?.get("signInOptions"); + if (!options) { + setSignInOptions(["google"]); + } else { + setSignInOptions(options); + } + }) .catch(() => setSignInOptions(["google"])); }, []); From f29489de773fdfaa4656ffd96b08da7d7d73bfab Mon Sep 17 00:00:00 2001 From: Sidney Alcantara Date: Mon, 12 Jul 2021 21:03:51 +1000 Subject: [PATCH 5/7] add UpdateChecker --- www/package.json | 2 +- .../components/Navigation/UpdateChecker.tsx | 153 ++++++++++++++++++ www/src/components/Navigation/UserMenu.tsx | 22 +-- www/src/components/Navigation/index.tsx | 2 +- www/src/constants/wikiLinks.ts | 9 ++ 5 files changed, 167 insertions(+), 21 deletions(-) create mode 100644 www/src/components/Navigation/UpdateChecker.tsx create mode 100644 www/src/constants/wikiLinks.ts diff --git a/www/package.json b/www/package.json index 9fe5c05f0..027b8976a 100644 --- a/www/package.json +++ b/www/package.json @@ -4,7 +4,7 @@ "homepage": "https://firetable.io/", "repository": { "type": "git", - "url": "https://github.com/AntlerVC/firetable.git" + "url": "https://github.com/FiretableProject/firetable.git" }, "private": true, "dependencies": { diff --git a/www/src/components/Navigation/UpdateChecker.tsx b/www/src/components/Navigation/UpdateChecker.tsx new file mode 100644 index 000000000..3c8d6676a --- /dev/null +++ b/www/src/components/Navigation/UpdateChecker.tsx @@ -0,0 +1,153 @@ +import { useState, useEffect } from "react"; +import createPersistedState from "use-persisted-state"; +import { differenceInDays } from "date-fns"; + +import { + makeStyles, + createStyles, + MenuItem, + ListItemText, + ListItemSecondaryAction, + Link, +} from "@material-ui/core"; +import OpenInNewIcon from "@material-ui/icons/OpenInNew"; + +import meta from "../../../package.json"; +import WIKI_LINKS from "constants/wikiLinks"; + +const useLastCheckedUpdateState = createPersistedState( + "_FT_LAST_CHECKED_UPDATE" +); +const useLatestUpdateState = createPersistedState("_FT_LATEST_UPDATE"); + +const useStyles = makeStyles((theme) => + createStyles({ + secondaryAction: { pointerEvents: "none" }, + secondaryIcon: { + display: "block", + color: theme.palette.action.active, + }, + + version: { + display: "block", + padding: theme.spacing(1, 2), + userSelect: "none", + color: theme.palette.text.disabled, + }, + }) +); + +export default function UpdateChecker() { + const classes = useStyles(); + + const [ + lastCheckedUpdate, + setLastCheckedUpdate, + ] = useLastCheckedUpdateState(); + const [latestUpdate, setLatestUpdate] = useLatestUpdateState>(null); + + const [checkState, setCheckState] = useState( + null + ); + + const checkForUpdate = async () => { + setCheckState("LOADING"); + + // https://docs.github.com/en/rest/reference/repos#get-the-latest-release + const endpoint = meta.repository.url + .replace("github.com", "api.github.com/repos") + .replace(/.git$/, "/releases/latest"); + try { + const res = await fetch(endpoint, { + headers: { + Accept: "application/vnd.github.v3+json", + }, + }); + const json = await res.json(); + + if (json.tag_name > "v" + meta.version) { + setLatestUpdate(json); + setCheckState(null); + } else { + setCheckState("NO_UPDATE"); + } + + setLastCheckedUpdate(new Date().toISOString()); + } catch (e) { + console.error(e); + setLatestUpdate(null); + setCheckState("NO_UPDATE"); + } + }; + + // Check for new updates on page load, if last check was more than 7 days ago + useEffect(() => { + if (!lastCheckedUpdate) checkForUpdate(); + else if (differenceInDays(new Date(), new Date(lastCheckedUpdate)) > 7) + checkForUpdate(); + }, [lastCheckedUpdate]); + + // Verify latest update is not installed yet + useEffect(() => { + if (latestUpdate?.tag_name <= "v" + meta.version) setLatestUpdate(null); + }, [latestUpdate, setLatestUpdate]); + + return ( + <> + {checkState === "LOADING" ? ( + Checking for updates… + ) : checkState === "NO_UPDATE" ? ( + No updates available + ) : latestUpdate === null ? ( + Check for updates + ) : ( + <> + + + + + + + + + + + + + + + )} + + + {meta.name} v{meta.version} + + + ); +} diff --git a/www/src/components/Navigation/UserMenu.tsx b/www/src/components/Navigation/UserMenu.tsx index c4b2ccc5b..fe9515583 100644 --- a/www/src/components/Navigation/UserMenu.tsx +++ b/www/src/components/Navigation/UserMenu.tsx @@ -8,7 +8,6 @@ import { IconButtonProps, Avatar, Menu, - Link as MuiLink, MenuItem, ListItemAvatar, ListItemText, @@ -20,10 +19,11 @@ import AccountCircleIcon from "@material-ui/icons/AccountCircle"; import ArrowRightIcon from "@material-ui/icons/ArrowRight"; import CheckIcon from "@material-ui/icons/Check"; +import UpdateChecker from "./UpdateChecker"; import { useAppContext } from "contexts/AppContext"; import routes from "constants/routes"; -import meta from "../../../package.json"; import { projectId } from "../../firebase"; + const useStyles = makeStyles((theme) => createStyles({ spacer: { @@ -55,13 +55,6 @@ const useStyles = makeStyles((theme) => theme.palette.background.paper, marginTop: theme.spacing(-1), }, - - version: { - display: "block", - padding: theme.spacing(1, 2), - userSelect: "none", - color: theme.palette.text.disabled, - }, }) ); @@ -194,16 +187,7 @@ export default function UserMenu(props: IconButtonProps) { - - {meta.name} v{meta.version} - + ); diff --git a/www/src/components/Navigation/index.tsx b/www/src/components/Navigation/index.tsx index 09129a15f..faaf6929a 100644 --- a/www/src/components/Navigation/index.tsx +++ b/www/src/components/Navigation/index.tsx @@ -93,7 +93,7 @@ export default function Navigation({ - {/* */} + {/* */} diff --git a/www/src/constants/wikiLinks.ts b/www/src/constants/wikiLinks.ts new file mode 100644 index 000000000..2e97c48e9 --- /dev/null +++ b/www/src/constants/wikiLinks.ts @@ -0,0 +1,9 @@ +import meta from "../../package.json"; + +const WIKI_LINK_ROOT = meta.repository.url.replace(".git", "/wiki/"); + +export const WIKI_LINKS = { + updatingFiretable: WIKI_LINK_ROOT + "Updating-Firetable", +}; + +export default WIKI_LINKS; From ea336a63662943ea8f757814d741a32b2b53f262 Mon Sep 17 00:00:00 2001 From: Sidney Alcantara Date: Mon, 12 Jul 2021 21:14:17 +1000 Subject: [PATCH 6/7] migrate all links to WIKI_LINKS --- .../FieldSettings/DefaultValueInput.tsx | 3 ++- .../Table/ColumnMenu/FieldSettings/index.tsx | 4 ++-- .../components/Table/TableHeader/Sparks.tsx | 4 ++-- .../components/Table/TableHeader/TableLogs.tsx | 9 ++++----- www/src/components/TableSettings/form.tsx | 3 ++- .../components/fields/Derivative/Settings.tsx | 4 +++- www/src/constants/wikiLinks.ts | 18 ++++++++++++++---- www/src/pages/Auth/SetupGuide.tsx | 3 ++- www/src/pages/Home.tsx | 7 ++----- 9 files changed, 33 insertions(+), 22 deletions(-) diff --git a/www/src/components/Table/ColumnMenu/FieldSettings/DefaultValueInput.tsx b/www/src/components/Table/ColumnMenu/FieldSettings/DefaultValueInput.tsx index c29a4892e..99b7f8700 100644 --- a/www/src/components/Table/ColumnMenu/FieldSettings/DefaultValueInput.tsx +++ b/www/src/components/Table/ColumnMenu/FieldSettings/DefaultValueInput.tsx @@ -17,6 +17,7 @@ import CodeEditorHelper from "components/CodeEditorHelper"; import CodeEditor from "components/Table/editors/CodeEditor"; import FormAutosave from "./FormAutosave"; import { FieldType } from "constants/fields"; +import WIKI_LINKS from "constants/wikiLinks"; const useStyles = makeStyles((theme) => createStyles({ @@ -130,7 +131,7 @@ export default function DefaultValueInput({ {config.defaultValue?.type === "dynamic" && ( <> - +
- Cloud Run trigger URL not configured. Configuration guide:{" "} + Cloud Run trigger URL not configured. - https://github.com/FiretableProject/firetable/wiki/Setting-up-cloud-Run-FT-Builder + Configuration guide } diff --git a/www/src/components/TableSettings/form.tsx b/www/src/components/TableSettings/form.tsx index b22e6330b..670a2e7cc 100644 --- a/www/src/components/TableSettings/form.tsx +++ b/www/src/components/TableSettings/form.tsx @@ -5,6 +5,7 @@ import { Link, Typography } from "@material-ui/core"; import OpenInNewIcon from "@material-ui/icons/OpenInNew"; import { MONO_FONT } from "Themes"; import { projectId } from "../../firebase"; +import WIKI_LINKS from "constants/wikiLinks"; export const tableSettings = ( mode: TableSettingsDialogModes | null, @@ -117,7 +118,7 @@ export const tableSettings = ( Choose which roles have access to this table. Remember to set the appropriate Firestore Security Rules for this collection. import( @@ -45,7 +47,7 @@ const Settings = ({ config, handleChange }) => { }} /> derivative script - + }> WIKI_LINK_ROOT + path +); export default WIKI_LINKS; diff --git a/www/src/pages/Auth/SetupGuide.tsx b/www/src/pages/Auth/SetupGuide.tsx index b033d5d44..79a2af681 100644 --- a/www/src/pages/Auth/SetupGuide.tsx +++ b/www/src/pages/Auth/SetupGuide.tsx @@ -2,6 +2,7 @@ import { Typography, Button } from "@material-ui/core"; import OpenInNewIcon from "@material-ui/icons/OpenInNew"; import AuthLayout from "components/Auth/AuthLayout"; +import WIKI_LINKS from "constants/wikiLinks"; export default function AuthSetupGuide() { return ( @@ -20,7 +21,7 @@ export default function AuthSetupGuide() { variant="contained" endIcon={} component="a" - href="https://github.com/FiretableProject/firetable/wiki/Set-Up-Firebase-Authentication" + href={WIKI_LINKS.setUpAuth} target="_blank" rel="noopener" > diff --git a/www/src/pages/Home.tsx b/www/src/pages/Home.tsx index e4f8d5d0a..38d8e551a 100644 --- a/www/src/pages/Home.tsx +++ b/www/src/pages/Home.tsx @@ -33,6 +33,7 @@ import TableSettingsDialog, { import ProjectSettings from "components/ProjectSettings"; import EmptyState from "components/EmptyState"; +import WIKI_LINKS from "constants/wikiLinks"; const useStyles = makeStyles((theme) => createStyles({ "@global": { @@ -155,11 +156,7 @@ export default function HomePage() { If you are the project owner please follow the instructions{" "} - + here {" "} to setup the project rules. From f6d5dfe601230526d30fdc07d50dc604d8b0b286 Mon Sep 17 00:00:00 2001 From: Sidney Alcantara Date: Mon, 12 Jul 2021 21:27:21 +1000 Subject: [PATCH 7/7] add badge to UserMenu when update is available --- www/package.json | 2 +- .../components/Navigation/UpdateChecker.tsx | 2 +- www/src/components/Navigation/UserMenu.tsx | 13 +++++-- www/yarn.lock | 34 +++++++++---------- 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/www/package.json b/www/package.json index 027b8976a..6c1235eac 100644 --- a/www/package.json +++ b/www/package.json @@ -11,7 +11,7 @@ "@antlerengineering/form-builder": "^2.6.0", "@antlerengineering/multiselect": "^0.9.2", "@date-io/date-fns": "1.x", - "@material-ui/core": "^4.11.3", + "@material-ui/core": "^4.12.1", "@material-ui/icons": "^4.11.2", "@material-ui/lab": "^4.0.0-alpha.56", "@material-ui/pickers": "^3.2.10", diff --git a/www/src/components/Navigation/UpdateChecker.tsx b/www/src/components/Navigation/UpdateChecker.tsx index 3c8d6676a..dabfce8f1 100644 --- a/www/src/components/Navigation/UpdateChecker.tsx +++ b/www/src/components/Navigation/UpdateChecker.tsx @@ -18,7 +18,7 @@ import WIKI_LINKS from "constants/wikiLinks"; const useLastCheckedUpdateState = createPersistedState( "_FT_LAST_CHECKED_UPDATE" ); -const useLatestUpdateState = createPersistedState("_FT_LATEST_UPDATE"); +export const useLatestUpdateState = createPersistedState("_FT_LATEST_UPDATE"); const useStyles = makeStyles((theme) => createStyles({ diff --git a/www/src/components/Navigation/UserMenu.tsx b/www/src/components/Navigation/UserMenu.tsx index fe9515583..4bfd6c3c6 100644 --- a/www/src/components/Navigation/UserMenu.tsx +++ b/www/src/components/Navigation/UserMenu.tsx @@ -14,15 +14,17 @@ import { ListItemSecondaryAction, ListItemIcon, Divider, + Badge, } from "@material-ui/core"; import AccountCircleIcon from "@material-ui/icons/AccountCircle"; import ArrowRightIcon from "@material-ui/icons/ArrowRight"; import CheckIcon from "@material-ui/icons/Check"; -import UpdateChecker from "./UpdateChecker"; +import UpdateChecker, { useLatestUpdateState } from "./UpdateChecker"; import { useAppContext } from "contexts/AppContext"; import routes from "constants/routes"; import { projectId } from "../../firebase"; +import meta from "../../../package.json"; const useStyles = makeStyles((theme) => createStyles({ @@ -64,6 +66,7 @@ export default function UserMenu(props: IconButtonProps) { const anchorEl = useRef(null); const [open, setOpen] = useState(false); const [themeSubMenu, setThemeSubMenu] = useState(null); + const [latestUpdate] = useLatestUpdateState>(); const { currentUser, @@ -118,7 +121,13 @@ export default function UserMenu(props: IconButtonProps) { onClick={() => setOpen(true)} className={classes.iconButton} > - {avatar} + {latestUpdate?.tag_name > "v" + meta.version ? ( + + {avatar} + + ) : ( + avatar + )}