samnoh / offline-graphql-demo

Apollo Markdown Note Web App

Home Page:https://dazzling-knuth-408b42.netlify.com/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Offline GraphQL Demo

  • Markdown Live Preview
  • Download Markdown File
  • Highlight Code Syntax
  • Works Offline (localStorage)
  • Responsive Web
  • No Redux (GraphQL Local State)

Live Demo

Netlify Status

Screenshots

Install

  • apollo-cache-inmemory
  • apollo-client
  • graphql
  • graphql-tag
  • react-fontawesome
  • react-router-dom
  • react-markdown
  • react-textarea-autosize
    • A textarea component that automatically resizes textarea as content changes
  • styled-components
  • styled-reset
    • Reset CSS for styled-components
  • github-markdown-css
  • prismjs

TIL

GraphQL Fragment

  • Share fields across queries
fragment NameParts on Person {
    firstName
    lastName
}

query GetPerson {
    people(id: 7) {
        ...NameParts
        avatar(size: LARGE)
    }
}

Apollo Local State Management

  • Configure
    • apollo-link-state is deprecated
    • apollo-client@2.5 can handle local state now
import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';

import { resolvers, typeDefs, defaults } from './clientState';

const cache = new InMemoryCache();

const client = new ApolloClient({
    cache,
    resolvers,
    typeDefs
});

cache.writeData({
    data: defaults // default data
});

export default client;
  • cache
    • cache.readFragment({ fragment, id })
    • cache.readQuery({ query })
    • cache.writeDate({ data: {} })
    • Maniuplate or read the cache
  • getCacheKey({ __typename, id })
    • Get a key from the cache using __typename and id
Query: {
    note: (_, { id }, { cache, getCacheKey }) => {
        const noteId = getCacheKey({ __typename: 'Note', id });
        const note = cache.readFragment({ fragment: NOTE_FRAGMENT, id: noteId });
        return note;
    }
}
Mutation: {
    createNote: (_, { title, content }, { cache }) => {
        const { notes } = cache.readQuery({ query: GET_NOTES });
        const newNote = { id: uuid(), title, content, __typename: 'Note' };
        cache.writeData({ data: { notes: [...notes, newNote] } });
        return newNote;
    }
}
  • @client
    • Used for offline queries
{
    notes @client {
        ...
    }
}
  • Mutation
export const ADD_NOTE = gql`
    mutation createNote($title: String!, $content: String) {
        createNote(title: $title, content: $content) @client {...}
    }
`;
import { Mutation } from 'react-apollo';
...
<Mutation mutation={ADD_NOTE}>
    {createNote => <EditorContainer submit={createNote} />}
</Mutation>
submit({ variables: { id, title, content } });

react-markdown + github-markdown-css

  • Renders markdown strings to HTML
    • escapes HTML tags by default for security issues
import ReactMarkdown from 'react-markdown';
import MarkdownStyle from '../styles/markdown';
...
<MarkdownStyle>
    <ReactMarkdown className="markdown-body" source={content} />
</MarkdownStyle>
  • Markdown Styles
import styled from 'styled-components';
import markdownStyles from 'github-markdown-css';

export default styled.div`${markdownStyles}`;

Create & Download File

  • Blob
const element = document.createElement('a');
const file = new Blob([note.content], { type: 'text/plain' });
element.href = URL.createObjectURL(file);
element.download = `${note.title}.md`;
document.body.appendChild(element);
element.click();
document.body.removeChild(element);

react-fontawesome

  • Install
npm install --save @fontawesome/fontawesome-svg-core @fontawesome/free-solid-svg-icons @fontawesome/react-fontawesome
  • Usage
    • icon & size
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faChevronLeft} from '@fortawesome/free-solid-svg-icons';
...
<FontAwesomeIcon icon={faChevronLeft} size="sm" />

About

Apollo Markdown Note Web App

https://dazzling-knuth-408b42.netlify.com/


Languages

Language:JavaScript 95.1%Language:HTML 4.9%