diff --git a/.github/img/editor.png b/.github/img/editor.png new file mode 100644 index 0000000..cb8ab81 Binary files /dev/null and b/.github/img/editor.png differ diff --git a/.github/img/home.png b/.github/img/home.png new file mode 100644 index 0000000..c0fe5b5 Binary files /dev/null and b/.github/img/home.png differ diff --git a/.github/img/snippet.png b/.github/img/snippet.png new file mode 100644 index 0000000..168e91d Binary files /dev/null and b/.github/img/snippet.png differ diff --git a/.github/img/snippets.png b/.github/img/snippets.png new file mode 100644 index 0000000..d8e530e Binary files /dev/null and b/.github/img/snippets.png differ diff --git a/README.md b/README.md new file mode 100644 index 0000000..601b8c6 --- /dev/null +++ b/README.md @@ -0,0 +1,75 @@ +# Snippet Box + +![Snippet library screenshot](./.github/img/snippets.png) + +## Description + +Snippet Box is a simple self-hosted app for organizing your code snippets. It allows you to easily create, edit, browse and manage your snippets in various languages. With built-in Markdown support, Snippet Box makes it very easy to add notes or simple documentation to your code. + +## Technology + +- Backend + - Node.js + - Express.js + - Sequelize ORM + SQLite +- Frontend + - React + - TypeScript + - Bootstrap +- Deployment + - Docker + +## Development + +```sh +# clone repository +git clone https://github.com/pawelmalak/snippet-box +cd snippet-box + +# install dependencies (run only once) +npm run init + +# start backend and frontend development servers +npm run dev +``` + +## Installation + +### With Docker + +#### Building image + +```sh +docker build -t snippet-box . +``` + +#### Deployment + +```sh +# run container +docker run -p 5000:5000 -v /path/to/data:/app/data snippet-box +``` + +## Functionality + +- Pinned snippets + - Pin your favorite / important snippets to home screen for easy and quick access + +![Homescreen screenshot](./.github/img/home.png) + +- Snippet library + - Manage your snippets through snippet library + - Easily filter and access your code + +![Snippet library screenshot](./.github/img/snippets.png) + +- Snippet + - View your code, snippet details and documentation + - Easily perform snippet actions like edit, pin or delete from a single place + +![Snippet screenshot](./.github/img/snippet.png) + +- Edditor + - Create and edit your snippets from simple and easy to use editor + +![Editor screenshot](./.github/img/editor.png) diff --git a/client/src/components/Snippets/SnippetCode.tsx b/client/src/components/Snippets/SnippetCode.tsx index 51db0e2..3d5b4ff 100644 --- a/client/src/components/Snippets/SnippetCode.tsx +++ b/client/src/components/Snippets/SnippetCode.tsx @@ -8,7 +8,7 @@ export const SnippetCode = (props: Props): JSX.Element => { diff --git a/client/src/components/UI/Spinner.module.css b/client/src/components/UI/Spinner.module.css deleted file mode 100644 index 6b72b3f..0000000 --- a/client/src/components/UI/Spinner.module.css +++ /dev/null @@ -1,59 +0,0 @@ -.Spinner, -.Spinner:before, -.Spinner:after { - background: #212529; - -webkit-animation: load1 1s infinite ease-in-out; - animation: load1 1s infinite ease-in-out; - width: 1em; - height: 4em; -} -.Spinner { - color: #212529; - text-indent: -9999em; - margin: 88px auto; - position: relative; - font-size: 11px; - -webkit-transform: translateZ(0); - -ms-transform: translateZ(0); - transform: translateZ(0); - -webkit-animation-delay: -0.16s; - animation-delay: -0.16s; -} -.Spinner:before, -.Spinner:after { - position: absolute; - top: 0; - content: ''; -} -.Spinner:before { - left: -1.5em; - -webkit-animation-delay: -0.32s; - animation-delay: -0.32s; -} -.Spinner:after { - left: 1.5em; -} -@-webkit-keyframes load1 { - 0%, - 80%, - 100% { - box-shadow: 0 0; - height: 4em; - } - 40% { - box-shadow: 0 -2em; - height: 5em; - } -} -@keyframes load1 { - 0%, - 80%, - 100% { - box-shadow: 0 0; - height: 4em; - } - 40% { - box-shadow: 0 -2em; - height: 5em; - } -} diff --git a/client/src/components/UI/Spinner.tsx b/client/src/components/UI/Spinner.tsx deleted file mode 100644 index e76bca4..0000000 --- a/client/src/components/UI/Spinner.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import classes from './Spinner.module.css'; - -export const Spinner = (): JSX.Element => { - return
Loading...
; -}; diff --git a/client/src/components/UI/index.ts b/client/src/components/UI/index.ts index e7b2826..184e70b 100644 --- a/client/src/components/UI/index.ts +++ b/client/src/components/UI/index.ts @@ -2,6 +2,5 @@ export * from './Layout'; export * from './Badge'; export * from './Card'; export * from './PageHeader'; -export * from './Spinner'; export * from './Button'; export * from './EmptyState'; diff --git a/client/src/containers/Home.tsx b/client/src/containers/Home.tsx index 0261f22..e506c8c 100644 --- a/client/src/containers/Home.tsx +++ b/client/src/containers/Home.tsx @@ -1,6 +1,6 @@ import { useEffect, useContext, Fragment } from 'react'; import { SnippetsContext } from '../store'; -import { Layout, Spinner, PageHeader, EmptyState } from '../components/UI'; +import { Layout, PageHeader, EmptyState } from '../components/UI'; import { SnippetGrid } from '../components/Snippets/SnippetGrid'; export const Home = (): JSX.Element => { @@ -24,13 +24,6 @@ export const Home = (): JSX.Element => { )} - - -
- !s.isPinned).slice(0, 6)} - /> -
)} diff --git a/client/src/containers/Snippets.tsx b/client/src/containers/Snippets.tsx index 329638c..ffe8e31 100644 --- a/client/src/containers/Snippets.tsx +++ b/client/src/containers/Snippets.tsx @@ -1,14 +1,7 @@ import { useEffect, useContext, useState, Fragment } from 'react'; import { SnippetsContext } from '../store'; import { SnippetGrid } from '../components/Snippets/SnippetGrid'; -import { - Badge, - Button, - Card, - EmptyState, - Layout, - Spinner -} from '../components/UI'; +import { Button, Card, EmptyState, Layout } from '../components/UI'; import { Snippet } from '../typescript/interfaces'; export const Snippets = (): JSX.Element => { @@ -45,7 +38,13 @@ export const Snippets = (): JSX.Element => { ) : (
- + +
All snippets
+
+ Total + {snippets.length} +
+
Filter by language
{languageCount.map((el, idx) => { const isActiveFilter = filter === el.language;