diff --git a/.eslintrc b/.eslintrc index 74fa349e3..3841621ad 100644 --- a/.eslintrc +++ b/.eslintrc @@ -19,7 +19,10 @@ "camelcase": "warn", "sort-imports": "off", "react-hooks/rules-of-hooks": "error", // Checks rules of Hooks - "react-hooks/exhaustive-deps": "error" // Checks effect dependencies + "react-hooks/exhaustive-deps": "error", // Checks effect dependencies + "eol-last": "error", + "no-multiple-empty-lines": ["error", { "max": 1, "maxEOF": 0 }], + "no-trailing-spaces": "error" }, "env": { "browser": true diff --git a/.gitignore b/.gitignore index 4656f67cc..01c40b0e4 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ # OS & IDE .DS_Store +.idea # Ignore bundler config. /.bundle diff --git a/Gemfile.lock b/Gemfile.lock index c578fae74..d2fe3cd95 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -213,7 +213,7 @@ DEPENDENCIES dotenv-rails haml lograge (~> 0.11.2) - newrelic_rpm + newrelic_rpm (~> 7.0) non-stupid-digest-assets puma rack-cors diff --git a/app/assets/icons/ic-copy.svg b/app/assets/icons/ic-copy.svg new file mode 100644 index 000000000..9ad40e8f1 --- /dev/null +++ b/app/assets/icons/ic-copy.svg @@ -0,0 +1,3 @@ + diff --git a/app/assets/icons/ic-download.svg b/app/assets/icons/ic-download.svg new file mode 100644 index 000000000..de2c70fc2 --- /dev/null +++ b/app/assets/icons/ic-download.svg @@ -0,0 +1,3 @@ + diff --git a/app/assets/icons/ic-info.svg b/app/assets/icons/ic-info.svg new file mode 100644 index 000000000..47ea73219 --- /dev/null +++ b/app/assets/icons/ic-info.svg @@ -0,0 +1,3 @@ + diff --git a/app/assets/javascripts/app.ts b/app/assets/javascripts/app.ts index e7470bbe0..b493808ad 100644 --- a/app/assets/javascripts/app.ts +++ b/app/assets/javascripts/app.ts @@ -65,7 +65,7 @@ import { NotesContextMenuDirective } from './components/NotesContextMenu'; import { NotesOptionsPanelDirective } from './components/NotesOptionsPanel'; import { IconDirective } from './components/Icon'; import { NoteTagsContainerDirective } from './components/NoteTagsContainer'; -import { PreferencesDirective } from './components/preferences'; +import { PreferencesDirective } from './preferences'; function reloadHiddenFirefoxTab(): boolean { /** diff --git a/app/assets/javascripts/components/Button.tsx b/app/assets/javascripts/components/Button.tsx new file mode 100644 index 000000000..bf13b5509 --- /dev/null +++ b/app/assets/javascripts/components/Button.tsx @@ -0,0 +1,32 @@ +import { FunctionComponent } from 'preact'; + +const baseClass = `rounded px-4 py-1.75 font-bold text-sm fit-content`; + +const normalClass = `${baseClass} bg-default color-text border-solid border-gray-300 border-1 \ +focus:bg-contrast hover:bg-contrast`; +const primaryClass = `${baseClass} no-border bg-info color-info-contrast hover:brightness-130 \ +focus:brightness-130`; + +export const Button: FunctionComponent<{ + className?: string; + type: 'normal' | 'primary'; + label: string; + onClick: () => void; + disabled?: boolean; +}> = ({ type, label, className = '', onClick, disabled = false }) => { + const buttonClass = type === 'primary' ? primaryClass : normalClass; + const cursorClass = disabled ? 'cursor-default' : 'cursor-pointer'; + + return ( + + ); +}; diff --git a/app/assets/javascripts/components/CircleProgress.tsx b/app/assets/javascripts/components/CircleProgress.tsx new file mode 100644 index 000000000..16fa917dc --- /dev/null +++ b/app/assets/javascripts/components/CircleProgress.tsx @@ -0,0 +1,38 @@ +import { FunctionComponent } from 'preact'; + +export const CircleProgress: FunctionComponent<{ + percent: number; + className?: string; +}> = ({ percent, className = '' }) => { + const size = 16; + const ratioStrokeRadius = 0.25; + const outerRadius = size / 2; + + const radius = outerRadius * (1 - ratioStrokeRadius); + const stroke = outerRadius - radius; + + const circumference = radius * 2 * Math.PI; + const offset = circumference - (percent / 100) * circumference; + + const transition = `transition: 0.35s stroke-dashoffset;`; + const transform = `transform: rotate(-90deg);`; + const transformOrigin = `transform-origin: 50% 50%;`; + const dasharray = `stroke-dasharray: ${circumference} ${circumference};`; + const dashoffset = `stroke-dashoffset: ${offset};`; + const style = `${transition} ${transform} ${transformOrigin} ${dasharray} ${dashoffset}`; + return ( +