diff --git a/pages/_document.js b/pages/_document.js index b6147b6012..5b5216aef3 100644 --- a/pages/_document.js +++ b/pages/_document.js @@ -1,6 +1,7 @@ import React from 'react' import Document, { Head, Main, NextScript } from 'next/document' import { ServerStyleSheet } from 'styled-components' + import { META_BASE_TITLE, META_DESCRIPTION, diff --git a/pages/doc.js b/pages/doc.js index ce71d3d4be..aacf29815a 100644 --- a/pages/doc.js +++ b/pages/doc.js @@ -1,137 +1,40 @@ -/* global docsearch:readonly */ - -import React, { useCallback, useEffect, useState } from 'react' +import React from 'react' import PropTypes from 'prop-types' -import styled from 'styled-components' -import Error from 'next/error' -import Router from 'next/router' import fetch from 'isomorphic-fetch' -// components -import Page from '../src/Page' -import { HeadInjector } from '../src/Documentation/HeadInjector' -import Hamburger from '../src/Hamburger' -import SearchForm from '../src/SearchForm' -import SidebarMenu from '../src/Documentation/SidebarMenu/SidebarMenu' -import Markdown from '../src/Documentation/Markdown/Markdown' -import RightPanel from '../src/Documentation/RightPanel/RightPanel' -// sidebar data and helpers -import { getItemByPath, structure } from '../src/utils/sidebar' -import { extractSlugFromTitle } from '../src/Documentation/Markdown/Markdown' -// styles -import { media } from '../src/styles' +import Error from 'next/error' +import Head from 'next/head' -const ROOT_ELEMENT = 'bodybag' -const SIDEBAR_MENU = 'sidebar-menu' +import Documentation from '../src/components/Documentation' -const parseHeadings = text => { - const headingRegex = /\n(## \s*)(.*)/g - const matches = [] - let match - do { - match = headingRegex.exec(text) - if (match) { - const [title, slug] = extractSlugFromTitle(match[2]) - matches.push({ - text: title, - slug: slug - }) - } - } while (match) +import { getItemByPath } from '../src/utils/sidebar' - return matches -} +import { META_BASE_TITLE } from '../src/consts' -export default function Documentation({ item, headings, markdown, errorCode }) { +export default function DocumentationPage({ item, markdown, errorCode }) { if (errorCode) { return } - const { source, path, label, next, prev, tutorials } = item - - const [isMenuOpen, setIsMenuOpen] = useState(false) - const [isSearchAvaible, setIsSearchAvaible] = useState(false) - - const toggleMenu = useCallback(() => setIsMenuOpen(!isMenuOpen), [isMenuOpen]) - - useEffect(() => { - try { - docsearch - - setIsSearchAvaible(true) - - if (isSearchAvaible) { - docsearch({ - apiKey: '755929839e113a981f481601c4f52082', - indexName: 'dvc', - inputSelector: '#doc-search', - debug: false // Set to `true` if you want to inspect the dropdown - }) - } - } catch (ReferenceError) { - // nothing there - } - }, [isSearchAvaible]) - - useEffect(() => { - const handleRouteChange = () => { - const rootElement = document.getElementById(ROOT_ELEMENT) - if (rootElement) { - rootElement.scrollTop = 0 - } - } - - Router.events.on('routeChangeComplete', handleRouteChange) - - return () => Router.events.off('routeChangeComplete', handleRouteChange) - }, []) - - const githubLink = `https://github.com/iterative/dvc.org/blob/master/public${source}` - return ( - - - - - - - - - - - {isSearchAvaible && ( - - - - )} - - - - - - - - - + <> + + + {item.label} | {META_BASE_TITLE} + + + + ) } -Documentation.getInitialProps = async ({ asPath, req }) => { +DocumentationPage.propTypes = { + item: PropTypes.object, + markdown: PropTypes.string, + errorCode: PropTypes.number +} + +DocumentationPage.getInitialProps = async ({ asPath, req }) => { const item = getItemByPath(asPath.split(/[?#]/)[0]) if (!item) { @@ -152,147 +55,14 @@ Documentation.getInitialProps = async ({ asPath, req }) => { } } - const text = await res.text() + const markdown = await res.text() return { - item: item, - headings: parseHeadings(text), - markdown: text + item, + markdown } } catch { console.error(`Can't fetch ${protocol}//${host}${item.source}`) window.location.reload() } } - -Documentation.propTypes = { - item: PropTypes.object, - headings: PropTypes.array, - markdown: PropTypes.string, - errorCode: PropTypes.number -} - -const Container = styled.div` - display: flex; - flex-direction: row; - max-width: 1200px; - margin: 0 auto; - background: white; - z-index: 2; - - &:before { - content: ''; - display: block; - position: fixed; - top: 0; - left: 0; - bottom: 0; - width: 50%; - background-color: #eef4f8; - z-index: -1; - pointer-events: none; - } -` - -const Backdrop = styled.div` - display: none; - - ${media.phablet` - display: block; - opacity: 0; - pointer-events: none; - transition: opacity .3s linear; - - ${props => - props.visible && - ` - content: ''; - position: fixed; - top: 0; - left: 0; - bottom: 0; - right: 0; - background-color: rgba(0, 0, 0, 0.4); - z-index: 1; - opacity: 1; - pointer-events: all; - `} - `}; -` - -const Side = styled.div` - width: 280px; - background-color: #eef4f8; - - @media only screen and (max-width: 1200px) { - padding-left: 15px; - } - - ${media.phablet` - position: fixed; - display: block; - z-index: 2; - top: 78px; - bottom: 0; - left: 0; - right: 60px; - box-shadow: rgba(0, 0, 0, 0.14) 0px 0px 4px, rgba(0, 0, 0, 0.28) 0px 4px 8px; - transform: translateX(-110%); - transition: transform .35s ease; - - ${props => - props.isOpen && - ` - transform: translateX(0); - `} - `}; -` - -const SearchArea = styled.div` - height: 60px; - display: flex; - align-items: center; - background-color: #eef4f8; - z-index: 10; - position: sticky; - top: 0; - - ${media.phablet` - position: relative; - padding: 0 20px; - `}; - - form { - height: 40px; - } -` - -const SideToggle = styled.div` - display: none; - position: fixed; - z-index: 2; - left: 8px; - bottom: 20px; - width: 45px; - height: 45px; - border-radius: 50%; - background-color: rgba(255, 255, 255, 0.9); - box-shadow: 0 0px 9px 0 rgba(0, 0, 0, 0.15); - transition: transform 0.3s ease; - justify-content: center; - align-items: center; - - ${media.phablet` - display: flex; - - > div { - transform: scale(0.75); - } - `}; - - ${({ isMenuOpen }) => - isMenuOpen && - ` - transform: translateX(calc(100vw - 60px)); - `}; -` diff --git a/pages/features.js b/pages/features.js index b3ad984fa4..e8d0145e79 100644 --- a/pages/features.js +++ b/pages/features.js @@ -1,223 +1,18 @@ import React from 'react' -import styled from 'styled-components' import Head from 'next/head' -import { container } from '../src/styles' -import { media } from '../src/styles' +import Features from '../src/components/Features' -import Page from '../src/Page' -import Hero from '../src/Hero' -import FeaturesHero from '../src/FeaturesHero' -import TrySection from '../src/TrySection' import { META_BASE_TITLE } from '../src/consts' -const HeadInjector = () => ( - - Features | {META_BASE_TITLE} - -) - export default function FeaturesPage() { return ( - - - - - - - - - - Git compatible - - Git-compatible - - DVC runs on top of any Git repository and is compatible with any - standard Git server or provider (GitHub, GitLab, etc). Data file - contents can be shared by network-accessible storage or any - supported cloud solution. DVC offers all the advantages of a - distributed version control system — lock-free, local branching, - and versioning. - - - - - Storage agnostic - - Storage agnostic - - Use Amazon S3, Microsoft Azure Blob Storage, Google Drive, Google - Cloud Storage, Aliyun OSS, SSH/SFTP, HDFS, HTTP, network-attached - storage, or rsync to store data. The list of supported remote - storage is constantly expanding. - - - - - Reproducibility - - Reproducible - - The single 'dvc repro' command reproduces experiments - end-to-end. DVC guarantees reproducibility by consistently - maintaining a combination of input data, configuration, and the - code that was initially used to run an experiment. - - - - - Low-friction branching - - Low friction branching - - DVC fully supports instantaneous Git branching, even with large - files. Branches beautifully reflect the non-linear structure and - highly iterative nature of a ML process. Data is not duplicated — - one file version can belong to dozens of experiments. Create as - many experiments as you want, instantaneously switch back and - forth, and save a history of all attempts. - - - - - - - Metric tracking - - Metrics are first-class citizens in DVC. DVC includes a command to - list all branches, along with metric values, to track the progress - or pick the best version. - - - - - ML pipelines framework - - ML pipeline framework - - DVC has a built-in way to connect ML steps into a DAG and run the - full pipeline end-to-end. DVC handles caching of intermediate - results and does not run a step again if input data or code are - the same. - - - - - Language & framework agnostic - - Language- & framework-agnostic - - No matter which programming language or libraries are in use or - how code is structured, reproducibility and pipelines are based on - input and output files or directories. Python, R, Julia, Scala - Spark, custom binary, Notebooks, flatfiles/TensorFlow, PyTorch, - etc. are all supported. - - - - - HDFS, Hive & Apache Spark - - HDFS, Hive & Apache Spark - - Include Spark and Hive jobs in the DVC data versioning cycle along - with local ML modeling steps or manage Spark and Hive jobs with - DVC end-to-end. Drastically decrease a feedback loop by - decomposing a heavy cluster job into smaller DVC pipeline steps. - Iterate on the steps independently with respect to dependencies. - - - - - Failure tracking - - Track failures - - Bad ideas can sometimes spark more ideas among colleagues than - successful ones. Retaining knowledge of failed attempts can save - time in the future. DVC is built to track everything in a - reproducible and easily accessible way. - - - - - - + <> + + Features | {META_BASE_TITLE} + + + ) } - -const Container = styled.div` - ${container}; -` - -const Features = styled.div` - display: flex; - flex-flow: row; - flex-wrap: wrap; - padding-top: 110px; - padding-bottom: 90px; - - ${media.phablet` - padding-top: 70px; - padding-bottom: 50px; - `}; -` - -const Feature = styled.div` - flex: 33.3%; - flex-basis: 311px; - margin-bottom: 63px; -` - -const Icon = styled.div` - height: 48px; - - img { - width: 48px; - height: 48px; - } -` - -const Name = styled.h3` - font-family: BrandonGrotesqueMed; - margin-top: 10px; - margin-bottom: 10px; - - font-size: 20px; - font-weight: 500; - color: #40364d; - - min-height: 28px; -` - -const Description = styled.div` - max-width: 311px; - - font-size: 16px; - color: #5f6c72; -` diff --git a/pages/index.js b/pages/index.js index b62f04c6bb..73c2c0faa3 100644 --- a/pages/index.js +++ b/pages/index.js @@ -1,58 +1,29 @@ import React from 'react' -import styled from 'styled-components' + import Head from 'next/head' -import LearnMore from '../src/LearnMore' +import Home from '../src/components/Home' -import Page from '../src/Page' -import Hero from '../src/Hero' -import LandingHero from '../src/LandingHero' -import Diagram from '../src/Diagram' -import PromoSection from '../src/PromoSection' -import UseCases from '../src/UseCases' -import Subscribe from '../src/Subscribe' import { META_BASE_TITLE } from '../src/consts' -const HeadInjector = () => ( - - - - {META_BASE_TITLE} - -) - export default function HomePage() { return ( - - - - - - - - - - - - - - + <> + + + + {META_BASE_TITLE} + + + ) } - -const LearnMoreSection = styled.div` - z-index: 2; - position: absolute; - transform: translate(-50%, 0%); - left: 50%; - bottom: 16px; -` diff --git a/pages/support.js b/pages/support.js index b9b91e4fd0..79a80ce0b8 100644 --- a/pages/support.js +++ b/pages/support.js @@ -1,259 +1,18 @@ import React from 'react' -import styled from 'styled-components' -import { Mark } from '../src/styles' -import color from 'color' import Head from 'next/head' -import { OnlyDesktop, container, media } from '../src/styles' +import Support from '../src/components/Support' -import Page from '../src/Page' -import Hero from '../src/Hero' -import TrySection from '../src/TrySection' -import Popover from '../src/Popover/Popover' import { META_BASE_TITLE } from '../src/consts' -const HeadInjector = () => ( - - Support | {META_BASE_TITLE} - -) - export default function SupportPage() { return ( - - - - - Questions, feedback, or just need to get in touch? - - - - - - - - Slack-like Chat - - - Join data science practitioners in our welcoming{' '} - - DVC community - - . It’s the fastest way to ask for a help. - - - - - - - - } - enterExitTransitionDurationMs={200} - > - - - - - - - - - Bugs & Features - - - Found an issue or have an idea? Check our GitHub{' '} - - issues tracker - {' '} - to see if there is already a fix or report a new one. - - - - - - - - - Forum - - - Discuss your ideas or{' '} - - best practices - {' '} - in the DVC forum. - - - - - - - - - Email - - - Don’t hesitate to shoot us an email at{' '} - - - support@dvc.org - - {' '} - with any questions. - - - - - - - - - + <> + + Support | {META_BASE_TITLE} + + + ) } - -const SupportHero = styled.div` - padding-top: 90px; - padding-bottom: 80px; - overflow: hidden; -` - -const Heading = styled.h1` - font-family: BrandonGrotesqueMed; - margin: 0px auto; - max-width: 610px; - font-size: 40px; - font-weight: 500; - line-height: 1.4; - text-align: center; - color: #40364d; -` - -const Container = styled.div` - ${container}; -` - -const Features = styled.div` - display: flex; - flex-flow: row; - flex-wrap: wrap; - padding-top: 80px; - padding-bottom: 70px; - max-width: 800px; - margin: 0 auto; - - ${media.phablet` - padding-top: 70px; - padding-bottom: 50px; - `}; -` - -const Feature = styled.div` - flex: 1 0 300px; - margin: 0 20px 60px; - padding: 10px; -` - -const FeatureHeading = styled.div` - display: flex; - align-items: center; - margin-bottom: 10px; -` - -const Icon = styled.div` - height: 50px; - width: 50px; - border-radius: 50%; - background-color: ${props => - color(props.color) - .alpha(0.15) - .string()}; - margin-right: 10px; - - &::after { - content: ' '; - display: block; - width: 50px; - height: 50px; - opacity: 1; - mask-image: url(${props => props.url}); - mask-repeat: no-repeat; - mask-position: center; - background-color: ${props => props.color}; - transform: translate(-10px, 0); - } -` - -const Name = styled.h3` - font-family: BrandonGrotesqueMed; - margin-top: 10px; - margin-bottom: 10px; - font-size: 22px; - font-weight: 500; - color: #40364d; - min-height: 28px; -` - -const Description = styled.div` - font-size: 20px; - color: #5f6c72; -` - -const FlexRow = styled.div` - display: flex; - align-items: center; -` - -const Link = styled.a` - text-decoration: none; -` - -const Button = styled.button` - text-decoration: none; - margin-top: 20px; - border-radius: 4px; - background-color: white; - border: 2px solid ${props => props.color}; - color: ${props => props.color}; - font-family: BrandonGrotesqueMed, Tahoma, Arial; - height: 42px; - font-size: 18px; - cursor: pointer; - transition: 0.2s background-color ease-out; - padding: 5px 20px; - - &:hover { - background-color: ${props => props.color}; - color: white; - } -` - -const DiscrodWidget = styled.img` - display: block; - margin-top: 20px; - margin-left: 20px; - width: 50px; - height: 50px; - cursor: pointer; - mask-image: url('/static/img/support/discord.svg'); - mask-repeat: no-repeat; - mask-position: center; - background-color: #b88eeb; - - &:hover { - opacity: 0.7; - } -` diff --git a/src/Documentation/HeadInjector.js b/src/Documentation/HeadInjector.js deleted file mode 100644 index b00cab0f29..0000000000 --- a/src/Documentation/HeadInjector.js +++ /dev/null @@ -1,17 +0,0 @@ -import Head from 'next/head' -import PropTypes from 'prop-types' -import React from 'react' - -import { META_BASE_TITLE } from '../consts' - -export const HeadInjector = ({ sectionName = 'Documentation' }) => ( - - - {sectionName} | {META_BASE_TITLE} - - -) - -HeadInjector.propTypes = { - sectionName: PropTypes.string -} diff --git a/src/Documentation/LightButton.js b/src/Documentation/LightButton.js deleted file mode 100644 index 90d083a59c..0000000000 --- a/src/Documentation/LightButton.js +++ /dev/null @@ -1,31 +0,0 @@ -import styled from 'styled-components' - -export const LightButton = styled.a` - display: inline-flex; - justify-content: center; - align-items: center; - color: #575e64; - background-color: white; - border: 1px solid #575e64; - text-decoration: none; - font-weight: 600; - line-height: 30px; - padding: 2px 16px; - border-radius: 3px; - cursor: pointer; - transition: 0.2s background-color ease-out; - z-index: 1 - - &:hover { - background-color: #f5f7f9; - } - - i { - background-size: contain; - background-repeat: no-repeat; - background-position: center; - width: 1em; - height: 1em; - margin-right: 7px; - } -` diff --git a/src/FeaturesHero/index.js b/src/FeaturesHero/index.js deleted file mode 100644 index a6f6614a74..0000000000 --- a/src/FeaturesHero/index.js +++ /dev/null @@ -1,31 +0,0 @@ -import React from 'react' -import styled from 'styled-components' - -export default function FeaturesHero() { - return ( - - - DVC brings agility, reproducibility, and collaboration into your - existing data science workflow - - - ) -} - -const Wrapper = styled.div` - padding-top: 87px; - padding-bottom: 58px; - overflow: hidden; -` - -const Heading = styled.h1` - font-family: BrandonGrotesqueMed; - margin: 0px auto; - max-width: 610px; - min-height: 185px; - font-size: 40px; - font-weight: 500; - line-height: 1.4; - text-align: center; - color: #40364d; -` diff --git a/src/Footer/index.js b/src/Footer/index.js deleted file mode 100644 index f37e56c854..0000000000 --- a/src/Footer/index.js +++ /dev/null @@ -1,208 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import styled from 'styled-components' -import NextLink from 'next/link' -import { columns, container, media } from '../styles' - -const SocialLink = ({ src, href, children }) => ( - - {children} - -) - -SocialLink.propTypes = { - src: PropTypes.string.isRequired, - href: PropTypes.string.isRequired, - children: PropTypes.node.isRequired -} - -export default function Footer(props) { - return ( - - - - - - site logo - - - - - - Product - - - Overview - - - Features - - - - - Help - - - Support - - - Get started - - - Chat - - - Documentation - - - - - Company - - Blog - - Iterative.ai - - Privacy Policy - - - - Social - - - Twitter - - - GitHub - - - Discord - - - - - - - - ) -} - -Footer.propTypes = { - isDocPage: PropTypes.bool -} - -const Wrapper = styled.section` - min-height: 300px; - background-color: #40364d; - color: #fff; - - ${media.phablet` - min-height: auto; - `}; -` - -const Container = styled.div` - ${container}; - ${props => props.wide && `max-width: 1200px;`}; - padding-top: 64px !important; - padding-bottom: 44px; - - ${media.tablet` - padding: 64px 61px 44px 67px; - max-width: auto; - `} - - ${media.phablet` - padding: 30px 25px; - max-width: auto; - `}; -` - -const Top = styled.div` - height: 40px; - margin-bottom: 40.7px; -` - -const Logo = styled.a`` - -const Columns = styled.div` - ${columns}; - - ${media.phablet` - justify-content: space-between; - `}; -` - -const Column = styled.div` - display: flex; - flex-direction: column; - flex-basis: 150px; - margin-right: 66px; - - ${media.phablet` - margin-right: 0px; - `}; -` - -const Heading = styled.h2` - font-family: BrandonGrotesqueLight; - opacity: 0.61; - color: #ffffff; - font-size: 20px; - font-weight: 100; -` - -const Links = styled.div` - margin-top: 29px; - display: flex; - flex-direction: column; -` - -const Link = styled.a` - line-height: 23px; - font-size: 20px; - margin-bottom: 17px; - display: flex; - color: #fff; - text-decoration: none; - - &:hover { - color: #ccc; - } - - ${props => - props.src && - ` - &::before { - margin-right: 14px; - width: 26px; - height: 26px; - content: ' '; - display: block; - background-image: url(${props.src}); - background-repeat: no-repeat; - background-position: center center; - background-size: contain; - } - `}; -` - -const Copyright = styled.div` - padding-bottom: 18px; - padding-top: 18px; - font-size: 14px; -` diff --git a/src/Nav/index.js b/src/Nav/index.js deleted file mode 100644 index e3e9da5dc4..0000000000 --- a/src/Nav/index.js +++ /dev/null @@ -1,142 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import styled from 'styled-components' -import { media } from '../styles' -import { logEvent } from '../utils/ga' -import NextLink from 'next/link' -import Router from 'next/router' - -const getStarted = () => { - logEvent('menu', 'get-started') - - Router.push('/doc/get-started') -} - -export default function Nav({ mobile = false }) { - return ( - - - - { - logEvent('menu', 'features') - }} - > - Features - - - - { - logEvent('menu', 'doc') - }} - > - Doc - - - { - logEvent('menu', 'blog') - }} - > - Blog - - { - logEvent('menu', 'chat') - }} - > - Chat - - { - logEvent('menu', 'github') - }} - > - GitHub - - - { - logEvent('menu', 'support') - }} - > - Support - - - - Get Started - - ) -} - -Nav.propTypes = { - mobile: PropTypes.bool -} - -const Links = styled.div` - display: flex; - flex-direction: row; -` - -const Link = styled.a` - text-decoration: none; - text-transform: uppercase; - - font-family: BrandonGrotesqueBold, Tahoma, Arial; - font-size: 13px; - color: #838d93; - padding-top: 10px; - padding-bottom: 3px; - border-bottom: 1.5px solid #fff; - margin-left: 30px; - - &:hover { - color: #40364d; - border-bottom: 1.5px solid #40364d; - } -` - -const Wrapper = styled.div` - display: flex; - flex-shrink: 0; - flex-direction: row; - align-items: center; - - ${props => - props.mobile && - ` - display: none; - `} - - ${media.phablet` - ${props => - !props.mobile && - ` - display: none; - `} - `}; -` - -const GetStartedButton = styled.button` - text-decoration: none; - margin-left: 40px; - border-radius: 4px; - background-color: #13adc7; - font-family: BrandonGrotesqueMed, Tahoma, Arial; - color: #fff; - width: 113px; - height: 38px; - font-size: 16px; - border: none; - cursor: pointer; - transition: 0.2s background-color ease-out; - padding: 1px 7px 2px; - - &:hover { - background-color: #13a3bd; - } -` diff --git a/src/TopMenu/index.js b/src/TopMenu/index.js deleted file mode 100644 index 9633fdf86a..0000000000 --- a/src/TopMenu/index.js +++ /dev/null @@ -1,133 +0,0 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import NextLink from 'next/link' -// components -import Nav from '../Nav' -// utils -import throttle from 'lodash.throttle' -// styles -import styled from 'styled-components' -import { media } from '../styles' -// constants -import { HEADER } from '../consts' - -const MIN_HEIGHT = 78 - -class TopMenu extends Component { - constructor() { - super() - this.state = { - scrolled: false - } - this.handleScrollThrottled = throttle(this.handleScroll, 300) - } - - componentDidMount() { - this.bodybag = document.getElementById('bodybag') - this.isPhablet = window.innerWidth <= 572 - - if (!this.isPhablet) { - this.bodybag.addEventListener('scroll', this.handleScrollThrottled) - this.handleScroll() - } - } - - componentWillUnmount() { - if (!this.isPhablet) { - this.bodybag.removeEventListener('scroll', this.handleScrollThrottled) - } - } - - handleScroll = e => { - if (this.props.isDocPage) return - const scrollTop = e ? e.target.scrollTop : 0 - this.setState({ - scrolled: scrollTop > 25 - }) - } - - render() { - const { isDocPage } = this.props - const { scrolled } = this.state - - return ( - - - - - dvc.org - - -