From 4292e43020a5e577e346457df0218359780fc3fa Mon Sep 17 00:00:00 2001 From: Fred Israel Date: Thu, 23 May 2024 16:43:23 -0300 Subject: [PATCH 01/27] fix warnings in console due to invalid tags under

tag. --- next/components/organisms/DatabaseCard.js | 1 + next/pages/index.js | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/next/components/organisms/DatabaseCard.js b/next/components/organisms/DatabaseCard.js index 3660d296..ae95ee68 100644 --- a/next/components/organisms/DatabaseCard.js +++ b/next/components/organisms/DatabaseCard.js @@ -163,6 +163,7 @@ export default function DatabaseCard({ - $ pip install basedosdados + $ pip install basedosdados @@ -415,6 +415,7 @@ export function StepText ({index, text}) { gridGap="8px" > @@ -530,7 +531,7 @@ function Support() { letterSpacing="0.2px" > Doe R$ 1 real por dia -

para fazer databasers felizes.

+ para fazer databasers felizes. Date: Mon, 1 Jul 2024 12:02:53 -0300 Subject: [PATCH 02/27] feat: add new anual plans --- next/components/organisms/PaymentSystem.js | 4 --- .../api/stripe/{getPrices.js => getPlans.js} | 19 +++++++--- next/pages/api/stripe/index.js | 5 --- next/pages/precos.js | 35 +++++++++++++++++++ 4 files changed, 50 insertions(+), 13 deletions(-) rename next/pages/api/stripe/{getPrices.js => getPlans.js} (50%) delete mode 100644 next/pages/api/stripe/index.js diff --git a/next/components/organisms/PaymentSystem.js b/next/components/organisms/PaymentSystem.js index 870618d2..2d8841ae 100644 --- a/next/components/organisms/PaymentSystem.js +++ b/next/components/organisms/PaymentSystem.js @@ -15,10 +15,6 @@ import { import Button from "../atoms/RoundedButton"; import styles from "../../styles/paymentSystem.module.css"; -import { - getPrices, -} from "../../pages/api/stripe"; - const stripePromise = loadStripe(process.env.NEXT_PUBLIC_KEY_STRIPE) const PaymentForm = ({ onSucess, onErro }) => { diff --git a/next/pages/api/stripe/getPrices.js b/next/pages/api/stripe/getPlans.js similarity index 50% rename from next/pages/api/stripe/getPrices.js rename to next/pages/api/stripe/getPlans.js index 7122265c..735e2d8d 100644 --- a/next/pages/api/stripe/getPrices.js +++ b/next/pages/api/stripe/getPlans.js @@ -2,7 +2,7 @@ import axios from "axios"; const API_URL= `${process.env.NEXT_PUBLIC_API_URL}/api/v1/graphql` -export default async function getPrices() { +async function getPlans() { try { const res = await axios({ url: API_URL, @@ -10,14 +10,15 @@ export default async function getPrices() { data: { query: ` query { - allStripePrice { + allStripePrice (active: true) { edges { node { _id amount productName productSlug - productSlots + interval + isActive } } } @@ -25,9 +26,19 @@ export default async function getPrices() { ` } }) - const data = res?.data?.data?.allStripePrice?.edges + const data = res.data return data } catch (error) { console.error(error) + return "err" } } + +export default async function handler(req, res) { + const result = await getPlans() + + if(result.errors) return res.status(500).json({error: result.errors, success: false}) + if(result === "err") return res.status(500).json({error: "err", success: false}) + + res.status(200).json({data: result?.data?.allStripePrice?.edges, success: true}) +} diff --git a/next/pages/api/stripe/index.js b/next/pages/api/stripe/index.js deleted file mode 100644 index 2b92c5b1..00000000 --- a/next/pages/api/stripe/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import getPrices from "./getPrices"; - -export { - getPrices, -} diff --git a/next/pages/precos.js b/next/pages/precos.js index 9169c436..84691565 100644 --- a/next/pages/precos.js +++ b/next/pages/precos.js @@ -279,6 +279,41 @@ export default function Price({ username ,isBDPro, isBDEmp }) { const [toggleAnual, setToggleAnual] = useState(false) const [priceBDPro, setPriceBDPro] = useState("47") const [priceBDEmp, setPriceBDEmp] = useState("350") + const [plans, setPlans] = useState(null) + + useEffect(() => { + async function fecthPlans() { + try { + const result = await fetch(`/api/stripe/getPlans`, { method: "GET" }) + .then(res => res.json()) + + if(result.success === true) { + function filterData(productName, interval, isActive) { + let array = result.data + + return array.filter(item => + (productName ? item.node.productName === productName : true) && + (interval ? item.node.interval === interval : true) && + (isActive !== undefined ? item.node.isActive === isActive : true) + ) + } + + const filteredPlans = { + bd_pro_month : filterData("BD Pro", "month", true)[0].node, + bd_pro_year : filterData("BD Pro", "year", true)[0].node, + bd_empresas_month : filterData("BD Empresas", "month", true)[0].node, + bd_empresas_year : filterData("BD Empresas", "year", true)[0].node + } + + setPlans(filteredPlans) + } + } catch (error) { + console.error(error) + } + } + + fecthPlans() + }, []) useEffect(() => { if(toggleAnual === true) { From 86d9cc4d3edc02a8a548a00ac185a4ec8518364b Mon Sep 17 00:00:00 2001 From: aldemirLucas Date: Thu, 25 Jul 2024 16:58:17 -0300 Subject: [PATCH 03/27] feat: add api get for download security url --- .../molecules/DataInformationQuery.js | 76 +++++++++++++------ next/pages/api/tables/downloadTable.js | 52 +++++++++++++ next/pages/api/user/validateToken.js | 24 +++--- next/utils.js | 2 +- 4 files changed, 116 insertions(+), 38 deletions(-) create mode 100644 next/pages/api/tables/downloadTable.js diff --git a/next/components/molecules/DataInformationQuery.js b/next/components/molecules/DataInformationQuery.js index 8d04397e..e4ef1274 100644 --- a/next/components/molecules/DataInformationQuery.js +++ b/next/components/molecules/DataInformationQuery.js @@ -171,7 +171,8 @@ export function CodeHighlight({ language, children }) { export default function DataInformationQuery({ resource }) { const [tabAccessIndex, setTabAccessIndex] = useState(0) const [tabIndex, setTabIndex] = useState(0) - const [downloadNotAllowed, setDownloadNotAllowed] = useState(false) + const [downloadPermitted, setDownloadPermitted] = useState(false) + const [downloadWarning, setDownloadWarning] = useState("") const [checkedColumns, setCheckedColumns] = useState([]) const [numberColumns, setNumberColumns] = useState(0) const [columnsTranslationPro, setColumnsTranslationPro] = useState([]) @@ -185,7 +186,6 @@ export default function DataInformationQuery({ resource }) { const [gcpProjectID, setGcpProjectID] = useState("") const [gcpDatasetID, setGcpDatasetID] = useState("") const [gcpTableId, setGcpTableId] = useState("") - const [downloadUrl, setDownloadUrl] = useState("") const isUserPro = () => { let user @@ -200,21 +200,31 @@ export default function DataInformationQuery({ resource }) { }, [resource.dataset]) useEffect(() => { - if (resource?.numberRows === 0) setDownloadNotAllowed(false) - if (resource?.numberRows) resource?.numberRows > 200000 ? setDownloadNotAllowed(false) : setDownloadNotAllowed(true) + if (resource?.uncompressedFileSize) { + const limit100MB = 100 * 1024 * 1024; + const limit1GB = 1 * 1024 * 1024 * 1024; + + if (resource?.uncompressedFileSize < limit100MB) { + setDownloadPermitted(true) + setDownloadWarning("free") + } else if (resource?.uncompressedFileSize < limit1GB) { + isUserPro() === true + ? setDownloadPermitted(true) + : setDownloadPermitted(false) + + setDownloadWarning("100mbBetween1gb") + } else { + setDownloadWarning("biggest1gb") + setDownloadPermitted(false) + } + } if (resource?.cloudTables?.[0]) { setGcpProjectID(resource.cloudTables[0]?.gcpProjectId || "") setGcpDatasetID(resource.cloudTables[0]?.gcpDatasetId || "") setGcpTableId(resource.cloudTables[0]?.gcpTableId || "") } - - if (gcpDatasetID) { - if (gcpTableId) { - setDownloadUrl(`https://storage.googleapis.com/basedosdados-public/one-click-download/${gcpDatasetID}/${gcpTableId}/${gcpTableId}.csv.gz`) - } - } - }, [resource.numberRows, resource.cloudTables]) + }, [resource.uncompressedFileSize, resource.cloudTables]) useEffect(() => { if(resource._id === undefined) return @@ -524,8 +534,7 @@ export default function DataInformationQuery({ resource }) { marginTop="16px" padding={0} > - {downloadNotAllowed ? - isUserPro() ? "" : + {isUserPro() === false && downloadWarning === "free" && Estes dados estão disponíveis porque diversas pessoas colaboram para a sua manutenção. Antes de baixar os dados, apoie você também com uma doação financeira ou @@ -540,33 +549,50 @@ export default function DataInformationQuery({ resource }) { saiba como contribuir com seu tempo. - : + } + {isUserPro() === false && downloadWarning === "100mbBetween1gb" && + + O download de tabelas com tamanho entre 100 MB e 1 GB está disponível apenas para + assinantes dos nossos planos pagos + . No entanto, você pode acessar a tabela gratuitamente utilizando SQL, Python, R ou Stata. Considere atualizar para um plano pago para fazer o download. + + } + {downloadWarning === "biggest1gb" && } { triggerGAEvent("download_da_tabela",` - { + href={`/api/tables/downloadTable?p=${btoa(gcpDatasetID)}&q=${btoa(gcpTableId)}&d=${btoa(downloadPermitted)}&s=${btoa(downloadWarning)}`} + target="_blank" + onClick={() => { + triggerGAEvent("download_da_tabela",`{ gcp: ${gcpProjectID+"."+gcpDatasetID+"."+gcpTableId}, tamanho: ${formatBytes(resource.uncompressedFileSize) || ""}, dataset: ${resource?.dataset?._id}, table: ${resource?._id}, - }` - ) }} - target="_blank" + }`) + }} display="flex" alignItems="center" height="40px" width="fit-content" borderRadius="8px" - backgroundColor={downloadNotAllowed ? "#2B8C4D" : "#ACAEB1"} + backgroundColor={downloadPermitted ? "#2B8C4D" : "#ACAEB1"} padding="8px 16px" - cursor={downloadNotAllowed ? "pointer" : "default"} + cursor={downloadPermitted ? "pointer" : "default"} color="#FFF" fill="#FFF" fontFamily="Roboto" @@ -574,7 +600,7 @@ export default function DataInformationQuery({ resource }) { fontSize="14px" gap="8px" lineHeight="20px" - pointerEvents={downloadNotAllowed ? "default" : "none"} + pointerEvents={downloadPermitted ? "default" : "none"} _hover={{ backgroundColor: "#22703E" }} @@ -583,7 +609,7 @@ export default function DataInformationQuery({ resource }) { width="24px" height="24px" /> - Download da tabela {downloadNotAllowed && `(${formatBytes(resource.uncompressedFileSize)})`} + Download da tabela {downloadPermitted && `(${formatBytes(resource.uncompressedFileSize)})`} diff --git a/next/pages/api/tables/downloadTable.js b/next/pages/api/tables/downloadTable.js new file mode 100644 index 00000000..0c3c1b96 --- /dev/null +++ b/next/pages/api/tables/downloadTable.js @@ -0,0 +1,52 @@ +import axios from "axios"; + +const API_URL= `${process.env.NEXT_PUBLIC_API_URL}/api/v1/graphql` + +async function validateToken(token) { + try { + const res = await axios({ + url: API_URL, + method: "POST", + data: { query: ` mutation { verifyToken ( token: "${token}" ) { payload } }` + } + }) + const data = res.data?.data?.verifyToken?.payload + return data + } catch (error) { + console.error(error) + return "err" + } +} + +async function downloadTable(url, datasetID, tableId, token, res) { +// let payloadToken +// if(token !== null) payloadToken = await validateToken(token) + + try { + const fileUrl = url === "free" + ?`${process.env.URL_DOWNLOAD_TABLE}/${datasetID}/${tableId}/${tableId}.csv.gz` + :`${process.env.URL_DOWNLOAD_PRIVATE_TABLE}/${datasetID}/${tableId}/${tableId}.csv.gz` + + const response = await axios({ + url: fileUrl, + method: 'GET', + responseType: 'stream' + }) + + res.setHeader('Content-Disposition', `attachment; filename=${datasetID}_${tableId}.csv.gz`) + res.setHeader('Content-Type', 'application/gzip') + + response.data.pipe(res) + } catch (error) { + console.error(error) + res.status(500).json({ message: 'Error downloading the file' }) + } +} + +export default async function handler(req, res) { + const token = req.cookies.token || null + + if(atob(req.query.d) === "false") return res.status(500).json({error: "Você não tem permissão para fazer esse download"}) + + return downloadTable(atob(req.query.s),atob(req.query.p), atob(req.query.q), token, res) +} \ No newline at end of file diff --git a/next/pages/api/user/validateToken.js b/next/pages/api/user/validateToken.js index c62ce024..d831f890 100644 --- a/next/pages/api/user/validateToken.js +++ b/next/pages/api/user/validateToken.js @@ -3,19 +3,19 @@ import axios from "axios"; const API_URL= `${process.env.NEXT_PUBLIC_API_URL}/api/v1/graphql` async function validateToken(token) { - const res = await axios({ - url: API_URL, - method: "POST", - data: { - query: ` - mutation { - verifyToken ( token: "${token}" ) { - payload, - } - }` - } - }) try { + const res = await axios({ + url: API_URL, + method: "POST", + data: { + query: ` + mutation { + verifyToken ( token: "${token}" ) { + payload, + } + }` + } + }) const data = res.data return data } catch (error) { diff --git a/next/utils.js b/next/utils.js index ead5990c..41581fa9 100644 --- a/next/utils.js +++ b/next/utils.js @@ -218,7 +218,7 @@ export function cleanString(string) { export function formatBytes(bytes) { if (bytes < 1024) { - return `${bytes}B` + return `${bytes} B` } else if (bytes < 1024 * 1024) { return `${(bytes / 1024).toFixed(2)} KB` } else if (bytes < 1024 * 1024 * 1024) { From f179c186699a94e64b944cdd20f5873543c73eb0 Mon Sep 17 00:00:00 2001 From: aldemirLucas Date: Wed, 31 Jul 2024 18:22:02 -0300 Subject: [PATCH 04/27] feat: wip feature of download section --- next/components/molecules/ColumnsTable.js | 167 ++++++++++++------ .../molecules/DataInformationQuery.js | 41 ++--- next/pages/api/tables/downloadTable.js | 10 +- next/pages/api/tables/getColumnsBdmTable.js | 1 + next/pages/dataset/[dataset].js | 1 + 5 files changed, 141 insertions(+), 79 deletions(-) diff --git a/next/components/molecules/ColumnsTable.js b/next/components/molecules/ColumnsTable.js index 186cf785..78d8f21b 100644 --- a/next/components/molecules/ColumnsTable.js +++ b/next/components/molecules/ColumnsTable.js @@ -15,8 +15,10 @@ import { import { useState, useEffect } from 'react'; import FuzzySearch from 'fuzzy-search'; import Latex from 'react-latex-next'; +import cookies from 'js-cookie'; import { ControlledInputSimple } from '../atoms/ControlledInput'; import Checkbox from '../atoms/Checkbox'; +import { triggerGAEvent, formatBytes } from '../../utils'; import { getColumnsBdmTable @@ -102,6 +104,14 @@ export default function ColumnsTable({ const isChecked = (columnSlug) => checkedColumns.includes(columnSlug) + const isUserPro = () => { + let user + if(cookies.get("userBD")) user = JSON.parse(cookies.get("userBD")) + + if(user?.proSubscriptionStatus === "active") return true + return false + } + const handleCheckboxChange = (columnSlug) => { if (isChecked(columnSlug)) { onChangeCheckedColumns(checkedColumns.filter(slug => slug !== columnSlug)) @@ -213,67 +223,118 @@ export default function ColumnsTable({ return 0 } - function TranslationTable({ value }) { - if(value === null) return ( - - Não precisa de tradução - - ) + function TranslationTable({ value, dictionary }) { + let downloadPermitted = false + let downloadWarning = "" - if(value?.table?.isClosed) return ( - - - Acessar tabela que faz a tradução desta coluna - - - {value?.table?.dataset?.name} - {value?.table?.name} - - ) + if (value?.table?.uncompressedFileSize) { + const limit100MB = 100 * 1024 * 1024; + const limit1GB = 1 * 1024 * 1024 * 1024; + + if (value?.table?.uncompressedFileSize < limit100MB) { + downloadPermitted = true + downloadWarning = "free" + } else if (value?.table?.uncompressedFileSize < limit1GB) { + downloadPermitted = isUserPro() + downloadWarning = "100mbBetween1gb" + } else { + downloadWarning = "biggest1gb" + downloadPermitted = false + } + } const cloudValues = value?.table?.cloudTables?.edges?.[0]?.node + const gcpProjectID = cloudValues?.gcpProjectId || "" const gcpDatasetID = cloudValues?.gcpDatasetId || "" const gcpTableId = cloudValues?.gcpTableId || "" - const downloadUrl = `https://storage.googleapis.com/basedosdados-public/one-click-download/${gcpDatasetID}/${gcpTableId}/${gcpTableId}.csv.gz` const datasetName = value?.table?.dataset?.name || "" const tableName = value?.table?.name || "" - + + if(gcpDatasetID === "br_bd_diretorios_data_tempo") return ( + + Não precisa de tradução + + ) + return ( - - Baixar tabela que faz a tradução desta coluna - - - {datasetName} - {tableName} + {value === null && + + Não precisa de tradução + + } + + {value !== null && + + { + triggerGAEvent("download_da_tabela",`{ + gcp: ${gcpProjectID+"."+gcpDatasetID+"."+gcpTableId}, + tamanho: ${formatBytes(value?.table?.uncompressedFileSize) || ""}, + dataset: ${value?.table?.dataset?._id}, + table: ${value?.table?._id}, + columnDownload: true + }`) + }} + flexDirection="row" + alignItems="center" + gap="4px" + color="#0068C5" + fill="#0068C5" + _hover={{ + color:"#0057A4", + fill:"#0057A4" + }} + > + {value?.table?.isClosed + ? + <> + Acessar tabela que faz a tradução desta coluna + + + : + <> + Baixar tabela que faz a tradução desta coluna + + + } + + {datasetName} - {tableName} + + } + + {/* {dictionary === true && + + + Baixar tabela que faz a tradução desta coluna + + + {datasetName} - {tableName} + + } */} ) } @@ -519,9 +580,11 @@ export default function ColumnsTable({ {template === "download" ? - + : - elm?.node?.coveredByDictionary === true ? "Sim" : elm?.node?.directoryPrimaryKey?._id ? "Sim" : elm?.node?.coveredByDictionary === false ? "Não" diff --git a/next/components/molecules/DataInformationQuery.js b/next/components/molecules/DataInformationQuery.js index e4ef1274..317dfe82 100644 --- a/next/components/molecules/DataInformationQuery.js +++ b/next/components/molecules/DataInformationQuery.js @@ -208,17 +208,13 @@ export default function DataInformationQuery({ resource }) { setDownloadPermitted(true) setDownloadWarning("free") } else if (resource?.uncompressedFileSize < limit1GB) { - isUserPro() === true - ? setDownloadPermitted(true) - : setDownloadPermitted(false) - + setDownloadPermitted(isUserPro()) setDownloadWarning("100mbBetween1gb") } else { setDownloadWarning("biggest1gb") - setDownloadPermitted(false) } } - + if (resource?.cloudTables?.[0]) { setGcpProjectID(resource.cloudTables[0]?.gcpProjectId || "") setGcpDatasetID(resource.cloudTables[0]?.gcpDatasetId || "") @@ -816,13 +812,13 @@ export default function DataInformationQuery({ resource }) { > {`import basedosdados as bd - billing_id = +billing_id = - query = """ - ${sqlCode} - """ +query = """ + ${sqlCode} +""" - bd.read_sql(query = query, billing_project_id = billing_id)`} +bd.read_sql(query = query, billing_project_id = billing_id)`} @@ -885,17 +881,18 @@ export default function DataInformationQuery({ resource }) { width="100%" isLoaded={!isLoadingCode} > - {` - # Defina o seu projeto no Google Cloud - set_billing_id("") - - # Para carregar o dado direto no R - query <- " - ${sqlCode} - " - - read_sql(query, billing_project_id = get_billing_id()) - `} + {`install.packages("basedosdados") +library("basedosdados") +# Defina o seu projeto no Google Cloud +set_billing_id("") + +# Para carregar o dado direto no R +query <- " +${sqlCode} +" + +read_sql(query, billing_project_id = get_billing_id()) +`} diff --git a/next/pages/api/tables/downloadTable.js b/next/pages/api/tables/downloadTable.js index 0c3c1b96..1b5fa146 100644 --- a/next/pages/api/tables/downloadTable.js +++ b/next/pages/api/tables/downloadTable.js @@ -19,13 +19,13 @@ async function validateToken(token) { } async function downloadTable(url, datasetID, tableId, token, res) { -// let payloadToken -// if(token !== null) payloadToken = await validateToken(token) + let payloadToken + if(token !== null) payloadToken = await validateToken(token) try { const fileUrl = url === "free" - ?`${process.env.URL_DOWNLOAD_TABLE}/${datasetID}/${tableId}/${tableId}.csv.gz` - :`${process.env.URL_DOWNLOAD_PRIVATE_TABLE}/${datasetID}/${tableId}/${tableId}.csv.gz` + ? `${process.env.URL_DOWNLOAD_TABLE}/${datasetID}/${tableId}/${tableId}.csv.gz` + : payloadToken?.pro_subscription_status === "active" ? `${process.env.URL_DOWNLOAD_PRIVATE_TABLE}/${datasetID}/${tableId}/${tableId}.csv.gz` : "" const response = await axios({ url: fileUrl, @@ -48,5 +48,5 @@ export default async function handler(req, res) { if(atob(req.query.d) === "false") return res.status(500).json({error: "Você não tem permissão para fazer esse download"}) - return downloadTable(atob(req.query.s),atob(req.query.p), atob(req.query.q), token, res) + return downloadTable(atob(req.query.s), atob(req.query.p), atob(req.query.q), token, res) } \ No newline at end of file diff --git a/next/pages/api/tables/getColumnsBdmTable.js b/next/pages/api/tables/getColumnsBdmTable.js index 584e9149..0190be73 100644 --- a/next/pages/api/tables/getColumnsBdmTable.js +++ b/next/pages/api/tables/getColumnsBdmTable.js @@ -28,6 +28,7 @@ export default async function getColumnsBdmTable(id) { _id name isClosed + uncompressedFileSize cloudTables{ edges{ node{ diff --git a/next/pages/dataset/[dataset].js b/next/pages/dataset/[dataset].js index 9221b7d3..2e6255f8 100644 --- a/next/pages/dataset/[dataset].js +++ b/next/pages/dataset/[dataset].js @@ -110,6 +110,7 @@ export default function DatasetPage ({ dataset }) { > Date: Wed, 31 Jul 2024 19:48:03 -0300 Subject: [PATCH 05/27] feat: wip page for prices and cards price in userPage --- next/pages/precos.js | 191 +++++++++++++++++++--------------- next/pages/user/[username].js | 16 ++- 2 files changed, 113 insertions(+), 94 deletions(-) diff --git a/next/pages/precos.js b/next/pages/precos.js index e4fdd69a..e49e74b4 100644 --- a/next/pages/precos.js +++ b/next/pages/precos.js @@ -2,16 +2,11 @@ import { Box, Stack, Text, - Link, Tooltip, Badge, } from "@chakra-ui/react"; import { useEffect, useState } from "react"; import Head from "next/head"; -import Display from "../components/atoms/Display"; -import BigTitle from "../components/atoms/BigTitle" -import BodyText from "../components/atoms/BodyText"; -import RoundedButton from "../components/atoms/RoundedButton"; import Toggle from "../components/atoms/Toggle"; import { MainPageTemplate } from "../components/templates/main"; import { isMobileMod } from "../hooks/useCheckMobile.hook"; @@ -77,22 +72,29 @@ export const CardPrice = ({ alignItems="center" marginBottom="8px" > - {title} - {badge && - {badge}} + + {title} + - {subTitle} + + {subTitle} + R$ {price} /mês {anualPlan && {(price*12).toLocaleString('pt-BR', { style: 'currency', currency: 'BRL', minimumFractionDigits: 0 })} cobrado uma vez no ano } @@ -148,14 +151,14 @@ export const CardPrice = ({ flexDirection="column" justifyContent="space-between" > - + {textResource} @@ -177,29 +180,34 @@ export const CardPrice = ({ height="24px" fill="#2B8C4D" /> - {elm.name} - + {elm.tooltip && - + } @@ -213,7 +221,7 @@ export const CardPrice = ({ gap="16px" > {button.isCurrentPlan ? - {button.text} - + : - { if(button.onClick) return button.onClick() return window.open(button.href, "_self") }} - border={button.color && `1px solid ${button.colorText}`} - {...button.styles} + display="flex" + alignItems="center" + justifyContent="center" + width="100%" + borderRadius="8px" + backgroundColor="#0D99FC" + padding="12px 16px" + cursor="pointer" + color="#FFF" + fontFamily="Roboto" + fontWeight="500" + fontSize="20px" + lineHeight="30px" + _hover={{ + backgroundColor: "#0B89E2" + }} > {button.text} - + } Leia os - Termos de Serviço + alignItems="center" + color="#0D99FC" + _hover={{ + color: "#0B89E2" + }} + >Termos de Serviço . @@ -315,15 +335,17 @@ export default function Price({ username ,isBDPro, isBDEmp }) { margin="auto" spacing={0} > - Compare os planos - + Para você descobrir o potencial da plataforma de dados} + subTitle={<>Para você descobrir o potencial da plataforma de dados} price={"0"} textResource="Recursos:" resources={[ @@ -374,25 +396,23 @@ export default function Price({ username ,isBDPro, isBDEmp }) { {name: "Acesso em nuvem"}, {name: "Acesso via SQL, Python e R"}, {name: "Integração com ferramentas BI"}, + {name: "Download direto até 100 MB", tooltip: "Esse limite não se aplica ao acesso via SQL, Python e R."}, ]} button={{ text: "Explorar recursos", href: "/dataset", - target: "_self", - color: "#FFF", - colorText: "#42B0FF" }} /> Para você ter acesso aos
dados mais atualizados} + subTitle={<>Para você ter acesso aos
dados mais atualizados} price={priceBDPro} anualPlan={toggleAnual} textResource="Todos os recursos da BD Grátis, mais:" resources={[ {name: "Dezenas de bases de alta frequência atualizadas"}, - {name: "Tabela de referência de empresas com informações traduzidas e atualizadas"} + {name: "Download direto até 1 GB (80% das tabelas da plataforma)", tooltip: "Tabelas maiores que 5 GB não estão disponíveis para download parcial ou completo. Esse limite não se aplica ao acesso via SQL, Python e R."} ]} button={{ text: isBDPro ? "Plano atual" : `Iniciar teste grátis`, @@ -403,12 +423,13 @@ export default function Price({ username ,isBDPro, isBDEmp }) { Para sua empresa ganhar tempo
e qualidade em decisões} + subTitle={<>Para sua empresa ganhar tempo
e qualidade em decisões} price={priceBDEmp} anualPlan={toggleAnual} textResource="Todos os recursos da BD Pro, mais:" resources={[ - {name: "Acesso para 10 contas"},{name: "Suporte prioritário via email e Discord"} + {name: "Acesso para 10 contas"}, + {name: "Suporte prioritário via email e Discord"} ]} button={{ text: isBDEmp ? "Plano atual" : "Iniciar teste grátis", diff --git a/next/pages/user/[username].js b/next/pages/user/[username].js index 1f2300e1..b958e2d8 100644 --- a/next/pages/user/[username].js +++ b/next/pages/user/[username].js @@ -39,7 +39,6 @@ import RoundedButton from "../../components/atoms/RoundedButton"; import ButtonSimple from "../../components/atoms/SimpleButton"; import InputForm from "../../components/atoms/SimpleInput"; import Link from "../../components/atoms/Link"; -import BodyText from "../../components/atoms/BodyText"; import Toggle from "../../components/atoms/Toggle"; import { CardPrice } from "../precos"; import PaymentSystem from "../../components/organisms/PaymentSystem"; @@ -1923,7 +1922,7 @@ const PlansAndPayment = ({ userData }) => { > Para você descobrir o potencial da plataforma de dados} + subTitle={<>Para você descobrir o potencial da plataforma de dados} price={"0"} textResource="Recursos:" resources={[ @@ -1932,26 +1931,24 @@ const PlansAndPayment = ({ userData }) => { {name: "Acesso em nuvem"}, {name: "Acesso via SQL, Python e R"}, {name: "Integração com ferramentas BI"}, + {name: "Download direto até 100 MB", tooltip: "Esse limite não se aplica ao acesso via SQL, Python e R."}, ]} button={{ text: "Explorar recursos", href: "/dataset", - target: "_self", noHasModal: true, - color: "#FFF", - colorText: "#42B0FF" }} /> Para você ter acesso aos
dados mais atualizados} + subTitle={<>Para você ter acesso aos
dados mais atualizados} price={priceBDPro} anualPlan={toggleAnual} textResource="Todos os recursos da BD Grátis, mais:" resources={[ {name: "Dezenas de bases de alta frequência atualizadas"}, - {name: "Tabela de referência de empresas com informações traduzidas e atualizadas"} + {name: "Download direto até 1 GB (80% das tabelas da plataforma)", tooltip: "Tabelas maiores que 5 GB não estão disponíveis para download parcial ou completo. Esse limite não se aplica ao acesso via SQL, Python e R."} ]} button={{ text: `${userData?.proSubscription === "bd_pro" ? "Plano atual" : "Assinar"}`, @@ -1966,12 +1963,13 @@ const PlansAndPayment = ({ userData }) => { Para sua empresa ganhar tempo
e qualidade em decisões} + subTitle={<>Para sua empresa ganhar tempo
e qualidade em decisões} price={priceBDEmp} anualPlan={toggleAnual} textResource="Todos os recursos da BD Pro, mais:" resources={[ - {name: "Acesso para 10 contas"},{name: "Suporte prioritário via email e Discord"} + {name: "Acesso para 10 contas"}, + {name: "Suporte prioritário via email e Discord"} ]} button={{ text: `${userData?.proSubscription === "bd_pro_empresas" ? "Plano atual" : "Assinar"}`, From f5d45c321290698efa84987d50e5bc8de8163156 Mon Sep 17 00:00:00 2001 From: aldemirLucas Date: Thu, 1 Aug 2024 19:56:49 -0300 Subject: [PATCH 06/27] feat: download table dictionary --- next/components/molecules/ColumnsTable.js | 108 +++++++++++++------- next/components/organisms/BdmTablePage.js | 14 +++ next/pages/api/tables/getDictionaryTable.js | 61 +++++++++++ next/pages/precos.js | 2 +- next/pages/user/[username].js | 2 +- 5 files changed, 148 insertions(+), 39 deletions(-) create mode 100644 next/pages/api/tables/getDictionaryTable.js diff --git a/next/components/molecules/ColumnsTable.js b/next/components/molecules/ColumnsTable.js index 78d8f21b..67ef0e30 100644 --- a/next/components/molecules/ColumnsTable.js +++ b/next/components/molecules/ColumnsTable.js @@ -13,6 +13,7 @@ import { Skeleton, } from '@chakra-ui/react'; import { useState, useEffect } from 'react'; +import { useRouter } from 'next/router'; import FuzzySearch from 'fuzzy-search'; import Latex from 'react-latex-next'; import cookies from 'js-cookie'; @@ -96,6 +97,8 @@ export default function ColumnsTable({ template, columnsPro }) { + const router = useRouter() + const { query } = router const [resource, setResource] = useState({}) const [columns, setColumns] = useState({}) const [isError, setIsError] = useState(false) @@ -223,26 +226,78 @@ export default function ColumnsTable({ return 0 } - function TranslationTable({ value, dictionary }) { + function HasDownloadPermitted(value) { let downloadPermitted = false let downloadWarning = "" - if (value?.table?.uncompressedFileSize) { + if (value) { const limit100MB = 100 * 1024 * 1024; const limit1GB = 1 * 1024 * 1024 * 1024; - if (value?.table?.uncompressedFileSize < limit100MB) { + if (value < limit100MB) { downloadPermitted = true downloadWarning = "free" - } else if (value?.table?.uncompressedFileSize < limit1GB) { + } else if (value < limit1GB) { downloadPermitted = isUserPro() downloadWarning = "100mbBetween1gb" } else { - downloadWarning = "biggest1gb" downloadPermitted = false + downloadWarning = "biggest1gb" } } + return { + downloadPermitted : downloadPermitted, + downloadWarning : downloadWarning + } + } + + function DictionaryDownload() { + async function downloadTable() { + const result = await fetch(`/api/tables/getDictionaryTable?p=${btoa(query.dataset)}`, {method: "GET"}) + .then(res => res.json()) + + if(result?.error) return + + let cloudTables = result?.cloudTables?.edges[0]?.node + const downloadInfo = HasDownloadPermitted(result?.uncompressedFileSize) + + triggerGAEvent("download_da_tabela",`{ + gcp: ${cloudTables?.gcpProjectId+"."+cloudTables?.gcpDatasetId+"."+cloudTables?.gcpTableId}, + tamanho: ${formatBytes(result.uncompressedFileSize) || ""}, + dataset: ${query.dataset}, + table: ${resource?._id}, + columnDownload: true + }`) + window.open(`/api/tables/downloadTable?p=${btoa(cloudTables?.gcpDatasetId)}&q=${btoa(cloudTables?.gcpTableId)}&d=${btoa(downloadInfo.downloadPermitted)}&s=${btoa(downloadInfo.downloadWarning)}`) + } + + return ( + + downloadTable()} + display="flex" + flexDirection="row" + alignItems="center" + gap="4px" + color="#0068C5" + fill="#0068C5" + _hover={{ + color:"#0057A4", + fill:"#0057A4" + }} + > + Baixar tabela que faz a tradução desta coluna + + + Dicionário + + ) + } + + function TranslationTable({ value, dictionary }) { + const downloadInfo = HasDownloadPermitted(value?.table?.uncompressedFileSize) const cloudValues = value?.table?.cloudTables?.edges?.[0]?.node const gcpProjectID = cloudValues?.gcpProjectId || "" @@ -260,23 +315,22 @@ export default function ColumnsTable({ return ( - {value === null && - + {value === null ? + Não precisa de tradução - } - - {value !== null && + : { + onClick={() => { + if(!downloadInfo.downloadPermitted) return triggerGAEvent("download_da_tabela",`{ gcp: ${gcpProjectID+"."+gcpDatasetID+"."+gcpTableId}, tamanho: ${formatBytes(value?.table?.uncompressedFileSize) || ""}, @@ -295,7 +349,7 @@ export default function ColumnsTable({ fill:"#0057A4" }} > - {value?.table?.isClosed + {value?.table?.isClosed || !downloadInfo.downloadPermitted ? <> Acessar tabela que faz a tradução desta coluna @@ -312,29 +366,9 @@ export default function ColumnsTable({ } - {/* {dictionary === true && - - - Baixar tabela que faz a tradução desta coluna - - - {datasetName} - {tableName} - - } */} + {dictionary === true && + + } ) } diff --git a/next/components/organisms/BdmTablePage.js b/next/components/organisms/BdmTablePage.js index 04fcef49..d0782163 100644 --- a/next/components/organisms/BdmTablePage.js +++ b/next/components/organisms/BdmTablePage.js @@ -404,6 +404,20 @@ export default function BdmTablePage({ id }) { {getUpdateFormat(resource?.rawDataSource?.[0]?.updates?.[0]?.entity?.slug)} } + {!resource?.rawDataSource?.[0]?.updates?.[0] && + + Sem previsão de atualização + + }
{ textResource="Todos os recursos da BD Grátis, mais:" resources={[ {name: "Dezenas de bases de alta frequência atualizadas"}, - {name: "Download direto até 1 GB (80% das tabelas da plataforma)", tooltip: "Tabelas maiores que 5 GB não estão disponíveis para download parcial ou completo. Esse limite não se aplica ao acesso via SQL, Python e R."} + {name: "Download direto até 1GB (80% das tabelas da plataforma)", tooltip: "Tabelas maiores que 5 GB não estão disponíveis para download parcial ou completo. Esse limite não se aplica ao acesso via SQL, Python e R."} ]} button={{ text: `${userData?.proSubscription === "bd_pro" ? "Plano atual" : "Assinar"}`, From 06812dd2a0082d654a11522ed0bc030f6b0584f6 Mon Sep 17 00:00:00 2001 From: aldemirLucas Date: Mon, 5 Aug 2024 12:09:53 -0300 Subject: [PATCH 07/27] feat: ajust Data update frequency --- next/components/organisms/BdmTablePage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/next/components/organisms/BdmTablePage.js b/next/components/organisms/BdmTablePage.js index d0782163..6f56991b 100644 --- a/next/components/organisms/BdmTablePage.js +++ b/next/components/organisms/BdmTablePage.js @@ -404,7 +404,7 @@ export default function BdmTablePage({ id }) { {getUpdateFormat(resource?.rawDataSource?.[0]?.updates?.[0]?.entity?.slug)} } - {!resource?.rawDataSource?.[0]?.updates?.[0] && + {!resource?.rawDataSource?.[0]?.updates?.[0] || !resource?.updates?.[0]?.frequency && Date: Thu, 8 Aug 2024 17:49:51 -0300 Subject: [PATCH 08/27] feat: ajust card logical redirect and paymentsystem --- next/components/organisms/PaymentSystem.js | 18 +------ next/pages/precos.js | 22 ++------ next/pages/user/[username].js | 63 ++++++++++++++-------- next/pages/user/login.js | 11 ++-- 4 files changed, 52 insertions(+), 62 deletions(-) diff --git a/next/components/organisms/PaymentSystem.js b/next/components/organisms/PaymentSystem.js index 2d8841ae..9b13d0b7 100644 --- a/next/components/organisms/PaymentSystem.js +++ b/next/components/organisms/PaymentSystem.js @@ -107,24 +107,8 @@ export default function PaymentSystem({ userData, plan, onSucess, onErro }) { return setClientSecret(secret) } - async function customerCreat(plan) { - const prices = await getPrices() - - const findPlan = (slug, slots) => { - const foundPlan = prices.find(p => { - return p.node.productSlug === slug && p.node.productSlots === slots - }) - - return foundPlan ? foundPlan.node : null - } - - const idPlan = findPlan(plan.slug, plan.slots)?._id - - customerCreatPost(idPlan) - } - useEffect(() => { - customerCreat(plan) + customerCreatPost(plan.id) }, []) const SkeletonBox = ({ type, ...props }) => { diff --git a/next/pages/precos.js b/next/pages/precos.js index 5cf90fe9..6a20884b 100644 --- a/next/pages/precos.js +++ b/next/pages/precos.js @@ -297,8 +297,6 @@ export const CardPrice = ({ export default function Price({ username ,isBDPro, isBDEmp }) { const [toggleAnual, setToggleAnual] = useState(false) - const [priceBDPro, setPriceBDPro] = useState("47") - const [priceBDEmp, setPriceBDEmp] = useState("350") const [plans, setPlans] = useState(null) useEffect(() => { @@ -335,16 +333,6 @@ export default function Price({ username ,isBDPro, isBDEmp }) { fecthPlans() }, []) - useEffect(() => { - if(toggleAnual === true) { - setPriceBDPro("37") - setPriceBDEmp("280") - } else { - setPriceBDPro("47") - setPriceBDEmp("350") - } - }, [toggleAnual]) - return ( @@ -406,7 +394,7 @@ export default function Price({ username ,isBDPro, isBDEmp }) { letterSpacing="0.1px" color="#252A32" > - Desconto anual Economize 20% + Desconto anual Economize 20% @@ -442,7 +430,7 @@ export default function Price({ username ,isBDPro, isBDEmp }) { Para você ter acesso aos
dados mais atualizados} - price={priceBDPro} + price={plans?.["bd_pro_month"].amount || 47} anualPlan={toggleAnual} textResource="Todos os recursos da BD Grátis, mais:" resources={[ @@ -451,7 +439,7 @@ export default function Price({ username ,isBDPro, isBDEmp }) { ]} button={{ text: isBDPro ? "Plano atual" : `Iniciar teste grátis`, - href: username === null ? "/user/login?p=plans&q=pro" :`/user/${username}?plans_and_payment&q=pro`, + href: username === null ? `/user/login?q=pro&i=${plans?.["bd_pro_month"]._id}` :`/user/${username}?plans_and_payment&q=pro&i=${plans?.["bd_pro_month"]._id}`, isCurrentPlan: isBDPro, }} /> @@ -459,7 +447,7 @@ export default function Price({ username ,isBDPro, isBDEmp }) { Para sua empresa ganhar tempo
e qualidade em decisões} - price={priceBDEmp} + price={plans?.["bd_empresas_month"].amount || 350} anualPlan={toggleAnual} textResource="Todos os recursos da BD Pro, mais:" resources={[ @@ -468,7 +456,7 @@ export default function Price({ username ,isBDPro, isBDEmp }) { ]} button={{ text: isBDEmp ? "Plano atual" : "Iniciar teste grátis", - href: username === null ? "/user/login?p=plans&q=empresas" :`/user/${username}?plans_and_payment&q=empresas`, + href: username === null ? `/user/login?q=empresas&i=${plans?.["bd_empresas_month"]._id}` :`/user/${username}?plans_and_payment&q=empresas&i=${plans?.["bd_empresas_month"]._id}`, isCurrentPlan: isBDEmp, }} /> diff --git a/next/pages/user/[username].js b/next/pages/user/[username].js index 882f009a..8fd827b0 100644 --- a/next/pages/user/[username].js +++ b/next/pages/user/[username].js @@ -1450,33 +1450,52 @@ const PlansAndPayment = ({ userData }) => { const [isLoading, setIsLoading] = useState(false) const [isLoadingH, setIsLoadingH] = useState(false) const [isLoadingCanSub, setIsLoadingCanSub] = useState(false) + + const [plans, setPlans] = useState(null) const [toggleAnual, setToggleAnual] = useState(false) - const [priceBDPro, setPriceBDPro] = useState("47") - const [priceBDEmp, setPriceBDEmp] = useState("350") useEffect(() => { - if(query.q === "pro") { - if(userData.proSubscriptionStatus === "active") return AlertChangePlanModal.onOpen() - setPlan({title: "BD Pro", slug:"bd_pro", slots: "0"}) - PaymentModal.onOpen() + async function fecthPlans() { + try { + const result = await fetch(`/api/stripe/getPlans`, { method: "GET" }) + .then(res => res.json()) + + if(result.success === true) { + function filterData(productName, interval, isActive) { + let array = result.data + + return array.filter(item => + (productName ? item.node.productName === productName : true) && + (interval ? item.node.interval === interval : true) && + (isActive !== undefined ? item.node.isActive === isActive : true) + ) + } + + const filteredPlans = { + bd_pro_month : filterData("BD Pro", "month", true)[0].node, + bd_pro_year : filterData("BD Pro", "year", true)[0].node, + bd_empresas_month : filterData("BD Empresas", "month", true)[0].node, + bd_empresas_year : filterData("BD Empresas", "year", true)[0].node + } + + setPlans(filteredPlans) + } + } catch (error) { + console.error(error) + } } - if(query.q === "empresas") { + + fecthPlans() + }, []) + + useEffect(() => { + if(query.i) { if(userData.proSubscriptionStatus === "active") return AlertChangePlanModal.onOpen() - setPlan({title: "BD Empresas", slug:"bd_pro_empresas", slots: "10"}) + setPlan({id: query.i}) PaymentModal.onOpen() } }, [query]) - useEffect(() => { - if(toggleAnual === true) { - setPriceBDPro("37") - setPriceBDEmp("280") - } else { - setPriceBDPro("47") - setPriceBDEmp("350") - } - }, [toggleAnual]) - const resources={ "BD Gratis" : { title: "BD Grátis", @@ -1943,7 +1962,7 @@ const PlansAndPayment = ({ userData }) => { Para você ter acesso aos
dados mais atualizados} - price={priceBDPro} + price={plans?.["bd_pro_month"].amount || 47} anualPlan={toggleAnual} textResource="Todos os recursos da BD Grátis, mais:" resources={[ @@ -1953,7 +1972,7 @@ const PlansAndPayment = ({ userData }) => { button={{ text: `${userData?.proSubscription === "bd_pro" ? "Plano atual" : "Assinar"}`, onClick: userData?.proSubscription === "bd_pro" ? () => {} : () => { - setPlan({title: "BD Pro", slug:"bd_pro", slots: "0"}) + setPlan({id: plans?.["bd_pro_month"]._id}) PlansModal.onClose() PaymentModal.onOpen() }, @@ -1964,7 +1983,7 @@ const PlansAndPayment = ({ userData }) => { Para sua empresa ganhar tempo
e qualidade em decisões} - price={priceBDEmp} + price={plans?.["bd_empresas_month"].amount || 350} anualPlan={toggleAnual} textResource="Todos os recursos da BD Pro, mais:" resources={[ @@ -1974,7 +1993,7 @@ const PlansAndPayment = ({ userData }) => { button={{ text: `${userData?.proSubscription === "bd_pro_empresas" ? "Plano atual" : "Assinar"}`, onClick: userData?.proSubscription === "bd_pro_empresas" ? () => {} : () => { - setPlan({title: "BD Empresas", slug:"bd_pro_empresas", slots: "10"}) + setPlan({id: plans?.["bd_empresas_month"]._id}) PlansModal.onClose() PaymentModal.onOpen() }, diff --git a/next/pages/user/login.js b/next/pages/user/login.js index 032585b2..b9f38da3 100644 --- a/next/pages/user/login.js +++ b/next/pages/user/login.js @@ -81,13 +81,12 @@ export default function Login() { cookies.set('userBD', JSON.stringify(userData)) - if(query.p === "plans") { - if(query.q) return window.open(`/user/${userData.username}?plans_and_payment&q=${query.q}`, "_self") - return window.open(`/user/${userData.username}?plans_and_payment&p=plans`, "_self") - } else { - if(userData.availableForResearch === null) return window.open("/user/survey", "_self") - return window.open("/", "_self") + if(query.p && query.i) { + return window.open(`/user/${userData.username}?plans_and_payment&q=${query.q}&i=${query.i}`, "_self") } + + if(userData.availableForResearch === null) return window.open("/user/survey", "_self") + return window.open("/", "_self") } const LabelTextForm = ({ text, ...props }) => { From e2bab4975eb9dabffdb1ce1a1f83c7fb8afdf4ed Mon Sep 17 00:00:00 2001 From: aldemirLucas Date: Fri, 9 Aug 2024 10:52:39 -0300 Subject: [PATCH 09/27] feat: ajust redirect plans user page --- next/pages/user/[username].js | 28 +++++++++++++++------------- next/pages/user/login.js | 2 +- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/next/pages/user/[username].js b/next/pages/user/[username].js index 8fd827b0..43fe3521 100644 --- a/next/pages/user/[username].js +++ b/next/pages/user/[username].js @@ -88,9 +88,9 @@ export async function getServerSideProps(context) { const validateTokenResponse = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL_FRONTEND}/api/user/validateToken?p=${btoa(req.cookies.token)}`, {method: "GET"}) const validateToken = await validateTokenResponse.json() - if(validateToken.error) { - const refreshTokenResponse = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL_FRONTEND}/api/user/refreshToken?p=${btoa(req.cookies.token)}`, {method: "GET"}) - const refreshToken = await refreshTokenResponse.json() + if(validateToken.error) { + const refreshTokenResponse = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL_FRONTEND}/api/user/refreshToken?p=${btoa(req.cookies.token)}`, {method: "GET"}) + const refreshToken = await refreshTokenResponse.json() if(refreshToken.error) { res.setHeader('Set-Cookie', serialize('token', '', {maxAge: -1, path: '/', })) @@ -128,7 +128,7 @@ export async function getServerSideProps(context) { return { props: { - getUser + getUser, } } } @@ -1455,6 +1455,8 @@ const PlansAndPayment = ({ userData }) => { const [toggleAnual, setToggleAnual] = useState(false) useEffect(() => { + if(PlansModal.isOpen === false) return + async function fecthPlans() { try { const result = await fetch(`/api/stripe/getPlans`, { method: "GET" }) @@ -1486,7 +1488,7 @@ const PlansAndPayment = ({ userData }) => { } fecthPlans() - }, []) + }, [PlansModal.isOpen]) useEffect(() => { if(query.i) { @@ -1616,14 +1618,14 @@ const PlansAndPayment = ({ userData }) => { setIsLoadingCanSub(false) } - do { - const statusSub = await fetch(`/api/stripe/userGetSubscription?p=${btoa(id)}`, {method: "GET"}) - .then(res => res.json()) - if(statusSub?.proSubscriptionStatus !== "active") { - break - } - await new Promise (resolve => setTimeout(resolve ,1000)) - } while (true) + // do { + // const statusSub = await fetch(`/api/stripe/userGetSubscription?p=${btoa(id)}`, {method: "GET"}) + // .then(res => res.json()) + // if(statusSub?.proSubscriptionStatus !== "active") { + // break + // } + // await new Promise (resolve => setTimeout(resolve ,1000)) + // } while (true) const user = await fetch(`/api/user/getUser?p=${btoa(id)}`, {method: "GET"}) .then(res => res.json()) diff --git a/next/pages/user/login.js b/next/pages/user/login.js index b9f38da3..7040e4d7 100644 --- a/next/pages/user/login.js +++ b/next/pages/user/login.js @@ -81,7 +81,7 @@ export default function Login() { cookies.set('userBD', JSON.stringify(userData)) - if(query.p && query.i) { + if(query.i) { return window.open(`/user/${userData.username}?plans_and_payment&q=${query.q}&i=${query.i}`, "_self") } From 89193e7c17029833da723c8ec62147aaa9fa4e94 Mon Sep 17 00:00:00 2001 From: aldemirLucas Date: Tue, 13 Aug 2024 15:14:01 -0300 Subject: [PATCH 10/27] chore: ajust text and fix tableDownload free --- next/components/organisms/BdmTablePage.js | 20 ++++++++++---------- next/pages/api/tables/downloadTable.js | 2 +- next/pages/dataset/[dataset].js | 7 +++++-- next/pages/transparencia.js | 4 ++-- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/next/components/organisms/BdmTablePage.js b/next/components/organisms/BdmTablePage.js index 9d805816..90c2a7cb 100644 --- a/next/components/organisms/BdmTablePage.js +++ b/next/components/organisms/BdmTablePage.js @@ -196,16 +196,16 @@ export default function BdmTablePage({ id }) { let formats {yearFrequency ? formats = { - "second":`Atualização a cada ${frequency} por segundo`, - "minute":`Atualização a cada ${frequency} por minuto`, - "hour":`Atualização a cada ${frequency} por hora`, - "day":`Atualização a cada ${frequency} diária`, - "week":`Atualização a cada ${frequency} semanal`, - "month":`Atualização a cada ${frequency} mensal`, - "bimester":`Atualização a cada ${frequency} bimestral`, - "quarter":`Atualização a cada ${frequency} trimestral`, - "semester":`Atualização a cada ${frequency} semestral`, - "year":`Atualização a cada ${frequency} anual`, + "second":`Atualização a cada ${frequency} segundos`, + "minute":`Atualização a cada ${frequency} minutos`, + "hour":`Atualização a cada ${frequency} horas`, + "day":`Atualização a cada ${frequency} dias`, + "week":`Atualização a cada ${frequency} semanas`, + "month":`Atualização a cada ${frequency} meses`, + "bimester":`Atualização a cada ${frequency} bimestres`, + "quarter":`Atualização a cada ${frequency} trimestres`, + "semester":`Atualização a cada ${frequency} semestres`, + "year":`Atualização a cada ${frequency} anos`, } : formats = { diff --git a/next/pages/api/tables/downloadTable.js b/next/pages/api/tables/downloadTable.js index 1b5fa146..dcd8d112 100644 --- a/next/pages/api/tables/downloadTable.js +++ b/next/pages/api/tables/downloadTable.js @@ -20,7 +20,7 @@ async function validateToken(token) { async function downloadTable(url, datasetID, tableId, token, res) { let payloadToken - if(token !== null) payloadToken = await validateToken(token) + if(url !== "free" && token !== null) payloadToken = await validateToken(token) try { const fileUrl = url === "free" diff --git a/next/pages/dataset/[dataset].js b/next/pages/dataset/[dataset].js index 2e6255f8..a07b97fb 100644 --- a/next/pages/dataset/[dataset].js +++ b/next/pages/dataset/[dataset].js @@ -182,7 +182,10 @@ export default function DatasetPage ({ dataset }) { > Organização - + {dataset?.organization?.name || "Nenhuma organização fornecida."} - +
diff --git a/next/pages/transparencia.js b/next/pages/transparencia.js index 76a62101..636af6bb 100644 --- a/next/pages/transparencia.js +++ b/next/pages/transparencia.js @@ -231,12 +231,12 @@ export default function Transparencia({ pages }) { gridGap={{ base: "64px", lg: "80px" }} > From a67ec44913c1f9a5cdd2d61ac4fe1fdd03e4f65d Mon Sep 17 00:00:00 2001 From: aldemirLucas Date: Wed, 14 Aug 2024 12:37:26 -0300 Subject: [PATCH 11/27] chore: remove repetition in a code snippet --- next/components/organisms/BdmTablePage.js | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/next/components/organisms/BdmTablePage.js b/next/components/organisms/BdmTablePage.js index 90c2a7cb..03512e10 100644 --- a/next/components/organisms/BdmTablePage.js +++ b/next/components/organisms/BdmTablePage.js @@ -444,20 +444,6 @@ export default function BdmTablePage({ id }) { : <> } - {!resource?.rawDataSource?.[0]?.updates?.[0] || !resource?.updates?.[0]?.frequency && - - Sem previsão de atualização - - } Date: Wed, 14 Aug 2024 16:31:10 -0300 Subject: [PATCH 12/27] fix: url download tables pro ajust --- next/pages/api/tables/downloadTable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/next/pages/api/tables/downloadTable.js b/next/pages/api/tables/downloadTable.js index dcd8d112..027e10c2 100644 --- a/next/pages/api/tables/downloadTable.js +++ b/next/pages/api/tables/downloadTable.js @@ -25,7 +25,7 @@ async function downloadTable(url, datasetID, tableId, token, res) { try { const fileUrl = url === "free" ? `${process.env.URL_DOWNLOAD_TABLE}/${datasetID}/${tableId}/${tableId}.csv.gz` - : payloadToken?.pro_subscription_status === "active" ? `${process.env.URL_DOWNLOAD_PRIVATE_TABLE}/${datasetID}/${tableId}/${tableId}.csv.gz` : "" + : payloadToken?.pro_subscription_status === "active" ? `${process.env.URL_DOWNLOAD_PRIVATE_TABLE}/${datasetID}/${tableId}/${tableId}_bdpro.csv.gz` : "" const response = await axios({ url: fileUrl, From 913ce8b2eb2cfa355db280d7b111419316997f70 Mon Sep 17 00:00:00 2001 From: aldemirLucas Date: Wed, 14 Aug 2024 19:01:25 -0300 Subject: [PATCH 13/27] feat: year promotion cards att --- next/components/atoms/Toggle.js | 4 ++-- next/pages/precos.js | 36 +++++++++++++++++++++------------ next/pages/user/[username].js | 31 +++++++++++++++++++--------- next/styles/toggle.module.css | 26 +++++++++++++++--------- 4 files changed, 63 insertions(+), 34 deletions(-) diff --git a/next/components/atoms/Toggle.js b/next/components/atoms/Toggle.js index cd2e1815..f9d74fe0 100644 --- a/next/components/atoms/Toggle.js +++ b/next/components/atoms/Toggle.js @@ -1,10 +1,10 @@ import { Switch } from "@chakra-ui/react"; import styles from "../../styles/toggle.module.css"; -export default function Toggle({ value, onChange, ...props }) { +export default function Toggle({ value, onChange, className = "toggle", ...props }) { return ( R$ {price} + >R$ {anualPlan ? price/12 : price} {(price*12).toLocaleString('pt-BR', { style: 'currency', currency: 'BRL', minimumFractionDigits: 0 })} cobrado uma vez no ano + >{(price).toLocaleString('pt-BR', { style: 'currency', currency: 'BRL', minimumFractionDigits: 0 })} cobrado uma vez no ano } @@ -371,7 +369,7 @@ export default function Price({ username ,isBDPro, isBDEmp }) { setToggleAnual(!toggleAnual)} /> - Desconto anual Economize 20% + Desconto anual + Economize 20% @@ -430,7 +440,7 @@ export default function Price({ username ,isBDPro, isBDEmp }) { Para você ter acesso aos
dados mais atualizados} - price={plans?.["bd_pro_month"].amount || 47} + price={plans?.[`bd_pro_${toggleAnual ? "year" : "month"}`].amount || 47} anualPlan={toggleAnual} textResource="Todos os recursos da BD Grátis, mais:" resources={[ @@ -439,7 +449,7 @@ export default function Price({ username ,isBDPro, isBDEmp }) { ]} button={{ text: isBDPro ? "Plano atual" : `Iniciar teste grátis`, - href: username === null ? `/user/login?q=pro&i=${plans?.["bd_pro_month"]._id}` :`/user/${username}?plans_and_payment&q=pro&i=${plans?.["bd_pro_month"]._id}`, + href: username === null ? `/user/login?q=pro&i=${plans?.[`bd_pro_${toggleAnual ? "year" : "month"}`]._id}` :`/user/${username}?plans_and_payment&q=pro&i=${plans?.[`bd_pro_${toggleAnual ? "year" : "month"}`]._id}`, isCurrentPlan: isBDPro, }} /> @@ -447,7 +457,7 @@ export default function Price({ username ,isBDPro, isBDEmp }) { Para sua empresa ganhar tempo
e qualidade em decisões} - price={plans?.["bd_empresas_month"].amount || 350} + price={plans?.[`bd_empresas_${toggleAnual ? "year" : "month"}`].amount || 350} anualPlan={toggleAnual} textResource="Todos os recursos da BD Pro, mais:" resources={[ @@ -456,7 +466,7 @@ export default function Price({ username ,isBDPro, isBDEmp }) { ]} button={{ text: isBDEmp ? "Plano atual" : "Iniciar teste grátis", - href: username === null ? `/user/login?q=empresas&i=${plans?.["bd_empresas_month"]._id}` :`/user/${username}?plans_and_payment&q=empresas&i=${plans?.["bd_empresas_month"]._id}`, + href: username === null ? `/user/login?q=empresas&i=${plans?.[`bd_empresas_${toggleAnual ? "year" : "month"}`]._id}` :`/user/${username}?plans_and_payment&q=empresas&i=${plans?.[`bd_empresas_${toggleAnual ? "year" : "month"}`]._id}`, isCurrentPlan: isBDEmp, }} /> diff --git a/next/pages/user/[username].js b/next/pages/user/[username].js index 43fe3521..e213e4e2 100644 --- a/next/pages/user/[username].js +++ b/next/pages/user/[username].js @@ -1901,7 +1901,7 @@ const PlansAndPayment = ({ userData }) => { /> { onChange={() => setToggleAnual(!toggleAnual)} /> - Desconto anual Economize 20% + Desconto anual + Economize 20% @@ -1964,7 +1975,7 @@ const PlansAndPayment = ({ userData }) => { Para você ter acesso aos
dados mais atualizados} - price={plans?.["bd_pro_month"].amount || 47} + price={plans?.[`bd_pro_${toggleAnual ? "year" : "month"}`].amount || 47} anualPlan={toggleAnual} textResource="Todos os recursos da BD Grátis, mais:" resources={[ @@ -1974,7 +1985,7 @@ const PlansAndPayment = ({ userData }) => { button={{ text: `${userData?.proSubscription === "bd_pro" ? "Plano atual" : "Assinar"}`, onClick: userData?.proSubscription === "bd_pro" ? () => {} : () => { - setPlan({id: plans?.["bd_pro_month"]._id}) + setPlan({id: plans?.[`bd_pro_${toggleAnual ? "year" : "month"}`]._id}) PlansModal.onClose() PaymentModal.onOpen() }, @@ -1985,7 +1996,7 @@ const PlansAndPayment = ({ userData }) => { Para sua empresa ganhar tempo
e qualidade em decisões} - price={plans?.["bd_empresas_month"].amount || 350} + price={plans?.[`bd_empresas_${toggleAnual ? "year" : "month"}`].amount || 350} anualPlan={toggleAnual} textResource="Todos os recursos da BD Pro, mais:" resources={[ @@ -1995,7 +2006,7 @@ const PlansAndPayment = ({ userData }) => { button={{ text: `${userData?.proSubscription === "bd_pro_empresas" ? "Plano atual" : "Assinar"}`, onClick: userData?.proSubscription === "bd_pro_empresas" ? () => {} : () => { - setPlan({id: plans?.["bd_empresas_month"]._id}) + setPlan({id: plans?.[`bd_empresas_${toggleAnual ? "year" : "month"}`]._id}) PlansModal.onClose() PaymentModal.onOpen() }, diff --git a/next/styles/toggle.module.css b/next/styles/toggle.module.css index 79a21267..9d0157a6 100644 --- a/next/styles/toggle.module.css +++ b/next/styles/toggle.module.css @@ -1,4 +1,4 @@ -.toggle { +.toggle, .toggle_variant { --switch-track-diff: 17px !important; --switch-thumb-x: 17px !important; --switch-track-width: 0 !important; @@ -6,23 +6,27 @@ border-color: transparent !important; } -.toggle span{ +.toggle span, .toggle_variant span{ background-color: #878A8E; width: 42px; height: 24px; } -.toggle span[data-checked]{ +.toggle span[data-checked], .toggle_variant span[data-checked]{ background-color: #2B8C4D; width: 42px; height: 24px; } -.toggle span[data-focus]{ +.toggle_variant span[data-checked]{ + background-color: #0D99FC; +} + +.toggle span[data-focus], .toggle_variant span[data-focus]{ box-shadow: none; } -.toggle span span{ +.toggle span span, .toggle_variant span span{ background-color: #FFF; position: relative; top: 1px; @@ -31,17 +35,17 @@ height: 21px; } -.toggle span span[data-checked]{ +.toggle span span[data-checked], .toggle_variant span span[data-checked]{ background-color: #FFF; width: 21px; height: 21px; } -.toggle span:hover { +.toggle span:hover, .toggle_variant span:hover { background-color: #71757A; } -.toggle span span:hover { +.toggle span span:hover, .toggle_variant span span:hover{ background-color: #FFF; } @@ -49,6 +53,10 @@ background-color: #22703E; } -.toggle span[data-checked] span:hover { +.toggle_variant span[data-checked]:hover { + background-color: #0D99FC; +} + +.toggle span[data-checked] span:hover, .toggle_variant span[data-checked] span:hover { background-color: #FFF; } \ No newline at end of file From c18828a9287babff60d5af6a8aa252cf74bc6939 Mon Sep 17 00:00:00 2001 From: aldemirLucas Date: Thu, 15 Aug 2024 20:22:56 -0300 Subject: [PATCH 14/27] feat: 914 added price modal in download and pro system interactions --- .../molecules/DataInformationQuery.js | 50 +++- .../molecules/TemporalCoverageDisplay.js | 38 ++- next/pages/precos.js | 262 +++++++++--------- next/pages/servicos.js | 1 - next/pages/transparencia.js | 19 ++ next/pages/user/[username].js | 162 ++++++----- 6 files changed, 319 insertions(+), 213 deletions(-) diff --git a/next/components/molecules/DataInformationQuery.js b/next/components/molecules/DataInformationQuery.js index 80a1b2fa..74aefb63 100644 --- a/next/components/molecules/DataInformationQuery.js +++ b/next/components/molecules/DataInformationQuery.js @@ -10,7 +10,9 @@ import { useClipboard, Tooltip, Skeleton, - Stack + Stack, + useDisclosure, + ModalCloseButton } from "@chakra-ui/react"; import { useState, useEffect, useRef } from "react"; import hljs from "highlight.js/lib/core"; @@ -23,6 +25,8 @@ import 'highlight.js/styles/obsidian.css' import GreenTab from "../atoms/GreenTab"; import Toggle from "../atoms/Toggle"; import ColumnsTable from "./ColumnsTable"; +import { SectionPrice } from "../../pages/precos"; +import { ModalGeneral } from "./uiUserPage"; import { AlertDiscalimerBox} from "./DisclaimerBox"; import { triggerGAEvent, formatBytes } from "../../utils"; @@ -182,6 +186,7 @@ export default function DataInformationQuery({ resource }) { const [hasLoadingColumns, setHasLoadingColumns] = useState(true) const [isLoadingCode, setIsLoadingCode] = useState(false) const [hasLoadingResponse, setHasLoadingResponse] = useState(false) + const plansModal = useDisclosure() const [gcpProjectID, setGcpProjectID] = useState("") const [gcpDatasetID, setGcpDatasetID] = useState("") @@ -297,6 +302,36 @@ export default function DataInformationQuery({ resource }) { border="1px solid #DEDFE0" borderRadius="16px" > + + + + Compare os planos + + + + + + + { + onClick={() => { + if(downloadWarning === "100mbBetween1gb") return plansModal.onOpen() triggerGAEvent("download_da_tabela",`{ gcp: ${gcpProjectID+"."+gcpDatasetID+"."+gcpTableId}, tamanho: ${formatBytes(resource.uncompressedFileSize) || ""}, @@ -578,9 +614,9 @@ export default function DataInformationQuery({ resource }) { height="40px" width="fit-content" borderRadius="8px" - backgroundColor={downloadPermitted ? "#2B8C4D" : "#ACAEB1"} + backgroundColor={downloadWarning !== "biggest1gb" ? "#2B8C4D" : "#ACAEB1"} padding="8px 16px" - cursor={downloadPermitted ? "pointer" : "default"} + cursor={downloadWarning !== "biggest1gb" ? "pointer" : "default"} color="#FFF" fill="#FFF" fontFamily="Roboto" @@ -588,7 +624,7 @@ export default function DataInformationQuery({ resource }) { fontSize="14px" gap="8px" lineHeight="20px" - pointerEvents={downloadPermitted ? "default" : "none"} + pointerEvents={downloadWarning !== "biggest1gb" ? "default" : "none"} _hover={{ backgroundColor: "#22703E" }} @@ -597,7 +633,7 @@ export default function DataInformationQuery({ resource }) { width="24px" height="24px" /> - Download da tabela {downloadPermitted && `(${formatBytes(resource.uncompressedFileSize)})`} + Download da tabela {downloadWarning !== "biggest1gb" && `(${formatBytes(resource.uncompressedFileSize)})`} diff --git a/next/components/molecules/TemporalCoverageDisplay.js b/next/components/molecules/TemporalCoverageDisplay.js index 96a56b93..28d04638 100644 --- a/next/components/molecules/TemporalCoverageDisplay.js +++ b/next/components/molecules/TemporalCoverageDisplay.js @@ -5,9 +5,13 @@ import { Text, Box, Tooltip, + useDisclosure, + ModalCloseButton } from "@chakra-ui/react"; import { useState, useEffect } from "react"; import { CalendarComunIcon } from "../../public/img/icons/calendarIcon"; +import { SectionPrice } from "../../pages/precos"; +import { ModalGeneral } from "./uiUserPage"; import RedirectIcon from "../../public/img/icons/redirectIcon"; export function TemporalCoverage ({ @@ -126,6 +130,7 @@ export function TemporalCoverageString({ export function TemporalCoverageBar ({ value }) { const [values, setValues] = useState({}) + const plansModal = useDisclosure() const TextData = ({ string, ...style }) => { return ( @@ -168,6 +173,36 @@ export function TemporalCoverageBar ({ value }) { alignItems="normal" spacing={0} > + + + + Compare os planos + + + + + + + plansModal.onOpen()} > PAGO {button.text} @@ -293,11 +275,23 @@ export const CardPrice = ({ ) } -export default function Price({ username ,isBDPro, isBDEmp }) { +export function SectionPrice() { const [toggleAnual, setToggleAnual] = useState(false) const [plans, setPlans] = useState(null) + const [username, setUsername] = useState(null) + const [isBDPro, setIsBDPro] = useState(false) + const [isBDEmp, setIsBDEmp] = useState(false) useEffect(() => { + let user = null + if(cookies.get("userBD")) user = JSON.parse(cookies.get("userBD")) + + if(user != null) { + setUsername(user?.username) + setIsBDPro(user?.proSubscription === "bd_pro") + setIsBDEmp(user?.proSubscription === "bd_pro_empresas") + } + async function fecthPlans() { try { const result = await fetch(`/api/stripe/getPlans`, { method: "GET" }) @@ -331,6 +325,119 @@ export default function Price({ username ,isBDPro, isBDEmp }) { fecthPlans() }, []) + return ( + + + setToggleAnual(!toggleAnual)} + /> + + Desconto anual + Economize 20% + + + + + Para você descobrir o potencial da plataforma de dados} + price={"0"} + textResource="Recursos:" + resources={[ + {name: "Tabelas tratadas"}, + {name: "Dados integrados", tooltip: "Nossa metodologia de padronização e compatibilização de dados permite que você cruze tabelas de diferentes instituições e temas de maneira simplificada."}, + {name: "Acesso em nuvem"}, + {name: "Acesso via SQL, Python e R"}, + {name: "Integração com ferramentas BI"}, + {name: "Download direto até 100 MB", tooltip: "Esse limite não se aplica ao acesso via SQL, Python e R."}, + ]} + button={{ + text: "Explorar recursos", + href: "/dataset", + }} + /> + + Para você ter acesso aos
dados mais atualizados} + price={plans?.[`bd_pro_${toggleAnual ? "year" : "month"}`].amount || 47} + anualPlan={toggleAnual} + textResource="Todos os recursos da BD Grátis, mais:" + resources={[ + {name: "Dezenas de bases de alta frequência atualizadas"}, + {name: "Download direto até 1GB (80% das tabelas da plataforma)", tooltip: "Tabelas maiores que 1 GB não estão disponíveis para download parcial ou completo. Esse limite não se aplica ao acesso via SQL, Python e R."} + ]} + button={{ + text: isBDPro ? "Plano atual" : `Iniciar teste grátis`, + href: username === null ? `/user/login?q=pro&i=${plans?.[`bd_pro_${toggleAnual ? "year" : "month"}`]._id}` :`/user/${username}?plans_and_payment&q=pro&i=${plans?.[`bd_pro_${toggleAnual ? "year" : "month"}`]._id}`, + isCurrentPlan: isBDPro, + }} + /> + + Para sua empresa ganhar tempo
e qualidade em decisões} + price={plans?.[`bd_empresas_${toggleAnual ? "year" : "month"}`].amount || 350} + anualPlan={toggleAnual} + textResource="Todos os recursos da BD Pro, mais:" + resources={[ + {name: "Acesso para 10 contas"}, + {name: "Suporte prioritário via email e Discord"} + ]} + button={{ + text: isBDEmp ? "Plano atual" : "Iniciar teste grátis", + href: username === null ? `/user/login?q=empresas&i=${plans?.[`bd_empresas_${toggleAnual ? "year" : "month"}`]._id}` :`/user/${username}?plans_and_payment&q=empresas&i=${plans?.[`bd_empresas_${toggleAnual ? "year" : "month"}`]._id}`, + isCurrentPlan: isBDEmp, + }} + /> +
+
+ ) +} + +export default function Price() { return ( @@ -353,6 +460,7 @@ export default function Price({ username ,isBDPro, isBDEmp }) { width="100%" maxWidth="1264px" flexDirection="column" + marginBottom="80px !important" margin="auto" spacing={0} > @@ -368,109 +476,7 @@ export default function Price({ username ,isBDPro, isBDEmp }) { Compare os planos - - setToggleAnual(!toggleAnual)} - /> - - Desconto anual - Economize 20% - - - - - Para você descobrir o potencial da plataforma de dados} - price={"0"} - textResource="Recursos:" - resources={[ - {name: "Tabelas tratadas"}, - {name: "Dados integrados", tooltip: "Nossa metodologia de padronização e compatibilização de dados permite que você cruze tabelas de diferentes instituições e temas de maneira simplificada."}, - {name: "Acesso em nuvem"}, - {name: "Acesso via SQL, Python e R"}, - {name: "Integração com ferramentas BI"}, - {name: "Download direto até 100 MB", tooltip: "Esse limite não se aplica ao acesso via SQL, Python e R."}, - ]} - button={{ - text: "Explorar recursos", - href: "/dataset", - }} - /> - - Para você ter acesso aos
dados mais atualizados} - price={plans?.[`bd_pro_${toggleAnual ? "year" : "month"}`].amount || 47} - anualPlan={toggleAnual} - textResource="Todos os recursos da BD Grátis, mais:" - resources={[ - {name: "Dezenas de bases de alta frequência atualizadas"}, - {name: "Download direto até 1GB (80% das tabelas da plataforma)", tooltip: "Tabelas maiores que 5 GB não estão disponíveis para download parcial ou completo. Esse limite não se aplica ao acesso via SQL, Python e R."} - ]} - button={{ - text: isBDPro ? "Plano atual" : `Iniciar teste grátis`, - href: username === null ? `/user/login?q=pro&i=${plans?.[`bd_pro_${toggleAnual ? "year" : "month"}`]._id}` :`/user/${username}?plans_and_payment&q=pro&i=${plans?.[`bd_pro_${toggleAnual ? "year" : "month"}`]._id}`, - isCurrentPlan: isBDPro, - }} - /> - - Para sua empresa ganhar tempo
e qualidade em decisões} - price={plans?.[`bd_empresas_${toggleAnual ? "year" : "month"}`].amount || 350} - anualPlan={toggleAnual} - textResource="Todos os recursos da BD Pro, mais:" - resources={[ - {name: "Acesso para 10 contas"}, - {name: "Suporte prioritário via email e Discord"} - ]} - button={{ - text: isBDEmp ? "Plano atual" : "Iniciar teste grátis", - href: username === null ? `/user/login?q=empresas&i=${plans?.[`bd_empresas_${toggleAnual ? "year" : "month"}`]._id}` :`/user/${username}?plans_and_payment&q=empresas&i=${plans?.[`bd_empresas_${toggleAnual ? "year" : "month"}`]._id}`, - isCurrentPlan: isBDEmp, - }} - /> -
+
) diff --git a/next/pages/servicos.js b/next/pages/servicos.js index ed7c6aab..5cdba911 100644 --- a/next/pages/servicos.js +++ b/next/pages/servicos.js @@ -2,7 +2,6 @@ import { Stack, VStack, Image, - Text, Box, Skeleton } from "@chakra-ui/react"; diff --git a/next/pages/transparencia.js b/next/pages/transparencia.js index 636af6bb..cda9011e 100644 --- a/next/pages/transparencia.js +++ b/next/pages/transparencia.js @@ -298,6 +298,25 @@ export default function Transparencia({ pages }) { + + + BD Relatório Anual 2023 + + + { isCentered={isMobileMod() ? false : true} > - + Compare os planos - + + + { justifyContent="center" alignitems="center" gap="8px" - margin="20px 0 24px !important" > { >Economize 20% - - - Para você descobrir o potencial da plataforma de dados} - price={"0"} - textResource="Recursos:" - resources={[ - {name: "Tabelas tratadas"}, - {name: "Dados integrados", tooltip: "Nossa metodologia de padronização e compatibilização de dados permite que você cruze tabelas de diferentes instituições e temas de maneira simplificada."}, - {name: "Acesso em nuvem"}, - {name: "Acesso via SQL, Python e R"}, - {name: "Integração com ferramentas BI"}, - {name: "Download direto até 100 MB", tooltip: "Esse limite não se aplica ao acesso via SQL, Python e R."}, - ]} - button={{ - text: "Explorar recursos", - href: "/dataset", - noHasModal: true, - }} - /> + + Para você descobrir o potencial da plataforma de dados} + price={"0"} + textResource="Recursos:" + resources={[ + {name: "Tabelas tratadas"}, + {name: "Dados integrados", tooltip: "Nossa metodologia de padronização e compatibilização de dados permite que você cruze tabelas de diferentes instituições e temas de maneira simplificada."}, + {name: "Acesso em nuvem"}, + {name: "Acesso via SQL, Python e R"}, + {name: "Integração com ferramentas BI"}, + {name: "Download direto até 100 MB", tooltip: "Esse limite não se aplica ao acesso via SQL, Python e R."}, + ]} + button={{ + text: "Explorar recursos", + href: "/dataset", + noHasModal: true, + }} + /> - Para você ter acesso aos
dados mais atualizados} - price={plans?.[`bd_pro_${toggleAnual ? "year" : "month"}`].amount || 47} - anualPlan={toggleAnual} - textResource="Todos os recursos da BD Grátis, mais:" - resources={[ - {name: "Dezenas de bases de alta frequência atualizadas"}, - {name: "Download direto até 1GB (80% das tabelas da plataforma)", tooltip: "Tabelas maiores que 5 GB não estão disponíveis para download parcial ou completo. Esse limite não se aplica ao acesso via SQL, Python e R."} - ]} - button={{ - text: `${userData?.proSubscription === "bd_pro" ? "Plano atual" : "Assinar"}`, - onClick: userData?.proSubscription === "bd_pro" ? () => {} : () => { - setPlan({id: plans?.[`bd_pro_${toggleAnual ? "year" : "month"}`]._id}) - PlansModal.onClose() - PaymentModal.onOpen() - }, - isCurrentPlan: userData?.proSubscription === "bd_pro" ? true : false, - }} - /> + Para você ter acesso aos
dados mais atualizados} + price={plans?.[`bd_pro_${toggleAnual ? "year" : "month"}`].amount || 47} + anualPlan={toggleAnual} + textResource="Todos os recursos da BD Grátis, mais:" + resources={[ + {name: "Dezenas de bases de alta frequência atualizadas"}, + {name: "Download direto até 1GB (80% das tabelas da plataforma)", tooltip: "Tabelas maiores que 1 GB não estão disponíveis para download parcial ou completo. Esse limite não se aplica ao acesso via SQL, Python e R."} + ]} + button={{ + text: `${userData?.proSubscription === "bd_pro" ? "Plano atual" : "Assinar"}`, + onClick: userData?.proSubscription === "bd_pro" ? () => {} : () => { + setPlan({id: plans?.[`bd_pro_${toggleAnual ? "year" : "month"}`]._id}) + PlansModal.onClose() + PaymentModal.onOpen() + }, + isCurrentPlan: userData?.proSubscription === "bd_pro" ? true : false, + }} + /> - Para sua empresa ganhar tempo
e qualidade em decisões} - price={plans?.[`bd_empresas_${toggleAnual ? "year" : "month"}`].amount || 350} - anualPlan={toggleAnual} - textResource="Todos os recursos da BD Pro, mais:" - resources={[ - {name: "Acesso para 10 contas"}, - {name: "Suporte prioritário via email e Discord"} - ]} - button={{ - text: `${userData?.proSubscription === "bd_pro_empresas" ? "Plano atual" : "Assinar"}`, - onClick: userData?.proSubscription === "bd_pro_empresas" ? () => {} : () => { - setPlan({id: plans?.[`bd_empresas_${toggleAnual ? "year" : "month"}`]._id}) - PlansModal.onClose() - PaymentModal.onOpen() - }, - isCurrentPlan: userData?.proSubscription === "bd_pro_empresas" ? true : false, - }} - /> -
+ Para sua empresa ganhar tempo
e qualidade em decisões} + price={plans?.[`bd_empresas_${toggleAnual ? "year" : "month"}`].amount || 350} + anualPlan={toggleAnual} + textResource="Todos os recursos da BD Pro, mais:" + resources={[ + {name: "Acesso para 10 contas"}, + {name: "Suporte prioritário via email e Discord"} + ]} + button={{ + text: `${userData?.proSubscription === "bd_pro_empresas" ? "Plano atual" : "Assinar"}`, + onClick: userData?.proSubscription === "bd_pro_empresas" ? () => {} : () => { + setPlan({id: plans?.[`bd_empresas_${toggleAnual ? "year" : "month"}`]._id}) + PlansModal.onClose() + PaymentModal.onOpen() + }, + isCurrentPlan: userData?.proSubscription === "bd_pro_empresas" ? true : false, + }} + /> +
+ Date: Fri, 16 Aug 2024 17:56:41 -0300 Subject: [PATCH 15/27] feat: added new fields to post-registration questions --- next/pages/api/user/getUser.js | 1 + next/pages/api/user/updateProfileSurvey.js | 18 +- next/pages/user/login.js | 2 +- next/pages/user/survey.js | 208 +++++++++++++++------ 4 files changed, 168 insertions(+), 61 deletions(-) diff --git a/next/pages/api/user/getUser.js b/next/pages/api/user/getUser.js index 01e63fc0..a89fb0e1 100644 --- a/next/pages/api/user/getUser.js +++ b/next/pages/api/user/getUser.js @@ -33,6 +33,7 @@ async function getUser(id, token) { proSubscriptionRole proSubscriptionSlots proSubscriptionStatus + workDataTool availableForResearch } } diff --git a/next/pages/api/user/updateProfileSurvey.js b/next/pages/api/user/updateProfileSurvey.js index 3a74b8d9..268e4972 100644 --- a/next/pages/api/user/updateProfileSurvey.js +++ b/next/pages/api/user/updateProfileSurvey.js @@ -6,6 +6,10 @@ async function updateProfileSurvey({ id, workArea, workRole, + workSize, + workDataTool, + workGoal, + discoveryMethod, availableForResearch }, token, skip ) { @@ -18,6 +22,10 @@ async function updateProfileSurvey({ availableForResearch: "NO" workArea: null workRole: null + workSize: null + workDataTool: "NONE" + workGoal: null + discoveryMethod: null } ) { @@ -35,6 +43,10 @@ async function updateProfileSurvey({ id: "${id}" workArea: "${workArea}" workRole: "${workRole}" + workSize: "${workSize}" + workDataTool: "${workDataTool}" + workGoal: "${workGoal}" + discoveryMethod: "${discoveryMethod}" availableForResearch: "${availableForResearch}" } ) @@ -69,12 +81,16 @@ async function updateProfileSurvey({ export default async function handler(req, res) { const token = req.cookies.token - const { p, f, l, e, s} = req.query + const { p, f, l, i, t, g, d, e, s} = req.query const object = { id:atob(p), workArea:atob(f), workRole:atob(l), + workSize:atob(i), + workDataTool:atob(t), + workGoal:atob(g), + discoveryMethod:atob(d), availableForResearch:atob(e), } diff --git a/next/pages/user/login.js b/next/pages/user/login.js index 7040e4d7..a6c30d19 100644 --- a/next/pages/user/login.js +++ b/next/pages/user/login.js @@ -85,7 +85,7 @@ export default function Login() { return window.open(`/user/${userData.username}?plans_and_payment&q=${query.q}&i=${query.i}`, "_self") } - if(userData.availableForResearch === null) return window.open("/user/survey", "_self") + if(userData.workDataTool === null) return window.open("/user/survey", "_self") return window.open("/", "_self") } diff --git a/next/pages/user/survey.js b/next/pages/user/survey.js index 11aa98c4..fb2e9b0d 100644 --- a/next/pages/user/survey.js +++ b/next/pages/user/survey.js @@ -5,7 +5,7 @@ import { Progress, Spinner } from "@chakra-ui/react"; -import { useState } from "react"; +import { useState, useCallback } from "react"; import cookies from 'js-cookie'; import Button from "../../components/atoms/Button"; @@ -23,21 +23,32 @@ export async function getStaticProps() { export default function Survey() { const [err, setErr] = useState("") const [index, setIndex] = useState(0) - const [stageOne, setStageOne] = useState([]) - const [stageTwo, setStageTwo] = useState([]) - const [stageThree, setStageThree] = useState([]) + const [stages, setStages] = useState(Array(7).fill([])) const [isLoading, setIsLoading] = useState(false) async function fetchUpdateProfileSurvey(skip) { setIsLoading(true) - const id = JSON.parse(cookies.get("userBD")).id.replace(new RegExp('\\bAccountNode:\\b', 'gi'), '') - const result = await fetch(`/api/user/updateProfileSurvey?p=${btoa(id)}&f=${btoa(stageOne[0] || "")}&l=${btoa(stageTwo[0] || "")}&e=${btoa(stageThree[0] || "")}&s=${skip}`, { method: "GET" }) + const id = JSON.parse(cookies.get("userBD")).id.replace(/\bAccountNode:\b/g, '') + const params = { + p: btoa(id), + f: btoa(stages[0][0] || ""), + l: btoa(stages[1][0] || ""), + i: btoa(stages[2][0] || ""), + t: btoa(stages[3][0] || ""), + g: btoa(stages[4][0] || ""), + d: btoa(stages[5][0] || ""), + e: btoa(stages[6][0] || ""), + s: skip + } + + const queryString = new URLSearchParams(params).toString() + const result = await fetch(`/api/user/updateProfileSurvey?${queryString}`, { method: "GET" }) .then(res => res.json()) if(result.errors.length > 0) { setErr("Ocorreu um erro interno no servidor. Por favor, tente novamente mais tarde.") console.error(result.errors) - setIsLoading(false) + return setIsLoading(false) } const userData = await fetch(`/api/user/getUser?p=${btoa(id)}`, { method: "GET" }) @@ -60,13 +71,14 @@ export default function Survey() { ["Jornalismo", "JORNALISMO"], ["Outra", "OUTRA"] ], - buttons: [{ text: "Pular", style: "clean",function: async () => fetchUpdateProfileSurvey("true")}, - {text: "Continuar", function: () => { - if(stageOne.length === 0) return setErr("Por favor, selecione uma das opções abaixo.") - setErr("") - setIndex(1) - }}], - stage: setStageOne + buttons: [ + {text: "Pular", style: "clean",function: async () => fetchUpdateProfileSurvey("true")}, + {text: "Continuar", function: () => { + if(stages[0].length === 0) return setErr("Por favor, selecione uma das opções abaixo.") + setErr("") + setIndex(1) + }} + ], }, { question: "Qual o seu cargo?", @@ -85,45 +97,118 @@ export default function Survey() { ["Empreendedor(a)", "EMPREENDEDOR"], ["Outro", "OUTRO"] ], - buttons: [{text: "Voltar", function: () => setIndex(0), style: "clean"}, {text: "Continuar", function: () => { - if(stageTwo.length === 0) return setErr("Por favor, selecione uma das opções abaixo.") - setErr("") - setIndex(2) - }}], - stage: setStageTwo + buttons: [ + {text: "Voltar", function: () => setIndex(0), style: "clean"}, + {text: "Continuar", function: () => { + if(stages[1].length === 0) return setErr("Por favor, selecione uma das opções abaixo.") + setErr("") + setIndex(2) + }} + ] + }, + { + question: "Qual o tamanho da empresa em que você trabalha?", + options: [ + ["1-10 funcionários", "PEQUENA_1_10"], + ["11-50 funcionários", "PEQUENA_11_50"], + ["51-200 funcionários", "MEDIA_51_200"], + ["201-500 funcionários", "MEDIA_201_500"], + ["Mais de 500 funcionários", "GRANDE_MAIS_500"], + ], + buttons: [ + {text: "Voltar", function: () => setIndex(1), style: "clean"}, + {text: "Continuar", function: () => { + if(stages[2].length === 0) return setErr("Por favor, selecione uma das opções abaixo.") + setErr("") + setIndex(3) + }} + ] + }, + { + question: "Qual a principal ferramenta que você utiliza para realizar análises de dados?", + options: [ + ["SQL", "SQL"], + ["Python", "PYTHON"], + ["R", "R"], + ["Stata", "STATA"], + ["Excel", "EXCEL"], + ["Nenhuma", "NONE"], + ["Outra", "OTHER"], + ], + buttons: [ + {text: "Voltar", function: () => setIndex(2), style: "clean"}, + {text: "Continuar", function: () => { + if(stages[3].length === 0) return setErr("Por favor, selecione uma das opções abaixo.") + setErr("") + setIndex(4) + }} + ] + }, + { + question: "Qual o seu principal objetivo com a BD?", + options: [ + ["Análise de mercado", "MARKET_ANALYSIS"], + ["Monitoramento de concorrência", "COMPETITOR_MONITORING"], + ["Pesquisa acadêmica", "ACADEMIC_RESEARCH"], + ["Gestão de riscos", "RISK_MANAGEMENT"], + ["Desenvolvimento de produto", "PRODUCT_DEVELOPMENT"], + ["Compliance e regulatório", "COMPLIANCE_REGULATORY"], + ["Análise de políticas públicas", "PUBLIC_POLICY_ANALYSIS"], + ["Outro", "OTHER"], + ], + buttons: [ + {text: "Voltar", function: () => setIndex(3), style: "clean"}, + {text: "Continuar", function: () => { + if(stages[4].length === 0) return setErr("Por favor, selecione uma das opções abaixo.") + setErr("") + setIndex(5) + }} + ] + }, + { + question: "Como você conheceu a BD?", + options: [ + ["Redes sociais", "SOCIAL_MEDIA"], + ["Indicação", "REFERRAL"], + ["Pesquisa online", "ONLINE_SEARCH"], + ["Eventos", "EVENTS"], + ["Publicidade", "ADVERTISING"], + ["Outros", "OTHER"], + ], + buttons: [ + {text: "Voltar", function: () => setIndex(4), style: "clean"}, + {text: "Continuar", function: () => { + if(stages[5].length === 0) return setErr("Por favor, selecione uma das opções abaixo.") + setErr("") + setIndex(6) + }} + ] }, { question: "Estamos sempre buscando aprimorar a plataforma e consideramos fundamental ouvir a nossa comunidade nesse processo. Podemos contatar você para futuras pesquisas?", options: [["Sim", "YES"], ["Não", "NO"]], - buttons: [{text: "Voltar", function: () => setIndex(1), style: "clean"}, {text: "Enviar", function: () => { - if(stageThree.length === 0) return setErr("Por favor, selecione uma das opções abaixo.") + buttons: [{text: "Voltar", function: () => setIndex(5), style: "clean"}, {text: "Enviar", function: () => { + if(stages[6].length === 0) return setErr("Por favor, selecione uma das opções abaixo.") setErr("") fetchUpdateProfileSurvey("false") - }}], - stage: setStageThree + }}] } ] - const selectedValueStage = (elm) => { - if(index === 0) return stageOne.includes(elm) - if(index === 1) return stageTwo.includes(elm) - if(index === 2) return stageThree.includes(elm) - } + const handleSelected = useCallback((value, stageIndex) => { + setStages((prevStages) => prevStages.map((stage, i) => + i === stageIndex ? (stage.includes(value) ? [] : [value]) : stage + )) + }, []) - const progressValue = () => { - const value = [20, 60, 100] - return value[index] - } + const selectedValueStage = useCallback((value, stageIndex) => { + return stages[stageIndex].includes(value) + }, [stages]) - function handleSelected(value, setStage) { - setStage((stage) => { - if (stage.includes(value)) { - return [] - } else { - return [value] - } - }) - } + const progressValue = useCallback(() => { + const values = [15, 30, 45, 60, 75, 90, 100] + return values[index] + }, [index]) return ( {question[index].question} + > + {question[index].question} + - {err} + {err && ( + + {err} + + )} handleSelected(elm[1], question[index].stage)} + onClick={() => handleSelected(elm[1], index)} pointerEvents={isLoading ? "none" : "default"} borderRadius="16px" cursor="pointer" - border={selectedValueStage(elm[1]) ? "2px solid #42B0FF" : "1px solid #DEDFE0"} - backgroundColor={selectedValueStage(elm[1]) ? "#CFEBFE" : "#FFF"} + border={selectedValueStage(elm[1], index) ? "2px solid #42B0FF" : "1px solid #DEDFE0"} + backgroundColor={selectedValueStage(elm[1], index) ? "#CFEBFE" : "#FFF"} width="fit-content" - padding={selectedValueStage(elm[1]) ? "11px" : "12px"} + padding={selectedValueStage(elm[1], index) ? "11px" : "12px"} fontFamily="Roboto" fontWeight="500" fontSize="18px" @@ -231,7 +321,7 @@ export default function Survey() { backgroundColor: elm.style ? "" : "#0B89E2" }} > - {isLoading ? elm.text === "Pular" || elm.text === "Enviar" ? : elm.text : elm.text} + {isLoading ? (elm.text === "Pular" || elm.text === "Enviar") ? : elm.text : elm.text} )} From 0dc00c66a1bfa243c462d6d089dfb87ea446025e Mon Sep 17 00:00:00 2001 From: Jhony Lucas Date: Sat, 17 Aug 2024 00:42:20 -0300 Subject: [PATCH 16/27] chore: Import secrets from HashiCorp Vault in release workflows --- .github/workflows/release-dev.yaml | 13 +++++++++++++ .github/workflows/release-prod.yaml | 12 ++++++++++++ .github/workflows/release-staging.yaml | 12 ++++++++++++ next/Dockerfile | 7 +++++++ 4 files changed, 44 insertions(+) diff --git a/.github/workflows/release-dev.yaml b/.github/workflows/release-dev.yaml index d5eb20b5..d010a9fc 100644 --- a/.github/workflows/release-dev.yaml +++ b/.github/workflows/release-dev.yaml @@ -36,6 +36,16 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} + - name: Import Secrets + id: import_secrets + uses: hashicorp/vault-action@v2.4.1 + with: + url: https://vault.basedosdados.org + token: ${{ secrets.VAULT_TOKEN }} + secrets: | + secret/data/url_download_data URL_DOWNLOAD_CLOSED | URL_DOWNLOAD_CLOSED ; + secret/data/url_download_data URL_DOWNLOAD_OPEN | URL_DOWNLOAD_OPEN ; + - name: Build and push uses: docker/build-push-action@v3 with: @@ -48,3 +58,6 @@ jobs: NEXT_PUBLIC_SITE_NAME=${{ env.NEXT_PUBLIC_SITE_NAME }} NEXT_PUBLIC_KEY_STRIPE=${{ env.NEXT_PUBLIC_KEY_STRIPE }} NEXT_PUBLIC_BASE_URL_FRONTEND=${{ env.NEXT_PUBLIC_BASE_URL_FRONTEND }} + URL_DOWNLOAD_CLOSED=${{ steps.import_secrets.outputs.URL_DOWNLOAD_CLOSED }} + URL_DOWNLOAD_OPEN=${{ steps.import_secrets.outputs.URL_DOWNLOAD_OPEN }} + diff --git a/.github/workflows/release-prod.yaml b/.github/workflows/release-prod.yaml index 6b8c23c9..d34d74d9 100644 --- a/.github/workflows/release-prod.yaml +++ b/.github/workflows/release-prod.yaml @@ -36,6 +36,16 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} + - name: Import Secrets + id: import_secrets + uses: hashicorp/vault-action@v2.4.1 + with: + url: https://vault.basedosdados.org + token: ${{ secrets.VAULT_TOKEN }} + secrets: | + secret/data/url_download_data URL_DOWNLOAD_CLOSED | URL_DOWNLOAD_CLOSED ; + secret/data/url_download_data URL_DOWNLOAD_OPEN | URL_DOWNLOAD_OPEN ; + - name: Build and push uses: docker/build-push-action@v3 with: @@ -48,3 +58,5 @@ jobs: NEXT_PUBLIC_SITE_NAME=${{ env.NEXT_PUBLIC_SITE_NAME }} NEXT_PUBLIC_KEY_STRIPE=${{ env.NEXT_PUBLIC_KEY_STRIPE }} NEXT_PUBLIC_BASE_URL_FRONTEND=${{ env.NEXT_PUBLIC_BASE_URL_FRONTEND }} + URL_DOWNLOAD_CLOSED=${{ steps.import_secrets.outputs.URL_DOWNLOAD_CLOSED }} + URL_DOWNLOAD_OPEN=${{ steps.import_secrets.outputs.URL_DOWNLOAD_OPEN }} diff --git a/.github/workflows/release-staging.yaml b/.github/workflows/release-staging.yaml index b8796fc3..762c079b 100644 --- a/.github/workflows/release-staging.yaml +++ b/.github/workflows/release-staging.yaml @@ -36,6 +36,16 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} + - name: Import Secrets + id: import_secrets + uses: hashicorp/vault-action@v2.4.1 + with: + url: https://vault.basedosdados.org + token: ${{ secrets.VAULT_TOKEN }} + secrets: | + secret/data/url_download_data URL_DOWNLOAD_CLOSED | URL_DOWNLOAD_CLOSED ; + secret/data/url_download_data URL_DOWNLOAD_OPEN | URL_DOWNLOAD_OPEN ; + - name: Build and push uses: docker/build-push-action@v3 with: @@ -48,3 +58,5 @@ jobs: NEXT_PUBLIC_SITE_NAME=${{ env.NEXT_PUBLIC_SITE_NAME }} NEXT_PUBLIC_KEY_STRIPE=${{ env.NEXT_PUBLIC_KEY_STRIPE }} NEXT_PUBLIC_BASE_URL_FRONTEND=${{ env.NEXT_PUBLIC_BASE_URL_FRONTEND }} + URL_DOWNLOAD_CLOSED=${{ steps.import_secrets.outputs.URL_DOWNLOAD_CLOSED }} + URL_DOWNLOAD_OPEN=${{ steps.import_secrets.outputs.URL_DOWNLOAD_OPEN }} diff --git a/next/Dockerfile b/next/Dockerfile index 5b4c8378..28631011 100644 --- a/next/Dockerfile +++ b/next/Dockerfile @@ -14,12 +14,19 @@ RUN \ # Rebuild the source code only when needed FROM node:18.17.0-alpine AS builder + ARG NEXT_PUBLIC_API_URL ARG NEXT_PUBLIC_KEY_STRIPE ARG NEXT_PUBLIC_BASE_URL_FRONTEND +ARG URL_DOWNLOAD_CLOSED +ARG URL_DOWNLOAD_OPEN + ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL ENV NEXT_PUBLIC_KEY_STRIPE=$NEXT_PUBLIC_KEY_STRIPE ENV NEXT_PUBLIC_BASE_URL_FRONTEND=$NEXT_PUBLIC_BASE_URL_FRONTEND +ENV URL_DOWNLOAD_CLOSED=$URL_DOWNLOAD_CLOSED +ENV URL_DOWNLOAD_OPEN=$URL_DOWNLOAD_OPEN + WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . From e5d66c69ec4924262b503b766d64a853e64d5f09 Mon Sep 17 00:00:00 2001 From: aldemirLucas Date: Sat, 17 Aug 2024 01:13:55 -0300 Subject: [PATCH 17/27] chore: adjusted the name of the ENVs for table downloads --- next/pages/api/tables/downloadTable.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/next/pages/api/tables/downloadTable.js b/next/pages/api/tables/downloadTable.js index 027e10c2..ff676e55 100644 --- a/next/pages/api/tables/downloadTable.js +++ b/next/pages/api/tables/downloadTable.js @@ -24,8 +24,8 @@ async function downloadTable(url, datasetID, tableId, token, res) { try { const fileUrl = url === "free" - ? `${process.env.URL_DOWNLOAD_TABLE}/${datasetID}/${tableId}/${tableId}.csv.gz` - : payloadToken?.pro_subscription_status === "active" ? `${process.env.URL_DOWNLOAD_PRIVATE_TABLE}/${datasetID}/${tableId}/${tableId}_bdpro.csv.gz` : "" + ? `${process.env.URL_DOWNLOAD_OPEN}/${datasetID}/${tableId}/${tableId}.csv.gz` + : payloadToken?.pro_subscription_status === "active" ? `${process.env.URL_DOWNLOAD_CLOSED}/${datasetID}/${tableId}/${tableId}_bdpro.csv.gz` : "" const response = await axios({ url: fileUrl, From 087f48ba627f1e382eb98b3c2f3acce77d82b839 Mon Sep 17 00:00:00 2001 From: aldemirLucas Date: Sat, 17 Aug 2024 02:03:45 -0300 Subject: [PATCH 18/27] chore: ajust dockerfile from env's download --- next/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/next/Dockerfile b/next/Dockerfile index 28631011..4d4e2233 100644 --- a/next/Dockerfile +++ b/next/Dockerfile @@ -24,8 +24,6 @@ ARG URL_DOWNLOAD_OPEN ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL ENV NEXT_PUBLIC_KEY_STRIPE=$NEXT_PUBLIC_KEY_STRIPE ENV NEXT_PUBLIC_BASE_URL_FRONTEND=$NEXT_PUBLIC_BASE_URL_FRONTEND -ENV URL_DOWNLOAD_CLOSED=$URL_DOWNLOAD_CLOSED -ENV URL_DOWNLOAD_OPEN=$URL_DOWNLOAD_OPEN WORKDIR /app COPY --from=deps /app/node_modules ./node_modules @@ -44,6 +42,8 @@ WORKDIR /app ENV NODE_ENV production ENV NODE_OPTIONS '-r next-logger' +ENV URL_DOWNLOAD_CLOSED=$URL_DOWNLOAD_CLOSED +ENV URL_DOWNLOAD_OPEN=$URL_DOWNLOAD_OPEN # Uncomment the following line in case you want to disable telemetry during runtime. # ENV NEXT_TELEMETRY_DISABLED 1 From b4f0032358b6478ba2b39e84d011477e8baa5596 Mon Sep 17 00:00:00 2001 From: Jhony Lucas Date: Mon, 19 Aug 2024 10:43:23 -0300 Subject: [PATCH 19/27] chore: Update Dockerfile with new environment variables for download URLs --- next/Dockerfile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/next/Dockerfile b/next/Dockerfile index 4d4e2233..21a34e24 100644 --- a/next/Dockerfile +++ b/next/Dockerfile @@ -12,6 +12,9 @@ RUN \ else echo "Lockfile not found." && exit 1; \ fi +ARG URL_DOWNLOAD_CLOSED +ARG URL_DOWNLOAD_OPEN + # Rebuild the source code only when needed FROM node:18.17.0-alpine AS builder @@ -40,6 +43,9 @@ RUN npm run build FROM node:18.17.0-alpine AS runner WORKDIR /app +ARG URL_DOWNLOAD_CLOSED +ARG URL_DOWNLOAD_OPEN + ENV NODE_ENV production ENV NODE_OPTIONS '-r next-logger' ENV URL_DOWNLOAD_CLOSED=$URL_DOWNLOAD_CLOSED From 78b63e09a03d4b2db40449f87fd3d3dd1ebbdd38 Mon Sep 17 00:00:00 2001 From: aldemirLucas Date: Mon, 19 Aug 2024 11:06:48 -0300 Subject: [PATCH 20/27] fix: fix / in url download --- next/pages/api/tables/downloadTable.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/next/pages/api/tables/downloadTable.js b/next/pages/api/tables/downloadTable.js index ff676e55..efec1f93 100644 --- a/next/pages/api/tables/downloadTable.js +++ b/next/pages/api/tables/downloadTable.js @@ -24,8 +24,8 @@ async function downloadTable(url, datasetID, tableId, token, res) { try { const fileUrl = url === "free" - ? `${process.env.URL_DOWNLOAD_OPEN}/${datasetID}/${tableId}/${tableId}.csv.gz` - : payloadToken?.pro_subscription_status === "active" ? `${process.env.URL_DOWNLOAD_CLOSED}/${datasetID}/${tableId}/${tableId}_bdpro.csv.gz` : "" + ? `${process.env.URL_DOWNLOAD_OPEN}${datasetID}/${tableId}/${tableId}.csv.gz` + : payloadToken?.pro_subscription_status === "active" ? `${process.env.URL_DOWNLOAD_CLOSED}${datasetID}/${tableId}/${tableId}_bdpro.csv.gz` : "" const response = await axios({ url: fileUrl, From cc918187f5e1f772c5210694ab53956215f1c151 Mon Sep 17 00:00:00 2001 From: aldemirLucas Date: Mon, 19 Aug 2024 11:19:06 -0300 Subject: [PATCH 21/27] fix: ajust url from download --- next/pages/api/tables/downloadTable.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/next/pages/api/tables/downloadTable.js b/next/pages/api/tables/downloadTable.js index efec1f93..00ea80db 100644 --- a/next/pages/api/tables/downloadTable.js +++ b/next/pages/api/tables/downloadTable.js @@ -22,10 +22,19 @@ async function downloadTable(url, datasetID, tableId, token, res) { let payloadToken if(url !== "free" && token !== null) payloadToken = await validateToken(token) + const urlDownloadOpen = process.env.URL_DOWNLOAD_OPEN.replace("gs://", "") + const urlDownloadClosed = process.env.URL_DOWNLOAD_CLOSED.replace("gs://", "") + + const prefixUrl = "https://storage.googleapis.com/" + try { - const fileUrl = url === "free" - ? `${process.env.URL_DOWNLOAD_OPEN}${datasetID}/${tableId}/${tableId}.csv.gz` - : payloadToken?.pro_subscription_status === "active" ? `${process.env.URL_DOWNLOAD_CLOSED}${datasetID}/${tableId}/${tableId}_bdpro.csv.gz` : "" + let fileUrl = "" + + if(url === "free") { + fileUrl =`${prefixUrl}${urlDownloadOpen}${datasetID}/${tableId}/${tableId}.csv.gz` + }else if(payloadToken?.pro_subscription_status === "active") { + fileUrl = `${prefixUrl}${urlDownloadClosed}${datasetID}/${tableId}/${tableId}_bdpro.csv.gz` + } const response = await axios({ url: fileUrl, From ebaa7d21fdba34c36bac8660dd9019f38307f2d3 Mon Sep 17 00:00:00 2001 From: aldemirLucas Date: Mon, 19 Aug 2024 12:06:47 -0300 Subject: [PATCH 22/27] fix: verify payloadToken in download --- next/pages/api/tables/downloadTable.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/next/pages/api/tables/downloadTable.js b/next/pages/api/tables/downloadTable.js index 00ea80db..40b6d384 100644 --- a/next/pages/api/tables/downloadTable.js +++ b/next/pages/api/tables/downloadTable.js @@ -20,7 +20,9 @@ async function validateToken(token) { async function downloadTable(url, datasetID, tableId, token, res) { let payloadToken - if(url !== "free" && token !== null) payloadToken = await validateToken(token) + if(url !== "free") { + if(token !== null) payloadToken = await validateToken(token) + } const urlDownloadOpen = process.env.URL_DOWNLOAD_OPEN.replace("gs://", "") const urlDownloadClosed = process.env.URL_DOWNLOAD_CLOSED.replace("gs://", "") From 610cf7727e389b79fbceb1412e9354a5c3581951 Mon Sep 17 00:00:00 2001 From: aldemirLucas Date: Tue, 20 Aug 2024 12:07:51 -0300 Subject: [PATCH 23/27] fix: logic download table bdpro --- next/components/molecules/DataInformationQuery.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/next/components/molecules/DataInformationQuery.js b/next/components/molecules/DataInformationQuery.js index 74aefb63..4f19cfb7 100644 --- a/next/components/molecules/DataInformationQuery.js +++ b/next/components/molecules/DataInformationQuery.js @@ -598,10 +598,10 @@ export default function DataInformationQuery({ resource }) { { - if(downloadWarning === "100mbBetween1gb") return plansModal.onOpen() + if(downloadWarning !== "free" && isUserPro() === false) return plansModal.onOpen() + window.open(`/api/tables/downloadTable?p=${btoa(gcpDatasetID)}&q=${btoa(gcpTableId)}&d=${btoa(downloadPermitted)}&s=${btoa(downloadWarning)}`, "_blank") triggerGAEvent("download_da_tabela",`{ gcp: ${gcpProjectID+"."+gcpDatasetID+"."+gcpTableId}, tamanho: ${formatBytes(resource.uncompressedFileSize) || ""}, From e6d03e01042327d24bd023f6bcbe91250476a055 Mon Sep 17 00:00:00 2001 From: aldemirLucas Date: Tue, 20 Aug 2024 15:30:04 -0300 Subject: [PATCH 24/27] fix: download pro url --- next/pages/api/tables/downloadTable.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/next/pages/api/tables/downloadTable.js b/next/pages/api/tables/downloadTable.js index 40b6d384..35c31288 100644 --- a/next/pages/api/tables/downloadTable.js +++ b/next/pages/api/tables/downloadTable.js @@ -20,9 +20,7 @@ async function validateToken(token) { async function downloadTable(url, datasetID, tableId, token, res) { let payloadToken - if(url !== "free") { - if(token !== null) payloadToken = await validateToken(token) - } + if(token !== null) payloadToken = await validateToken(token) const urlDownloadOpen = process.env.URL_DOWNLOAD_OPEN.replace("gs://", "") const urlDownloadClosed = process.env.URL_DOWNLOAD_CLOSED.replace("gs://", "") @@ -32,10 +30,10 @@ async function downloadTable(url, datasetID, tableId, token, res) { try { let fileUrl = "" - if(url === "free") { - fileUrl =`${prefixUrl}${urlDownloadOpen}${datasetID}/${tableId}/${tableId}.csv.gz` - }else if(payloadToken?.pro_subscription_status === "active") { + if(payloadToken?.pro_subscription_status === "active") { fileUrl = `${prefixUrl}${urlDownloadClosed}${datasetID}/${tableId}/${tableId}_bdpro.csv.gz` + }else if(url === "free") { + fileUrl =`${prefixUrl}${urlDownloadOpen}${datasetID}/${tableId}/${tableId}.csv.gz` } const response = await axios({ From 0dba9f2f0669270f5af10f88b090204e7ff4c4d6 Mon Sep 17 00:00:00 2001 From: aldemirLucas Date: Tue, 20 Aug 2024 16:24:25 -0300 Subject: [PATCH 25/27] fix: pro download --- next/pages/api/tables/downloadTable.js | 31 ++++++++++++++++++-------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/next/pages/api/tables/downloadTable.js b/next/pages/api/tables/downloadTable.js index 35c31288..894f6ed0 100644 --- a/next/pages/api/tables/downloadTable.js +++ b/next/pages/api/tables/downloadTable.js @@ -27,15 +27,15 @@ async function downloadTable(url, datasetID, tableId, token, res) { const prefixUrl = "https://storage.googleapis.com/" - try { - let fileUrl = "" + let fileUrl = "" - if(payloadToken?.pro_subscription_status === "active") { - fileUrl = `${prefixUrl}${urlDownloadClosed}${datasetID}/${tableId}/${tableId}_bdpro.csv.gz` - }else if(url === "free") { - fileUrl =`${prefixUrl}${urlDownloadOpen}${datasetID}/${tableId}/${tableId}.csv.gz` - } + if(payloadToken?.pro_subscription_status === "active") { + fileUrl = `${prefixUrl}${urlDownloadClosed}${datasetID}/${tableId}/${tableId}_bdpro.csv.gz` + }else if(url === "free") { + fileUrl =`${prefixUrl}${urlDownloadOpen}${datasetID}/${tableId}/${tableId}.csv.gz` + } + try { const response = await axios({ url: fileUrl, method: 'GET', @@ -47,8 +47,21 @@ async function downloadTable(url, datasetID, tableId, token, res) { response.data.pipe(res) } catch (error) { - console.error(error) - res.status(500).json({ message: 'Error downloading the file' }) + try { + const response = await axios({ + url: `${prefixUrl}${urlDownloadOpen}${datasetID}/${tableId}/${tableId}.csv.gz`, + method: 'GET', + responseType: 'stream' + }) + + res.setHeader('Content-Disposition', `attachment; filename=${datasetID}_${tableId}.csv.gz`) + res.setHeader('Content-Type', 'application/gzip') + + response.data.pipe(res) + } catch (error) { + console.error(error) + res.status(500).json({ message: 'Error downloading the file' }) + } } } From 1deb828aa5037ceb5b1e2a1cdbbd591c2661c5f0 Mon Sep 17 00:00:00 2001 From: aldemirLucas Date: Tue, 20 Aug 2024 16:53:41 -0300 Subject: [PATCH 26/27] chore: remove anul plans --- next/pages/precos.js | 2 +- next/pages/user/[username].js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/next/pages/precos.js b/next/pages/precos.js index 9f9dbfd3..325e23e1 100644 --- a/next/pages/precos.js +++ b/next/pages/precos.js @@ -332,7 +332,7 @@ export function SectionPrice() { gridGap="40px" > { gridGap="40px" > Date: Tue, 20 Aug 2024 17:14:54 -0300 Subject: [PATCH 27/27] chore: code R ajust space --- next/components/molecules/DataInformationQuery.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/next/components/molecules/DataInformationQuery.js b/next/components/molecules/DataInformationQuery.js index 4f19cfb7..7fc633ea 100644 --- a/next/components/molecules/DataInformationQuery.js +++ b/next/components/molecules/DataInformationQuery.js @@ -910,8 +910,8 @@ bd.read_sql(query = query, billing_project_id = billing_id)`} isLoaded={!isLoadingCode} > {` - # Defina o seu projeto no Google Cloud - set_billing_id("") +# Defina o seu projeto no Google Cloud +set_billing_id("") # Para carregar o dado direto no R query <- "