diff --git a/next/components/atoms/Button.js b/next/components/atoms/Button.js
new file mode 100644
index 00000000..cef1264c
--- /dev/null
+++ b/next/components/atoms/Button.js
@@ -0,0 +1,33 @@
+import {
+ Box,
+} from "@chakra-ui/react";
+
+export default function Button({ children, onClick, ...props }) {
+ return (
+
+ {children}
+
+ )
+}
\ No newline at end of file
diff --git a/next/components/atoms/Checkbox.js b/next/components/atoms/Checkbox.js
new file mode 100644
index 00000000..0029ac25
--- /dev/null
+++ b/next/components/atoms/Checkbox.js
@@ -0,0 +1,59 @@
+import {
+ Checkbox,
+ Icon
+} from '@chakra-ui/react';
+
+function CustomCheckbockIcon({ variant, isIndeterminate, isChecked, ...props }) {
+ function variantIcon() {
+ if(isIndeterminate) return "M5.06135 11.0002C4.76599 11.0002 4.51496 10.9029 4.30826 10.7084C4.10157 10.514 3.99823 10.2778 3.99823 9.99984C3.99823 9.72193 4.10157 9.48573 4.30826 9.29124C4.51496 9.09676 4.76599 8.99951 5.06135 8.99951H14.9391C15.2344 8.99951 15.4855 9.09676 15.6922 9.29124C15.8988 9.48573 16.0022 9.72193 16.0022 9.99984C16.0022 10.2778 15.8988 10.514 15.6922 10.7084C15.4855 10.9029 15.2344 11.0002 14.9391 11.0002H5.06135Z"
+ return "M7.17894 10.9259L13.306 4.7988C13.5043 4.60057 13.7378 4.50146 14.0068 4.50146C14.2758 4.50146 14.5094 4.60057 14.7076 4.7988C14.9058 4.99702 15.0049 5.23196 15.0049 5.50364C15.0049 5.7753 14.9058 6.01024 14.7076 6.20846L7.87972 13.0444C7.6815 13.2427 7.44791 13.3418 7.17894 13.3418C6.90998 13.3418 6.67639 13.2427 6.47817 13.0444L3.2943 9.86058C3.09609 9.66236 2.99834 9.42742 3.00103 9.15576C3.00373 8.88408 3.10418 8.64914 3.30241 8.45091C3.50063 8.25269 3.73557 8.15358 4.00725 8.15358C4.27891 8.15358 4.51385 8.25269 4.71207 8.45091L7.17894 10.9259Z"
+ }
+
+ return (
+
+
+
+ )
+}
+
+export default function CustomCheckbox({ children, hasIndeterminate = false , icon, ...props}) {
+ return (
+
+ }
+ {...props}
+ >
+ {children}
+
+ )
+}
\ No newline at end of file
diff --git a/next/components/atoms/ControlledInput.js b/next/components/atoms/ControlledInput.js
index 6718f979..f6e508cf 100644
--- a/next/components/atoms/ControlledInput.js
+++ b/next/components/atoms/ControlledInput.js
@@ -3,12 +3,12 @@ import {
InputGroup,
InputRightAddon,
InputRightElement,
+ InputLeftElement
} from "@chakra-ui/react";
import { useEffect, useState } from "react";
export default function ControlledInput({
placeholder,
- variant,
value,
onChange,
onEnterPress,
@@ -117,3 +117,76 @@ export function DebouncedControlledInput({
);
}
+
+export function ControlledInputSimple({
+ refInput = null,
+ placeholder,
+ value,
+ onChange,
+ onEnterPress,
+ inputFocus,
+ changeInputFocus,
+ icon = null,
+ inputStyle,
+ inputElementStyle,
+ fill,
+ ...props
+}) {
+ async function checkForEnter(e) {
+ if (e.key === "Enter" && onEnterPress) {
+ onEnterPress();
+ }
+ }
+
+ return (
+
+
+
+ onChange(e.target.value)}
+ onKeyDown={checkForEnter}
+ onFocus={() => changeInputFocus(true)}
+ onBlur={() => changeInputFocus(false)}
+ autoComplete="off"
+ variant="outline"
+ border="2px solid transparent !important"
+ color="#464A51"
+ _hover={{
+ border:"2px solid transparent !important",
+ backgroundColor:"#DEDFE0",
+ }}
+ _focus={{
+ border:"2px solid #0068C5 !important",
+ backgroundColor: "#FFF",
+ }}
+ paddingLeft="52px !important"
+ backgroundColor="#EEEEEE"
+ height="40px"
+ fontSize="14px"
+ lineHeight="20px"
+ width="100%"
+ fontFamily="Roboto"
+ fontWeight="400"
+ borderRadius="14px"
+ _placeholder={{color: "#464A51", opacity: 1}}
+ {...inputStyle}
+ />
+
+ )
+}
\ No newline at end of file
diff --git a/next/components/atoms/FilterAccordion.js b/next/components/atoms/FilterAccordion.js
index 8a09c85c..413643df 100644
--- a/next/components/atoms/FilterAccordion.js
+++ b/next/components/atoms/FilterAccordion.js
@@ -4,20 +4,17 @@ import {
AccordionIcon,
AccordionItem,
Box,
- Checkbox,
CheckboxGroup,
VStack,
Text,
- Image,
HStack,
+ Skeleton
} from "@chakra-ui/react";
import { useEffect, useState } from "react";
-import ControlledInput from "./ControlledInput";
+import Checkbox from "../atoms/Checkbox";
+import { ControlledInput, ControlledInputSimple} from "./ControlledInput";
import SectionText from "./SectionText";
import SearchIcon from "../../public/img/icons/searchIcon"
-import BDLogoPlusImage from "../../public/img/logos/bd_logo_plus";
-import BDLogoProImage from "../../public/img/logos/bd_logo_pro";
-
export function BaseFilterAccordion({
fieldName,
@@ -26,8 +23,6 @@ export function BaseFilterAccordion({
isOpen = null,
isActive = false,
onChange = () => { },
- bdPlus = null,
- bdPro = false,
alwaysOpen = false,
isHovering = true
}) {
@@ -39,9 +34,8 @@ export function BaseFilterAccordion({
{fieldName}
- {bdPlus &&
-
- }
- {bdPro &&
-
- }
- {!alwaysOpen ? : <>>}
+ {!alwaysOpen ? : <>>}
{(isOpen && isOpen === true) || (isOpen == null && isExpanded) ? (
-
+ <>
{children}
-
+ >
) : (
<>>
)}
@@ -109,11 +83,14 @@ export function CheckboxFilterAccordion({
isActive = false,
isOpen = null,
canSearch = false,
+ isLoading
}) {
const [options , setOptions] = useState([])
const [search, setSearch] = useState("");
+ const [inputFocus, setInputFocus] = useState(false)
useEffect(() => {
+ if (choices.length === 0) return
setOptions(choices)
}, [choices])
@@ -135,48 +112,91 @@ export function CheckboxFilterAccordion({
overflowX="hidden"
alwaysOpen={alwaysOpen}
>
-
- {canSearch &&
-
-
- }
- />
+
+
+ {canSearch &&
+
+
+ }
+ />
+
+ }
+
+ {options.length > 0 && options.map((c) => (
+
+ { onChange(e.target.value)}}
+ minWidth="18px"
+ minHeight="18px"
+ maxWidth="18px"
+ maxHeight="18px"
+ marginRight="14px"
+ flexShrink={0}
+ />
+
+ {c[displayField]}
+
+
+ {c["count"] ? `(${c["count"]})` : `(0)`}
+
+
+ ))}
- }
-
- {options.length > 0 && options.map((c) => (
- { onChange(e.target.value)}}
- >
- {c[displayField]} {c["count"] ? `(${c["count"]})` : `(0)`}
-
- ))}
-
-
+
+
);
}
@@ -265,73 +285,6 @@ export function RangeFilterAccordion({
);
}
-export function FilterAccordion({
- fieldName,
- choices,
- onChange,
- onToggle,
- value,
- bdPlus = null,
- bdPro = false,
- valueField = "id",
- displayField = "display_name",
- isOpen = null,
- alwaysOpen = false,
- isActive = false,
- isHovering,
-}) {
- if(choices.length < 1) return null
-
- return (
-
-
- {choices.map((c) => (
-
- onChange(c[valueField])}
- >
- {c[displayField]}
-
-
- ))}
-
-
- );
-}
-
export function SimpleFilterAccordion({
fieldName,
children,
@@ -349,7 +302,7 @@ export function SimpleFilterAccordion({
diff --git a/next/components/atoms/GreenTab.js b/next/components/atoms/GreenTab.js
index 7d4916a2..1c5bf8d3 100644
--- a/next/components/atoms/GreenTab.js
+++ b/next/components/atoms/GreenTab.js
@@ -4,20 +4,24 @@ import { Tab } from "@chakra-ui/react";
export default function GreenTab({ children, ...style }) {
return (
diff --git a/next/components/atoms/HelpWidget.js b/next/components/atoms/HelpWidget.js
index 0df5adf0..2481a353 100644
--- a/next/components/atoms/HelpWidget.js
+++ b/next/components/atoms/HelpWidget.js
@@ -6,40 +6,29 @@ import {
MenuDivider,
Tooltip
} from "@chakra-ui/react";
-import { useDisclosure } from "@chakra-ui/hooks";
-import { useState, useEffect } from 'react';
-import { useCheckMobile } from "../../hooks/useCheckMobile.hook";
import HelpIcon from "../../public/img/icons/helpIcon"
export default function HelpWidget({options, tooltip}) {
- const isMobile = useCheckMobile();
- const [isMobileMode, setIsMobileMode] = useState(false)
-
- useEffect(() => {
- setIsMobileMode(isMobile)
- },[isMobile])
-
- const { isOpen } = useDisclosure()
-
const optionsRender = (options) => {
- return options.map((option) => {
+ return options.map((option, i) => {
if(option.name){ return (
window.open(option.url, "_blank")}
>
{option.name}
)
- } else { return }
+ } else { return }
})
}
@@ -50,12 +39,12 @@ export default function HelpWidget({options, tooltip}) {
-
+
{
- const settingsImage = {
- alt: title || "",
- borderRadius:"32px",
- boxShadow:"0px 4px 8px rgba(100, 96, 103, 0.16)",
- width:{ base: "25%", lg: "100%" },
- minWidth:"250px",
- maxWidth:"250px",
- minHeight:"250px",
- maxHeight:"250px",
- height:{ base: "25%", lg: "100%" },
- objectFit:"contain",
- widthImage:"100%",
- heightImage:"100%"
- }
-
- if(!image) return
-
- return (
-
- )
-}
-
diff --git a/next/components/atoms/LinkDash.js b/next/components/atoms/LinkDash.js
deleted file mode 100644
index 960515ae..00000000
--- a/next/components/atoms/LinkDash.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import { Link } from "@chakra-ui/react";
-
-export default function LinkDash({ children, href, dash = true, ...style }) {
- return (
-
- {children} {dash ? ">>" : null}
-
- )
-}
diff --git a/next/components/atoms/ObservationLevelTable.js b/next/components/atoms/ObservationLevelTable.js
new file mode 100644
index 00000000..595f6c8f
--- /dev/null
+++ b/next/components/atoms/ObservationLevelTable.js
@@ -0,0 +1,108 @@
+import {
+ TableContainer,
+ Table,
+ Thead,
+ Tbody,
+ Tr,
+ Th,
+ Td,
+} from "@chakra-ui/react";
+
+export default function ObservationLevel({ resource }) {
+ const headers = ["Entidade","Colunas Correspondentes"]
+
+ let array = []
+ const keys = Object.keys(resource?.observationLevels)
+
+ keys.forEach((elm) => {
+ const value = resource?.observationLevels[elm]
+
+ const newValue = [value?.entity?.name || "Não informado", value?.columns[0]?.name || "Não informado"]
+ array.push(newValue)
+ })
+
+ return (
+
+
+
+
+ {headers.map((elm, i) => (
+
+ {elm}
+
+ ))}
+
+
+
+
+ {array.map((elm, i) => (
+
+
+ {elm[0]}
+
+
+ {elm[1]}
+
+
+ ))}
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/next/components/atoms/ReadMore.js b/next/components/atoms/ReadMore.js
index b06a14b0..bff6393f 100644
--- a/next/components/atoms/ReadMore.js
+++ b/next/components/atoms/ReadMore.js
@@ -1,41 +1,93 @@
import {
- VStack,
+ Flex,
Text,
} from "@chakra-ui/react";
-import { useState, useEffect } from "react";
-import LinkDash from "./LinkDash";
+import { useState, useEffect, useRef } from "react";
-export default function ReadMore({ children, textSize = 240, isMobileMod, ...props}) {
- const [isReadMore, setIsReadMore] = useState(true)
- const text = children
+export default function ReadMore({ children, id, ...props}) {
+ const [isReadMore, setIsReadMore] = useState(false)
+ const [isOverflowing, setIsOverflowing] = useState(false)
+ const textRef = useRef(null)
+
+ const modifiedChildren = `
+ ${children.trim()}
+
+ Ler menos `
useEffect(() => {
- if(text.length < textSize) setIsReadMore(false)
+ if (textRef.current) {
+ const { clientHeight, scrollHeight } = textRef.current
+ setIsOverflowing(scrollHeight > clientHeight)
+ }
}, [children])
-
+
+ useEffect(() => {
+ const readLess = document.getElementById(id)
+ if (readLess) readLess.addEventListener('click', toggleReadMore)
+ return () => { if (readLess) readLess.removeEventListener('click', toggleReadMore)}
+ }, [isReadMore])
+
const toggleReadMore = () => {
setIsReadMore(!isReadMore)
}
return (
-
+
- {isReadMore ? text.slice(0, textSize)+"..." : text}
+ {isOverflowing ?
+
+ :
+ children
+ }
-
- {text.length > textSize &&
-
- {isReadMore ? "Ler mais" : " Ler menos"}
-
+ {isOverflowing &&
+
+ ... Ler mais
+
}
-
+
)
-}
\ No newline at end of file
+}
diff --git a/next/components/atoms/Tag.js b/next/components/atoms/Tag.js
index 54b652ed..614a6b94 100644
--- a/next/components/atoms/Tag.js
+++ b/next/components/atoms/Tag.js
@@ -25,3 +25,32 @@ export default function TagBase({
)
}
+
+export function TagFilter({text, handleClick}) {
+ return (
+
+ {text}
+ handleClick()}
+ />
+
+ )
+}
\ No newline at end of file
diff --git a/next/components/atoms/Toggle.js b/next/components/atoms/Toggle.js
index 4807ebff..cd2e1815 100644
--- a/next/components/atoms/Toggle.js
+++ b/next/components/atoms/Toggle.js
@@ -1,12 +1,13 @@
import { Switch } from "@chakra-ui/react";
import styles from "../../styles/toggle.module.css";
-export default function Toggle({ value, onChange }) {
+export default function Toggle({ value, onChange, ...props }) {
return (
)
}
\ No newline at end of file
diff --git a/next/components/molecules/ColumnDatasets.js b/next/components/molecules/ColumnDatasets.js
deleted file mode 100644
index e95e2720..00000000
--- a/next/components/molecules/ColumnDatasets.js
+++ /dev/null
@@ -1,416 +0,0 @@
-import {
- TableContainer,
- Table,
- Thead,
- Tbody,
- Tr,
- Th,
- Td,
- Tooltip,
- HStack,
- Stack,
- Box,
- Text,
- Input,
- InputGroup,
- InputRightElement,
- InputLeftAddon,
- Select,
-} from '@chakra-ui/react';
-import { useState, useEffect } from 'react';
-import FuzzySearch from 'fuzzy-search';
-import Latex from 'react-latex-next';
-import { useCheckMobile } from "../../hooks/useCheckMobile.hook";
-import SectionText from '../atoms/SectionText';
-import LoadingSpin from '../atoms/Loading'
-import Tag from "../atoms/Tag";
-import { TemporalCoverage } from "./TemporalCoverageDisplay";
-
-import {
- getColumnsBdmTable
-} from "../../pages/api/datasets/index";
-
-import InfoIcon from '../../public/img/icons/infoIcon';
-import RedirectIcon from '../../public/img/icons/redirectIcon';
-import FilterIcon from '../../public/img/icons/filterIcon';
-import SearchIcon from '../../public/img/icons/searchIcon';
-import CrossIcon from '../../public/img/icons/crossIcon';
-import 'katex/dist/katex.min.css';
-
-function TableDatasets({ headers, values }) {
- const [columnsHeaders, setColumnsHeaders] = useState([])
- const [columnsValues, setColumnsValues] = useState([])
-
- function sortElements(a, b) {
- if (a.node.order < b.node.order) {
- return -1
- }
- if (a.node.order > b.node.order) {
- return 1
- }
- return 0
- }
-
- useEffect(() => {
- const newValues = values?.map((elm) => {
- delete elm.node._id
- return elm
- })
-
- setColumnsHeaders(Object.keys(headers))
- setColumnsValues(newValues.sort(sortElements))
- },[values, headers])
-
-
- const empty = () => {
- return (
-
- Não listado
-
- )
- }
-
- function valueVerification (value) {
- if(value === null || value === undefined) return empty()
-
- if(typeof value === "function") return value()
-
- if(value === true) return "Sim"
- if(value === false) return "Não"
-
- if(value) {
- if(value === "Não listado"){
- return empty()
- } else {
- return value
- }
- } else {
- return empty()
- }
- }
-
- const directoryColumnValue = (value) => {
- const dataset = value?.table?.dataset
- const table = value?.table
- const newDirectoryColumn = `${dataset?.slug}.${table?.slug}:${value?.name}`
-
- if (newDirectoryColumn === "undefined.undefined:undefined") return empty()
-
- return (
-
- {newDirectoryColumn}
-
-
-
-
- )
- }
-
- const measurementUnit = (value) => {
- if(!value) return null
-
- const measurementUnitLatex = () => {
- const splitValue = value.split(/([^a-z])/)
- const translated = (value) => value.map((elm) => elm)
- return (
- {`$${translated(splitValue).join("")}$`}
- )
- }
- return measurementUnitLatex
- }
-
- const TableHeader = ({ header, ...props }) => {
- if(header === undefined) return null
-
- return (
-
-
- {headers[header].pt}
-
-
-
-
-
- )
- }
-
- function TreatmentValues({ value }) {
- const objectValue = value?.node
- let data = []
-
- data.push({ value: objectValue.name, style:{position:"sticky", left:"0", zIndex:2, background:"linear-gradient(to left,#EAEAEA, #EAEAEA 2px, #FFF 2px, #FFF 100%)"}});
- data.push({ value: objectValue.bigqueryType.name, style:{textTransform: "uppercase"}})
- data.push({ value: objectValue.description})
- data.push({ value: objectValue.coverage})
- data.push({ value: objectValue.coveredByDictionary})
- data.push({ value: directoryColumnValue(objectValue.directoryPrimaryKey)})
- data.push({ value: measurementUnit(objectValue.measurementUnit)})
- data.push({ value: objectValue.containsSensitiveData})
- data.push({ value: objectValue.observations})
-
- return data.map((elm, i) =>
-
- {i===3 ? : valueVerification(elm.value)}
-
- )
- }
-
- function TableValue({children, ...props}) {
- return (
-
- {children}
-
- )
- }
-
- return (
-
-
-
-
-
- {columnsHeaders.map((elm, i) => (
- i != 0 &&
- ))}
-
-
- {columnsValues?.length > 0 && columnsValues.map((elm) => (
-
-
-
- ))}
-
-
-
-
- )
-}
-
-export default function ColumnsDatasets({ tableId }) {
- const [resource, setResource] = useState({})
- const [isError, setIsError] = useState({})
- const [isLoading, setIsLoading] = useState(false)
-
- const featchColumns = async () => {
- setIsLoading(true)
- try {
- const result = await getColumnsBdmTable(tableId)
- setResource(result)
- } catch (error) {
- setIsError(error)
- console.error(error)
- }
- setIsLoading(false)
- }
-
- useEffect(() => {
- featchColumns()
- },[tableId])
-
- const headers = {
- name: {
- pt: "Nome",
- tooltip:"Nome da coluna."
- },
- bigqueryType: {
- pt: "Tipo No BigQuery",
- tooltip:"Tipo de dado no BigQuery — categorias: INTEGER (Inteiro), STRING (Texto), DATE (Data), FLOAT64 (Decimal), GEOGRAPHY (Geográfico)."
- },
- description: {
- pt: "Descrição",
- tooltip:"Descrição dos dados da coluna."
- },
- datetimeRanges: {
- pt: "Cobertura Temporal",
- tooltip:"Data inicial e final de cobertura dos dados. Pode variar entre colunas, de acordo com a disponibilidade nos dados originais."
- },
- coveredByDictionary: {
- pt: "Coberta Por Um Dicionário",
- tooltip:"Indica se a coluna possui categorias descritas na tabela 'dicionario', explicando o significado das suas chaves e valores — ex: 'sexo' possui os valores 0 e 1 na coluna, e, no dicionario, você irá encontrar 'sexo' com as categorias (chave: 1 - valor: Feminino), (chave: 0 - valor: Masculino)."
- },
- directoryPrimaryKey: {
- pt: "Coluna Correspondente Nos Diretórios",
- tooltip:"Caso preenchida, indica que a coluna é chave primária de uma entidade — ex: id_municipio = chave primária de municípios. Isso significa que a coluna é igual em todos os conjuntos do datalake. Informações centralizadas da entidade se encontram no diretório conforme: [diretorio].[tabela]:[coluna]."
- },
- measurementUnit: {
- pt: "Unidade De Medida",
- tooltip:"Unidade de medida da coluna — ex: km, m2, kg."
- },
- containsSensitiveData: {
- pt: "Contém Dados Sensíveis (LGPD)",
- tooltip:"Indica se a coluna possui dados sensíveis — ex: CPF identificado, dados de conta bancária, etc."
- },
- observations: {
- pt: "Observações",
- tooltip:"Descreve processos de tratamentos realizados na coluna que precisam ser evidenciados."
- }
- }
-
- if(isLoading) return
-
- if(isError?.message?.length > 0) return Nenhuma informação foi encontrada.
- if(resource === undefined || Object.keys(resource).length === 0) return Nenhuma informação de coluna fornecida.
-
- return (
-
- {/*
-
-
-
- Filtrar
-
- setHeaderSelection(event.target.value) }
- >
- {Object.keys(headers).map((option) =>
- {headers?.[option]?.pt}
- )}
-
-
-
-
-
- {tagFilter.length > 0 && (
-
- {tagFilter.map((elm) => (
-
- {elm.header}
- removeTagFilter(elm, null)}
- />
-
- ))}
-
- }
- />
- )}
-
- setFilter(e.target.value)}
- variant="outline"
- letterSpacing="0.5px"
- fontWeight="300"
- border="none"
- borderRadius="16px"
- fontFamily="lato"
- fontSize="16px"
- color="#252A32"
- width="100%"
- minWidth="200px"
- height="40px"
- placeholder="Insira o nome ou o valor da propriedade"
- _placeholder={{color:"#6F6F6F"}}
- />
- appliedFilter()}
- />
- :
- {
- setTagFilter([])
- setHeaderSelection("")
- setColumnValues(defaultValues)
- setFilter("")
- }}
- />
- }/>
-
-
- */}
-
-
-
- )
-}
diff --git a/next/components/molecules/ColumnsTable.js b/next/components/molecules/ColumnsTable.js
new file mode 100644
index 00000000..a5e93a4d
--- /dev/null
+++ b/next/components/molecules/ColumnsTable.js
@@ -0,0 +1,685 @@
+import {
+ TableContainer,
+ Table,
+ Thead,
+ Tbody,
+ Tr,
+ Th,
+ Td,
+ Tooltip,
+ Stack,
+ Box,
+ Text,
+ 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';
+import { ControlledInputSimple } from '../atoms/ControlledInput';
+import Checkbox from '../atoms/Checkbox';
+import { triggerGAEvent, formatBytes } from '../../utils';
+
+import {
+ getColumnsBdmTable
+} from "../../pages/api/tables/index";
+
+import InternalError from '../../public/img/internalError'
+import InfoIcon from '../../public/img/icons/infoIcon';
+import DownloadIcon from '../../public/img/icons/downloadIcon';
+import SearchIcon from '../../public/img/icons/searchIcon';
+import RedirectIcon from '../../public/img/icons/redirectIcon';
+import 'katex/dist/katex.min.css';
+
+function SearchColumn({ isLoaded, resource, columns }) {
+ const [inputFocus, setInputFocus] = useState(false)
+ const [search, setSearch] = useState("")
+ const [value, setValue] = useState("")
+ const [_timeout, _setTimeout] = useState(null)
+
+ useEffect(() => {
+ clearTimeout(_timeout)
+ isLoaded(true)
+ if(value.trim() === "") {
+ isLoaded(false)
+ return columns(resource)
+ }
+
+ _setTimeout(setTimeout(() => {
+ const result = searcherColumn.search(search.trim())
+ if(result.length > 0) {
+ columns(result)
+ } else {
+ columns(resource)
+ }
+ isLoaded(false)
+ }, 500))
+ }, [value])
+
+ useEffect(() => {
+ setValue(search)
+ }, [search])
+
+ const searcherColumn = new FuzzySearch (
+ resource, ["node.name", "node.description"], {sort: true}
+ )
+
+ return (
+
+ }
+ />
+ )
+}
+
+export default function ColumnsTable({
+ tableId,
+ checkedColumns,
+ onChangeCheckedColumns,
+ hasLoading,
+ setHasLoading,
+ numberColumns,
+ template,
+ columnsPro
+}) {
+ const router = useRouter()
+ const { query } = router
+ const [resource, setResource] = useState({})
+ const [columns, setColumns] = useState({})
+ const [isError, setIsError] = useState(false)
+ const [isLoading, setIsLoading] = useState(true)
+ const [isSearchLoading, setIsSearchLoading] = useState(true)
+
+ 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))
+ } else {
+ onChangeCheckedColumns([...checkedColumns, columnSlug])
+ }
+ }
+
+ const handleMasterCheckboxChange = () => {
+ if(checkedColumns.length > 0) return onChangeCheckedColumns([])
+ const allColumnSlugs = resource.map(column => column.node.name)
+
+ if (checkedColumns.length === allColumnSlugs.length) {
+ onChangeCheckedColumns([])
+ } else {
+ onChangeCheckedColumns(allColumnSlugs)
+ }
+ }
+
+ useEffect(() => {
+ if(tableId === undefined) return
+
+ const filterClosedTables = (data) => {
+ return data.filter(elm => {
+ const table = elm?.node?.directoryPrimaryKey?.table
+ return table && table.isClosed === true
+ })
+ }
+
+ const featchColumns = async () => {
+ setHasLoading(true)
+
+ try {
+ const result = await getColumnsBdmTable(tableId)
+
+ if(result) {
+ setResource(result.sort(sortElements))
+ numberColumns(result.length)
+ columnsPro(filterClosedTables(result))
+ setColumns(result.sort(sortElements))
+ setHasLoading(false)
+ setIsSearchLoading(false)
+ }
+
+ } catch (error) {
+ console.error(error)
+ setIsError(true)
+ }
+ }
+
+ featchColumns()
+ },[tableId])
+
+ useEffect(() => {
+ setIsLoading(hasLoading)
+ }, [hasLoading])
+
+ const headers = [
+ {
+ pt: "Nome",
+ tooltip:"Nome da coluna."
+ },
+ {
+ pt:
+ template === "download" ?
+ "Tabela de tradução"
+ :
+ "Precisa de tradução"
+ ,
+ tooltip:
+ template === "download" ?
+ "Para traduzir os códigos institucionais da tabela você precisa utilizar as tabelas de dicionário e diretórios, dependendo de qual coluna você quiser usar."
+ :
+ "A coluna possui códigos institucionais a serem traduzidos."
+ },
+ {
+ pt: "Descrição",
+ tooltip:"Descrição dos dados da coluna."
+ },
+ {
+ pt: "Tipo No BigQuery",
+ tooltip:"Tipo de dado no BigQuery — categorias: INTEGER (Inteiro), STRING (Texto), DATE (Data), FLOAT64 (Decimal), GEOGRAPHY (Geográfico)."
+ },
+ {
+ pt: "Cobertura Temporal",
+ tooltip:"Data inicial e final de cobertura dos dados. Pode variar entre colunas, de acordo com a disponibilidade nos dados originais."
+ },
+ {
+ pt: "Unidade De Medida",
+ tooltip:"Unidade de medida da coluna — ex: km, m2, kg."
+ },
+ {
+ pt: "Contém Dados Sensíveis (LGPD)",
+ tooltip:"Indica se a coluna possui dados sensíveis — ex: CPF identificado, dados de conta bancária, etc."
+ },
+ {
+ pt: "Observações",
+ tooltip:"Descreve processos de tratamentos realizados na coluna que precisam ser evidenciados."
+ }
+ ]
+
+ function sortElements(a, b) {
+ if (a.node.order < b.node.order) {
+ return -1
+ }
+ if (a.node.order > b.node.order) {
+ return 1
+ }
+ return 0
+ }
+
+ function HasDownloadPermitted(value) {
+ let downloadPermitted = false
+ let downloadWarning = ""
+
+ if (value) {
+ const limit100MB = 100 * 1024 * 1024;
+ const limit1GB = 1 * 1024 * 1024 * 1024;
+
+ if (value < limit100MB) {
+ downloadPermitted = true
+ downloadWarning = "free"
+ } else if (value < limit1GB) {
+ downloadPermitted = isUserPro()
+ downloadWarning = "100mbBetween1gb"
+ } else {
+ 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
+
+ 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(`https://storage.googleapis.com/basedosdados-public/one-click-download/${cloudTables?.gcpDatasetId}/${cloudTables?.gcpTableId}/${cloudTables?.gcpTableId}.csv.gz`)
+ }
+
+ 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 || ""
+ const gcpDatasetID = cloudValues?.gcpDatasetId || ""
+ const gcpTableId = cloudValues?.gcpTableId || ""
+
+ 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"
+ if(gcpDatasetID === "br_bd_diretorios_brasil") {
+ if(gcpTableId === "empresa" || gcpTableId === "cep") return "Não precisa de tradução"
+ }
+ if(value?.name === "ddd") return "Não precisa de tradução"
+
+ const downloadUrl = `https://storage.googleapis.com/basedosdados-public/one-click-download/${gcpDatasetID}/${gcpTableId}/${gcpTableId}.csv.gz`
+
+ return (
+
+ {value === null ?
+
+ Não precisa de tradução
+
+ :
+
+ {
+ if(!downloadInfo.downloadPermitted) return
+ 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 || !downloadInfo.downloadPermitted
+ ?
+ <>
+ Acessar tabela que faz a tradução desta coluna
+
+ >
+ :
+ <>
+ Baixar tabela que faz a tradução desta coluna
+
+ >
+ }
+
+ {datasetName} - {tableName}
+
+ }
+
+ {dictionary === true &&
+
+ }
+
+ )
+ }
+
+ const measurementUnit = (value) => {
+ if(!value) return "Não informado"
+
+ const splitValue = value.split(/([^a-z])/)
+ const translated = (value) => value.map((elm) => elm)
+
+ return (
+ {`$${translated(splitValue).join("")}$`}
+ )
+ }
+
+ function TableHeader({ header, ...props }) {
+ return (
+
+
+ {header.pt}
+
+
+
+
+
+
+
+ )
+ }
+
+ function TableValue({children, ...props}) {
+ return (
+
+ {children}
+
+ )
+ }
+
+ function TranslationColumnException({ value }) {
+ const cloudValues = value?.node?.directoryPrimaryKey?.table?.cloudTables?.edges?.[0]?.node
+ const gcpDatasetID = cloudValues?.gcpDatasetId || ""
+ const gcpTableId = cloudValues?.gcpTableId || ""
+
+ if(gcpDatasetID === "br_bd_diretorios_data_tempo") return "Não"
+ if(gcpDatasetID === "br_bd_diretorios_brasil") {
+ if(gcpTableId === "empresa" || gcpTableId === "cep") return "Não"
+ }
+ if(value?.node?.name === "ddd") return "Não"
+ if(value?.node?.coveredByDictionary === true) return "Sim"
+ if(value?.node?.directoryPrimaryKey?._id) return "Sim"
+ if(value?.node?.coveredByDictionary === false) return "Não"
+ return "Não informado"
+ }
+
+ if(isError) return (
+
+
+
+ )
+
+ return (
+
+
+
+
+
+
+
+
+
+
+ {template === "checks" &&
+
+
+ 0}
+ hasIndeterminate={checkedColumns.length !== resource.length && checkedColumns.length > 0}
+ />
+
+
+
+ }
+
+
+
+ {headers.map((elm, i) => (
+ i != 0 &&
+ ))}
+
+
+
+
+ {columns.length > 0 && columns.map((elm,i) => (
+
+ {template === "checks" &&
+
+
+ handleCheckboxChange(elm.node.name)}
+ />
+
+
+ }
+
+
+ {elm?.node?.name ? elm.node.name : "Não informado"}
+
+
+
+
+ {template === "download" ?
+
+ :
+
+ }
+
+
+
+ {elm?.node?.description ? elm.node.description : "Não informado"}
+
+
+
+ {elm?.node?.bigqueryType?.name ? elm.node.bigqueryType.name : "Não informado"}
+
+
+
+ {elm?.node?.coverage?.start && elm?.node?.coverage?.end ?
+ elm.node.coverage.start +" - "+ elm.node.coverage.end
+ :
+ "Não informado"
+ }
+
+
+
+ {elm?.node?.measurementUnit ?
+ measurementUnit(elm.node.measurementUnit)
+ :
+ "Não informado"
+ }
+
+
+
+ {
+ elm?.node?.containsSensitiveData === true ? "Sim"
+ :
+ elm?.node?.containsSensitiveData === false ? "Não"
+ :
+ "Não informado"
+ }
+
+
+
+ {elm?.node?.observations ? elm.node.observations : "Não informado"}
+
+
+ ))}
+
+
+
+
+
+ )
+}
diff --git a/next/components/molecules/DataInformationQuery.js b/next/components/molecules/DataInformationQuery.js
index f44bc089..73aaec93 100644
--- a/next/components/molecules/DataInformationQuery.js
+++ b/next/components/molecules/DataInformationQuery.js
@@ -1,359 +1,883 @@
import {
VStack,
- Stack,
Tabs,
TabList,
+ Tab,
TabPanel,
TabPanels,
Text,
- Image,
Box,
useClipboard,
- Button,
- HStack,
- Menu,
- MenuItem,
- MenuList,
- MenuButton,
- IconButton,
+ Tooltip,
+ Skeleton,
+ Stack
} from "@chakra-ui/react";
-import { useState, useEffect } from "react";
-import { isMobileMod } from "../../hooks/useCheckMobile.hook";
+import { useState, useEffect, useRef } from "react";
+import hljs from "highlight.js/lib/core";
+import sqlHighlight from "highlight.js/lib/languages/sql";
+import pythonHighlight from "highlight.js/lib/languages/python";
+import rHighlight from "highlight.js/lib/languages/r";
+import cookies from "js-cookie";
+import 'highlight.js/styles/obsidian.css'
-import Link from "../atoms/Link";
import GreenTab from "../atoms/GreenTab";
-import SectionText from "../atoms/SectionText";
-import Subtitle from "../atoms/Subtitle";
-import RoundedButton from "../atoms/RoundedButton";
+import Toggle from "../atoms/Toggle";
+import ColumnsTable from "./ColumnsTable";
+import { AlertDiscalimerBox} from "./DisclaimerBox";
+import { triggerGAEvent, formatBytes } from "../../utils";
+
+import {
+ getBigTableQuery
+} from "../../pages/api/tables"
-import DisclaimerBox from "./DisclaimerBox";
-import { triggerGAEvent } from "../../utils";
import { CopyIcon } from "../../public/img/icons/copyIcon";
import DownloadIcon from "../../public/img/icons/downloadIcon";
-import ExclamationIcon from "../../public/img/icons/exclamationIcon";
-import MenuVerticalIcon from "../../public/img/icons/menuVerticalIcon";
+import InfoIcon from "../../public/img/icons/infoIcon";
+import ChevronIcon from "../../public/img/icons/chevronIcon";
+import CheckIcon from "../../public/img/icons/checkIcon";
-export function BoxBigQueryGoogle({ href }) {
- return (
-
-
-
-
- Para usar o BigQuery basta ter uma conta Google. Primeira vez?
- Siga o passo a passo.
-
-
-
-
- )
-}
+export function CodeHighlight({ language, children }) {
+ const textRef = useRef(null)
+ const [isOverflowing, setIsOverflowing] = useState(false)
+ const [isExpanded, setIsExpanded] = useState(true)
-export function PrismCodeHighlight({ language, children }) {
+ const [highlightedCode, setHighlightedCode] = useState("")
const { hasCopied, onCopy } = useClipboard(children)
+ useEffect(() => {
+ if(language === "sql") hljs.registerLanguage("sql", sqlHighlight)
+ if(language === "python") hljs.registerLanguage("python", pythonHighlight)
+ if(language === "r") hljs.registerLanguage("r", rHighlight)
+
+ const highlighted = hljs.highlight(children, { language:language }).value
+ setHighlightedCode(highlighted)
+ }, [children, language])
+
+ useEffect(() => {
+ if (textRef.current) {
+ setIsOverflowing(false)
+ setIsExpanded(true)
+ const { clientHeight } = textRef.current
+ setIsOverflowing(clientHeight > 190)
+ if(clientHeight > 190) setIsExpanded(false)
+ }
+ }, [highlightedCode])
+
return (
-
-
- {children}
-
-
-
- {hasCopied ? "Copiado" : "Copiar"}
-
-
-
+
+
+
+ {hasCopied ? "Copiado" : "Copiar"}
+ {hasCopied ?
+
+ :
+
+ }
+
+
+
+ {isOverflowing && (
+ setIsExpanded(!isExpanded)}
+ fill="#878A8E"
+ color="#878A8E"
+ _hover={{
+ fill:"#9D9FA3",
+ color:"#9D9FA3"
+ }}
+ >
+
+
+ {isExpanded ? "Recolher" : "Expandir"}
+
+
+ )}
+
)
}
export default function DataInformationQuery({ resource }) {
- const gcpDatasetID = resource?.cloudTables[0]?.gcpDatasetId
- const gcpTableId = resource?.cloudTables[0]?.gcpTableId
- const downloadUrl = `https://storage.googleapis.com/basedosdados-public/one-click-download/${gcpDatasetID}/${gcpTableId}/${gcpTableId}.csv.gz`
- const queryBQ = `${gcpDatasetID}.${gcpTableId}`
+ const [tabAccessIndex, setTabAccessIndex] = useState(0)
const [tabIndex, setTabIndex] = useState(0)
const [downloadNotAllowed, setDownloadNotAllowed] = useState(false)
+ const [checkedColumns, setCheckedColumns] = useState([])
+ const [numberColumns, setNumberColumns] = useState(0)
+ const [columnsTranslationPro, setColumnsTranslationPro] = useState([])
+ const [sqlCode, setSqlCode] = useState("")
+ const [insufficientChecks, setInsufficientChecks] = useState(false)
+ const [includeTranslation, setIncludeTranslation] = useState(true)
+ const [hasLoadingColumns, setHasLoadingColumns] = useState(true)
+ const [isLoadingCode, setIsLoadingCode] = useState(false)
+ const [hasLoadingResponse, setHasLoadingResponse] = useState(false)
+
+ const [gcpProjectID, setGcpProjectID] = useState("")
+ const [gcpDatasetID, setGcpDatasetID] = useState("")
+ const [gcpTableId, setGcpTableId] = useState("")
+ const [downloadUrl, setDownloadUrl] = useState("")
+
+ const isUserPro = () => {
+ let user
+ if(cookies.get("userBD")) user = JSON.parse(cookies.get("userBD"))
+
+ if(user?.proSubscriptionStatus === "active") return true
+ return false
+ }
useEffect(() => {
- if (window) window?.Prism?.highlightAll()
+ if(resource?.dataset?._id === "e083c9a2-1cee-4342-bedc-535cbad6f3cd") setIncludeTranslation(false)
+ }, [resource.dataset])
- if (resource?.numberRows === 0) return setDownloadNotAllowed(false)
- if (resource?.numberRows) return resource?.numberRows > 200000 ? setDownloadNotAllowed(false) : setDownloadNotAllowed(true)
- }, [resource])
+ useEffect(() => {
+ if (resource?.numberRows === 0) setDownloadNotAllowed(false)
+ if (resource?.numberRows) resource?.numberRows > 200000 ? setDownloadNotAllowed(false) : setDownloadNotAllowed(true)
+
+ 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])
+
+ useEffect(() => {
+ if(resource._id === undefined) return
+ setIsLoadingCode(true)
+ setHasLoadingResponse(false)
+ setSqlCode("")
+ setInsufficientChecks(false)
+ }, [resource._id, checkedColumns, includeTranslation])
+
+ useEffect(() => {
+ if(hasLoadingResponse === true) {
+ SqlCodeString()
+ }
+ }, [hasLoadingResponse])
+
+ useEffect(() => {
+ if(sqlCode !== "") scrollFocus()
+ }, [sqlCode])
+
+ function scrollFocus() {
+ let idTab
+
+ if (tabIndex === 0) idTab = "SQL_section"
+ else if (tabIndex === 1) idTab = "python_section"
+ else if (tabIndex === 2) idTab = "r_section"
+ else return
+
+ const targetElement = document.getElementById(idTab)
+
+ if (targetElement) {
+ const { top } = targetElement.getBoundingClientRect()
+ const heightScreen = window.innerHeight
+ const positionTarget = top + window.pageYOffset
+
+ window.scrollTo({
+ top: positionTarget - (heightScreen / 2),
+ behavior: "smooth",
+ })
+ }
+ }
- const handlerDownload = () => {
- if (downloadNotAllowed === false) return null
+ async function SqlCodeString() {
+ const result = await getBigTableQuery(resource._id, checkedColumns, includeTranslation)
+ setSqlCode(result.trim())
+ setIsLoadingCode(false)
+ }
+
+ const handleAccessIndexes = (index) => {
+ const categoryValues = ["BigQuery e Pacotes", "Download"]
+ setTabAccessIndex(index)
+ triggerGAEvent("category_click", categoryValues[index])
+ }
- return window.open(downloadUrl)
+ const handleCategoryIndexes = (index) => {
+ const categoryValues = ["SQL", "Python", "R"]
+ setTabIndex(index)
+ triggerGAEvent("category_click", categoryValues[index])
}
- const handleIndexes = (index) => {
- const categoryValues = ["SQL", "Python", "R", "Stata", "Download"];
- setTabIndex(index);
- triggerGAEvent("category_click", categoryValues[index]);
+ const queryLanguage = () => {
+ const language = {
+ 0 : "SQL",
+ 1 : "Python",
+ 2 : "R"
+ }
+ return language[tabIndex] ? language[tabIndex] : ""
}
return (
- Consulta aos dados
handleIndexes(index)}
- index={tabIndex}
+ width="100%"
+ variant="unstyled"
+ isLazy
+ onChange={(index) => handleAccessIndexes(index)}
+ index={tabAccessIndex}
+ overflow="hidden"
>
-
- SQL
-
-
- Python
-
-
- R
-
-
- Stata
-
- {resource?.isClosed ? <>> :
- isMobileMod() ?
-
-
- }
- borderRadius="none"
- borderBottom={tabIndex === 4 && "3px solid #2B8C4D"}
- />
-
- handleIndexes(4)}>Download
-
-
- :
-
- Download
- }
+ BigQuery e Pacotes
+ Download
-
-
- {resource?.isClosed ?
-
- Com uma assinatura BD Pro válida, copie o código abaixo e cole no Editor de Consultas no BigQuery:
-
- :
-
+
+
+
- Copie o código abaixo,
- clique aqui
- para ir ao datalake no BigQuery e cole no Editor de Consultas:
-
- }
-
- {`SELECT * FROM \`basedosdados.${queryBQ}\` LIMIT 100`}
-
+ {tabAccessIndex === 0 ? "Selecione as colunas que você deseja acessar:" : "Confira as colunas da tabela:"}
+
+
-
-
-
-
-
- Criamos um pacote em Python para você acessar o datalake . Basta rodar o código:
-
+
+ Essa tabela possui códigos institucionais que variam entre anos. Por isso, ainda estamos trabalhando para automatizar o processo de tradução.
+ Por enquanto, recomendamos acessar o dicionário e os diretórios para entender como traduzir os códigos presentes na tabela.
+
+
-
- {`import basedosdados as bd
+
+
+
+ setIncludeTranslation(!includeTranslation)}
+ />Traduzir códigos institucionais
+
+
+
+
+
+
-# Para carregar o dado direto no pandas
-df = bd.read_table(dataset_id='${gcpDatasetID}',
-table_id='${gcpTableId}',
-billing_project_id="")`}
-
+ {checkedColumns.length > 0 && resource.uncompressedFileSize && resource.uncompressedFileSize/(1024 * 1024 * 1024) > 5 &&
+
+
+ Essa tabela completa, com todas as colunas, tem {formatBytes(resource.uncompressedFileSize)} . Cuidado para não ultrapassar o limite de processamento gratuito do BigQuery.
+ {numberColumns === checkedColumns.length && "Para otimizar a consulta, você pode selecionar menos colunas ou adicionar filtros no BigQuery."}
+
+
+ }
-
-
-
+ {columnsTranslationPro.length > 0 && tabAccessIndex !== 1 &&
+
+ A tabela de tradução da{columnsTranslationPro.length > 1 && "s"} coluna{columnsTranslationPro.length > 1 && "s"} {columnsTranslationPro.map((elm) => elm?.node?.name).join(", ")} é exclusiva para assinantes . Todos os demais códigos institucionais são de acesso aberto.
+
+ }
-
-
+
+
+ }
+
+
- Criamos um pacote em R para você acessar o datalake . Basta rodar o código:
-
+ {
+ if(checkedColumns.length === 0) return setInsufficientChecks(true)
+ triggerGAEvent("gerar_consulta_click", queryLanguage())
+ setHasLoadingResponse(true)
+ }}
+ display="flex"
+ alignItems="center"
+ height="40px"
+ width="fit-content"
+ borderRadius="8px"
+ backgroundColor="#2B8C4D"
+ padding="8px 16px"
+ cursor="pointer"
+ color="#FFF"
+ fill="#FFF"
+ fontFamily="Roboto"
+ fontWeight="500"
+ fontSize="14px"
+ gap="8px"
+ lineHeight="20px"
+ _hover={{
+ backgroundColor:"#22703E"
+ }}
+ >
+ Gerar consulta
+
+
+
-
- {`install.packages("basedosdados")
-library("basedosdados")
+
+
+ {downloadNotAllowed ?
+ isUserPro() ? "" :
+
+ 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
+
+ saiba como contribuir com seu tempo.
+
+
+ :
+
+ }
-# Defina o seu projeto no Google Cloud
-set_billing_id("")
+ { 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"}
+ padding="8px 16px"
+ cursor={downloadNotAllowed ? "pointer" : "default"}
+ color="#FFF"
+ fill="#FFF"
+ fontFamily="Roboto"
+ fontWeight="500"
+ fontSize="14px"
+ gap="8px"
+ lineHeight="20px"
+ pointerEvents={downloadNotAllowed ? "default" : "none"}
+ _hover={{
+ backgroundColor: "#22703E"
+ }}
+ >
+
+ Download da tabela {downloadNotAllowed && `(${formatBytes(resource.uncompressedFileSize)})`}
+
+
+
-# Para carregar o dado direto no R
-query <- bdplyr("${queryBQ}")
-df <- bd_collect(query)`}
-
+
+ handleCategoryIndexes(index)}
+ index={tabIndex}
+ overflow="hidden"
+ >
+
+ SQL
+ Python
+ R
+
-
-
-
+
+
+
+
+
+ No editor de consultas do BigQuery, digite a seguinte instrução:
+
+
-
-
- Criamos um pacote em Stata para você acessar o datalake . Basta rodar o código:
-
+
+
+ Primeira vez usando o BigQuery?
+
+ Siga o passo a passo.
+
+
+
-
- {`net install basedosdados, from("https://raw.githubusercontent.com/basedosdados/mais/master/stata-package")
+
+
+
+
+ Acessar o BigQuery
+
+
+
+
-bd_read_table, ///
- path("") ///
- dataset_id("${gcpDatasetID}") ///
- table_id("${gcpTableId}") ///
- billing_project_id("")`}
-
+
+
+ {sqlCode}
+
+
+
-
-
-
-
-
-
- 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 saiba como contribuir com seu tempo.
-
-
- {!downloadNotAllowed &&
-
-
-
-
- ATENÇÃO: O tamanho da tabela ultrapassou o limite permitido para download, de 200.000 linhas.
- Para acessar os dados, utilize nosso datalake no BigQuery ou nossos pacotes em Python, R e Stata.
-
-
-
- }
+
+
+
+ No terminal do Python, digite a seguinte instrução:
+
+
- handlerDownload()}
- >
-
- Download dos dados
-
-
-
+
+
+ Primeira vez usando o pacote Python?
+
+ Siga o passo a passo.
+
+
+
+
+
+ {`import basedosdados as bd
+
+billing_id =
+
+query = """
+ ${sqlCode}
+"""
+
+bd.read_sql(query = query, billing_project_id = billing_id)`}
+
+
+
+
+
+
+
+ No terminal do R, digite a seguinte instrução:
+
+
+
+
+
+ Primeira vez usando o pacote R?
+
+ Siga o passo a passo.
+
+
+
+
+
+ {`
+# 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/components/molecules/DisclaimerBox.js b/next/components/molecules/DisclaimerBox.js
index a741c10e..031794e1 100644
--- a/next/components/molecules/DisclaimerBox.js
+++ b/next/components/molecules/DisclaimerBox.js
@@ -1,7 +1,15 @@
-import { Stack } from "@chakra-ui/react";
+import {
+ Stack,
+ Box,
+ Text,
+} from "@chakra-ui/react";
import SectionText from "../atoms/SectionText";
+import InfoIcon from "../../public/img/icons/infoIcon";
+import WarningIcon from "../../public/img/icons/warningIcon";
+import ExclamationIcon from "../../public/img/icons/exclamationIcon";
+import { SolidSuccessIcon } from "../../public/img/icons/successIcon";
-export default function DisclaimerBox({ title, text, children, ...style }) {
+export function DisclaimerBox({ title, text, children, ...style }) {
return (
- );
+ )
}
+
+export function AlertDiscalimerBox({ type = "info", text, children, ...props }) {
+ const backgroundColor = {
+ info: "#E4F2FF",
+ warning: "#FFF8DF",
+ error: "#F6E3E3",
+ success: "#D5E8DB"
+ }
+ const borderColor = {
+ info: "#0068C5",
+ warning: "#F9C50B",
+ error: "#BF3434",
+ success: "#2B8C4D"
+ }
+
+ return (
+
+
+
+ {type === "info" &&
+
+ }
+
+ {type === "warning" &&
+
+ }
+
+ {type === "error" &&
+
+ }
+
+ {type === "success" &&
+
+ }
+
+
+ {text}
+ {children}
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/next/components/molecules/Footer.js b/next/components/molecules/Footer.js
index 44d08a6e..ca4600cc 100644
--- a/next/components/molecules/Footer.js
+++ b/next/components/molecules/Footer.js
@@ -2,11 +2,11 @@ import {
HStack,
Stack,
VStack,
+ Text
} from "@chakra-ui/react";
-import { useState, useEffect } from "react";
import Link from "../atoms/Link";
import BodyText from "../atoms/BodyText"
-import { useCheckMobile } from "../../hooks/useCheckMobile.hook"
+import { isMobileMod } from "../../hooks/useCheckMobile.hook"
import YoutubeIcon from "../../public/img/icons/youtubeIcon";
import TwitterIcon from "../../public/img/icons/twitterIcon";
@@ -62,13 +62,61 @@ function FooterLink(props) {
)
}
-export default function Footer({ ocult = false }) {
- const mobileCheck = useCheckMobile()
- const [isMobileMod, setIsMobileMod] = useState(false)
-
- useEffect(() => {
- setIsMobileMod(mobileCheck)
- },[])
+function TextFooterSimple({children, ...props}) {
+ return (
+
+ {children}
+
+ )
+}
+
+export default function Footer({ template, ocult = false }) {
+ if(template === "simple") return (
+
+
+
+
+ ® 2024 Base dos Dados
+
+
+ Termos de Uso
+
+
+ Políticas de Privacidade
+
+
+ Contato
+
+
+
+
+ )
if(ocult === true) return null
@@ -105,17 +153,17 @@ export default function Footer({ ocult = false }) {
-
+
Mecanismo de busca
@@ -133,7 +181,7 @@ export default function Footer({ ocult = false }) {
-
+
Captura de dados
@@ -148,7 +196,7 @@ export default function Footer({ ocult = false }) {
-
+
Documentação
@@ -157,7 +205,7 @@ export default function Footer({ ocult = false }) {
-
+
Quem somos
@@ -189,7 +237,7 @@ export default function Footer({ ocult = false }) {
@@ -198,17 +246,17 @@ export default function Footer({ ocult = false }) {
maxWidth="1264px"
margin="0 auto"
justifyContent="space-between"
- flexDirection={isMobileMod && "column-reverse"}
+ flexDirection={isMobileMod() && "column-reverse"}
alignItems="flex-start"
spacing={0}
>
® 2024 Base dos Dados
diff --git a/next/components/molecules/FormTable.js b/next/components/molecules/FormTable.js
index c33bf77a..ab8a7b8d 100644
--- a/next/components/molecules/FormTable.js
+++ b/next/components/molecules/FormTable.js
@@ -6,7 +6,6 @@ import {
Input,
Textarea,
Select,
- Checkbox,
Alert,
AlertIcon,
AlertTitle,
@@ -21,6 +20,7 @@ import {
} from "@chakra-ui/react";
import { useState, useEffect } from "react"
import { useRouter } from "next/router";
+import Checkbox from "../atoms/Checkbox";
import RoundedButton from "../atoms/RoundedButton";
import SelectSearch from "../atoms/SelectSearch";
import LoadingSpin from "../atoms/Loading";
diff --git a/next/components/molecules/Menu.js b/next/components/molecules/Menu.js
index 9859681b..ae77a85b 100644
--- a/next/components/molecules/Menu.js
+++ b/next/components/molecules/Menu.js
@@ -26,9 +26,10 @@ import { useRouter } from "next/router"
import cookies from "js-cookie";
import MenuDropdown from "./MenuDropdown";
import { isMobileMod, useCheckMobile } from "../../hooks/useCheckMobile.hook"
-import ControlledInput from "../atoms/ControlledInput";
+import { ControlledInputSimple } from "../atoms/ControlledInput";
import Link from "../atoms/Link";
import RoundedButton from "../atoms/RoundedButton";
+import HelpWidget from "../atoms/HelpWidget";
import { triggerGAEvent } from "../../utils";
import BDLogoProImage from "../../public/img/logos/bd_logo_pro";
@@ -37,7 +38,6 @@ import BDLogoLabImage from "../../public/img/logos/bd_logo_lab";
import BDLogoImage from "../../public/img/logos/bd_logo";
import FarBarsIcon from "../../public/img/icons/farBarsIcon";
import SearchIcon from "../../public/img/icons/searchIcon";
-import CrossIcon from "../../public/img/icons/crossIcon";
import RedirectIcon from "../../public/img/icons/redirectIcon";
import SettingsIcon from "../../public/img/icons/settingsIcon";
import SignOutIcon from "../../public/img/icons/signOutIcon";
@@ -62,6 +62,7 @@ function MenuDrawer({ userData, isOpen, onClose, links }) {
backgroundColor={b.color}
minWidth="100px"
height="38px"
+ fontFamily="Roboto"
fontSize="20px"
borderRadius="30px"
onClick={() => window.open(b.href, "_blank")}
@@ -81,7 +82,8 @@ function MenuDrawer({ userData, isOpen, onClose, links }) {
>
@@ -104,8 +106,9 @@ function MenuDrawer({ userData, isOpen, onClose, links }) {
display="flex"
gap="16px"
fontSize="16px"
- fontFamily="Ubuntu"
- fontWeight="300"
+ fontFamily="Roboto"
+ letterSpacing="0.1px"
+ fontWeight="400"
href={c.href}
>{c.icon && c.icon} {c.name}
)
@@ -119,7 +122,8 @@ function MenuDrawer({ userData, isOpen, onClose, links }) {
{key}
@@ -133,26 +137,56 @@ function MenuDrawer({ userData, isOpen, onClose, links }) {
<>>
:
- window.open("/user/login", "_self")}
+
Entrar
-
- window.open("/user/register", "_self")}
+
+
+
Cadastrar
-
+
}
@@ -200,19 +234,19 @@ function MenuDrawerUser({ userData, isOpen, onClose}) {
{userData?.username || ""}
{userData?.email || ""}
@@ -227,10 +261,10 @@ function MenuDrawerUser({ userData, isOpen, onClose}) {
Configurações
@@ -250,10 +284,10 @@ function MenuDrawerUser({ userData, isOpen, onClose}) {
key={index}
color="#575757"
fontSize="14px"
- fontFamily="Ubuntu"
+ fontFamily="Roboto"
+ letterSpacing="0.1px"
fontWeight="400"
lineHeight="27px"
- letterSpacing="0.3px"
onClick={() => {
onClose()
router.push({pathname: `/user/${userData.username}`, query: elm.value})}
@@ -268,24 +302,30 @@ function MenuDrawerUser({ userData, isOpen, onClose}) {
{
cookies.remove('userBD', { path: '/' })
cookies.remove('token', { path: '/' })
window.open("/", "_self")
}}
>
-
+
Sair
@@ -322,7 +362,7 @@ function MenuUser ({ userData, onOpen, onClose }) {
{userData?.username ? userData?.username : ""}
{userData?.email ? userData?.email : ""}
@@ -420,20 +460,20 @@ function MenuUser ({ userData, onOpen, onClose }) {
window.open(`/user/${userData.username}`, "_self")}
>
-
+
Configurações
@@ -442,10 +482,10 @@ function MenuUser ({ userData, onOpen, onClose }) {
{
cookies.remove('userBD', { path: '/' })
cookies.remove('token', { path: '/' })
@@ -455,11 +495,11 @@ function MenuUser ({ userData, onOpen, onClose }) {
Sair
@@ -471,169 +511,105 @@ function MenuUser ({ userData, onOpen, onClose }) {
}
-function SearchInput ({ status }) {
- const router = useRouter()
- const { query } = router
- const [showSearchInput, setShowSearchInput] = useState(false)
-
- const [showSearch, setShowSearch] = useState(false)
+function SearchInputUser ({ user }) {
+ const inputMobileRef = useRef(null)
const [search, setSearch] = useState("")
+ const [showInput, setShowInput] = useState(false)
+ const [inputFocus, setInputFocus] = useState(false)
- const searchStatus = () => {
- const newStatus = !showSearch
- setShowSearch(newStatus)
- status({
- status: newStatus
- })
+ function openSearchLink() {
+ if(search.trim() === "") return
+ triggerGAEvent("search_menu", search.trim())
+ window.open(`/dataset?q=${search.trim()}`, "_self")
}
- useEffect(() => {
- if(query.dataset) return setShowSearchInput(true)
- },[query])
-
- function openSearchLink() {
- triggerGAEvent("search_menu", search)
- window.open(`/dataset?q=${search}`, "_self")
+ const handleClickOutside = (event) => {
+ if (inputMobileRef.current && !inputMobileRef.current.contains(event.target)) {
+ setShowInput(false);
+ }
}
- if(!showSearchInput) return null
-
- return (
- <>
- {!showSearch ?
-
- :
- {
+ if (showInput) {
+ document.addEventListener('click', handleClickOutside)
+ } else {
+ document.removeEventListener('click', handleClickOutside)
+ }
+
+ return () => {
+ document.removeEventListener('click', handleClickOutside)
+ }
+ }, [showInput])
+
+ if (isMobileMod()) return (
+
+
+ openSearchLink()}
/>
}
/>
- }
- >
+
+
+ {
+ setShowInput(true)
+ setTimeout(() => {
+ inputMobileRef.current.focus()
+ }, 0)
+ }}
+ />
+
)
-}
-
-function SearchInputUser () {
- const [search, setSearch] = useState("")
- const [showSearch, setShowSearch] = useState(false)
-
- function openSearchLink() {
- triggerGAEvent("search_menu", search)
- window.open(`/dataset?q=${search}`, "_self")
- }
-
- // if(isMobileMod()) return (
- //
- // setShowSearch(true)}
- // />
- //
- // openSearchLink()}
- // />
- // }
- // />
- //
- //
- // )
-
- if(isMobileMod()) return null
return (
- openSearchLink()}
/>
}
@@ -643,12 +619,6 @@ function SearchInputUser () {
}
function DesktopLinks({ userData, links, position = false, path, userTemplate = false }) {
- const [statusSearch, setStatusSearch] = useState(false)
-
- const searchStatus = (elm) => {
- setStatusSearch(elm.status)
- }
-
function LinkMenuDropDown ({ url, text, icon }) {
const [flag, setFlag] = useBoolean()
@@ -658,13 +628,14 @@ function DesktopLinks({ userData, links, position = false, path, userTemplate =
@@ -703,7 +674,11 @@ function DesktopLinks({ userData, links, position = false, path, userTemplate =
backgroundColor={b.color}
minWidth="80px"
height="35px"
- fontSize="15px"
+ fontSize="14px"
+ fontFamily="Roboto"
+ letterSpacing="0.1px"
+ fontWeight="400"
+ lineHeight="20px"
borderRadius="30px"
>
{b.name}
@@ -721,9 +696,11 @@ function DesktopLinks({ userData, links, position = false, path, userTemplate =
marginTop="10px"
minWidth="202px"
borderColor="#FFF"
- fontFamily="Ubuntu"
+ fontSize="14px"
+ fontFamily="Roboto"
+ letterSpacing="0.1px"
fontWeight="400"
- letterSpacing="0.3px"
+ lineHeight="20px"
borderRadius="10px"
padding="32px"
_first={{ paddingTop: "10px"}}
@@ -745,11 +722,12 @@ function DesktopLinks({ userData, links, position = false, path, userTemplate =
return (
@@ -759,31 +737,93 @@ function DesktopLinks({ userData, links, position = false, path, userTemplate =
})}
-
- {userTemplate && !isMobileMod() && }
-
- {!statusSearch &&
-
- {userData ? (
-
-
-
- ) : (
- <>
-
- Entrar
-
-
-
- Cadastrar
-
-
- >
- )}
-
+ {userTemplate && !isMobileMod() &&
+
}
+
+
+ {(path === "/dataset" || path === "/dataset/[dataset]") &&
+
+ }
+
+ {userData ? (
+
+
+
+ ) : (
+ <>
+
+ Entrar
+
+
+
+ Cadastrar
+
+ >
+ )}
+
- );
+ )
}
export default function MenuNav({ simpleTemplate = false, userTemplate = false }) {
@@ -797,6 +837,32 @@ export default function MenuNav({ simpleTemplate = false, userTemplate = false }
const [isScrollDown, setIsScrollDown] = useState(false)
const [userData, setUserData] = useState(null)
+ const [lastScrollY, setLastScrollY] = useState(0)
+ const [menuVisible, setMenuVisible] = useState(true)
+
+ const handleScroll = () => {
+ const currentScrollY = window.scrollY
+ if (currentScrollY > lastScrollY) {
+ setMenuVisible(false)
+ } else {
+ setMenuVisible(true)
+ }
+ setLastScrollY(currentScrollY)
+ }
+
+ useEffect(() => {
+ if(route !== "/dataset/[dataset]") return
+ window.addEventListener('scroll', handleScroll)
+ return () => {
+ window.removeEventListener('scroll', handleScroll)
+ }
+ }, [lastScrollY])
+
+ function maxWidthDataset() {
+ if (route === "/dataset" || route === "/dataset/[dataset]") return "1440px"
+ return "1264px"
+ }
+
useEffect(() => {
let userInfo = userBD
if(userInfo !== null && userInfo !== "undefined") {
@@ -833,7 +899,7 @@ export default function MenuNav({ simpleTemplate = false, userTemplate = false }
],
Contato: "/contato",
Button: []
- };
+ }
useEffect(() => {
document.addEventListener("scroll", () => {
@@ -863,16 +929,17 @@ export default function MenuNav({ simpleTemplate = false, userTemplate = false }
width="100%"
left="0px"
backgroundColor="#FFFFFF"
- padding="16px 28px"
+ padding={isMobileMod() ? "15px 20px" : "15px 24px"}
zIndex="99"
transition="0.5s"
as="nav"
+ transform={menuVisible ? 'translateY(0)' : 'translateY(-100%)'}
>
@@ -883,6 +950,7 @@ export default function MenuNav({ simpleTemplate = false, userTemplate = false }
top="0"
left="0"
margin="20px 0 0 20px"
+ marginRight="auto"
width="30px"
height="30px"
onClick={menuDisclosure.onOpen}
@@ -895,8 +963,13 @@ export default function MenuNav({ simpleTemplate = false, userTemplate = false }
aria-label="Home"
width={
route === "/" ?
- isScrollDown ? "88px" : "0"
- : "88px"
+ isScrollDown ? "80px" : "0"
+ : "80px"
+ }
+ minWidth={
+ route === "/" ?
+ isScrollDown ? "80px" : "0"
+ : "80px"
}
_hover={{opacity:"none"}}
href={route === "/" ? "/#home" : "/"}
@@ -921,7 +994,11 @@ export default function MenuNav({ simpleTemplate = false, userTemplate = false }
/>
}
- {userTemplate && isMobileMod() && }
+ {userTemplate && isMobileMod() &&
+
+ }
{useCheckMobile() && userData &&
{
return (
{string}
@@ -146,285 +142,233 @@ export function TemporalCoverageBar ({ value }) {
)
}
- value = !!value ? Object.values(value) : null
+ useEffect(() => {
+ if (value === null || value === undefined) return setValues(null)
- if(!value) return
- if(!value.length) return
+ let newValue = {}
- let dateStart = ""
- let dateMid = ""
- let dateEnd = ""
+ if(value["2"]?.type === "closed") newValue["3"] = value["2"].date
- if (value.length === 2) {
- dateStart = value[0]
- dateEnd = value[1]
- }
+ if(value["0"]?.type === "open") newValue["0"] = value["0"].date
+ if(value["0"]?.type === "closed") newValue["2"] = value["0"].date
- if (value.length === 3) {
- dateStart = value[0]
- dateMid = value[1]
- dateEnd = value[2]
- }
+ if(value["1"]?.type === "open") newValue["1"] = value["1"].date
+ if(value["1"]?.type === "closed") newValue["3"] = value["1"].date
- const checkoutBdpro = (value) => {
- if(value === "open") return
- window.open("/precos", "_blank")
- }
+ setValues(newValue)
+ }, [value])
- const BadgeContainer = ({
- value,
- bool = false,
- mouseOn = null,
- mouseOff = null,
- ...props
- }) => {
- const toggleTag = value === "open"
+ if(values === null) return
- return (
- checkoutBdpro(value)}
- _hover={toggleTag ? "" : {opacity: 0.7}}
- opacity={bool && 0.7}
- onMouseEnter={mouseOn}
- onMouseLeave={mouseOff}
- cursor="pointer"
- >{toggleTag ?
- "GRÁTIS" :
- PAGO
-
- }
-
- )
- }
-
- const TooltipContent = ({children, text, firstValue, lastValue, ...props}) => {
- return (
+ return (
+
+
+ GRÁTIS
+
+
- {text}
-
-
+
-
-
- ─
-
-
-
-
+
-
- }
- hasArrow
- bg="#2A2F38"
- fontSize="16px"
- fontWeight="400"
- padding="5px 16px 6px"
- marginTop="10px"
- color="#FFF"
- borderRadius="6px"
- placement="top"
- top="-4px"
- fontFamily="lato"
- {...props}
- >
- {children}
-
- )
- }
- return (
-
-
-
-
-
-
-
-
-
-
-
- {dateMid !== "" &&
-
-
-
+
-
-
+ position="absolute"
+ display="flex"
+ alignItems="center"
+ flexDirection="column"
+ right={0}
+ top="-3px"
+ >
+
+
+
-
-
-
-
-
+
- }
+
-
-
+
- checkoutBdpro(dateEnd?.type)}
- onMouseEnter={setFlag.on}
- onMouseLeave={setFlag.off}
- />
-
-
-
-
-
-
-
-
-
+ width="100%"
+ borderBottom="solid 3px #0068C5"
+ marginBottom="10px"
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
)
}
\ No newline at end of file
diff --git a/next/components/organisms/BdmTablePage.js b/next/components/organisms/BdmTablePage.js
index 4c303173..d83bd530 100644
--- a/next/components/organisms/BdmTablePage.js
+++ b/next/components/organisms/BdmTablePage.js
@@ -1,99 +1,100 @@
import {
- VStack,
+ HStack,
Stack,
Box,
Text,
- Grid,
- GridItem,
+ Skeleton,
+ SkeletonText,
+ Divider,
Tooltip,
} from "@chakra-ui/react";
import { useState, useEffect } from "react";
-import { useCheckMobile } from "../../hooks/useCheckMobile.hook";
-import Link from "../atoms/Link";
-import SectionText from "../atoms/SectionText";
-import { SimpleTable } from "../atoms/SimpleTable";
-import LoadingSpin from "../atoms/Loading";
-import Subtitle from "../atoms/Subtitle";
+import ReadMore from "../atoms/ReadMore";
+import { formatBytes } from "../../utils";
+import ObservationLevel from "../atoms/ObservationLevelTable";
import { TemporalCoverageBar } from "../molecules/TemporalCoverageDisplay";
-import ColumnDatasets from "../molecules/ColumnDatasets";
-import BaseResourcePage from "../molecules/BaseResourcePage";
import DataInformationQuery from "../molecules/DataInformationQuery";
import FourOFour from "../templates/404";
-import StarIcon from "../../public/img/icons/starIcon";
-import FrequencyIcon from "../../public/img/icons/frequencyIcon";
-import PartitionIcon from "../../public/img/icons/partitionIcon";
-import UserIcon from "../../public/img/icons/userIcon";
-import VersionIcon from "../../public/img/icons/versionIcon";
import EmailIcon from "../../public/img/icons/emailIcon";
import GithubIcon from "../../public/img/icons/githubIcon";
import WebIcon from "../../public/img/icons/webIcon";
import TwitterIcon from "../../public/img/icons/twitterIcon";
-import FileIcon from "../../public/img/icons/fileIcon";
import InfoIcon from "../../public/img/icons/infoIcon";
import DownloadIcon from "../../public/img/icons/downloadIcon";
+import RedirectIcon from "../../public/img/icons/redirectIcon";
export default function BdmTablePage({ id }) {
const [isLoading, setIsLoading] = useState(true)
const [resource, setResource] = useState({})
- const [isError, setIsError] = useState({})
-
- const fetchBdmTable = async () => {
- try {
- const result = await fetch(`/api/tables/getBdmTable?p=${id}`, { method: "GET" })
- .then(res => res.json())
- setResource(result)
- } catch (error) {
- setIsError(error)
- console.error(error)
- }
- setIsLoading(false)
- }
+ const [isError, setIsError] = useState(false)
useEffect(() => {
- fetchBdmTable()
+ const fetchData = async () => {
+ setIsLoading(true)
+ try {
+ const response = await fetch(`/api/tables/getBdmTable?p=${id}`, { method: "GET" })
+ const result = await response.json()
+
+ if (result.success) {
+ setResource(result.resource)
+ setIsError(false)
+ } else {
+ console.error(result.error)
+ setIsError(true)
+ }
+ } catch (error) {
+ console.error("Fetch error: ", error)
+ setIsError(true)
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ fetchData()
}, [id])
- const AddInfoTextBase = ({title, text, info, children, ...style}) => {
+ const TooltipText = ({ text, info, ...props }) => {
return (
-
+
{title}
- {info &&
-
-
-
- }
-
-
+ >
{text}
-
- {children}
+
+
+
+
)
}
@@ -125,225 +126,621 @@ export default function BdmTablePage({ id }) {
return {
alt: alt,
cursor: "pointer",
- width:"18px",
- height:"18px",
- fill: "#42B0FF",
+ width:"20px",
+ height:"20px",
+ fill: "#0068C5",
+ _hover: {
+ fill: "#0057A4"
+ },
onClick: () => {window.open(href)}
}
}
const PublishedOrDataCleanedBy = ({ resource }) => {
-
return (
- <>
- {resource?.firstName && resource?.lastName ? {`${resource.firstName} ${resource.lastName}`} : Não listado }
+
+ {resource?.firstName && resource?.lastName ?
+
+ {`${resource.firstName} ${resource.lastName}`}
+
+ :
+
+ Não informado
+
+ }
{resource?.email && }
{resource?.github && }
{resource?.website && }
{resource?.twitter && }
- >
+
)
}
- const UpdateFrequency = () => {
- const value = resource?.updates?.[0]
- if(value === undefined || Object.keys(value).length === 0) return "Não listado"
-
- if(value?.frequency >= 0 && value?.entity?.name) return `${value.frequency} ${value.entity.name}`
- if(value?.entity?.name) return `${value.entity.name}`
-
- return "Não listado"
- }
-
- const Empty = () => {
+ const StackSkeleton = ({ children, ...props }) => {
return (
-
- Não listado
-
+
+ {children}
+
)
}
- const ObservationLevel = () => {
- const notFound = Nenhum nível da observação fornecido.
- if(resource?.observationLevels === undefined || Object.keys(resource?.observationLevels).length === 0) return notFound
-
- let array = []
- const keys = Object.keys(resource?.observationLevels)
-
- keys.forEach((elm) => {
- const value = resource?.observationLevels[elm]
+ const formatDate = (value) => {
+ const date = new Date(value);
+ const formattedDate = date.getFullYear()+"-"+String(date.getMonth() + 1).padStart(2, "0")+"-"+String(date.getDate()).padStart(2, "0")
+ return formattedDate
+ }
- const newValue = [value?.entity?.name || , value?.columns[0]?.name || ]
- array.push(newValue)
- })
+ const getUpdateFormat = (value) => {
+ const formats = {
+ "second":"Atualização por segundo",
+ "minute":"Atualização por minuto",
+ "hour":"Atualização por hora",
+ "day":"Atualização diária",
+ "week":"Atualização semanal",
+ "month":"Atualização mensal",
+ "bimester":"Atualização bimestral",
+ "quarter":"Atualização trimestral",
+ "semester":"Atualização semestral",
+ "year":"Atualização anual",
+ }
- return (
-
- )
+ return formats[value] ? formats[value] : "Atualização não definida"
}
- if(isError?.message?.length > 0 || resource === null || Object.keys(resource).length < 0) return
-
- if(isLoading) return
+ if(isError) return
return (
-
-
-
-
- Descrição
-
- {resource.description || "Nenhuma descrição fornecida."}
-
-
-
-
+
+ {resource?.name}
+
+ {resource?.uncompressedFileSize &&
+
+ {`(${formatBytes(resource.uncompressedFileSize)})`}
+
+ }
+
+
+
- Cobertura temporal
-
-
-
-
-
- Colunas
-
-
-
-
-
-
- Nível da observação
-
-
-
-
-
-
- Informações adicionais
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ {resource?.description || "Não informado"}
+
+
+
+
+
+
+ Cobertura temporal da tabela
+
+
+
+
+
+
+
+
+
+
+
+ Acesso aos dados
+
+
+
+
+
+
+
+
+
+ Frequência de atualização dos dados
+
+
+
+
+
+ {resource?.updates?.[0]?.latest ?
+ formatDate(resource.updates[0].latest)
+ :
+ "Não informado"
+ }: Última vez que atualizamos na BD
+ {resource?.updates?.[0]?.entity?.slug &&
Publicação por
-
-
-
-
-
-
-
-
-
+ >
+ {getUpdateFormat(resource.updates[0].entity.slug)}
+
+ }
+ {!resource?.updates?.[0] &&
Tratamento por
-
-
-
-
-
-
-
-
-
+ Sem previsão de atualização
+
+ }
+
+
+ {resource?.rawDataSource?.[0]?.updates?.[0]?.latest ?
+ formatDate(resource.rawDataSource[0].updates[0].latest)
+ :
+ "Não informado"
+ }: Última vez que atualizaram na fonte original
+ {resource?.rawDataSource?.[0]?.updates?.[0]?.entity?.slug ?
+
+ {getUpdateFormat(resource?.rawDataSource?.[0]?.updates?.[0]?.entity?.slug)}
+
+ :
+ !resource?.rawDataSource?.[0]?.updates?.[0] || !resource?.updates?.[0]?.frequency ?
+
+ Sem previsão de atualização
+
+ :
+ <>>
+ }
+
+
+ {resource?.rawDataSource?.[0]?.polls?.[0]?.latest ?
+ formatDate(resource.rawDataSource[0].polls[0].latest)
+ :
+ "Não informado"
+ }: Última vez que verificamos a fonte original
+
+
+
+
+
+
+
+ ID do BigQuery
+
+
+
+
+
+ {!resource?.cloudTables ?
+ "Não informado"
+ :
+ resource?.cloudTables?.[0]?.gcpProjectId+"."+resource?.cloudTables?.[0]?.gcpDatasetId+"."+resource?.cloudTables?.[0]?.gcpTableId
+ }
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+ {resource?.partitions ? resource.partitions :"Não informado"}
+
+
+
+
+
+
+
+
+
+
+ {resource?.observationLevels && Object.keys(resource?.observationLevels).length > 0 ?
+
+ :
+
- {resource?.auxiliaryFilesUrl &&
-
- Download dos arquivos
-
-
- }
-
-
-
-
-
+ Não informado
+
+ }
+
+
+
+
+
+
+
+
+
+ {resource?.auxiliaryFilesUrl ?
+
+ Download dos arquivos
+
+
+ :
+ "Não informado"
+ }
+
+
+
+
+
+
+
+
+
+
+
+ {resource?.rawDataSource?.[0]?._id && resource?.rawDataSource?.[0]?.dataset?._id ?
+
+ {resource.rawDataSource[0].name}
+
+ :
+ "Não informado"
+ }
+
+
+
+
+
+
+
+
+ Informações adicionais
+
+
+
+
+ Publicação por
+
+
+
+
+ Tratamento por
+
+
+
+
+ Versão
+ {resource?.version || "Não informado"}
+
+
)
}
diff --git a/next/components/organisms/Database.js b/next/components/organisms/Database.js
index 5529952f..a661d5dc 100644
--- a/next/components/organisms/Database.js
+++ b/next/components/organisms/Database.js
@@ -1,21 +1,12 @@
import {
- Heading,
HStack,
Image,
Stack,
VStack,
- Flex,
Text,
- Center,
- Tooltip,
+ Box
} from "@chakra-ui/react";
import { useCheckMobile } from "../../hooks/useCheckMobile.hook";
-import { CategoryIcon } from "../atoms/CategoryIcon";
-import Title from "../atoms/Title";
-import Link from "../atoms/Link";
-import SectionText from "../atoms/SectionText";
-import { ImageOrganization } from "../atoms/ImageOrganization";
-import { TemporalCoverageString } from "../molecules/TemporalCoverageDisplay";
import LinkIcon from "../../public/img/icons/linkIcon";
import InfoArrowIcon from "../../public/img/icons/infoArrowIcon";
@@ -30,7 +21,6 @@ export default function Database({
rawDataSources,
informationRequests,
contains,
- themes = [],
}) {
const Tables = () => {
@@ -38,32 +28,38 @@ export default function Database({
if(tables.number === undefined) tablesNumber = 0
return (
- 0 && `/dataset/${id}?table=${tables.id}`}>
- 0 ? "pointer" : "normal"}
- _hover={tablesNumber > 0 && {opacity: "0.7"}}
+ 0 ? "pointer" : "normal"}
+ color={tablesNumber === 0 ? "#ACAEB1" : "#0068C5"}
+ fill={tablesNumber === 0 ? "#ACAEB1" : "#0068C5"}
+ pointerEvents={tablesNumber === 0 && "none"}
+ fontFamily="Roboto"
+ fontWeight="400"
+ fontSize="14px"
+ lineHeight="20px"
+ _hover={{
+ color: "#0057A4",
+ fill: "#0057A4"
+ }}
+ href={tablesNumber > 0 ? `/dataset/${id}?table=${tables.id}` : ""}
+ >
+
+
-
-
- {tablesNumber}{" "}
- {tablesNumber === 1 ? "tabela tratada" : "tabelas tratadas"}
-
-
-
+ {tablesNumber}{" "}
+ {tablesNumber === 1 ? "tabela tratada" : "tabelas tratadas"}
+
+
)
}
@@ -72,28 +68,38 @@ export default function Database({
if(rawDataSources.number === undefined) rawDataSourcesNumber = 0
return (
- 0 && `/dataset/${id}?raw_data_source=${rawDataSources.id}`}>
- 0 ? "pointer" : "normal"}
- _hover={rawDataSourcesNumber > 0 && {opacity: "0.7"}}
+ 0 ? "pointer" : "normal"}
+ color={rawDataSourcesNumber === 0 ? "#ACAEB1" : "#0068C5"}
+ fill={rawDataSourcesNumber === 0 ? "#ACAEB1" : "#0068C5"}
+ pointerEvents={rawDataSourcesNumber === 0 && "none"}
+ fontFamily="Roboto"
+ fontWeight="400"
+ fontSize="14px"
+ lineHeight="20px"
+ _hover={{
+ color: "#0057A4",
+ fill: "#0057A4"
+ }}
+ href={rawDataSourcesNumber > 0 ? `/dataset/${id}?raw_data_source=${rawDataSources.id}` : ""}
+ >
+
+
-
-
- {rawDataSourcesNumber}{" "}
- {rawDataSourcesNumber === 1 ? "fonte original" : "fontes originais"}
-
-
-
+ {rawDataSourcesNumber}{" "}
+ {rawDataSourcesNumber === 1 ? "fonte original" : "fontes originais"}
+
+
)
}
@@ -102,29 +108,38 @@ export default function Database({
if(informationRequests.number === undefined) informationRequestsNumber = 0
return (
- 0 && `/dataset/${id}?information_request=${informationRequests.id}`}>
- 0 ? "pointer" : "normal"}
- _hover={informationRequestsNumber > 0 && {opacity: "0.7"}}
+ 0 ? "pointer" : "normal"}
+ color={informationRequestsNumber === 0 ? "#ACAEB1" : "#0068C5"}
+ fill={informationRequestsNumber === 0 ? "#ACAEB1" : "#0068C5"}
+ pointerEvents={informationRequestsNumber === 0 && "none"}
+ fontFamily="Roboto"
+ fontWeight="400"
+ fontSize="14px"
+ lineHeight="20px"
+ _hover={{
+ color: "#0057A4",
+ fill: "#0057A4"
+ }}
+ href={informationRequestsNumber > 0 ? `/dataset/${id}?information_request=${informationRequests.id}` : ""}
+ >
+
+
-
-
- {informationRequestsNumber}{" "}
- {informationRequestsNumber === 1 ? "pedido LAI" : "pedidos LAI"}
-
-
-
+ {informationRequestsNumber}{" "}
+ {informationRequestsNumber === 1 ? "pedido LAI" : "pedidos LAI"}
+
+
)
}
@@ -134,7 +149,6 @@ export default function Database({
alignItems="flex-start"
width="100%"
spacing={{ base: 4, md: 0 }}
- padding="16px 0px"
>
-
-
+
-
+
+
-
-
-
-
- {name}
-
-
-
- {themes.slice(0,6).map((elm, i) => (
-
-
-
-
-
-
-
- ))}
-
-
-
-
+ {name}
+
+
+
+
-
- Organização:
-
-
- {organization?.name}
-
-
-
+
+ Organização:
+
+
+ {organization?.name}
+
+
-
+ Cobertura temporal:
+
+
- Cobertura temporal:
-
-
+ {temporalCoverageText ? temporalCoverageText : "Não informado"}
+
+
-
+ Recursos:
+
+
- Recursos:
-
- {contains.free && "Grátis"} {contains.free && contains.pro && "e"} {contains.pro && "Pro"}
- {!contains.free && !contains.pro && "Não listado"}
-
-
+ {contains.free && "Grátis"} {contains.free && contains.pro && "e"} {contains.pro && "Pagos"}
+ {!contains.free && !contains.pro && "Não informado"}
+
-
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/next/components/organisms/DatasetResource.js b/next/components/organisms/DatasetResource.js
index 6c98aba3..6d1f4c90 100644
--- a/next/components/organisms/DatasetResource.js
+++ b/next/components/organisms/DatasetResource.js
@@ -1,12 +1,13 @@
import {
Stack,
VStack,
+ Box,
+ HStack,
+ Divider,
+ Text
} from "@chakra-ui/react";
import { useEffect, useState } from "react";
import { useRouter } from "next/router";
-import { isMobileMod } from "../../hooks/useCheckMobile.hook";
-
-import { FilterAccordion } from "../atoms/FilterAccordion";
import BdmTablePage from "./BdmTablePage";
import RawDataSourcesPage from "./RawDataSourcesPage";
@@ -41,7 +42,18 @@ export default function DatasetResource({
}
useEffect(() => {
- const dataset_tables = dataset?.tables?.edges.map((elm) => elm.node).filter((elm) => elm?.status?.slug !== "under_review").sort(sortElements) || []
+ // Id do dataset do SAEB
+ let dataset_tables = []
+ if(dataset?._id === "e083c9a2-1cee-4342-bedc-535cbad6f3cd") {
+ dataset_tables = dataset?.tables?.edges.map((elm) => elm.node)
+ .filter((elm) => elm?.status?.slug !== "under_review").sort(sortElements) || []
+ } else {
+ dataset_tables = dataset?.tables?.edges.map((elm) => elm.node)
+ .filter((elm) => elm?.status?.slug !== "under_review")
+ .filter((elm) => elm?.slug !== "dicionario")
+ .filter((elm) => elm?.slug !== "dictionary").sort(sortElements) || []
+ }
+
const raw_data_sources = dataset?.rawDataSources?.edges.map((elm) => elm.node).filter((elm) => elm?.status?.slug !== "under_review").sort(sortElements) || []
const information_request = dataset?.informationRequests?.edges.map((elm) => elm.node).filter((elm) => elm?.status?.slug !== "under_review").sort(sortElements) || []
@@ -56,7 +68,7 @@ export default function DatasetResource({
if(raw_data_sources.length > 0) return pushQuery("raw_data_source", raw_data_sources[0]?._id)
if(information_request.length > 0) return pushQuery("information_request", information_request[0]?._id)
}
- },[])
+ }, [dataset])
function SwitchResource ({route}) {
if (route.hasOwnProperty("table")) return
@@ -65,70 +77,121 @@ export default function DatasetResource({
return null
}
+ function ContentFilter({
+ fieldName,
+ choices,
+ onChange,
+ value,
+ hasDivider = true
+ }) {
+ if(choices.length < 1) return null
+
+ return (
+
+
+
+
+ {fieldName}
+
+
+
+ {choices.map((elm, i) => (
+
+
+ onChange(elm._id)}
+ >
+ {elm.name || elm.number}
+
+
+ ))}
+
+
+ )
+ }
+
return (
-
- {
pushQuery("table", id)
}}
+ hasDivider={false}
/>
- {
pushQuery("raw_data_source", id)
}}
+ hasDivider={tables.length > 0 ? true : false}
/>
- {
pushQuery("information_request", id)
}}
+ hasDivider={tables.length > 0 || rawDataSources.length > 0 ? true : false}
/>
-
-
-
-
-
+
+
+
)
}
\ No newline at end of file
diff --git a/next/components/organisms/InformationRequestPage.js b/next/components/organisms/InformationRequestPage.js
index b1b39d07..ad04a34e 100644
--- a/next/components/organisms/InformationRequestPage.js
+++ b/next/components/organisms/InformationRequestPage.js
@@ -1,201 +1,259 @@
import {
- VStack,
- HStack,
Stack,
- Center,
- Image,
Box,
Text,
- Grid,
- GridItem,
+ Skeleton,
+ SkeletonText,
+ Divider
} from "@chakra-ui/react";
import { useEffect, useState } from "react";
-import { useCheckMobile } from "../../hooks/useCheckMobile.hook";
-import LoadingSpin from "../atoms/Loading";
-import Subtitle from "../atoms/Subtitle";
-import SectionText from "../atoms/SectionText";
-import RoundedButton from "../atoms/RoundedButton";
+import ReadMore from "../atoms/ReadMore";
import { TemporalCoverage } from "../molecules/TemporalCoverageDisplay";
-import BaseResourcePage from "../molecules/BaseResourcePage";
-import DisclaimerBox from "../molecules/DisclaimerBox";
+import { AlertDiscalimerBox } from "../molecules/DisclaimerBox";
import FourOFour from "../templates/404";
-import {
- getInformationRequest
-} from "../../pages/api/datasets/index";
-
-import StatusIcon from "../../public/img/icons/statusIcon";
-import UserIcon from "../../public/img/icons/userIcon";
-import ExclamationIcon from "../../public/img/icons/exclamationIcon";
import RedirectIcon from "../../public/img/icons/redirectIcon";
export default function InformationRequestPage({ id }) {
const [isLoading, setIsLoading] = useState(true)
const [resource, setResource] = useState({})
- const [isError, setIsError] = useState({})
-
- const featchInformationRequest = async () => {
- try {
- const result = await getInformationRequest(id)
- setResource(result)
- } catch (error) {
- setIsError(error)
- console.error(error)
- }
- setIsLoading(false)
- }
+ const [isError, setIsError] = useState(false)
useEffect(() => {
+ const featchInformationRequest = async () => {
+ setIsLoading(true)
+
+ try {
+ const response = await fetch(`/api/datasets/getInformationRequest?p=${id}`, { method: "GET" })
+ const result = await response.json()
+
+ if (result.success) {
+ setResource(result.resource)
+ setIsError(false)
+ } else {
+ console.error(result.error)
+ setIsError(true)
+ }
+ } catch (error) {
+ console.error("Fetch error: ", error)
+ setIsError(true)
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
featchInformationRequest()
},[id])
- const AddInfoTextBase = ({title, text, children, ...style}) => {
+ const AddInfoTextBase = ({ title, text, ...props }) => {
return (
-
+
{title}
-
- {text}
-
- {children}
-
+ {text || "Não informado"}
+
)
}
+ const StackSkeleton = ({ children, ...props }) => {
+ return (
+
+ {children}
+
+ )
+ }
- if(isError?.message?.length > 0 || resource === null || Object.keys(resource).length < 0) return
-
- if(isLoading) return
+ if(isError) return
return (
-
-
+
+ Número do pedido: {resource?.number}
+
+
+
+
+
+ Estes dados não passaram pela metodologia de tratamento da Base dos Dados.
+
+
+
+
-
- Consulta aos dados
-
-
-
-
- ATENÇÃO:
-
-
- Estes dados não passaram pela metodologia de tratamento da Base dos Dados.
-
-
-
-
-
+ Acessar dados
+
+
+
+
+ Acessar pedido
+
+
+
+
+
+
+
-
-
-
- Acessar dados
-
-
-
-
-
-
- Acessar pedido
-
-
-
-
-
-
+
+
+
- Descrição
-
- {resource?.observations || "Nenhuma descrição fornecida."}
-
-
-
-
- Cobertura temporal
-
-
-
-
-
-
-
- Informações adicionais
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ {resource?.observations || "Não informado"}
+
+
+
+
+
+
+
+
+ Informações adicionais
+
+
+
+
+
)
}
diff --git a/next/components/organisms/PaymentSystem.js b/next/components/organisms/PaymentSystem.js
index 870618d2..28633997 100644
--- a/next/components/organisms/PaymentSystem.js
+++ b/next/components/organisms/PaymentSystem.js
@@ -21,20 +21,35 @@ import {
const stripePromise = loadStripe(process.env.NEXT_PUBLIC_KEY_STRIPE)
-const PaymentForm = ({ onSucess, onErro }) => {
+const PaymentForm = ({ onSucess, onErro, clientSecret}) => {
const stripe = useStripe()
const elements = useElements()
const handlerSubmit = async (e) => {
e.preventDefault()
- const data = await stripe.confirmPayment({
- elements,
- redirect: 'if_required',
- })
-
- if(data?.error?.code === "card_declined") return onErro()
- if(data?.paymentIntent?.status === "succeeded") return onSucess()
+ const isSetupIntent = clientSecret.startsWith('seti_');
+ if (isSetupIntent) {
+ await elements.submit();
+
+ const data = await stripe.confirmSetup({
+ elements,
+ clientSecret: clientSecret,
+ redirect: 'if_required',
+ });
+
+ if (data?.error?.code === "card_declined") return onErro();
+ if (data?.setupIntent?.status === "succeeded") return onSucess();
+
+ } else {
+ const data = await stripe.confirmPayment({
+ elements,
+ redirect: 'if_required',
+ })
+
+ if(data?.error?.code === "card_declined") return onErro()
+ if(data?.paymentIntent?.status === "succeeded") return onSucess()
+ }
}
return (
@@ -89,26 +104,12 @@ export default function PaymentSystem({ userData, plan, onSucess, onErro }) {
}
const customerCreatPost = async (id) => {
- let secret = ""
-
- const subscriptionCreate = await fetch(`/api/stripe/createSubscription?p=${btoa(id)}`, {method: "GET"})
+ const clientSecret = await fetch(`/api/stripe/createSubscription?p=${btoa(id)}`, {method: "GET"})
.then(res => res.json())
- if(subscriptionCreate?.clientSecret) {
- secret = subscriptionCreate?.clientSecret
+ if (clientSecret) {
+ setClientSecret(clientSecret)
}
- if(secret !== "") return setClientSecret(secret)
-
- const result = await fetch(`/api/stripe/createCustomer`, {method: "GET"})
- .then(res => res.json())
-
- if(result?.id) {
- const subscriptionCreate = await fetch(`/api/stripe/createSubscription?p=${btoa(id)}`, {method: "GET"})
- .then(res => res.json())
- secret = subscriptionCreate?.clientSecret
- }
-
- return setClientSecret(secret)
}
async function customerCreat(plan) {
@@ -169,7 +170,12 @@ export default function PaymentSystem({ userData, plan, onSucess, onErro }) {
return (
-
+
)
}
\ No newline at end of file
diff --git a/next/components/organisms/PostDatasetForm.js b/next/components/organisms/PostDatasetForm.js
index 8aa842f8..83485ec6 100644
--- a/next/components/organisms/PostDatasetForm.js
+++ b/next/components/organisms/PostDatasetForm.js
@@ -6,7 +6,6 @@ import {
Input,
Textarea,
Select,
- Checkbox,
Text,
Alert,
AlertIcon,
@@ -22,10 +21,11 @@ import {
} from "@chakra-ui/react";
import { useState, useEffect } from "react"
import { useRouter } from "next/router";
-import SelectList from "../molecules/SelectList";
+import Checkbox from "../atoms/Checkbox";
import RoundedButton from "../atoms/RoundedButton";
import SelectSearch from "../atoms/SelectSearch";
import LoadingSpin from "../atoms/Loading";
+import SelectList from "../molecules/SelectList";
import {
postDataset,
diff --git a/next/components/organisms/RawDataSourcesPage.js b/next/components/organisms/RawDataSourcesPage.js
index e4e0d091..aa8545c4 100644
--- a/next/components/organisms/RawDataSourcesPage.js
+++ b/next/components/organisms/RawDataSourcesPage.js
@@ -1,64 +1,55 @@
import {
- VStack,
- HStack,
Stack,
- Center,
Box,
Text,
- Grid,
- GridItem
+ Skeleton,
+ SkeletonText,
+ Tooltip,
+ Divider
} from "@chakra-ui/react";
import { useState, useEffect } from "react";
-import { useCheckMobile } from "../../hooks/useCheckMobile.hook";
-import LoadingSpin from "../atoms/Loading";
-import { SimpleTable } from "../atoms/SimpleTable";
-import SectionText from "../atoms/SectionText";
-import Subtitle from "../atoms/Subtitle";
-import RoundedButton from "../atoms/RoundedButton";
+import ReadMore from "../atoms/ReadMore";
+import ObservationLevel from "../atoms/ObservationLevelTable";
import { TemporalCoverage } from "../molecules/TemporalCoverageDisplay";
-import BaseResourcePage from "../molecules/BaseResourcePage";
-import DisclaimerBox from "../molecules/DisclaimerBox";
+import { AlertDiscalimerBox } from "../molecules/DisclaimerBox";
import FourOFour from "../templates/404";
-import {
- getRawDataSources
-} from "../../pages/api/datasets/index";
-
import RedirectIcon from "../../public/img/icons/redirectIcon"
-import LanguageIcon from "../../public/img/icons/languageIcon";
-import DisplayIcon from "../../public/img/icons/displayIcon";
-import DataStructureIcon from "../../public/img/icons/dataStructureIcon";
-import ApiIcon from "../../public/img/icons/apiIcon";
-import FrequencyIcon from "../../public/img/icons/frequencyIcon";
-import ObservationLevelIcon from "../../public/img/icons/observationLevelIcon";
-import RegisterIcon from "../../public/img/icons/registerIcon";
-import IpIcon from "../../public/img/icons/ipIcon";
-import CoinIcon from "../../public/img/icons/coinIcon";
-import ExclamationIcon from "../../public/img/icons/exclamationIcon";
+import InfoIcon from "../../public/img/icons/infoIcon";
export default function RawDataSourcesPage({ id }) {
const [isLoading, setIsLoading] = useState(true)
const [resource, setResource] = useState({})
- const [isError, setIsError] = useState({})
-
- const featchRawDataSources = async () => {
- try {
- const result = await getRawDataSources(id)
- setResource(result)
- } catch (error) {
- setIsError(error)
- console.error(error)
- }
- setIsLoading(false)
- }
+ const [isError, setIsError] = useState(false)
useEffect(() => {
+ const featchRawDataSources = async () => {
+ setIsLoading(true)
+ try {
+ const response = await fetch(`/api/datasets/getRawDataSources?p=${id}`, { method: "GET" })
+ const result = await response.json()
+
+ if (result.success) {
+ setResource(result.resource)
+ setIsError(false)
+ } else {
+ console.error(result.error)
+ setIsError(true)
+ }
+ } catch (error) {
+ console.error("Fetch error: ", error)
+ setIsError(true)
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
featchRawDataSources()
},[id])
const ObjectValues = (value) => {
- if(value === undefined || Object.keys(value).length === 0) return "Não listado"
+ if(value === undefined || Object.keys(value).length === 0) return "Não informado"
const array = []
@@ -66,7 +57,7 @@ export default function RawDataSourcesPage({ id }) {
array.push(elm.name)
})
- if(array.length === 0) return "Não listado"
+ if(array.length === 0) return "Não informado"
return array.join(", ").toString()
}
@@ -79,213 +70,309 @@ export default function RawDataSourcesPage({ id }) {
return "Não"
break;
default:
- return "Não listado"
+ return "Não informado"
break;
}
}
const UpdateFrequency = () => {
const value = resource?.updates?.[0]
- if(value === undefined || Object.keys(value).length === 0) return "Não listado"
+ if(value === undefined || Object.keys(value).length === 0) return "Não informado"
if(value?.frequency >= 0 && value?.entity?.name) return `${value.frequency} ${value.entity.name}`
if(value?.entity?.name) return `${value.entity.name}`
- return "Não listado"
+ return "Não informado"
}
- const Empty = () => {
+ const TooltipText = ({ text, info, ...props }) => {
return (
-
- Não listado
-
+
+
+ {text}
+
+
+
+
+
)
}
- const ObservationLevel = () => {
- const notFound = Nenhum nível da observação fornecido.
- if(resource?.observationLevels === undefined || Object.keys(resource?.observationLevels).length === 0) return notFound
-
- let array = []
- const keys = Object.keys(resource?.observationLevels)
-
- keys.forEach((elm) => {
- const value = resource?.observationLevels[elm]
-
- const newValue = [value?.entity?.name || , value?.columns[0]?.name || ]
- array.push(newValue)
- })
-
+ const StackSkeleton = ({ children, ...props }) => {
return (
-
+
+ {children}
+
)
}
- const AddInfoTextBase = ({title, text, children, ...style}) => {
+ const AddInfoTextBase = ({ title, text, ...props }) => {
return (
-
+
{title}
-
- {text}
-
- {children}
-
+ {text || "Não informado"}
+
)
}
- if(isError?.message?.length > 0 || resource === null || Object.keys(resource).length < 0) return
-
- if(isLoading) return
+ if(isError) return
return (
-
-
- Consulta aos dados
-
-
-
-
- ATENÇÃO:
-
-
- Estes dados não passaram pela metodologia de tratamento da Base dos Dados.
-
-
-
-
-
+
+ {resource?.name}
+
+
+
+
+
+ Estes dados não passaram pela metodologia de tratamento da Base dos Dados.
+
+
+
+
+ window.open(resource?.url)}
+ fill="#FFF"
+ fontFamily="Roboto"
+ fontWeight="500"
+ fontSize="14px"
+ gap="8px"
+ lineHeight="20px"
+ _hover={{
+ backgroundColor: resource?.url ? "#22703E" : "#ACAEB1"
+ }}
>
Acessar fonte original
-
-
-
-
-
- Descrição
-
- {resource?.description || "Nenhuma descrição fornecida."}
-
-
-
-
- Cobertura temporal
-
-
-
-
-
-
-
- Informações adicionais
-
-
-
-
-
-
-
+
+
+
+
+
+
+ Descrição
+
+
+
+
+
+ {resource?.description || "Não informado"}
+
+
+
-
-
-
-
+
-
-
-
-
+
+
+ Informações adicionais
+
+
-
-
-
-
+
-
-
-
-
-
-
-
-
- Nível da observação
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+ {resource?.observationLevels && Object.keys(resource?.observationLevels).length > 0 ?
+
+ :
+
+ Não informado
+
+ }
+
+
+
+
+
+
+
+
+
)
}
diff --git a/next/components/templates/main.js b/next/components/templates/main.js
index 4c83a971..b0ce3a54 100644
--- a/next/components/templates/main.js
+++ b/next/components/templates/main.js
@@ -8,21 +8,28 @@ export function MainPageTemplate({
backgroundColor = "#FFFFFF",
cleanTemplate = false,
userTemplate = false,
+ footerTemplate = "default",
...style
}) {
return (
-
+
{children}
-
+
);
}
diff --git a/next/content/FAQ.js b/next/content/FAQ.js
index bfe5ed85..5a176d21 100644
--- a/next/content/FAQ.js
+++ b/next/content/FAQ.js
@@ -1,4 +1,4 @@
-import { CopyIcon } from "../public/img/icons/copyIcon"
+import { CopyIcon } from "../public/img/icons/copyIcon";
export const QuestionFAQ = [
{
@@ -433,19 +433,21 @@ export const QuestionFAQ = [
Para verificar uma amostra de todas as variáveis da tabela, use:
-
- {`SELECT * FROM dataset.table_name LIMIT 100`}
-
+
+
+ SELECT * FROM dataset.table_name LIMIT 100
+
+
A primeira dica valiosa é selecionar as colunas que você vai usar.
O BigQuery funciona usando um modelo colunar, portanto, quanto menos colunas você usar,
- melhor vai ser o desempenho da sua consulta. Isso significa evitar o clássico SELECT * FROM table_name
e
+ melhor vai ser o desempenho da sua consulta. Isso significa evitar o clássico SELECT * FROM table_name
e
escolher as colunas de seu interesse. Parece chato, mas ajuda muito!
- Para tabelas grandes, uma boa prática é filtrar os anos e estados de seu interesse com a cláusula WHERE
.
+ Para tabelas grandes, uma boa prática é filtrar os anos e estados de seu interesse com a cláusula WHERE
.
Como utilizamos o sistema de particionamento, isso vai reduzir drasticamente o custo e o tempo de processamento.
@@ -710,7 +712,7 @@ export const QuestionFAQ = [
Utilizamos suas informações pessoais para fornecer e melhorar nossos serviços, incluindo o processamento de pagamentos, o fornecimento de suporte ao cliente e a personalização da experiência do usuário.
Não venderemos, alugaremos ou compartilharemos suas informações pessoais com terceiros não afiliados sem o seu consentimento explícito.
- Para mais informações, acesse nossos Termos de Uso e Políticas de Privacidade aqui .
+ Para mais informações, acesse nossos Termos de Uso e Políticas de Privacidade aqui .
)
diff --git a/next/package-lock.json b/next/package-lock.json
index a17cef1c..76e115f0 100644
--- a/next/package-lock.json
+++ b/next/package-lock.json
@@ -18,6 +18,7 @@
"cookie-parser": "^1.4.6",
"framer-motion": "^4.1.17",
"fuzzy-search": "^3.2.1",
+ "highlight.js": "^11.9.0",
"js-cookie": "^3.0.5",
"next": "^12.3.4",
"next-logger": "4.0.0",
@@ -1969,6 +1970,14 @@
"resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz",
"integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q=="
},
+ "node_modules/highlight.js": {
+ "version": "11.9.0",
+ "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.9.0.tgz",
+ "integrity": "sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==",
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
"node_modules/hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
diff --git a/next/package.json b/next/package.json
index f534b172..082fab59 100644
--- a/next/package.json
+++ b/next/package.json
@@ -21,6 +21,7 @@
"cookie-parser": "^1.4.6",
"framer-motion": "^4.1.17",
"fuzzy-search": "^3.2.1",
+ "highlight.js": "^11.9.0",
"js-cookie": "^3.0.5",
"next": "^12.3.4",
"next-logger": "4.0.0",
diff --git a/next/pages/api/cloudTables/index.js b/next/pages/api/cloudTables/index.js
deleted file mode 100644
index e69de29b..00000000
diff --git a/next/pages/api/datasets/getInformationRequest.js b/next/pages/api/datasets/getInformationRequest.js
index 1dfd4f33..819cebb9 100644
--- a/next/pages/api/datasets/getInformationRequest.js
+++ b/next/pages/api/datasets/getInformationRequest.js
@@ -3,7 +3,7 @@ import { cleanGraphQLResponse } from "../../../utils";
const API_URL= `${process.env.NEXT_PUBLIC_API_URL}/api/v1/graphql`
-export default async function getInformationRequest(id) {
+async function getInformationRequest(id) {
try {
const res = await axios({
url: API_URL,
@@ -19,11 +19,6 @@ export default async function getInformationRequest(id) {
url
dataUrl
observations
- startedBy {
- id
- firstName
- lastName
- }
updates {
edges {
node {
@@ -46,37 +41,6 @@ export default async function getInformationRequest(id) {
_id
name
}
- coverages {
- edges {
- node {
- _id
- datetimeRanges {
- edges {
- node {
- _id
- startYear
- startSemester
- startQuarter
- startMonth
- startDay
- startHour
- startMinute
- startSecond
- endYear
- endSemester
- endQuarter
- endMonth
- endDay
- endHour
- endMinute
- endSecond
- interval
- }
- }
- }
- }
- }
- }
}
}
}
@@ -85,9 +49,19 @@ export default async function getInformationRequest(id) {
variables: null
}
})
- const data = res?.data?.data?.allInformationrequest?.edges[0]?.node
- return cleanGraphQLResponse(data)
+ const data = res?.data
+ return data
} catch (error) {
console.error(error)
+ return "err"
}
-}
\ No newline at end of file
+}
+
+export default async function handler(req, res) {
+ const result = await getInformationRequest(req.query.p)
+
+ 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})
+
+ return res.status(200).json({resource: cleanGraphQLResponse(result?.data?.allInformationrequest?.edges[0]?.node), success: true})
+}
diff --git a/next/pages/api/datasets/getRawDataSources.js b/next/pages/api/datasets/getRawDataSources.js
index 61df9d4c..ae69b459 100644
--- a/next/pages/api/datasets/getRawDataSources.js
+++ b/next/pages/api/datasets/getRawDataSources.js
@@ -3,7 +3,7 @@ import { cleanGraphQLResponse } from "../../../utils";
const API_URL= `${process.env.NEXT_PUBLIC_API_URL}/api/v1/graphql`
-export default async function getRawDataSources(id) {
+async function getRawDataSources(id) {
try {
const res = await axios({
url: API_URL,
@@ -92,30 +92,6 @@ export default async function getRawDataSources(id) {
_id
name
}
- datetimeRanges {
- edges {
- node {
- _id
- startYear
- startSemester
- startQuarter
- startMonth
- startDay
- startHour
- startMinute
- startSecond
- endYear
- endSemester
- endQuarter
- endMonth
- endDay
- endHour
- endMinute
- endSecond
- interval
- }
- }
- }
}
}
}
@@ -127,9 +103,19 @@ export default async function getRawDataSources(id) {
variables: null
}
})
- const data = res?.data?.data?.allRawdatasource?.edges[0]?.node
- return cleanGraphQLResponse(data)
+ const data = res.data
+ return data
} catch (error) {
console.error(error)
+ return "err"
}
}
+
+export default async function handler(req, res) {
+ const result = await getRawDataSources(req.query.p)
+
+ 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})
+
+ return res.status(200).json({resource: cleanGraphQLResponse(result?.data?.allRawdatasource?.edges[0]?.node), success: true})
+}
diff --git a/next/pages/api/datasets/index.js b/next/pages/api/datasets/index.js
index c97c8157..49bc3d6a 100644
--- a/next/pages/api/datasets/index.js
+++ b/next/pages/api/datasets/index.js
@@ -1,8 +1,5 @@
import getSearchDatasets from "./getSearchDatasets";
-import getColumnsBdmTable from "./getColumnsBdmTable";
-import getInformationRequest from "./getInformationRequest";
import getListDatasets from "./getListDatasets";
-import getRawDataSources from "./getRawDataSources";
import getShowDataset from "./getShowDataset";
import postDataset from "./postDataset";
import getDatasetEdit from "./getDatasetEdit";
@@ -10,10 +7,7 @@ import deleteDataset from "./deleteDataset";
export {
getSearchDatasets,
- getColumnsBdmTable,
- getInformationRequest,
getListDatasets,
- getRawDataSources,
getShowDataset,
postDataset,
getDatasetEdit,
diff --git a/next/pages/api/stripe/createSubscription.js b/next/pages/api/stripe/createSubscription.js
index 91f8b8eb..814e1d07 100644
--- a/next/pages/api/stripe/createSubscription.js
+++ b/next/pages/api/stripe/createSubscription.js
@@ -14,10 +14,7 @@ async function createSubscription(id, token) {
query: `
mutation {
createStripeSubscription (priceId: ${id}) {
- subscription {
- id
- clientSecret
- }
+ clientSecret
}
}
`
@@ -38,5 +35,5 @@ export default async function handler(req, res) {
if(result.errors) return res.status(500).json({error: result.errors})
if(result === "err") return res.status(500).json({error: "err"})
- res.status(200).json(result?.data?.createStripeSubscription?.subscription)
+ res.status(200).json(result?.data?.createStripeSubscription?.clientSecret)
}
diff --git a/next/pages/api/tables/downloadTable.js b/next/pages/api/tables/downloadTable.js
new file mode 100644
index 00000000..d2997eb9
--- /dev/null
+++ b/next/pages/api/tables/downloadTable.js
@@ -0,0 +1,24 @@
+import axios from "axios";
+
+async function downloadTable(datasetID, tableId, res) {
+ try {
+ const fileUrl = `https://storage.googleapis.com/basedosdados-public/one-click-download/${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) {
+ return downloadTable(atob(req.query.p), atob(req.query.q), res)
+}
\ No newline at end of file
diff --git a/next/pages/api/tables/getBdmTable.js b/next/pages/api/tables/getBdmTable.js
index 960477ef..db4ce5a0 100644
--- a/next/pages/api/tables/getBdmTable.js
+++ b/next/pages/api/tables/getBdmTable.js
@@ -41,43 +41,38 @@ async function getBdmTable(id) {
}
}
version
- coverages {
+ fullCoverage
+ rawDataSource {
edges {
node {
_id
- datetimeRanges {
+ name
+ dataset {
+ _id
+ }
+ polls {
+ edges {
+ node {
+ _id
+ latest
+ }
+ }
+ }
+ updates {
edges {
node {
_id
- startYear
- startSemester
- startQuarter
- startMonth
- startDay
- startHour
- startMinute
- startSecond
- endYear
- endSemester
- endQuarter
- endMonth
- endDay
- endHour
- endMinute
- endSecond
- interval
+ latest
+ entity {
+ _id
+ slug
+ }
}
}
}
}
}
}
- fullCoverage
- license {
- _id
- name
- url
- }
updates {
edges {
node {
@@ -87,30 +82,15 @@ async function getBdmTable(id) {
latest
entity {
_id
- name
- category {
- _id
- name
- }
+ slug
}
}
}
}
- pipeline {
- _id
- githubUrl
- }
isDirectory
- dataCleaningDescription
- dataCleaningCodeUrl
- rawDataUrl
auxiliaryFilesUrl
- architectureUrl
- sourceBucketName
uncompressedFileSize
- compressedFileSize
numberRows
- numberColumns
partitions
publishedByInfo
dataCleanedByInfo
@@ -152,8 +132,8 @@ async function getBdmTable(id) {
export default async function handler(req, res) {
const result = await getBdmTable(req.query.p)
- if(result.errors) return res.status(500).json({error: result.errors})
- if(result === "err") return res.status(500).json({error: "err"})
+ 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(cleanGraphQLResponse(result?.data?.allTable?.edges[0]?.node))
+ return res.status(200).json({resource: cleanGraphQLResponse(result?.data?.allTable?.edges[0]?.node), success: true})
}
\ No newline at end of file
diff --git a/next/pages/api/tables/getBigTableQuery.js b/next/pages/api/tables/getBigTableQuery.js
new file mode 100644
index 00000000..bb25169c
--- /dev/null
+++ b/next/pages/api/tables/getBigTableQuery.js
@@ -0,0 +1,25 @@
+import axios from "axios";
+
+const API_URL= `${process.env.NEXT_PUBLIC_API_URL}/api/v1/graphql`
+
+export default async function getBigTableQuery(id, columns, includeTranslation) {
+ try {
+ const res = await axios({
+ url: API_URL,
+ method: "POST",
+ data: {
+ query: `
+ query {
+ getTableOneBigTableQuery (tableId: "${id}", columns: [${columns.map(item => `"${item}"`).join(", ")}], includeTableTranslation: ${includeTranslation})
+ }
+ `,
+ variables: null
+ }
+ })
+ const data = res.data.data.getTableOneBigTableQuery
+ return data
+ } catch (error) {
+ console.error(error)
+ return "err"
+ }
+}
diff --git a/next/pages/api/datasets/getColumnsBdmTable.js b/next/pages/api/tables/getColumnsBdmTable.js
similarity index 75%
rename from next/pages/api/datasets/getColumnsBdmTable.js
rename to next/pages/api/tables/getColumnsBdmTable.js
index 64222f03..0190be73 100644
--- a/next/pages/api/datasets/getColumnsBdmTable.js
+++ b/next/pages/api/tables/getColumnsBdmTable.js
@@ -18,26 +18,37 @@ export default async function getColumnsBdmTable(id) {
edges {
node {
_id
- name
order
- bigqueryType {
- name
- }
- description
- coverage
+ name
coveredByDictionary
directoryPrimaryKey {
_id
name
table {
_id
- slug
+ name
+ isClosed
+ uncompressedFileSize
+ cloudTables{
+ edges{
+ node{
+ gcpTableId
+ gcpDatasetId
+ gcpProjectId
+ }
+ }
+ }
dataset {
_id
- slug
+ name
}
}
}
+ description
+ bigqueryType {
+ name
+ }
+ coverage
measurementUnit
containsSensitiveData
observations
diff --git a/next/pages/api/tables/getDictionaryTable.js b/next/pages/api/tables/getDictionaryTable.js
new file mode 100644
index 00000000..4391851a
--- /dev/null
+++ b/next/pages/api/tables/getDictionaryTable.js
@@ -0,0 +1,61 @@
+import axios from "axios";
+
+const API_URL= `${process.env.NEXT_PUBLIC_API_URL}/api/v1/graphql`
+
+async function getDictionaryTable(id, slug) {
+ try {
+ const res = await axios({
+ url: API_URL,
+ method: "POST",
+ data: {
+ query: `
+ query {
+ allDataset (id: "${id}") {
+ edges {
+ node {
+ tables (slug: "${slug}") {
+ edges {
+ node {
+ _id
+ slug
+ uncompressedFileSize
+ cloudTables{
+ edges{
+ node{
+ gcpTableId
+ gcpDatasetId
+ gcpProjectId
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ `
+ }
+ })
+ const data = res?.data?.data?.allDataset?.edges[0]?.node?.tables?.edges[0]?.node
+ return data
+ } catch (error) {
+ console.error(error)
+ }
+}
+
+export default async function handler(req, res) {
+ const param = atob(req.query.p)
+ let result = await getDictionaryTable(param, "dicionario")
+
+ if (result === undefined) {
+ result = await getDictionaryTable(param, "dictionary")
+ }
+
+ if (result === undefined) {
+ res.status(500).json({ error: "Nenhum resultado encontrado" })
+ } else {
+ res.status(200).json(result)
+ }
+}
diff --git a/next/pages/api/tables/index.js b/next/pages/api/tables/index.js
index 732abdbc..4c4925d3 100644
--- a/next/pages/api/tables/index.js
+++ b/next/pages/api/tables/index.js
@@ -2,10 +2,14 @@ import deleteTable from "./deleteTable";
import getAllTableInDataset from "./getAllTableInDataset";
import getTableEdit from "./getTableEdit";
import postTable from "./postTable";
+import getBigTableQuery from "./getBigTableQuery";
+import getColumnsBdmTable from "../tables/getColumnsBdmTable";
export {
deleteTable,
getAllTableInDataset,
getTableEdit,
postTable,
+ getBigTableQuery,
+ getColumnsBdmTable
}
diff --git a/next/pages/api/user/getUser.js b/next/pages/api/user/getUser.js
index cf052abf..01e63fc0 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
+ availableForResearch
}
}
}
diff --git a/next/pages/api/user/updateProfileSurvey.js b/next/pages/api/user/updateProfileSurvey.js
new file mode 100644
index 00000000..3a74b8d9
--- /dev/null
+++ b/next/pages/api/user/updateProfileSurvey.js
@@ -0,0 +1,87 @@
+import axios from "axios";
+
+const API_URL= `${process.env.NEXT_PUBLIC_API_URL}/api/v1/graphql`
+
+async function updateProfileSurvey({
+ id,
+ workArea,
+ workRole,
+ availableForResearch
+}, token, skip
+) {
+ const query = skip === "true" ?
+ `
+ mutation {
+ CreateUpdateAccount (input:
+ {
+ id: "${id}"
+ availableForResearch: "NO"
+ workArea: null
+ workRole: null
+ }
+ )
+ {
+ errors {
+ field,
+ messages
+ }
+ }
+ }`
+ :
+ `
+ mutation {
+ CreateUpdateAccount (input:
+ {
+ id: "${id}"
+ workArea: "${workArea}"
+ workRole: "${workRole}"
+ availableForResearch: "${availableForResearch}"
+ }
+ )
+ {
+ errors {
+ field,
+ messages
+ }
+ }
+ }`
+
+ try {
+ const res = await axios({
+ url: API_URL,
+ method: "POST",
+ headers: {
+ Authorization: `Bearer ${token}`
+ },
+ data: {
+ query: query
+ }
+ })
+
+ const data = res?.data?.data?.CreateUpdateAccount
+ return data
+ } catch (error) {
+ console.error(error)
+ return "err"
+ }
+}
+
+export default async function handler(req, res) {
+ const token = req.cookies.token
+
+ const { p, f, l, e, s} = req.query
+
+ const object = {
+ id:atob(p),
+ workArea:atob(f),
+ workRole:atob(l),
+ availableForResearch:atob(e),
+ }
+
+ const result = await updateProfileSurvey(object, token, s)
+
+ if(result === null) return res.status(500).json({errors: "err"})
+ if(result.errors.length > 0) return res.status(500).json({errors: result.errors})
+ if(result === "err") return res.status(500).json({errors: "err"})
+ res.status(200).json(result)
+}
diff --git a/next/pages/contato-consultoria.js b/next/pages/contato-consultoria.js
new file mode 100644
index 00000000..32a36537
--- /dev/null
+++ b/next/pages/contato-consultoria.js
@@ -0,0 +1,65 @@
+import {
+ Box,
+ Stack,
+} from "@chakra-ui/react";
+import Head from "next/head";
+import { useEffect } from "react";
+import { MainPageTemplate } from "../components/templates/main";
+import { withPages } from "../hooks/pages.hook";
+
+export async function getStaticProps() {
+ return await withPages()
+}
+
+export default function ContactConsultancy() {
+ useEffect(() => {
+ const script = document.createElement('script');
+ script.src='https://js.hsforms.net/forms/embed/v2.js';
+ document.body.appendChild(script);
+
+ script.addEventListener('load', () => {
+ if (window.hbspt) {
+ window.hbspt.forms.create({
+ region: "na1",
+ portalId: "9331013",
+ formId: "1b1d4a12-5cbc-4ffc-837a-12b905c2d87b",
+ target: '#form-hbspt'
+ })
+ }
+ })
+ },[])
+
+ return (
+
+
+ Consultoria – Base dos Dados
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/next/pages/dataset/[dataset].js b/next/pages/dataset/[dataset].js
index 32299a0f..2e6255f8 100644
--- a/next/pages/dataset/[dataset].js
+++ b/next/pages/dataset/[dataset].js
@@ -1,34 +1,28 @@
import {
VStack,
- Stack,
- Center,
Tabs,
TabList,
TabPanel,
- TabPanels
+ TabPanels,
+ Grid,
+ GridItem,
+ Image,
+ Text,
} from "@chakra-ui/react";
import { useState, useEffect } from "react";
import { useRouter } from "next/router";
import Head from "next/head";
-import { isMobileMod } from "../../hooks/useCheckMobile.hook";
import BigTitle from "../../components/atoms/BigTitle";
-import Subtitle from "../../components/atoms/Subtitle";
-import SectionText from "../../components/atoms/SectionText";
import Link from "../../components/atoms/Link";
import GreenTab from "../../components/atoms/GreenTab";
import ReadMore from "../../components/atoms/ReadMore";
-import HelpWidget from "../../components/atoms/HelpWidget";
-import { ImageOrganization } from "../../components/atoms/ImageOrganization";
-import { TemporalCoverageString } from "../../components/molecules/TemporalCoverageDisplay";
import DatasetResource from "../../components/organisms/DatasetResource";
-import { MetadataPage } from "../../components/organisms/MetadataPage";
import { MainPageTemplate } from "../../components/templates/main";
import FourOFour from "../../components/templates/404";
import { DataBaseIcon } from "../../public/img/icons/databaseIcon";
-import DocIcon from "../../public/img/icons/docIcon";
-import CrossIcon from "../../public/img/icons/crossIcon";
+import CrossingIcon from "../../public/img/icons/crossingIcon";
import {
getListDatasets,
@@ -59,9 +53,7 @@ export async function getStaticPaths(context) {
}
}
-export default function DatasetPage ({
- dataset,
-}) {
+export default function DatasetPage ({ dataset }) {
const router = useRouter()
const { query } = router
const [tabIndex, setTabIndex] = useState(0)
@@ -69,13 +61,14 @@ export default function DatasetPage ({
const isDatasetEmpty = dataset === null || Object.keys(dataset).length === 0
useEffect(() => {
- if(isDatasetEmpty) return router.push(`${process.env.NEXT_PUBLIC_API_URL}/dataset_redirect?dataset=${query.dataset}`)
+ if (router.query?.dataset === "mundo-kaggle-olimpiadas") return window.open(`${process.env.NEXT_PUBLIC_BASE_URL_FRONTEND}/dataset/62f8cb83-ac37-48be-874b-b94dd92d3e2b`, "_self")
+ if (isDatasetEmpty) return router.push(`${process.env.NEXT_PUBLIC_API_URL}/dataset_redirect?dataset=${query.dataset}`)
}, [])
- if(isDatasetEmpty) return
+ if(isDatasetEmpty) return
return (
-
+
{dataset.name} – Base dos Dados
@@ -102,104 +95,140 @@ export default function DatasetPage ({
-
-
-
-
-
-
-
+
+
+
+
- {dataset.name || "Conjunto sem nome"}
-
-
-
- {dataset?.description || "Nenhuma descrição fornecida."}
-
-
-
-
- Organização
-
+
-
+
+
+
+
+ {dataset?.description || "Nenhuma descrição fornecida."}
+
+
+
+
+
+ Cobertura temporal do conjunto
+
+
+ {dataset.coverage || "Nenhuma cobertura temporal fornecida."}
+
+
+
+
+
+ Organização
+
+
+
- {dataset?.organization?.name || "Não listado"}
-
+ {dataset?.organization?.name || "Nenhuma organização fornecida."}
+
-
-
-
- Cobertura temporal
-
-
-
-
-
-
-
+
+
+
+
setTabIndex(index)}
+ variant="unstyled"
isLazy
- paddingTop="32px"
- width={{ base: "90vw", lg: "100%" }}
+ width="100%"
>
Dados
- {/*
-
+
- Metadados
- */}
- {dataset?.slug === "br_ibge_ipca" && Painéis }
+ Cruzamento
+
+
- {/*
- // precisa retrabalhar o MetadataPage
-
-
-
- */}
-
- {dataset?.slug === "br_ibge_ipca" &&
-
- {/* */}
-
- }
+
+
-
-
-
-
-
-
-
)
}
\ No newline at end of file
diff --git a/next/pages/dataset/index.js b/next/pages/dataset/index.js
index dd73803d..8ecbdcaa 100644
--- a/next/pages/dataset/index.js
+++ b/next/pages/dataset/index.js
@@ -1,15 +1,13 @@
import {
VStack,
- Heading,
HStack,
Text,
Divider,
Stack,
Skeleton,
- SkeletonText,
Flex,
Box,
- Spinner
+ Spinner,
} from "@chakra-ui/react";
import Head from "next/head";
import ReactPaginate from "react-paginate";
@@ -23,16 +21,9 @@ import {
getSearchDatasets
} from "../api/datasets/index";
-import { DebouncedControlledInput } from "../../components/atoms/ControlledInput";
-import {
- SimpleFilterAccordion,
- CheckboxFilterAccordion,
- RangeFilterAccordion,
-} from "../../components/atoms/FilterAccordion";
-import Tag from "../../components/atoms/Tag";
-import BodyText from "../../components/atoms/BodyText";
-import Display from "../../components/atoms/Display";
-import RoundedButton from "../../components/atoms/RoundedButton";
+import { CheckboxFilterAccordion } from "../../components/atoms/FilterAccordion";
+import Checkbox from "../../components/atoms/Checkbox";
+import { TagFilter } from "../../components/atoms/Tag";
import Database from "../../components/organisms/Database";
import { MainPageTemplate } from "../../components/templates/main";
@@ -43,48 +34,10 @@ export async function getStaticProps() {
return await withPages()
}
-function FilterTags({
- label,
- fieldName,
- values,
- setParamFilters,
- paramFilters,
- translations
-}) {
- function translate (field, translation) {
- return translation[field] || field
- }
-
- return (
-
-
- {label}
-
-
- {values.map((v) => (
- {
- let newArr = [...values];
- newArr.splice(values.indexOf(v), 1);
- setParamFilters({ ...paramFilters, [fieldName]: newArr });
- }}
- text={translations ? translate(v, translations) : v}
- />
- ))}
-
-
- )
-}
-
-export default function SearchPage() {
+export default function SearchDatasetPage() {
const router = useRouter()
const query = router.query
+
const [fetchApi, setFetchApi] = useState(null)
const [showEmptyState, setShowEmptyState] = useState(false)
const [resource, setResource] = useState([])
@@ -94,6 +47,17 @@ export default function SearchPage() {
const [pageInfo, setPageInfo] = useState({page: 0, count: 0})
const [isLoading, setIsLoading] = useState(true)
+ async function getDatasets({q, filters, page}) {
+ const res = await getSearchDatasets({q:q, filter: filters, page:page})
+ if(res === undefined) return router.push({pathname:"500"})
+ if(res?.count === 0) setShowEmptyState(true)
+ setPageInfo({page: page, count: res?.count})
+ setResource(res?.results || null)
+ setAggregations(res?.aggregations)
+ setCount(res?.count)
+ setIsLoading(false)
+ }
+
useEffect(() => {
if(fetchApi) clearTimeout(fetchApi)
setIsLoading(true)
@@ -112,37 +76,6 @@ export default function SearchPage() {
setFetchApi(fetchFunc)
}, [query])
- async function handleSearch (value) {
- let newQuery = {...query}
- if (value) value.replace(/\s+/g, ' ').trim()
- if (newQuery.page) delete newQuery?.page
- if (value === "") {
- delete newQuery?.q
- router.push({
- pathname: router.pathname,
- query: {...newQuery}
- })
- } else {
- triggerGAEvent("search", value)
- triggerGAEvent("search_dataset", value)
- router.push({
- pathname: router.pathname,
- query: {...newQuery, q: value }
- })
- }
- }
-
- async function getDatasets({q, filters, page}) {
- const res = await getSearchDatasets({q:q, filter: filters, page:page})
- if(res === undefined) return router.push({pathname:"500"})
- if(res?.count === 0) setShowEmptyState(true)
- setPageInfo({page: page, count: res?.count})
- setResource(res?.results || null)
- setAggregations(res?.aggregations)
- setCount(res?.count)
- setIsLoading(false)
- }
-
function flattenArray(arr) {
let result = []
@@ -166,7 +99,6 @@ export default function SearchPage() {
const indice = objQuery.findIndex(arr => arr[0] === id)
if (indice != -1) objQuery.splice(indice, 1)
}
- filterQueryFilters("q")
filterQueryFilters("page")
return flattenArray(objQuery)
@@ -211,7 +143,6 @@ export default function SearchPage() {
router.push({
pathname: router.pathname,
query: {
- ...(query.q ? { q: query.q } : {}),
...(queryParams || {}),
page: 1
}
@@ -232,112 +163,117 @@ export default function SearchPage() {
alignItems="center"
width="100%"
spacing={0}
- marginTop={!display && "24px !important"}
+ borderRadius="16px"
+ border={!display && "1px solid #DEDFE0"}
+ padding={display ? "0 16px 40px" :"40px 16px"}
>
{image &&
}
+
{display &&
- {display}
+ marginBottom="16px !important"
+ fontFamily="Roboto"
+ fontWeight="500"
+ fontSize="28px"
+ lineHeight="42px"
+ color="#252A32"
+ >{display}
}
+
{text}
-
{bodyText}
-
+
+
- window.open("https://discord.gg/Ec7tfBaTVV", "_blank")}
- >Fazer uma proposta
-
+ Fazer uma proposta
+
+
+ window.open("https://github.com/orgs/basedosdados/projects/17", "_blank")}
- >Ver roadmap de dados
+ display="flex"
+ alignItems="center"
+ height="40px"
+ width="fit-content"
+ borderRadius="8px"
+ backgroundColor="#FFF"
+ border="1px solid #2B8C4D"
+ padding="8px 16px"
+ cursor="pointer"
+ color="#2B8C4D"
+ fontFamily="Roboto"
+ fontWeight="500"
+ fontSize="14px"
+ gap="8px"
+ lineHeight="20px"
+ _hover={{
+ color: "#22703E"
+ }}
+ >
+ Ver roadmap de dados
+
)
}
- const optionsUpdateFrequencies = {
- "unique" : "-16",
- "hour": "-15",
- "day": "-14",
- "week": "-13",
- "month": "-12",
- "quarter": "-11",
- "semester": "-10",
- "one_year": "-9",
- "two_years": "-8",
- "three_years": "-7",
- "four_years": "-6",
- "five_years": "-5",
- "ten_years": "-4",
- "recurring": "-3",
- "uncertain": "-2",
- "other": "-1",
- }
-
- const optionsRawQualityTiers = {
- "low" : "-3",
- "medium": "-2",
- "high": "-1"
- }
-
- const fieldTranslations = {
- organization: "Organização",
- tag: "Etiqueta",
- group: "Tema",
- resource_type: "Conjuntos com",
- spatial_coverage: "Cobertura espacial",
- temporal_coverage: "Cobertura temporal",
- entity: "Nível da observação",
- update_frequency: "Frequência de atualização",
- raw_quality_tier: "Qualidade da fonte original",
- }
-
- const DatabaseCard = ({ data }) => {
+ function DatabaseCard({ data }) {
return (
({ name: item }))
+ } else {
+ newObj[key] = obj[key]
+ }
+ }
+ return newObj
+ }
+
+ let tags = { ...query }
+ delete tags.page
+
+ if(Object.keys(tags).length === 0) return null
+
+ return (
+
+ {Object.entries(mapArrayProps(tags)).map(([key, value]) =>
+ Array.isArray(value) ? (
+ value.map((tag, i) => (
+ handleSelectFilter([`${key}`,`${tag.name}`])}
+ />
+ ))
+ ) : (
+ handleSelectFilter([`${key}`,`${value}`])}
+ />
+ )
+ )}
+
+
+ Limpar filtros
+
+
+ )
+ }
+
const validateActiveFilterAccordin = (text) => {
return selectedFilters.map((elm) => elm[0] === text).find(res => res === true)
}
- const validateActiveSetsWith = (text) => {
- return selectedFilters.map((elm) =>
- elm[1] === "tables"
- ||elm[1] === "raw_data_sources"
- ||elm[1] === "information_requests").find(
- res => res === true
- )
- }
+ function CheckboxFilterComponent({value, text, count}) {
+ const validateContainsQuery = (value) => {
+ if (query?.contains === value) {
+ return true
+ }
+
+ if (Array.isArray(query?.contains)) {
+ return query.contains.some((elm) => elm === value)
+ }
+
+ return false
+ }
- const validateActiveResource = (text) => {
- return selectedFilters.map((elm) =>
- elm[1] === "open_data"
- ||elm[1] === "closed_data").find(
- res => res === true
+ return (
+
+
+ handleSelectFilter(["contains", e.target.value])}
+ isChecked={validateContainsQuery(value)}
+ minWidth="18px"
+ minHeight="18px"
+ maxWidth="18px"
+ maxHeight="18px"
+ marginRight="14px"
+ borderColor={count === 0 ? "#ACAEB1" : "#878A8E"}
+ backgroundColor={count === 0 ? "#EEEEEE" : "#FFF"}
+ flexShrink={0}
+ />
+
+ {text}
+
+
+ {`(${count})`}
+
+
+
)
}
@@ -393,13 +438,11 @@ export default function SearchPage() {
flexDirection="row"
gap="24px"
width="100%"
- height="172px"
- paddingY="16px"
borderRadius="12px"
backgroundColor="#FFF"
>
-
-
-
-
-
-
-
-
-
+
+
+
+
+
)
@@ -434,29 +473,33 @@ export default function SearchPage() {
backgroundColor="#FFF"
>
-
-
-
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
+
+
)
}
return (
-
+
Dados – Base dos Dados
- handleSearch(value)}
- placeholder={isMobileMod() ? "Palavras-chave, instituições ou temas" :"Pesquise palavras-chave, instituições ou temas"}
- justifyContent="center"
- inputStyle={{
- width: "90%",
- maxWidth: "1264px",
- margin: "0 auto 64px",
- padding: "20px",
- borderRadius: "17px",
- backgroundColor: "#FFF",
- color: "#6F6F6F",
- fontSize: "16px",
- height: "50px",
- boxShadow: "0 1px 3px 0.5 rgba(100 93 103 /0.16) !important",
- _placeholder:{color:"#6F6F6F"}
- }}
- marginTop={isMobileMod() ? "60px" : "46px" }
- />
-
-
+
- Filtrar resultados
+ Filtrar
- elm.key === 1)[0]?.count || 0
- },
- {
- key: "raw_data_sources",
- name: `Fontes originais`,
- count: aggregations?.contains_raw_data_sources?.filter(elm => elm.key === 1)[0]?.count || 0
- },
- {
- key: "information_requests",
- name: `Pedidos LAI`,
- count: aggregations?.contains_information_requests?.filter(elm => elm.key === 1)[0]?.count || 0
- },
- ]}
- isActive={validateActiveSetsWith("contains")}
- valueField="key"
- displayField="name"
- fieldName="Conjuntos com"
- valuesChecked={valuesCheckedFilter("contains")}
- onChange={(value) => handleSelectFilter(["contains",`${value}`])}
- />
+
+
+ Conjuntos com
+
- elm.key === 1)[0]?.count || 0
- },
- {
- key: "closed_data",
- name: "Pagos",
- count: aggregations?.contains_closed_data?.filter(elm => elm.key === 1)[0]?.count || 0
- }
- ]}
- isActive={validateActiveResource("contains")}
- valueField="key"
- displayField="name"
- fieldName="Recursos"
- valuesChecked={valuesCheckedFilter("contains")}
- onChange={(value) => handleSelectFilter(["contains",`${value}`])}
- />
+ elm.key === 1)[0]?.count || 0}
+ />
+
+ elm.key === 1)[0]?.count || 0}
+ />
+
+ elm.key === 1)[0]?.count || 0}
+ />
+
+
+
+
+
+
+ Recursos
+
+
+ elm.key === 1)[0]?.count || 0}
+ />
+
+ elm.key === 1)[0]?.count || 0}
+ />
+
+
+
handleSelectFilter(["theme",`${value}`])}
+ isLoading={!isLoading}
/>
+
+
handleSelectFilter(["organization",`${value}`])}
+ isLoading={!isLoading}
/>
+
+
handleSelectFilter(["tag",`${value}`])}
+ isLoading={!isLoading}
/>
+
+
handleSelectFilter(["observation_level",`${value}`])}
+ isLoading={!isLoading}
/>
+
+
+
+
+ {count ?
+ `${count} conjunto${count > 1 ? "s": ""} encontrado${count > 1 ? "s": ""} ${!!query.q ? ` para ${query.q}` : ""}`
+ :
+ count === 0 && showEmptyState ?
+ `0 conjuntos encontrados`
+ :
+
+ encontrando conjuntos {!!query.q ? ` para ${query.q}` : ""}
+
+ }
+
+
+
{showEmptyState &&
}
- {!showEmptyState &&
-
-
- {count ?
- `${count} conjunto${count > 1 ? "s": ""} encontrado${count > 1 ? "s": ""} ${!!query.q ? ` para ${query.q}` : ""}`
- :
-
- encontrando conjuntos {!!query.q ? ` para ${query.q}` : ""}
-
- }
-
-
- }
-
{isLoading
? new Array(10).fill(0).map((e, i) => (
-
- {useCheckMobile() ?
-
- :
-
- }
-
-
+ useCheckMobile() ?
+
+ :
+
))
:
(resource || []).map((res, i) => (
-
-
-
-
+
))
}
+ {pageInfo?.count >=1 && pageInfo?.count <=10 &&
+
+ }
+
+ {pageInfo.page >= 2 &&
+
+ }
+
{!showEmptyState &&
" : "Próxima"}
+ previousLabel={"Anterior"}
+ nextLabel={"Próxima"}
breakLabel={"..."}
breakClassName={"break-me"}
forcePage={pageInfo.page - 1 || 0}
@@ -700,26 +766,12 @@ export default function SearchPage() {
}}
containerClassName={"pagination"}
activeClassName={"active"}
- pageClassName={isLoading && "disabled"}
- previousClassName={isLoading && "disabled"}
- nextClassName={isLoading && "disabled"}
+ pageClassName={isLoading ? "disabled" : ""}
+ previousClassName={isLoading ? "disabled" : "previous-page"}
+ nextClassName={isLoading ? "disabled" : "next-page"}
/>
}
-
- {pageInfo?.count >=1 && pageInfo?.count <=10 &&
-
- }
-
- {pageInfo.page >= 2 &&
-
- }
diff --git a/next/pages/index.js b/next/pages/index.js
index 071544a1..98656ee6 100644
--- a/next/pages/index.js
+++ b/next/pages/index.js
@@ -726,7 +726,6 @@ export default function Home({ dataThemeCatalog }) {
-
);
}
diff --git a/next/pages/perguntas-frequentes.js b/next/pages/perguntas-frequentes.js
index 4a11d468..c867f560 100644
--- a/next/pages/perguntas-frequentes.js
+++ b/next/pages/perguntas-frequentes.js
@@ -23,6 +23,8 @@ import CrossIcon from "../public/img/icons/crossIcon";
import SearchIcon from "../public/img/icons/searchIcon";
import styles from "../styles/faq.module.css";
+import 'highlight.js/styles/obsidian.css';
+
export async function getStaticProps() {
return await withPages()
}
@@ -53,12 +55,11 @@ const QuestionsBox = ({ question, answer, id, active }) => {
const OpenCloseQuestion = () => {
setIsActive(!isActive)
- window.Prism.highlightAll()
}
return (
{
:
- questions.map((elm) =>
+ questions.map((elm, i) =>
-
-
-
)
}
\ No newline at end of file
diff --git a/next/pages/precos.js b/next/pages/precos.js
index 9169c436..afce0a7c 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={[
{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, R e Stata"},
+ {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: "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`,
@@ -402,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",
@@ -419,4 +441,4 @@ export default function Price({ username ,isBDPro, isBDEmp }) {
)
-}
+}
\ No newline at end of file
diff --git a/next/pages/servicos.js b/next/pages/servicos.js
index 45ead28c..ed7c6aab 100644
--- a/next/pages/servicos.js
+++ b/next/pages/servicos.js
@@ -2,6 +2,7 @@ import {
Stack,
VStack,
Image,
+ Text,
Box,
Skeleton
} from "@chakra-ui/react";
@@ -100,6 +101,31 @@ function Slogan () {
>
A Base dos Dados é a especialista que ajuda você ou sua equipe a trabalhar e extrair o máximo de valor dos dados.
+
+ Vamos fazer um projeto juntos
+
)
}
@@ -553,9 +579,33 @@ export default function Services() {
-
-
+
+ Vamos fazer um projeto juntos
+
+
)
}
diff --git a/next/pages/termos-e-privacidade.js b/next/pages/termos-e-privacidade.js
index 4a3ffef9..a0321581 100644
--- a/next/pages/termos-e-privacidade.js
+++ b/next/pages/termos-e-privacidade.js
@@ -37,7 +37,7 @@ export default function TermsAndPolitics() {
if(id === "terms") {
targetElement = document.getElementById("Termos de Serviço")
setSectionSelected("Termos de Serviço")
- movedScroll(useCheckMobile() ? 210 : 80)
+ movedScroll(useCheckMobile() ? 210 : 120)
}
if(id === "privacy") {
targetElement = document.getElementById("Políticas de Privacidade")
@@ -100,8 +100,7 @@ export default function TermsAndPolitics() {
+
Transparência – Base dos Dados
{
startColor="#F0F0F0"
endColor="#F3F3F3"
>
-
+
Tornar o e-mail de acesso à sua conta visível para o público.
-
+
@@ -1702,7 +1710,7 @@ const PlansAndPayment = ({ userData }) => {
marginBottom="24px"
spacing={0}
>
- {
>
Para você descobrir o potencial da plataforma de dados}
+ subTitle={<>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, R e Stata"},
+ {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: "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"}`,
@@ -1956,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"}`,
diff --git a/next/pages/user/login.js b/next/pages/user/login.js
index 73682555..032585b2 100644
--- a/next/pages/user/login.js
+++ b/next/pages/user/login.js
@@ -80,10 +80,12 @@ export default function Login() {
if(userData.error) return setErrors({login:"Não foi possível conectar ao servidor. Tente novamente mais tarde."})
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")
}
}
@@ -106,7 +108,7 @@ export default function Login() {
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)
+ }
+
+ const userData = await fetch(`/api/user/getUser?p=${btoa(id)}`, { method: "GET" })
+ .then(res => res.json())
+ cookies.set('userBD', JSON.stringify(userData))
+ triggerGAEvent("survey_login", skip === "true" ? "Skipou" : "Respondeu")
+ window.open("/", "_self")
+ }
+
+ const question = [
+ {
+ question: "Em que área você atua?",
+ options: [
+ ["Tecnologia", "TECNOLOGIA"],
+ ["Saúde", "SAUDE"],
+ ["Financeiro", "FINANCEIRO"],
+ ["Educação", "EDUCACAO"],
+ ["Varejo", "VAREJO"],
+ ["Energia", "ENERGIA"],
+ ["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
+ },
+ {
+ question: "Qual o seu cargo?",
+ options: [
+ ["CEO/Diretor(a)", "CEO_DIRETOR"],
+ ["Gerente", "GERENTE"],
+ ["Coordenador(a)", "COORDENADOR"],
+ ["Analista", "ANALISTA"],
+ ["Consultor(a)", "CONSULTOR"],
+ ["Especialista", "ESPECIALISTA"],
+ ["Assistente", "ASSISTENTE"],
+ ["Estagiário(a)", "ESTAGIARIO"],
+ ["Estudante", "ESTUDANTE"],
+ ["Professor(a)/Pesquisador(a)", "PROFESSOR_PESQUISADOR"],
+ ["Freelancer", "FREELANCER"],
+ ["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
+ },
+ {
+ 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.")
+ 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 progressValue = () => {
+ const value = [20, 60, 100]
+ return value[index]
+ }
+
+ function handleSelected(value, setStage) {
+ setStage((stage) => {
+ if (stage.includes(value)) {
+ return []
+ } else {
+ return [value]
+ }
+ })
+ }
+
+ return (
+
+
+ {question[index].question}
+
+ {err}
+
+
+ {question[index].options.map((elm, i) =>
+ handleSelected(elm[1], question[index].stage)}
+ pointerEvents={isLoading ? "none" : "default"}
+ borderRadius="16px"
+ cursor="pointer"
+ border={selectedValueStage(elm[1]) ? "2px solid #42B0FF" : "1px solid #DEDFE0"}
+ backgroundColor={selectedValueStage(elm[1]) ? "#CFEBFE" : "#FFF"}
+ width="fit-content"
+ padding={selectedValueStage(elm[1]) ? "11px" : "12px"}
+ fontFamily="Roboto"
+ fontWeight="500"
+ fontSize="18px"
+ lineHeight="28px"
+ color="#464A51"
+ >
+ {elm[0]}
+
+ )}
+
+
+
+
+
+
+ {question[index].buttons.map((elm, i) =>
+
+ {isLoading ? elm.text === "Pular" || elm.text === "Enviar" ? : elm.text : elm.text}
+
+ )}
+
+
+
+
+ )
+}
diff --git a/next/public/img/icons/crossingIcon.js b/next/public/img/icons/crossingIcon.js
new file mode 100644
index 00000000..c40a8417
--- /dev/null
+++ b/next/public/img/icons/crossingIcon.js
@@ -0,0 +1,14 @@
+import { createIcon } from '@chakra-ui/icons';
+
+const CrossingIcon = createIcon({
+ displayName: "crossing icon",
+ viewBox: "0 0 24 24",
+ path: (
+
+ )
+})
+
+export default CrossingIcon
diff --git a/next/public/img/icons/filterIcon.js b/next/public/img/icons/filterIcon.js
index 053e332a..baffee53 100644
--- a/next/public/img/icons/filterIcon.js
+++ b/next/public/img/icons/filterIcon.js
@@ -2,13 +2,13 @@ import { createIcon } from '@chakra-ui/icons';
const FilterIcon = createIcon({
displayName: "filter",
- viewBox: "0 0 25 25",
+ viewBox: "0 0 24 24",
path: (
)
})
-export default FilterIcon
\ No newline at end of file
+export default FilterIcon
diff --git a/next/public/img/icons/helpIcon.js b/next/public/img/icons/helpIcon.js
index b4dafb69..caac6b55 100644
--- a/next/public/img/icons/helpIcon.js
+++ b/next/public/img/icons/helpIcon.js
@@ -2,13 +2,13 @@ import { createIcon } from '@chakra-ui/icons';
const HelpIcon = createIcon({
displayName: "help",
- viewBox: "0 0 25 25",
+ viewBox: "0 0 28 28",
path: (
)
})
-export default HelpIcon
+export default HelpIcon
\ No newline at end of file
diff --git a/next/public/img/icons/settingsIcon.js b/next/public/img/icons/settingsIcon.js
index c5345385..44144b95 100644
--- a/next/public/img/icons/settingsIcon.js
+++ b/next/public/img/icons/settingsIcon.js
@@ -2,11 +2,11 @@ import { createIcon } from '@chakra-ui/icons';
const SettingsIcon = createIcon({
displayName: "settings",
- viewBox: "0 0 22 22",
+ viewBox: "0 0 40 40",
path: (
)
})
diff --git a/next/public/img/icons/signOutIcon.js b/next/public/img/icons/signOutIcon.js
index a7a5f601..e1b1e0cd 100644
--- a/next/public/img/icons/signOutIcon.js
+++ b/next/public/img/icons/signOutIcon.js
@@ -2,11 +2,11 @@ import { createIcon } from '@chakra-ui/icons';
const SignOutIcon = createIcon({
displayName: "signOut",
- viewBox: "0 0 16 16",
+ viewBox: "0 0 40 40",
path: (
)
})
diff --git a/next/public/img/icons/successIcon.js b/next/public/img/icons/successIcon.js
new file mode 100644
index 00000000..dd652689
--- /dev/null
+++ b/next/public/img/icons/successIcon.js
@@ -0,0 +1,23 @@
+import { createIcon } from '@chakra-ui/icons';
+
+export const SuccessIcon = createIcon({
+ displayName: "sucess",
+ viewBox: "0 0 90 64",
+ path: (
+
+ )
+})
+
+export const SolidSuccessIcon = createIcon({
+ displayName: "solid sucess",
+ viewBox: "0 0 20 20",
+ path: (
+
+ )
+})
diff --git a/next/public/img/icons/sucessIcon.js b/next/public/img/icons/sucessIcon.js
deleted file mode 100644
index d6725259..00000000
--- a/next/public/img/icons/sucessIcon.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import { createIcon } from '@chakra-ui/icons';
-
-const SucessIcon = createIcon({
- displayName: "sucess",
- viewBox: "0 0 90 64",
- path: (
-
- )
-})
-
-export default SucessIcon
\ No newline at end of file
diff --git a/next/public/img/icons/warningIcon.js b/next/public/img/icons/warningIcon.js
new file mode 100644
index 00000000..823c47d5
--- /dev/null
+++ b/next/public/img/icons/warningIcon.js
@@ -0,0 +1,13 @@
+import { createIcon } from '@chakra-ui/icons';
+
+const WarningIcon = createIcon({
+ displayName: "warning",
+ path: (
+
+
+
+
+ )
+})
+
+export default WarningIcon
\ No newline at end of file
diff --git a/next/public/vendor/prism.css b/next/public/vendor/prism.css
deleted file mode 100644
index a3990b2c..00000000
--- a/next/public/vendor/prism.css
+++ /dev/null
@@ -1,123 +0,0 @@
-/* PrismJS 1.25.0
-https://prismjs.com/download.html#themes=prism-twilight&languages=markup+css+clike+javascript+python+r+sql */
-code[class*=language-], pre[class*=language-] {
- color:#fff;
- background:0 0;
- font-family: Monaco,'Andale Mono','Ubuntu Mono',monospace;
- font-size:1em;
- text-align:left;
- text-shadow:0 -.1em .2em #000;
- white-space:pre;
- word-spacing:normal;
- word-break:normal;
- word-wrap:normal;
- line-height:1.5;
- -moz-tab-size:4;
- -o-tab-size:4;
- tab-size:4;
- -webkit-hyphens:none;
- -moz-hyphens:none;
- -ms-hyphens:none;
- hyphens:none
-}
-
-:not(pre)>code[class*=language-],pre[class*=language-] {
- background:#252A32
-}
-
-pre[class*=language-] {
- border-radius:8px;
- margin: 0;
- overflow:auto;
-}
-
-pre[class*=language-]::-moz-selection {
- background:#27292a
-}
-
-pre[class*=language-]::selection {
- background:#27292a
-}
-
-code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection {
- text-shadow:none;
- background:hsla(0,0%,93%,.15)
-}
-
-code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection {
- text-shadow:none;
- background:hsla(0,0%,93%,.15)
-}
-
-:not(pre)>code[class*=language-] {
- border-radius:.3em;
- border:.13em solid #252A32;
- box-shadow:1px 1px .3em -.1em #000 inset;
- padding:.15em .2em .05em;
- white-space:normal
-}
-
-.token.cdata,.token.comment,.token.doctype,.token.prolog {
- color:#777
-}
-
-.token.punctuation {
- opacity:.7
-}
-
-.token.namespace {
- opacity:.7
-}
-
-.token.boolean,.token.deleted,.token.number,.token.tag {
- color:#ce6849
-}
-
-.token.builtin,.token.constant,.token.keyword,.token.property,.token.selector,.token.symbol {
- color:#f9ed99
-}
-
-.language-css .token.string,.style .token.string,.token.attr-name,.token.attr-value,.token.char,.token.entity,.token.inserted,.token.operator,.token.string,.token.url,.token.variable {
- color:#909e6a
-}
-
-.token.atrule {
- color:#7385a5
-}
-
-.token.important,.token.regex {
- color:#e8c062
-}
-
-.token.bold,.token.important {
- font-weight:700
-}
-
-.token.italic {
- font-style:italic
-}
-
-.token.entity {
- cursor:help
-}
-
-.language-markup .token.attr-name,.language-markup .token.punctuation,.language-markup .token.tag {
- color:#ac885c
-}
-
-.token {
- position:relative;z-index:1
-}
-
-.line-highlight.line-highlight {
- background:hsla(0,0%,33%,.25);
- background:linear-gradient(to right,hsla(0,0%,33%,.1) 70%,hsla(0,0%,33%,0));
- border-bottom:1px dashed #545454;
- border-top:1px dashed #545454;
- margin-top:.75em;z-index:0
-}
-
-.line-highlight.line-highlight:before,.line-highlight.line-highlight[data-end]:after {
- background-color:#8693a6;
- color:#f4f1ef
-}
diff --git a/next/public/vendor/prism.js b/next/public/vendor/prism.js
deleted file mode 100644
index 07d67bb0..00000000
--- a/next/public/vendor/prism.js
+++ /dev/null
@@ -1,13 +0,0 @@
-/* PrismJS 1.28.0
-https://prismjs.com/download.html#themes=prism-twilight&languages=markup+css+clike+javascript+java+mata+python+r+sql+stata */
-var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(e){var n=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,r={},a={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof i?new i(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/=g.reach);A+=w.value.length,w=w.next){var E=w.value;if(n.length>e.length)return;if(!(E instanceof i)){var P,L=1;if(y){if(!(P=l(b,A,e,m))||P.index>=e.length)break;var S=P.index,O=P.index+P[0].length,j=A;for(j+=w.value.length;S>=j;)j+=(w=w.next).value.length;if(A=j-=w.value.length,w.value instanceof i)continue;for(var C=w;C!==n.tail&&(jg.reach&&(g.reach=W);var z=w.prev;if(_&&(z=u(n,z,_),A+=_.length),c(n,z,L),w=u(n,z,new i(f,p?a.tokenize(N,p):N,k,N)),M&&u(n,w,M),L>1){var I={cause:f+","+d,reach:W};o(e,n,t,w.prev,A,I),g&&I.reach>g.reach&&(g.reach=I.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function u(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a,r.prev=a,e.length++,a}function c(e,n,t){for(var r=n.next,a=0;a"+i.content+""+i.tag+">"},!e.document)return e.addEventListener?(a.disableWorkerMessageHandler||e.addEventListener("message",(function(n){var t=JSON.parse(n.data),r=t.language,i=t.code,l=t.immediateClose;e.postMessage(a.highlight(i,a.languages[r],r)),l&&e.close()}),!1),a):a;var g=a.util.currentScript();function f(){a.manual||a.highlightAll()}if(g&&(a.filename=g.src,g.hasAttribute("data-manual")&&(a.manual=!0)),!a.manual){var h=document.readyState;"loading"===h||"interactive"===h&&g&&g.defer?document.addEventListener("DOMContentLoaded",f):window.requestAnimationFrame?window.requestAnimationFrame(f):window.setTimeout(f,16)}return a}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism);
-Prism.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",(function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))})),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^$/i;var t={"included-cdata":{pattern://i,inside:s}};t["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var n={};n[a]={pattern:RegExp("(<__[^>]*>)(?:))*\\]\\]>|(?!)".replace(/__/g,(function(){return a})),"i"),lookbehind:!0,greedy:!0,inside:t},Prism.languages.insertBefore("markup","cdata",n)}}),Object.defineProperty(Prism.languages.markup.tag,"addAttribute",{value:function(a,e){Prism.languages.markup.tag.inside["special-attr"].push({pattern:RegExp("(^|[\"'\\s])(?:"+a+")\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))","i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[e,"language-"+e],inside:Prism.languages[e]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml;
-!function(s){var e=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:[^;{\\s\"']|\\s+(?!\\s)|"+e.source+")*?(?:;|(?=\\s*\\{))"),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+e.source+"|(?:[^\\\\\r\n()\"']|\\\\[^])*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+e.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+e.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:e,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var t=s.languages.markup;t&&(t.tag.addInlined("style","css"),t.tag.addAttribute("style","css"))}(Prism);
-Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/};
-Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp("(^|[^\\w$])(?:NaN|Infinity|0[bB][01]+(?:_[01]+)*n?|0[oO][0-7]+(?:_[0-7]+)*n?|0[xX][\\dA-Fa-f]+(?:_[\\dA-Fa-f]+)*n?|\\d+(?:_\\d+)*n|(?:\\d+(?:_\\d+)*(?:\\.(?:\\d+(?:_\\d+)*)?)?|\\.\\d+(?:_\\d+)*)(?:[Ee][+-]?\\d+(?:_\\d+)*)?)(?![\\w$])"),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp("((?:^|[^$\\w\\xA0-\\uFFFF.\"'\\])\\s]|\\b(?:return|yield))\\s*)/(?:(?:\\[(?:[^\\]\\\\\r\n]|\\\\.)*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}|(?:\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.)*\\])*\\])*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}v[dgimyus]{0,7})(?=(?:\\s|/\\*(?:[^*]|\\*(?!/))*\\*/)*(?:$|[\r\n,.;:})\\]]|//))"),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),Prism.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),Prism.languages.markup&&(Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.markup.tag.addAttribute("on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)","javascript")),Prism.languages.js=Prism.languages.javascript;
-!function(e){var n=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record(?!\s*[(){}[\]<>=%~.:,;?+\-*/&|^])|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,t="(?:[a-z]\\w*\\s*\\.\\s*)*(?:[A-Z]\\w*\\s*\\.\\s*)*",s={pattern:RegExp("(^|[^\\w.])"+t+"[A-Z](?:[\\d_A-Z]*[a-z]\\w*)?\\b"),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};e.languages.java=e.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"/,lookbehind:!0,greedy:!0},"class-name":[s,{pattern:RegExp("(^|[^\\w.])"+t+"[A-Z]\\w*(?=\\s+\\w+\\s*[;,=()]|\\s*(?:\\[[\\s,]*\\]\\s*)?::\\s*new\\b)"),lookbehind:!0,inside:s.inside},{pattern:RegExp("(\\b(?:class|enum|extends|implements|instanceof|interface|new|record|throws)\\s+)"+t+"[A-Z]\\w*\\b"),lookbehind:!0,inside:s.inside}],keyword:n,function:[e.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0},constant:/\b[A-Z][A-Z_\d]+\b/}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"},char:{pattern:/'(?:\\.|[^'\\\r\n]){1,6}'/,greedy:!0}}),e.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":s,keyword:n,punctuation:/[<>(),.:]/,operator:/[?&|]/}},import:[{pattern:RegExp("(\\bimport\\s+)"+t+"(?:[A-Z]\\w*|\\*)(?=\\s*;)"),lookbehind:!0,inside:{namespace:s.inside.namespace,punctuation:/\./,operator:/\*/,"class-name":/\w+/}},{pattern:RegExp("(\\bimport\\s+static\\s+)"+t+"(?:\\w+|\\*)(?=\\s*;)"),lookbehind:!0,alias:"static",inside:{namespace:s.inside.namespace,static:/\b\w+$/,punctuation:/\./,operator:/\*/,"class-name":/\w+/}}],namespace:{pattern:RegExp("(\\b(?:exports|import(?:\\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\\s+)(?!)[a-z]\\w*(?:\\.[a-z]\\w*)*\\.?".replace(//g,(function(){return n.source}))),lookbehind:!0,inside:{punctuation:/\./}}})}(Prism);
-!function(t){var e="\\bvoid\\b||\\b(?:complex|numeric|pointer(?:\\s*\\([^()]*\\))?|real|string|(?:class|struct)\\s+\\w+|transmorphic)(?:\\s*)?".replace(//g,"\\b(?:(?:col|row)?vector|matrix|scalar)\\b");t.languages.mata={comment:{pattern:/\/\/.*|\/\*(?:[^*/]|\*(?!\/)|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/)*\*\//,greedy:!0},string:{pattern:/"[^"\r\n]*"|[‘`']".*?"[’`']/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|struct)\s+)\w+(?=\s*(?:\{|\bextends\b))/,lookbehind:!0},type:{pattern:RegExp(e),alias:"class-name",inside:{punctuation:/[()]/,keyword:/\b(?:class|function|struct|void)\b/}},keyword:/\b(?:break|class|continue|do|else|end|extends|external|final|for|function|goto|if|pragma|private|protected|public|return|static|struct|unset|unused|version|virtual|while)\b/,constant:/\bNULL\b/,number:{pattern:/(^|[^\w.])(?:\d+(?:\.\d+)?(?:e[+-]?\d+)?|\d[a-f0-9]*(?:\.[a-f0-9]+)?x[+-]?\d+)i?(?![\w.])/i,lookbehind:!0},missing:{pattern:/(^|[^\w.])(?:\.[a-z]?)(?![\w.])/,lookbehind:!0,alias:"symbol"},function:/\b[a-z_]\w*(?=\s*\()/i,operator:/\.\.|\+\+|--|&&|\|\||:?(?:[!=<>]=|[+\-*/^<>&|:])|[!?=\\#’`']/,punctuation:/[()[\]{},;.]/}}(Prism);
-Prism.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},Prism.languages.python["string-interpolation"].inside.interpolation.inside.rest=Prism.languages.python,Prism.languages.py=Prism.languages.python;
-Prism.languages.r={comment:/#.*/,string:{pattern:/(['"])(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},"percent-operator":{pattern:/%[^%\s]*%/,alias:"operator"},boolean:/\b(?:FALSE|TRUE)\b/,ellipsis:/\.\.(?:\.|\d+)/,number:[/\b(?:Inf|NaN)\b/,/(?:\b0x[\dA-Fa-f]+(?:\.\d*)?|\b\d+(?:\.\d*)?|\B\.\d+)(?:[EePp][+-]?\d+)?[iL]?/],keyword:/\b(?:NA|NA_character_|NA_complex_|NA_integer_|NA_real_|NULL|break|else|for|function|if|in|next|repeat|while)\b/,operator:/->?>?|<(?:=|-)?|[>=!]=?|::?|&&?|\|\|?|[+*\/^$@~]/,punctuation:/[(){}\[\],;]/};
-Prism.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},variable:[{pattern:/@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,greedy:!0},/@[\w.$]+/],string:{pattern:/(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,greedy:!0,lookbehind:!0},identifier:{pattern:/(^|[^@\\])`(?:\\[\s\S]|[^`\\]|``)*`/,greedy:!0,lookbehind:!0,inside:{punctuation:/^`|`$/}},function:/\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:COL|_INSERT)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURN(?:ING|S)?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,boolean:/\b(?:FALSE|NULL|TRUE)\b/i,number:/\b0x[\da-f]+\b|\b\d+(?:\.\d*)?|\B\.\d+\b/i,operator:/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/};
-Prism.languages.stata={comment:[{pattern:/(^[ \t]*)\*.*/m,lookbehind:!0,greedy:!0},{pattern:/(^|\s)\/\/.*|\/\*[\s\S]*?\*\//,lookbehind:!0,greedy:!0}],"string-literal":{pattern:/"[^"\r\n]*"|[‘`']".*?"[’`']/,greedy:!0,inside:{interpolation:{pattern:/\$\{[^{}]*\}|[‘`']\w[^’`'\r\n]*[’`']/,inside:{punctuation:/^\$\{|\}$/,expression:{pattern:/[\s\S]+/,inside:null}}},string:/[\s\S]+/}},mata:{pattern:/(^[ \t]*mata[ \t]*:)[\s\S]+?(?=^end\b)/m,lookbehind:!0,greedy:!0,alias:"language-mata",inside:Prism.languages.mata},java:{pattern:/(^[ \t]*java[ \t]*:)[\s\S]+?(?=^end\b)/m,lookbehind:!0,greedy:!0,alias:"language-java",inside:Prism.languages.java},python:{pattern:/(^[ \t]*python[ \t]*:)[\s\S]+?(?=^end\b)/m,lookbehind:!0,greedy:!0,alias:"language-python",inside:Prism.languages.python},command:{pattern:/(^[ \t]*(?:\.[ \t]+)?(?:(?:bayes|bootstrap|by|bysort|capture|collect|fmm|fp|frame|jackknife|mfp|mi|nestreg|noisily|permute|quietly|rolling|simulate|statsby|stepwise|svy|version|xi)\b[^:\r\n]*:[ \t]*|(?:capture|noisily|quietly|version)[ \t]+)?)[a-zA-Z]\w*/m,lookbehind:!0,greedy:!0,alias:"keyword"},variable:/\$\w+|[‘`']\w[^’`'\r\n]*[’`']/,keyword:/\b(?:bayes|bootstrap|by|bysort|capture|clear|collect|fmm|fp|frame|if|in|jackknife|mi[ \t]+estimate|mfp|nestreg|noisily|of|permute|quietly|rolling|simulate|sort|statsby|stepwise|svy|varlist|version|xi)\b/,boolean:/\b(?:off|on)\b/,number:/\b\d+(?:\.\d+)?\b|\B\.\d+/,function:/\b[a-z_]\w*(?=\()/i,operator:/\+\+|--|##?|[<>!=~]=?|[+\-*^&|/]/,punctuation:/[(){}[\],:]/},Prism.languages.stata["string-literal"].inside.interpolation.inside.expression.inside=Prism.languages.stata;
\ No newline at end of file
diff --git a/next/public/vendor/terminal.css b/next/public/vendor/terminal.css
deleted file mode 100644
index 2cf022fc..00000000
--- a/next/public/vendor/terminal.css
+++ /dev/null
@@ -1,101 +0,0 @@
-/**
- * termynal.js
- *
- * @author Ines Montani
- * @version 0.0.1
- * @license MIT
- */
-
-:root {
- --color-bg: #252a33;
- --color-text: #eee;
- --color-text-subtle: #a2a2a2;
-}
-
-[data-termynal] {
- width: 750px;
- max-width: 100%;
- background: var(--color-bg);
- color: var(--color-text);
- font-size: 18px;
- font-family: "Fira Mono", Menlo, Monaco, "Courier New", Courier,
- monospace;
- border-radius: 10px;
- padding: 75px 45px 35px;
- position: relative;
- -webkit-box-sizing: border-box;
- box-sizing: border-box;
-}
-
-[data-termynal]:before {
- content: "";
- position: absolute;
- top: 15px;
- left: 15px;
- display: inline-block;
- width: 15px;
- height: 15px;
- border-radius: 50%;
- /* A little hack to display the window buttons in one pseudo element. */
- background: #d9515d;
- -webkit-box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930;
- box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930;
-}
-
-[data-termynal]:after {
- content: "bash";
- position: absolute;
- color: var(--color-text-subtle);
- top: 5px;
- left: 0;
- width: 100%;
- text-align: center;
-}
-
-[data-ty] {
- display: block;
- line-height: 2;
-}
-
-[data-ty]:before {
- /* Set up defaults and ensure empty lines are displayed. */
- content: "";
- display: inline-block;
- vertical-align: middle;
-}
-
-[data-ty="input"]:before,
-[data-ty-prompt]:before {
- margin-right: 0.75em;
- color: var(--color-text-subtle);
-}
-
-[data-ty="input"]:before {
- content: "$";
-}
-
-[data-ty][data-ty-prompt]:before {
- content: attr(data-ty-prompt);
-}
-
-[data-ty-cursor]:after {
- content: attr(data-ty-cursor);
- font-family: monospace;
- margin-left: 0.5em;
- -webkit-animation: blink 1s infinite;
- animation: blink 1s infinite;
-}
-
-/* Cursor animation */
-
-@-webkit-keyframes blink {
- 50% {
- opacity: 0;
- }
-}
-
-@keyframes blink {
- 50% {
- opacity: 0;
- }
-}
diff --git a/next/public/vendor/terminal.js b/next/public/vendor/terminal.js
deleted file mode 100644
index 1e208471..00000000
--- a/next/public/vendor/terminal.js
+++ /dev/null
@@ -1,10 +0,0 @@
-/**
- * termynal.js
- * A lightweight, modern and extensible animated terminal window, using
- * async/await.
- *
- * @author Ines Montani
- * @version 0.0.1
- * @license MIT
- */
-'use strict';var _createClass=function(){function a(b,c){for(var e,d=0;dz){break;}}}},{key:'_wait',value:function _wait(b){return new Promise(function(c){return setTimeout(c,b)})}}]),a} ();if(document.currentScript.hasAttribute('data-termynal-container')){var containers=document.currentScript.getAttribute('data-termynal-container');containers.split('|').forEach(function(a){return new Termynal(a)})}
\ No newline at end of file
diff --git a/next/styles/globals.css b/next/styles/globals.css
index 4c69e407..75664bcc 100644
--- a/next/styles/globals.css
+++ b/next/styles/globals.css
@@ -1,4 +1,4 @@
-@import url('https://fonts.googleapis.com/css2?family=Ubuntu:wght@100;200;300;400;500;600;700;800;900&family=Lato:wght@100;200;300;400;500;600;700;800;900&display=swap');
+@import url('https://fonts.googleapis.com/css2?family=Ubuntu:wght@100;200;300;400;500;600;700;800;900&family=Lato:wght@100;200;300;400;500;600;700;800;900&family=Roboto:wght@100;200;300;400;500;600;700;800;900&display=swap');
html,
body {
@@ -65,20 +65,8 @@ body {
scrollbar-width: none; /* Firefox */
}
-.chakra-checkbox__label {
- font-size: 14px !important;
- display: flex;
- flex-direction: row;
- gap: 8px;
-}
-
.chakra-checkbox__control {
- padding: 5px !important;
- width: 20px !important;
- height: 20px !important;
- border-width: 3px !important;
- border-radius: 4px !important;
- border-color: #DEDFE0 !important;
+ border-width: 0px !important;
}
.chakra-checkbox__control[data-focus] {
@@ -86,8 +74,8 @@ body {
}
.chakra-checkbox__control[data-checked] {
- background: #2b8c4d !important;
- border-color: #2b8c4d !important;
+ width: 100%;
+ height: 100%;
}
@keyframes gray-scale {
@@ -101,34 +89,77 @@ body {
list-style-type: none;
display: flex;
align-self: center;
- padding-top: 36px;
+ padding: 24px;
}
.pagination li {
text-align: center;
margin-right: 10px;
- border: 1px solid #dedfe0;
border-radius: 10px;
display: flex;
}
.pagination a {
- font-family: "Lato";
- font-weight: 700;
- min-width: 35px;
- padding: 5px 10px;
+ font-family: "Roboto";
+ font-weight: 500;
+ padding: 10px 16px;
+ font-size: 14px;
+ line-height: 20px;
+ letter-spacing: 0.1px;
+ border: 1px solid #dedfe0;
+ border-radius: 8px;
+ color: #252A32;
}
.pagination .active {
background-color: #2b8c4d;
color: white;
- border: 1px solid #2b8c4d;
+}
+
+.pagination .next-page a {
+ border: 1px solid transparent;
+ color: #2B8C4D;
+}
+
+.pagination .next-page a::after {
+ content: '';
+ display: inline-block;
+ width: 9px;
+ height: 9px;
+ border-color: #2B8C4D;
+ border-right: 2px solid;
+ border-bottom: 2px solid;
+ transform: rotate(-45deg);
+ margin-left: 8px;
+}
+
+.pagination .previous-page a {
+ display: flex;
+ flex-direction: row-reverse;
+ align-items: center;
+ border: 1px solid transparent;
+ color: #2B8C4D;
+}
+
+.pagination .previous-page a::after {
+ content: '';
+ display: inline-block;
+ position: relative;
+ top: -1px;
+ width: 9px;
+ height: 9px;
+ border-color: #2B8C4D;
+ border-left: 2px solid;
+ border-top: 2px solid;
+ transform: rotate(-45deg);
+ margin-right: 8px;
}
.pagination .disabled a {
cursor: default !important;
color: #dedfe0;
pointer-events: none;
+ border: 1px solid transparent;
}
.pagination .active a{
@@ -169,6 +200,10 @@ body {
background-color: #2b8c4d !important;
}
+.hljs {
+ background-color: #252A32 !important;
+}
+
.rjsf {
width: 100%;
white-space: break-spaces;
diff --git a/next/styles/themeBD.js b/next/styles/themeBD.js
index 3faa2431..c83d5145 100644
--- a/next/styles/themeBD.js
+++ b/next/styles/themeBD.js
@@ -3,8 +3,18 @@ import { extendTheme } from "@chakra-ui/react";
const themeBD = extendTheme({
colors: {
"greenBD.500": "#2B8C4D",
- "yellowPro.500" : "#9C8400"
- }
+ "yellowPro.500" : "#9C8400",
+ "blueBD.500": "#0D99FC"
+ },
+ components: {
+ Progress: {
+ baseStyle: {
+ filledTrack: {
+ bg: "blueBD.500",
+ },
+ },
+ },
+ },
})
export default themeBD
diff --git a/next/styles/toggle.module.css b/next/styles/toggle.module.css
index a032c938..79a21267 100644
--- a/next/styles/toggle.module.css
+++ b/next/styles/toggle.module.css
@@ -36,3 +36,19 @@
width: 21px;
height: 21px;
}
+
+.toggle span:hover {
+ background-color: #71757A;
+}
+
+.toggle span span:hover {
+ background-color: #FFF;
+}
+
+.toggle span[data-checked]:hover {
+ background-color: #22703E;
+}
+
+.toggle span[data-checked] span:hover {
+ background-color: #FFF;
+}
\ No newline at end of file
diff --git a/next/utils.js b/next/utils.js
index 256ba99c..41581fa9 100644
--- a/next/utils.js
+++ b/next/utils.js
@@ -38,14 +38,6 @@ function isNumeric(str) {
return true;
}
-export function limitTextSize(text, size) {
- if (text.length > size) {
- return text.slice(0, size) + "...";
- }
-
- return text;
-}
-
export function translate(keyTranslations, valueTranslations, object) {
const formatObject = (value) => {
if(typeof value === "object") {
@@ -222,4 +214,18 @@ export function cleanString(string) {
const returnString = newString.replace(/\s+/g, ' ')
return returnString
+}
+
+export function formatBytes(bytes) {
+ if (bytes < 1024) {
+ return `${bytes} B`
+ } else if (bytes < 1024 * 1024) {
+ return `${(bytes / 1024).toFixed(2)} KB`
+ } else if (bytes < 1024 * 1024 * 1024) {
+ return `${(bytes / (1024 * 1024)).toFixed(2)} MB`
+ } else if (bytes < 1024 * 1024 * 1024 * 1024) {
+ return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`
+ } else {
+ return `${(bytes / (1024 * 1024 * 1024 * 1024)).toFixed(2)} TB`
+ }
}
\ No newline at end of file