Refactoring (#423)

* Refactoring

* v0.7.2

* Add to travis

* Don't run a server

* Extra package

* Self hosted

* Fix tests
This commit is contained in:
Tania Rascia
2020-10-28 01:00:25 -05:00
committed by GitHub
parent 5982247b15
commit 5bc732ab41
23 changed files with 75 additions and 58 deletions
+2 -2
View File
@@ -30,8 +30,8 @@ install:
before_script:
# Start server and client for tests
- echo -e "CLIENT_ID=abc" > .env
- npm run dev:test &
- echo -e "CLIENT_ID=abc\nDEMO=true" > .env
- npm run client &
script:
# Run unit, component, and e2e tests
+11
View File
@@ -2,6 +2,17 @@
All notable changes to this project will be documented in this file.
## v0.7.2 10/27/2020
Refactoring.
- Add SonarQube via SonarCloud (https://sonarcloud.io/dashboard?id=taniarascia_takenote)
- Fix bugs and code smells
- Fix #422 /app redirect
- Add demo environment variable
- Add compression
- Remove prettier and associated massive Webpack bundle
## v0.7.1 10/25/2020
Add GitHub integration.
+7 -1
View File
@@ -5,6 +5,11 @@
<p align="center">
<img src="https://img.shields.io/badge/License-MIT-blue.svg">
<a href="https://travis-ci.org/taniarascia/takenote"><img src="https://travis-ci.org/taniarascia/takenote.svg?branch=master"></a>
<a href="https://app.netlify.com/sites/tnote/deploys"><img src="https://api.netlify.com/api/v1/badges/a0e055de-cab8-4217-80dd-5bd769b7d478/deploy-status"></a>
<a href="https://sonarcloud.io/dashboard?id=taniarascia_takenote"><img src="https://sonarcloud.io/api/project_badges/measure?project=taniarascia_takenote&metric=sqale_rating"></a>
<a href="https://sonarcloud.io/dashboard?id=taniarascia_takenote"><img src="https://sonarcloud.io/api/project_badges/measure?project=taniarascia_takenote&metric=reliability_rating"></a>
<a href="https://sonarcloud.io/api/project_badges/measure?project=taniarascia_takenote&metric=security_rating"><img src="https://sonarcloud.io/api/project_badges/measure?project=taniarascia_takenote&metric=sqale_rating"></a>
<a href='https://coveralls.io/github/taniarascia/takenote'><img src='https://coveralls.io/repos/github/taniarascia/takenote/badge.svg' alt='Coverage Status' /></a>
</p>
<p align="center">A free, open-source notes app for the web. (Demo only)</p>
@@ -64,7 +69,7 @@ Run a development server.
npm run client
```
## Full Application Development
## Full Application Development (self-hosted)
In `src/client/sagas/index.ts` and `src/client/components/LandingPage.tsx`, change `isDemo` to false.
@@ -248,6 +253,7 @@ Thanks goes to these wonderful people:
<!-- markdownlint-enable -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->
## Acknowledgements
+5 -1
View File
@@ -18,10 +18,14 @@ if (getEnvFromDotEnvFile.error) {
console.log('Getting environment variables from build args for production') // eslint-disable-line
envKeys = {
'process.env.CLIENT_ID': JSON.stringify(process.env.CLIENT_ID),
'process.env.DEMO': JSON.stringify(process.env.DEMO),
'process.env.NODE_ENV': JSON.stringify('production'),
}
} else {
envKeys = { 'process.env.CLIENT_ID': JSON.stringify(getEnvFromDotEnvFile.parsed['CLIENT_ID']) }
envKeys = {
'process.env.CLIENT_ID': JSON.stringify(getEnvFromDotEnvFile.parsed['CLIENT_ID']),
'process.env.DEMO': JSON.stringify(getEnvFromDotEnvFile.parsed['DEMO']),
}
}
module.exports = {
+6 -3
View File
@@ -3,6 +3,7 @@ const { merge } = require('webpack-merge')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const TerserJSPlugin = require('terser-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CompressionPlugin = require('compression-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const common = require('./webpack.common.js')
@@ -52,22 +53,24 @@ module.exports = merge(common, {
new webpack.SourceMapDevToolPlugin({
exclude: ['/node_modules/'],
}),
new CompressionPlugin(),
],
performance: {
hints: false,
hints: 'warning',
maxEntrypointSize: 512000,
maxAssetSize: 512000,
},
optimization: {
minimizer: [new TerserJSPlugin(), new OptimizeCSSAssetsPlugin()],
runtimeChunk: 'single',
runtimeChunk: 'multiple',
splitChunks: {
// Cache vendors since this code won't change very often
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/](react|react-dom|axios)[\\/]/,
test: /[\\/]node_modules[\\/](react|react-dom|axios|redux|react-redux)[\\/]/,
name: 'vendors',
chunks: 'all',
enforce: true,
},
},
},
+2 -2
View File
@@ -12,7 +12,7 @@ GIT_VERSION=$(git describe --always --abbrev --tags --long)
# Build and tag new Docker image and push up to Docker Hub
echo "Building and tagging new Docker image: ${IMAGE}:${GIT_VERSION}"
docker build --build-arg CLIENT_ID=${CLIENT_ID} -t ${IMAGE}:${GIT_VERSION} .
docker build --build-arg DEMO=true CLIENT_ID=${CLIENT_ID} -t ${IMAGE}:${GIT_VERSION} .
docker tag ${IMAGE}:${GIT_VERSION} ${IMAGE}:latest
# Login to Docker Hub and push newest build
@@ -37,6 +37,6 @@ echo "Stopping container name current and starting ${IMAGE}:${GIT_VERSION}"
doctl compute ssh ${DROPLET} --ssh-key-path deploy_key --ssh-command "docker pull ${IMAGE}:${GIT_VERSION} &&
docker stop current &&
docker rm current &&
docker run --name=current --restart unless-stopped -e CLIENT_ID=${CLIENT_ID} -e CLIENT_SECRET=${CLIENT_SECRET} -d -p 80:5000 ${IMAGE}:${GIT_VERSION} &&
docker run --name=current --restart unless-stopped -e DEMO=true CLIENT_ID=${CLIENT_ID} -e CLIENT_SECRET=${CLIENT_SECRET} -d -p 80:5000 ${IMAGE}:${GIT_VERSION} &&
docker system prune -a -f &&
docker image prune -a -f"
+2 -1
View File
@@ -1,6 +1,6 @@
{
"name": "takenote",
"version": "0.7.1",
"version": "0.7.2",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -2451,6 +2451,7 @@
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/@types/jszip/-/jszip-3.4.1.tgz",
"integrity": "sha512-TezXjmf3lj+zQ651r6hPqvSScqBLvyPI9FxdXBqpEwBijNGQ2NXpaFW/7joGzveYkKQUil7iiDHLo6LV71Pc0A==",
"dev": true,
"requires": {
"jszip": "*"
}
+4 -3
View File
@@ -1,6 +1,6 @@
{
"name": "takenote",
"version": "0.7.1",
"version": "0.7.2",
"description": "A free, open-source notes app for the web.",
"author": "Tania Rascia",
"license": "MIT",
@@ -18,7 +18,8 @@
"test:e2e:open": "cypress open --config-file config/cypress.config.json",
"test:coverage": "jest --config config/jest.config.js --coverage --watchAll=false",
"test:coverage:ci": "jest --config config/jest.config.js --ci --coverage --watchAll=false && cat ./coverage/lcov.info | coveralls",
"format": "prettier --write \"./**/*.{js,jsx,ts,tsx,css,scss,md}\""
"format": "prettier --write \"./**/*.{js,jsx,ts,tsx,css,scss,md}\"",
"eslint": "eslint src/**/*.{ts,tsx}"
},
"repository": {
"type": "git",
@@ -56,7 +57,6 @@
},
"dependencies": {
"@reduxjs/toolkit": "^1.4.0",
"@types/jszip": "^3.4.1",
"axios": "^0.20.0",
"codemirror": "^5.58.1",
"compression": "^1.7.4",
@@ -101,6 +101,7 @@
"@types/faker": "^5.1.2",
"@types/helmet": "0.0.48",
"@types/jest": "^26.0.14",
"@types/jszip": "^3.4.1",
"@types/lodash": "^4.14.162",
"@types/node": "^14.11.8",
"@types/prettier": "^2.1.3",
+1 -2
View File
@@ -1,5 +1,4 @@
import React from 'react'
import { Link } from 'react-router-dom'
import { isMobile } from 'react-device-detect'
import lightScreen from '@resources/assets/screenshot-light.png'
@@ -9,7 +8,7 @@ import logo from '@resources/assets/logo-square-color.svg'
import githubLogo from '@resources/assets/github-logo.png'
const clientId = process.env.CLIENT_ID
const isDemo = true
const isDemo = process.env.DEMO
const loginButton = (text: string) => (
<a
+15 -3
View File
@@ -1,6 +1,6 @@
import React, { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { Switch, Redirect } from 'react-router-dom'
import { Route, Switch, Redirect } from 'react-router-dom'
import { Helmet, HelmetProvider } from 'react-helmet-async'
import { LandingPage } from '@/components/LandingPage'
@@ -10,6 +10,8 @@ import { PrivateRoute } from '@/router/PrivateRoute'
import { getAuth } from '@/selectors'
import { login } from '@/slices/auth'
const isDemo = process.env.DEMO
export const App: React.FC = () => {
// ===========================================================================
// Selectors
@@ -54,8 +56,18 @@ export const App: React.FC = () => {
</Helmet>
<Switch>
<PublicRoute exact path="/" component={LandingPage} />
<PrivateRoute path="/app" component={TakeNoteApp} />
{isDemo ? (
<>
<Route exact path="/" component={LandingPage} />
<Route path="/app" component={TakeNoteApp} />
</>
) : (
<>
<PublicRoute exact path="/" component={LandingPage} />
<PrivateRoute path="/app" component={TakeNoteApp} />
</>
)}
<Redirect to="/" />
</Switch>
</HelmetProvider>
+1 -2
View File
@@ -82,8 +82,7 @@ export const CategoryList: React.FC = () => {
event.stopPropagation()
if (contextMenuRef?.current?.contains(clicked as HTMLDivElement)) {
} else {
if (!contextMenuRef?.current?.contains(clicked as HTMLDivElement)) {
setOptionsId(!optionsId || optionsId !== categoryId ? categoryId : '')
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
import React, { useContext } from 'react'
import { ArrowUp, Download, Star, Trash, X, Edit2, AlertTriangle } from 'react-feather'
import { ArrowUp, Download, Star, Trash, X, Edit2 } from 'react-feather'
import { useDispatch, useSelector } from 'react-redux'
import { LabelText } from '@resources/LabelText'
+3 -7
View File
@@ -2,10 +2,6 @@ import React from 'react'
import { useDispatch, useSelector } from 'react-redux'
import prettier from 'prettier/standalone'
import parserMarkdown from 'prettier/parser-markdown'
import parserHtml from 'prettier/parser-html'
import parserCss from 'prettier/parser-postcss'
import parserTs from 'prettier/parser-typescript'
import parserJs from 'prettier/parser-babel'
import { useTempState } from '@/contexts/TempStateContext'
import { Folder, Shortcuts } from '@/utils/enums'
@@ -85,9 +81,9 @@ export const KeyboardShortcuts: React.FC = () => {
const downloadNotesHandler = () => {
if (!activeNote || selectedNotesIds.length === 0) return
downloadNotes(
selectedNotesIds.includes(activeNote!.id)
selectedNotesIds.includes(activeNote.id)
? notes.filter((note) => selectedNotesIds.includes(note.id))
: [activeNote!],
: [activeNote],
categories
)
}
@@ -101,7 +97,7 @@ export const KeyboardShortcuts: React.FC = () => {
if (activeNote && activeNote.text) {
const formattedText = prettier.format(activeNote.text, {
parser: 'markdown',
plugins: [parserMarkdown, parserHtml, parserTs, parserJs, parserCss],
plugins: [parserMarkdown],
})
const updatedNote = {
+2 -1
View File
@@ -45,10 +45,11 @@ export const NoteEditor: React.FC = () => {
return <div className="empty-editor v-center">Loading...</div>
} else if (!activeNote) {
return <EmptyEditor />
} else if (previewMarkdown)
} else if (previewMarkdown) {
return (
<PreviewEditor directionText={codeMirrorOptions.direction} noteText={activeNote.text} />
)
}
return (
<CodeMirror
+2 -4
View File
@@ -106,8 +106,7 @@ export const NoteList: React.FC = () => {
event.stopPropagation()
if (contextMenuRef.current && contextMenuRef.current.contains(clicked as HTMLDivElement)) {
} else {
if (!contextMenuRef.current || !contextMenuRef.current.contains(clicked as HTMLDivElement)) {
setOptionsId(!optionsId || optionsId !== noteId ? noteId : '')
}
}
@@ -135,8 +134,7 @@ export const NoteList: React.FC = () => {
event.stopPropagation()
if (contextMenuRef.current && contextMenuRef.current.contains(clicked as HTMLDivElement)) {
} else {
if (!contextMenuRef.current || contextMenuRef.current.contains(clicked as HTMLDivElement)) {
setOptionsId(!optionsId || optionsId !== noteId ? noteId : '')
}
}
+1 -1
View File
@@ -10,7 +10,7 @@ import {
updateNotesSortStrategy,
} from '@/slices/settings'
import { logout } from '@/slices/auth'
import { shortcutMap, notesSortOptions, directionTextOptions, iconColor } from '@/utils/constants'
import { shortcutMap, notesSortOptions, directionTextOptions } from '@/utils/constants'
import { ReactMouseEvent } from '@/types'
import { getSettings, getAuth, getNotes, getCategories } from '@/selectors'
import { Option } from '@/components/SettingsModal/Option'
+3 -3
View File
@@ -64,11 +64,11 @@ export const TakeNoteApp: React.FC = () => {
const { destination, source } = result
if (!destination) return
if (destination.droppableId === source.droppableId && destination.index === source.index) return
switch (result.type) {
case 'CATEGORY':
_swapCategories(source.index, destination.index)
if (result.type === 'CATEGORY') {
_swapCategories(source.index, destination.index)
}
}
+1 -1
View File
@@ -20,7 +20,7 @@ import {
import { SyncAction } from '@/types'
import { getSettings } from '@/selectors'
const isDemo = true
const isDemo = process.env.DEMO
// Hit the Express endpoint to get the current GitHub user from the cookie
function* loginUser() {
+1 -1
View File
@@ -108,7 +108,7 @@ const noteSlice = createSlice({
) => {
state.activeNoteId = multiSelect
? state.notes.filter(({ id }) => state.selectedNotesIds.includes(id)).slice(-1)[0].id
: noteId!
: noteId
},
updateActiveCategoryId: (state, { payload }: PayloadAction<string>) => {
-2
View File
@@ -142,7 +142,6 @@
background: $primary;
outline: none;
.action-button-icon,
.action-button-icon {
stroke: white;
}
@@ -279,7 +278,6 @@
-webkit-appearance: none;
display: flex;
align-items: center;
padding: 0;
color: darken($light-font-color, 25%);
background: transparent;
font-size: 0.8rem;
+3 -6
View File
@@ -223,6 +223,9 @@ $dark-editor: #3f3f3f;
.settings-modal {
background: $dark-sidebar;
color: $light-font-color;
.subtitle {
color: darken($light-font-color, 20%);
}
.settings-option {
border-color: darken($dark-sidebar, 5%);
h3 {
@@ -266,12 +269,6 @@ $dark-editor: #3f3f3f;
border: 1px solid black;
}
.settings-modal {
.subtitle {
color: darken($light-font-color, 20%);
}
}
::-webkit-scrollbar {
width: 8px;
height: 8px;
+2 -8
View File
@@ -147,6 +147,8 @@ kbd {
display: block;
font-size: 0;
color: $primary;
width: 54px;
height: 18px;
}
.la-ball-beat.la-dark {
@@ -158,14 +160,6 @@ kbd {
float: none;
background-color: currentColor;
border: 0 solid currentColor;
}
.la-ball-beat {
width: 54px;
height: 18px;
}
.la-ball-beat > div {
width: 10px;
height: 10px;
margin: 4px;
-3
View File
@@ -113,8 +113,6 @@
// Code block styling
pre {
border: 0;
border-radius: 0;
background: lighten($note-sidebar-color, 8%);
padding: 1rem;
tab-size: 2;
@@ -188,7 +186,6 @@
color: $font-color;
top: 0;
right: 1rem;
box-shadow: none;
border: none;
background-color: $note-sidebar-color;
font-weight: 500;