mirror of
https://github.com/taniarascia/takenote.git
synced 2026-05-26 13:51:16 +00:00
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:
+2
-2
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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"
|
||||
|
||||
Generated
+2
-1
@@ -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
@@ -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,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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,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'
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 : '')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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>) => {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user