├── .nvmrc
├── .dockerignore
├── Procfile
├── test_helpers
├── fixtures
│ ├── empty_file.org
│ ├── schedule.org
│ ├── email.org
│ ├── more_tags.org
│ ├── phonenumber.org
│ ├── tags.org
│ ├── url.org
│ ├── content_but_no_headline.org
│ ├── schedule_with_repeater.org
│ ├── schedule_and_deadline.org
│ ├── newlines.org
│ ├── www_url.org
│ ├── nested_header.org
│ ├── schedule_and_timestamps.org
│ ├── schedule_with_repeater_and_nologrepeat.org
│ ├── properties.org
│ ├── indented_list.org
│ ├── planning_item_with_following_checkmark.org
│ ├── schedule_with_repeater_and_nologrepeat_and_other_options.org
│ ├── headline_filter.org
│ ├── bold_text.org
│ ├── properties_extended.org
│ ├── multiple_headlines_with_timestamps_simple.org
│ ├── checkboxes.org
│ ├── various_todos.org
│ ├── schedule_with_repeater_and_nologrepeat_property.org
│ ├── table.org
│ ├── logbook.org
│ ├── multiple_headlines_with_timestamps.org
│ ├── before-first-headline.org
│ ├── clock_entries.org
│ ├── large_table.org
│ ├── todo_keywords_interspersed.org
│ ├── logbook_and_log_notes.org
│ └── main_test_file.org
└── index.js
├── .prettierignore
├── src
├── components
│ ├── OrgFile
│ │ ├── components
│ │ │ ├── FinderModal
│ │ │ │ ├── stylesheet.css
│ │ │ │ └── index.js
│ │ │ ├── TableEditorModal
│ │ │ │ ├── stylesheet.css
│ │ │ │ ├── index.js
│ │ │ │ └── components
│ │ │ │ │ └── TableActionButtons
│ │ │ │ │ └── stylesheet.css
│ │ │ ├── DrawerActionBar
│ │ │ │ ├── stylesheet.css
│ │ │ │ └── components
│ │ │ │ │ └── DrawerActionButtons
│ │ │ │ │ └── stylesheet.css
│ │ │ ├── Table
│ │ │ │ ├── stylesheet.css
│ │ │ │ ├── TableCell
│ │ │ │ │ ├── stylesheet.css
│ │ │ │ │ └── index.js
│ │ │ │ ├── TableCellEditContainer
│ │ │ │ │ ├── stylesheet.css
│ │ │ │ │ └── index.js
│ │ │ │ └── index.js
│ │ │ ├── AttributedString
│ │ │ │ ├── components
│ │ │ │ │ ├── TimestampPart
│ │ │ │ │ │ ├── stylesheet.css
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── ListPart
│ │ │ │ │ │ ├── ListActionDrawer
│ │ │ │ │ │ │ ├── stylesheet.css
│ │ │ │ │ │ │ └── index.js
│ │ │ │ │ │ └── stylesheet.css
│ │ │ │ │ └── TablePart
│ │ │ │ │ │ ├── stylesheet.css
│ │ │ │ │ │ └── index.js
│ │ │ │ └── stylesheet.css
│ │ │ ├── NoteEditorModal
│ │ │ │ ├── stylesheet.css
│ │ │ │ └── index.js
│ │ │ ├── HeaderContent
│ │ │ │ ├── components
│ │ │ │ │ ├── LogBookEntries
│ │ │ │ │ │ ├── stylesheet.css
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── PropertyListItems
│ │ │ │ │ │ ├── stylesheet.css
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── PlanningItems
│ │ │ │ │ │ ├── stylesheet.css
│ │ │ │ │ │ └── index.js
│ │ │ │ └── stylesheet.css
│ │ │ ├── HeaderList
│ │ │ │ └── stylesheet.css
│ │ │ ├── ActionDrawer
│ │ │ │ ├── components
│ │ │ │ │ └── ActionButton
│ │ │ │ │ │ ├── stylesheet.css
│ │ │ │ │ │ └── index.js
│ │ │ │ └── stylesheet.css
│ │ │ ├── TaskListModal
│ │ │ │ ├── components
│ │ │ │ │ └── TaskListView
│ │ │ │ │ │ └── stylesheet.css
│ │ │ │ └── stylesheet.css
│ │ │ ├── SearchModal
│ │ │ │ ├── components
│ │ │ │ │ └── HeaderListView
│ │ │ │ │ │ ├── stylesheet.css
│ │ │ │ │ │ └── index.js
│ │ │ │ └── stylesheet.css
│ │ │ ├── SyncConfirmationModal
│ │ │ │ ├── stylesheet.css
│ │ │ │ └── index.js
│ │ │ ├── TimestampEditorModal
│ │ │ │ ├── stylesheet.css
│ │ │ │ └── components
│ │ │ │ │ └── TimestampEditor
│ │ │ │ │ └── stylesheet.css
│ │ │ ├── AgendaModal
│ │ │ │ ├── stylesheet.css
│ │ │ │ └── components
│ │ │ │ │ └── AgendaDay
│ │ │ │ │ ├── stylesheet.css
│ │ │ │ │ └── AgendaDay.unit.test.js
│ │ │ ├── PropertyListEditorModal
│ │ │ │ └── stylesheet.css
│ │ │ ├── TitleLine
│ │ │ │ ├── .index.js.swp
│ │ │ │ └── stylesheet.css
│ │ │ ├── CaptureModal
│ │ │ │ └── stylesheet.css
│ │ │ ├── Header
│ │ │ │ ├── stylesheet.css
│ │ │ │ └── components
│ │ │ │ │ └── HeaderActionDrawer
│ │ │ │ │ └── stylesheet.css
│ │ │ ├── DescriptionEditorModal
│ │ │ │ └── stylesheet.css
│ │ │ ├── TagsEditorModal
│ │ │ │ └── stylesheet.css
│ │ │ └── TitleEditorModal
│ │ │ │ └── stylesheet.css
│ │ └── stylesheet.css
│ ├── SyncServiceSignIn
│ │ ├── google_drive.png
│ │ └── stylesheet.css
│ ├── FileSettingsEditor
│ │ ├── stylesheet.css
│ │ └── components
│ │ │ └── FileSetting
│ │ │ └── stylesheet.css
│ ├── Landing
│ │ ├── fonts
│ │ │ └── metropolis
│ │ │ │ ├── Metropolis-Black.otf
│ │ │ │ ├── Metropolis-Bold.otf
│ │ │ │ ├── Metropolis-Light.otf
│ │ │ │ ├── Metropolis-Thin.otf
│ │ │ │ ├── Metropolis-Medium.otf
│ │ │ │ ├── Metropolis-Regular.otf
│ │ │ │ ├── Metropolis-BoldItalic.otf
│ │ │ │ ├── Metropolis-ExtraBold.otf
│ │ │ │ ├── Metropolis-ExtraLight.otf
│ │ │ │ ├── Metropolis-SemiBold.otf
│ │ │ │ ├── Metropolis-ThinItalic.otf
│ │ │ │ ├── Metropolis-BlackItalic.otf
│ │ │ │ ├── Metropolis-LightItalic.otf
│ │ │ │ ├── Metropolis-MediumItalic.otf
│ │ │ │ ├── Metropolis-ExtraBoldItalic.otf
│ │ │ │ ├── Metropolis-RegularItalic.otf
│ │ │ │ ├── Metropolis-SemiBoldItalic.otf
│ │ │ │ └── Metropolis-ExtraLightItalic.otf
│ │ ├── Landing.test.js
│ │ └── stylesheet.css
│ ├── PrivacyPolicy
│ │ └── stylesheet.css
│ ├── UI
│ │ ├── Checkbox
│ │ │ ├── stylesheet.css
│ │ │ └── index.js
│ │ ├── ExternalLink
│ │ │ └── index.js
│ │ ├── Switch
│ │ │ ├── stylesheet.css
│ │ │ └── index.js
│ │ ├── TabButtons
│ │ │ ├── stylesheet.css
│ │ │ └── index.js
│ │ └── Drawer
│ │ │ └── stylesheet.css
│ ├── KeyboardShortcutsEditor
│ │ ├── stylesheet.css
│ │ ├── components
│ │ │ └── ShortcutRow
│ │ │ │ └── stylesheet.css
│ │ └── index.js
│ ├── Entry
│ │ └── stylesheet.css
│ ├── CaptureTemplatesEditor
│ │ └── stylesheet.css
│ ├── LoadingIndicator
│ │ ├── stylesheet.css
│ │ └── index.js
│ ├── FileBrowser
│ │ ├── stylesheet.css
│ │ └── components
│ │ │ └── ActionDrawer
│ │ │ └── index.js
│ ├── HeaderBar
│ │ └── stylesheet.css
│ ├── Settings
│ │ └── stylesheet.css
│ └── Turnout
│ │ └── index.js
├── index.css
├── lib
│ ├── id_generator.js
│ ├── sample_capture_templates.js
│ ├── capture_template_substitution.js
│ ├── keybindings.js
│ ├── browser_utils.js
│ ├── share_utils.js
│ └── clocking.js
├── index.js
├── migrations
│ ├── migrate_access_token_to_dropbox_access_token.js
│ ├── index.js
│ ├── migrate_nonsense_values_in_localstorage.js
│ └── migrate_store_in_dropbox_to_store_in_sync_backend.js
├── sync_backend_clients
│ └── dropbox_sync_backend_client.test.js
├── service-worker.js
├── store.js
├── util
│ ├── misc.js
│ ├── settings_persister.test.js
│ └── parse_query_string.js
├── middleware
│ ├── toggle_color_scheme.js
│ ├── live_sync.js
│ └── sync_on_becoming_visible.js
├── reducers
│ ├── sync_backend.js
│ └── index.js
├── actions
│ └── capture.js
└── colors.css
├── .eslintignore
├── babel.config.json
├── public
├── favicon.ico
├── organice.png
├── organice-small.png
├── organice-192x192.png
├── organice-512x512.png
├── manifest.json
└── index.html
├── .editorconfig
├── config
└── jest
│ ├── SvgComponent.js
│ ├── fileTransform.js
│ ├── cssTransform.js
│ └── babelTransform.js
├── images
├── screenshot-overview.png
├── screenshot-settings.png
└── screenshot-introduction.png
├── .github
├── FUNDING.yml
└── ISSUE_TEMPLATE
│ ├── feature_request.md
│ └── bug_report.md
├── bin
├── entrypoint.sh
├── transient_env_vars.sh
├── compile_doc_and_upload.sh
├── compile_search_parser.sh
├── compile_and_upload.sh
└── compile_doc.sh
├── .parcelrc
├── .prettierrc.json
├── .gitattributes
├── .env.sample
├── contrib
├── organice-k8s
│ ├── service.yml
│ ├── ingress.yml
│ ├── README.org
│ ├── deployment.yml
│ └── load-balancer.yml
├── organice-pinephone
│ ├── organice.service
│ ├── webdav.service
│ └── Dockerfile
├── organice-webdav-traefik
│ ├── webdav
│ │ ├── Dockerfile
│ │ ├── webdav.conf
│ │ └── run.sh
│ ├── LICENSE
│ └── docker-compose.yml
├── organice-caddy-webdav
│ ├── Dockerfile
│ └── docker-compose.yml
├── organice-webdav-post
│ ├── organice_inbox.sh
│ ├── home.php
│ ├── inbox.php
│ └── Readme.md
├── organice-nextcloud-nginx
│ └── README.org
├── organice-nginx-cors
│ └── README.org
└── organice-on-android-with-webdav-server
│ └── README.md
├── doc
├── org2html
│ └── init.el
├── webdav
│ ├── Dockerfile
│ └── webdav.conf
└── setupfile
├── __mocks__
└── fileMock.js
├── Makefile
├── .gitignore
├── .eslintrc.yml
├── docker-compose.yml
├── jest.config.json
├── flake.lock
├── Dockerfile
└── flake.nix
/.nvmrc:
--------------------------------------------------------------------------------
1 | v20.17.0
2 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: serve build
2 |
--------------------------------------------------------------------------------
/test_helpers/fixtures/empty_file.org:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | build/
2 | dist/
3 | node_modules/
4 |
--------------------------------------------------------------------------------
/src/components/OrgFile/components/FinderModal/stylesheet.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/OrgFile/components/TableEditorModal/stylesheet.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | build/
2 | config/jest/
3 | __mocks__/
4 | node_modules/
5 |
--------------------------------------------------------------------------------
/babel.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [
3 | "babel-plugin-macros"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/test_helpers/fixtures/schedule.org:
--------------------------------------------------------------------------------
1 | * Spec header
2 | SCHEDULED: <2019-09-22 Sun>
3 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/public/organice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/public/organice.png
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [**.js{,on}]
4 | indent_style = space
5 | indent_size = 2
6 |
--------------------------------------------------------------------------------
/config/jest/SvgComponent.js:
--------------------------------------------------------------------------------
1 | export default function SvgComponent() {
2 | return null;
3 | }
4 |
--------------------------------------------------------------------------------
/test_helpers/fixtures/email.org:
--------------------------------------------------------------------------------
1 | * foo
2 | This is an e-mail foo.bar@baz.org in a line of text.
3 |
--------------------------------------------------------------------------------
/public/organice-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/public/organice-small.png
--------------------------------------------------------------------------------
/public/organice-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/public/organice-192x192.png
--------------------------------------------------------------------------------
/public/organice-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/public/organice-512x512.png
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: Verdana, sans-serif;
5 | }
6 |
--------------------------------------------------------------------------------
/test_helpers/fixtures/more_tags.org:
--------------------------------------------------------------------------------
1 | * Tagged header :t1:t2:t3:spec_tag:
2 |
--------------------------------------------------------------------------------
/images/screenshot-overview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/images/screenshot-overview.png
--------------------------------------------------------------------------------
/images/screenshot-settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/images/screenshot-settings.png
--------------------------------------------------------------------------------
/src/lib/id_generator.js:
--------------------------------------------------------------------------------
1 | export default (() => {
2 | let nextId = 1;
3 | return () => nextId++;
4 | })();
5 |
--------------------------------------------------------------------------------
/test_helpers/fixtures/phonenumber.org:
--------------------------------------------------------------------------------
1 | * foo
2 | +Don't+ call me on: +49123456789 (should become a tel: link)
3 |
--------------------------------------------------------------------------------
/test_helpers/fixtures/tags.org:
--------------------------------------------------------------------------------
1 | * Spec header :spec_tag:
2 |
--------------------------------------------------------------------------------
/test_helpers/fixtures/url.org:
--------------------------------------------------------------------------------
1 | * foo
2 | an =URL= https://foo.bar.baz/xyz?a=b&d#foo and /more text/ and so
3 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [200ok-ch]
4 | patreon: [200ok]
5 |
--------------------------------------------------------------------------------
/bin/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | bin/transient_env_vars.sh switch build serve
4 |
5 | serve -p 5000 -s build
6 |
--------------------------------------------------------------------------------
/test_helpers/fixtures/content_but_no_headline.org:
--------------------------------------------------------------------------------
1 | This is a legit Org mode file, yet it has not a single headline.
2 |
--------------------------------------------------------------------------------
/test_helpers/fixtures/schedule_with_repeater.org:
--------------------------------------------------------------------------------
1 | * TODO Header with repeater
2 | SCHEDULED: <2019-11-27 Wed +1d>
3 |
--------------------------------------------------------------------------------
/images/screenshot-introduction.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/images/screenshot-introduction.png
--------------------------------------------------------------------------------
/test_helpers/fixtures/schedule_and_deadline.org:
--------------------------------------------------------------------------------
1 | * Spec header
2 | SCHEDULED: <2019-08-01 Thu> DEADLINE: <2019-08-04 Sun>
3 |
--------------------------------------------------------------------------------
/.parcelrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@parcel/config-default",
3 | "transformers": {
4 | "url:*": ["@parcel/transformer-raw"]
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/test_helpers/fixtures/newlines.org:
--------------------------------------------------------------------------------
1 | * Main header (required for parser atm)
2 |
3 | * Second header
4 |
5 | - Some item
6 | - Another item
7 |
--------------------------------------------------------------------------------
/test_helpers/fixtures/www_url.org:
--------------------------------------------------------------------------------
1 | * Foo
2 | Parse www.example.com and www.service.example.com/signin.
3 | But not www.foo (missing TLD)!
4 |
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "trailingComma": "es5",
4 | "printWidth": 100,
5 | "arrowParens": "always"
6 | }
7 |
--------------------------------------------------------------------------------
/test_helpers/fixtures/nested_header.org:
--------------------------------------------------------------------------------
1 | * Top level header
2 | ** A nested header
3 | *** A deep nested header
4 | ** A second nested header
5 |
--------------------------------------------------------------------------------
/src/components/SyncServiceSignIn/google_drive.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/src/components/SyncServiceSignIn/google_drive.png
--------------------------------------------------------------------------------
/src/components/FileSettingsEditor/stylesheet.css:
--------------------------------------------------------------------------------
1 | .no-file-setting-message {
2 | text-align: center;
3 | color: var(--base0);
4 | padding: 20px;
5 | }
6 |
--------------------------------------------------------------------------------
/test_helpers/fixtures/schedule_and_timestamps.org:
--------------------------------------------------------------------------------
1 | * <2020-01-18 Sat> Spec header
2 | SCHEDULED: <2019-09-22 Sun>
3 |
4 | Description contains <2020-01-19 Sun>
5 |
--------------------------------------------------------------------------------
/test_helpers/fixtures/schedule_with_repeater_and_nologrepeat.org:
--------------------------------------------------------------------------------
1 | #+STARTUP: nologrepeat
2 |
3 | * TODO Header with repeater
4 | SCHEDULED: <2019-11-27 Wed +1d>
5 |
--------------------------------------------------------------------------------
/src/components/Landing/fonts/metropolis/Metropolis-Black.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/src/components/Landing/fonts/metropolis/Metropolis-Black.otf
--------------------------------------------------------------------------------
/src/components/Landing/fonts/metropolis/Metropolis-Bold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/src/components/Landing/fonts/metropolis/Metropolis-Bold.otf
--------------------------------------------------------------------------------
/src/components/Landing/fonts/metropolis/Metropolis-Light.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/src/components/Landing/fonts/metropolis/Metropolis-Light.otf
--------------------------------------------------------------------------------
/src/components/Landing/fonts/metropolis/Metropolis-Thin.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/src/components/Landing/fonts/metropolis/Metropolis-Thin.otf
--------------------------------------------------------------------------------
/test_helpers/fixtures/properties.org:
--------------------------------------------------------------------------------
1 | * TODO Test header
2 | SCHEDULED: <2019-12-08 Sun +1y>
3 | :PROPERTIES:
4 | :LAST_REPEAT: [2018-12-30 Sun 14:00]
5 | :END:
6 |
--------------------------------------------------------------------------------
/src/components/Landing/fonts/metropolis/Metropolis-Medium.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/src/components/Landing/fonts/metropolis/Metropolis-Medium.otf
--------------------------------------------------------------------------------
/src/components/Landing/fonts/metropolis/Metropolis-Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/src/components/Landing/fonts/metropolis/Metropolis-Regular.otf
--------------------------------------------------------------------------------
/src/components/Landing/fonts/metropolis/Metropolis-BoldItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/src/components/Landing/fonts/metropolis/Metropolis-BoldItalic.otf
--------------------------------------------------------------------------------
/src/components/Landing/fonts/metropolis/Metropolis-ExtraBold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/src/components/Landing/fonts/metropolis/Metropolis-ExtraBold.otf
--------------------------------------------------------------------------------
/src/components/Landing/fonts/metropolis/Metropolis-ExtraLight.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/src/components/Landing/fonts/metropolis/Metropolis-ExtraLight.otf
--------------------------------------------------------------------------------
/src/components/Landing/fonts/metropolis/Metropolis-SemiBold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/src/components/Landing/fonts/metropolis/Metropolis-SemiBold.otf
--------------------------------------------------------------------------------
/src/components/Landing/fonts/metropolis/Metropolis-ThinItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/src/components/Landing/fonts/metropolis/Metropolis-ThinItalic.otf
--------------------------------------------------------------------------------
/src/components/PrivacyPolicy/stylesheet.css:
--------------------------------------------------------------------------------
1 | .privacy-policy-container {
2 | margin-left: 10px;
3 | }
4 |
5 | .privacy-policy-container a {
6 | color: var(--base00);
7 | }
8 |
--------------------------------------------------------------------------------
/src/components/Landing/fonts/metropolis/Metropolis-BlackItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/src/components/Landing/fonts/metropolis/Metropolis-BlackItalic.otf
--------------------------------------------------------------------------------
/src/components/Landing/fonts/metropolis/Metropolis-LightItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/src/components/Landing/fonts/metropolis/Metropolis-LightItalic.otf
--------------------------------------------------------------------------------
/src/components/Landing/fonts/metropolis/Metropolis-MediumItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/src/components/Landing/fonts/metropolis/Metropolis-MediumItalic.otf
--------------------------------------------------------------------------------
/src/components/OrgFile/components/DrawerActionBar/stylesheet.css:
--------------------------------------------------------------------------------
1 | .static-action-bar {
2 | padding-top: 20px;
3 | padding-left: 20px;
4 | background-color: var(--base3);
5 | }
--------------------------------------------------------------------------------
/test_helpers/fixtures/indented_list.org:
--------------------------------------------------------------------------------
1 | * Header
2 | - Indented list line 1
3 | - Indented list line 2
4 | * Header 2
5 | - Indented list line 1
6 | - Indented list line 2
7 |
--------------------------------------------------------------------------------
/test_helpers/fixtures/planning_item_with_following_checkmark.org:
--------------------------------------------------------------------------------
1 | * WAITING Proofing "Announcement für EmacsConf"
2 | SCHEDULED: <2019-09-16 Mon>
3 | - [X] Write draft announcement
4 |
--------------------------------------------------------------------------------
/src/components/Landing/fonts/metropolis/Metropolis-ExtraBoldItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/src/components/Landing/fonts/metropolis/Metropolis-ExtraBoldItalic.otf
--------------------------------------------------------------------------------
/src/components/Landing/fonts/metropolis/Metropolis-RegularItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/src/components/Landing/fonts/metropolis/Metropolis-RegularItalic.otf
--------------------------------------------------------------------------------
/src/components/Landing/fonts/metropolis/Metropolis-SemiBoldItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/src/components/Landing/fonts/metropolis/Metropolis-SemiBoldItalic.otf
--------------------------------------------------------------------------------
/src/components/Landing/fonts/metropolis/Metropolis-ExtraLightItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/200ok-ch/organice/HEAD/src/components/Landing/fonts/metropolis/Metropolis-ExtraLightItalic.otf
--------------------------------------------------------------------------------
/test_helpers/fixtures/schedule_with_repeater_and_nologrepeat_and_other_options.org:
--------------------------------------------------------------------------------
1 | #+STARTUP: showeverything nologrepeat
2 |
3 | * TODO Header with repeater
4 | SCHEDULED: <2019-11-27 Wed +1d>
5 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Set the default behavior, in case people don't have core.autocrlf set.
2 | * text=auto
3 |
4 | # Declare files that will always have LF line endings on checkout.
5 | *.org text eol=lf
6 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 |
6 | ReactDOM.render(, document.getElementById('root'));
7 |
--------------------------------------------------------------------------------
/src/components/OrgFile/components/Table/stylesheet.css:
--------------------------------------------------------------------------------
1 | .table-part {
2 | align-self: center;
3 | border-collapse: collapse;
4 | margin-top: 2.5px;
5 | margin-bottom: 3px;
6 | empty-cells: show;
7 | }
8 |
9 |
--------------------------------------------------------------------------------
/src/components/OrgFile/components/AttributedString/components/TimestampPart/stylesheet.css:
--------------------------------------------------------------------------------
1 | .attributed-string__timestamp-part {
2 | cursor: pointer;
3 | color: var(--base02);
4 | text-decoration: underline;
5 | }
6 |
--------------------------------------------------------------------------------
/.env.sample:
--------------------------------------------------------------------------------
1 | REACT_APP_DROPBOX_CLIENT_ID=your_dropbox_client_id
2 | REACT_APP_GITLAB_CLIENT_ID=your_gitlab_client_id
3 | REACT_APP_GITLAB_SECRET=your_gitlab_secret
4 | REACT_APP_WEBDAV_URL=your_default_webdav_server_if_desired
5 |
--------------------------------------------------------------------------------
/src/components/OrgFile/components/NoteEditorModal/stylesheet.css:
--------------------------------------------------------------------------------
1 | @import '../../../../colors.css';
2 |
3 | .note-editor__done-btn {
4 | font-weight: bold;
5 | font-size: 18px;
6 |
7 | height: 60px;
8 | width: 100%;
9 | }
--------------------------------------------------------------------------------
/test_helpers/fixtures/headline_filter.org:
--------------------------------------------------------------------------------
1 | * TODO Spec header :spec_tag:tag2:#technology:
2 |
3 | :PROPERTIES:
4 | :prop1: abc
5 | :prop1: def
6 | :prop2: xyz
7 | :prop3:
8 | :END:
9 |
--------------------------------------------------------------------------------
/contrib/organice-k8s/service.yml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: v1
3 | kind: Service
4 | metadata:
5 | name: organice
6 | spec:
7 | ports:
8 | - name: http
9 | port: 80
10 | targetPort: 5000
11 | selector:
12 | name: organice
13 |
--------------------------------------------------------------------------------
/contrib/organice-pinephone/organice.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Organice
3 | After=webdav
4 |
5 | [Service]
6 | ExecStart=docker run --rm --name organice -p 3000:3000 organice:latest
7 |
8 | [Install]
9 | WantedBy=default.target
10 |
--------------------------------------------------------------------------------
/src/components/OrgFile/components/HeaderContent/components/LogBookEntries/stylesheet.css:
--------------------------------------------------------------------------------
1 | .logbook-entries__item-start,
2 | .logbook-entries__item-end {
3 | cursor: pointer;
4 | color: var(--base02);
5 | text-decoration: underline;
6 | }
7 |
--------------------------------------------------------------------------------
/src/components/UI/Checkbox/stylesheet.css:
--------------------------------------------------------------------------------
1 | @import '../../../colors.css';
2 |
3 | .checkbox__inner-container {
4 | display: flex;
5 | justify-content: center;
6 | }
7 |
8 | .checkbox__inner-container .fa-square {
9 | color: white;
10 | }
11 |
--------------------------------------------------------------------------------
/test_helpers/index.js:
--------------------------------------------------------------------------------
1 | /* global __dirname */
2 |
3 | import fs from 'fs';
4 | import path from 'path';
5 |
6 | export default function readFixture(name) {
7 | return fs.readFileSync(path.join(__dirname, `./fixtures/${name}.org`)).toString();
8 | }
9 |
--------------------------------------------------------------------------------
/src/components/UI/ExternalLink/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | export default ({ href, children }) => {
3 | return (
4 |
5 | {children ? children : href}
6 |
7 | );
8 | };
9 |
--------------------------------------------------------------------------------
/test_helpers/fixtures/bold_text.org:
--------------------------------------------------------------------------------
1 | * Main header (required for parser atm)
2 | *This is bold*: Hello spec!
3 |
4 | *Bold* text can also be just one word.
5 |
6 | *This is also bold*: And here goes for some more text which even
7 | includes more *bold* statements.
8 |
--------------------------------------------------------------------------------
/src/components/OrgFile/components/HeaderContent/components/PropertyListItems/stylesheet.css:
--------------------------------------------------------------------------------
1 | .property-list__property {
2 | font-weight: bold;
3 | color: var(--yellow);
4 |
5 | margin-right: 5px;
6 | }
7 |
8 | .property-list__item-container {
9 | display: flex;
10 | }
11 |
--------------------------------------------------------------------------------
/test_helpers/fixtures/properties_extended.org:
--------------------------------------------------------------------------------
1 | * Header
2 | :PROPERTIES:
3 | :foo: http://example.com
4 | :bar: xyz
5 | :baz: test
6 | :bay: since: [2019-12-24 Tue]
7 | :END:
8 |
9 | * Header 2
10 | :PROPERTIES:
11 | :foo2: abc
12 | :bar: zyx
13 | :baz: test
14 | :emptyprop:
15 | :END:
16 |
--------------------------------------------------------------------------------
/src/components/KeyboardShortcutsEditor/stylesheet.css:
--------------------------------------------------------------------------------
1 | .keyboard-shortcuts-editor-container a {
2 | text-decoration: none;
3 | }
4 |
5 | .keyboard-shortcuts-editor__btn-container {
6 | display: flex;
7 | flex-direction: column;
8 | align-items: center;
9 |
10 | margin-top: 20px;
11 | }
12 |
--------------------------------------------------------------------------------
/src/components/Entry/stylesheet.css:
--------------------------------------------------------------------------------
1 | .entry-container {
2 | font-size: 16px;
3 |
4 | display: flex;
5 | flex-direction: column;
6 | height: 100vh;
7 | min-height: 100vh;
8 | max-height: 100vh;
9 | overflow-x: hidden;
10 | }
11 |
12 | .entry-container--large-font {
13 | font-size: 20px;
14 | }
15 |
--------------------------------------------------------------------------------
/contrib/organice-k8s/ingress.yml:
--------------------------------------------------------------------------------
1 | apiVersion: extensions/v1beta1
2 | kind: Ingress
3 | metadata:
4 | name: organice-ingress
5 | spec:
6 | rules:
7 | - host: org.johnhame.link
8 | http:
9 | paths:
10 | - path: /
11 | backend:
12 | serviceName: organice
13 | servicePort: 5000
14 |
--------------------------------------------------------------------------------
/contrib/organice-pinephone/webdav.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=WebDAV server
3 |
4 | [Service]
5 | ExecStart=docker run --rm -v /home/mobian/org:/srv/dav --name apache-webdav-app -p 8080:80 apache-webdav
6 | ExecStop=docker exec apache-webdav-app apachectl -k graceful-stop
7 |
8 | [Install]
9 | WantedBy=default.target
10 |
--------------------------------------------------------------------------------
/contrib/organice-webdav-traefik/webdav/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine
2 |
3 | RUN apk add --no-cache nginx-mod-http-dav-ext nginx gettext
4 |
5 | VOLUME /data
6 | VOLUME /var/log/nginx
7 | EXPOSE 80
8 | COPY webdav.conf /etc/nginx/nginx.template.conf
9 |
10 | COPY run.sh /
11 | RUN chmod +x run.sh && rm /etc/nginx/nginx.conf
12 | CMD /run.sh
13 |
--------------------------------------------------------------------------------
/src/components/OrgFile/components/HeaderContent/components/PlanningItems/stylesheet.css:
--------------------------------------------------------------------------------
1 | .planning-items__item-container {
2 | display: flex;
3 | }
4 |
5 | .planning-item__type {
6 | color: var(--base0);
7 | }
8 |
9 | .planning-item__timestamp {
10 | cursor: pointer;
11 | color: var(--base02);
12 | text-decoration: underline;
13 | }
14 |
--------------------------------------------------------------------------------
/test_helpers/fixtures/multiple_headlines_with_timestamps_simple.org:
--------------------------------------------------------------------------------
1 | #+TODO: TODO | DONE
2 | #+TODO: START INPROGRESS STALLED | FINISHED
3 |
4 | * DONE This is a scheduled header
5 | SCHEDULED: <2019-08-04 Sun>
6 |
7 | * START This is a deadline header
8 | DEADLINE: <2019-08-27 Tue>
9 |
10 | * INPROGRESS This is a header without timestamp
11 |
--------------------------------------------------------------------------------
/src/components/OrgFile/components/Table/TableCell/stylesheet.css:
--------------------------------------------------------------------------------
1 | @import '../../../../../colors.css';
2 |
3 | .table-part__cell {
4 | border: 1px solid var(--base01);
5 | white-space: pre;
6 | vertical-align: top;
7 | min-width: 20px;
8 | height: 20px;
9 |
10 | }
11 |
12 | .table-part__cell--selected {
13 | background-color: var(--green-soft);
14 | }
15 |
--------------------------------------------------------------------------------
/test_helpers/fixtures/checkboxes.org:
--------------------------------------------------------------------------------
1 | * Header with checkboxes
2 | - [ ] Box A
3 | - [ ] Box B
4 | - [X] Box C
5 | * Another header [1/3]
6 | - [X] Box D
7 | - [-] Box E [50%]
8 | - [ ] Box G
9 | - [ ] Box H
10 | - [X] Box I
11 | - [-] Box J
12 | - [ ] Box K
13 | - [-] Box L
14 | - [ ] Box M
15 | - [X] Box N
16 | - [ ] Box O
17 | - Not a checkbox
18 |
--------------------------------------------------------------------------------
/doc/org2html/init.el:
--------------------------------------------------------------------------------
1 | (add-to-list 'load-path (file-name-directory load-file-name))
2 | (require 'htmlize)
3 | (load-library "tramp-gvfs")
4 | (setq tramp-gvfs-enabled t)
5 | (require 'org)
6 | (org-babel-do-load-languages
7 | 'org-babel-load-languages
8 | '((shell . t)
9 | (emacs-lisp . t)))
10 |
11 | ;; Don’t ask to execute a code block.
12 | (setq org-confirm-babel-evaluate nil)
13 |
--------------------------------------------------------------------------------
/test_helpers/fixtures/various_todos.org:
--------------------------------------------------------------------------------
1 | * DONE This is done
2 | * TODO Header with repeater
3 | * This is not a todo
4 | * TODO Task with active timestamp and repeater <2020-11-15 Sun +1d>
5 | * TODO Repeating task
6 | SCHEDULED: <2019-11-27 Wed +1d>
7 | * TODO Not done
8 | * TODO Not done with logs
9 | :LOGBOOK:
10 | CLOCK: [2025-06-01 Sun 00:29]--[2025-06-01 Sun 00:38] => 0:09
11 | :END:
12 |
--------------------------------------------------------------------------------
/src/components/CaptureTemplatesEditor/stylesheet.css:
--------------------------------------------------------------------------------
1 | .capture-templates-container {
2 | position: relative;
3 | }
4 |
5 | .new-capture-template-button-container {
6 | display: flex;
7 | justify-content: flex-end;
8 |
9 | margin-top: 10px;
10 | margin-right: 10px;
11 | }
12 |
13 | .no-capture-templates-message {
14 | text-align: center;
15 | color: var(--base0);
16 | padding: 20px;
17 | }
18 |
--------------------------------------------------------------------------------
/config/jest/fileTransform.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const path = require('path');
4 |
5 | // This is a custom Jest transformer turning file imports into filenames.
6 | // http://facebook.github.io/jest/docs/en/webpack.html
7 |
8 | module.exports = {
9 | process(src, filename) {
10 | const assetFilename = JSON.stringify(path.basename(filename));
11 | return `module.exports = ${assetFilename};`;
12 | },
13 | };
14 |
--------------------------------------------------------------------------------
/test_helpers/fixtures/schedule_with_repeater_and_nologrepeat_property.org:
--------------------------------------------------------------------------------
1 | * Header
2 | :PROPERTIES:
3 | :LOGGING: nologrepeat
4 | :END:
5 | ** Intermediate
6 | *** TODO Leaf
7 | DEADLINE: <2019-11-25 Mon ++1d>
8 | * Header Two
9 | ** Middle
10 | :PROPERTIES:
11 | :LOGGING: logrepeat
12 | :END:
13 | *** Beep
14 | ** Middle 2
15 | :PROPERTIES:
16 | :LOGGING: nologrepeat
17 | :END:
18 | *** Boop
19 |
--------------------------------------------------------------------------------
/src/components/OrgFile/components/Table/TableCellEditContainer/stylesheet.css:
--------------------------------------------------------------------------------
1 | @import '../../../../../colors.css';
2 |
3 |
4 | .table-cell__edit-container {
5 | width: 100%;
6 | }
7 |
8 | .table-cell__insert-timestamp-button {
9 | color: var(--base0);
10 |
11 | font-family: Courier;
12 |
13 | display: flex;
14 | align-items: center;
15 | }
16 |
17 | .insert-timestamp-icon {
18 | margin-right: 5px;
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/contrib/organice-caddy-webdav/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG CADDY_VERSION=2.6.4
2 | FROM caddy:${CADDY_VERSION}-builder AS builder
3 |
4 | RUN xcaddy build \
5 | --with github.com/lucaslorentz/caddy-docker-proxy/v2@v2.8.4 \
6 | --with github.com/mholt/caddy-webdav
7 | # --with
8 |
9 | FROM caddy:${CADDY_VERSION}-alpine
10 |
11 | COPY --from=builder /usr/bin/caddy /usr/bin/caddy
12 |
13 | CMD ["caddy", "docker-proxy"]
14 |
--------------------------------------------------------------------------------
/src/components/OrgFile/components/HeaderList/stylesheet.css:
--------------------------------------------------------------------------------
1 | @import '../../../../colors.css';
2 |
3 | .header-list-container {
4 | font-family: Courier;
5 | margin-top: 10px;
6 |
7 | z-index: 1;
8 |
9 | height: '100%';
10 | overflow: 'auto';
11 | }
12 |
13 | .header-list-container--narrowed {
14 | box-shadow: inset 0px 0px 5px 0px var(--base0-soft);
15 | margin: 0;
16 | margin-top: 10px;
17 | border-radius: 5px;
18 | }
19 |
--------------------------------------------------------------------------------
/src/components/LoadingIndicator/stylesheet.css:
--------------------------------------------------------------------------------
1 | @import '../../colors.css';
2 |
3 | .loading-indicator {
4 | color: var(--base00);
5 | background-color: var(--base2);
6 | font-weight: bold;
7 | opacity: 0.9;
8 | padding: 18px;
9 | display: inline-block;
10 | position: fixed;
11 | font-size: 20px;
12 | left: 50%;
13 | top: 85px;
14 | width: 80%;
15 | text-align: center;
16 | transform: translateX(-50%);
17 | z-index: 1;
18 | }
19 |
--------------------------------------------------------------------------------
/src/components/OrgFile/components/ActionDrawer/components/ActionButton/stylesheet.css:
--------------------------------------------------------------------------------
1 | .action-drawer__btn--letter {
2 | font-size: 24px;
3 | }
4 |
5 | .action-drawer__btn--with-sub-icon {
6 | padding-right: 3px;
7 | padding-bottom: 3px;
8 | }
9 |
10 | .action-drawer__btn__sub-icon {
11 | position: absolute;
12 | bottom: 10px;
13 | right: 10px;
14 | }
15 |
16 | .action-drawer__btn__sub-icon--rotated {
17 | transform: rotate(270deg);
18 | }
19 |
--------------------------------------------------------------------------------
/src/components/Landing/Landing.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render, cleanup } from '@testing-library/react';
3 | import { MemoryRouter } from 'react-router-dom';
4 |
5 | import Landing from './';
6 |
7 | afterEach(cleanup);
8 |
9 | test(' renders', () => {
10 | const { container } = render(
11 |
12 |
13 |
14 | );
15 |
16 | expect(container).toMatchSnapshot();
17 | });
18 |
--------------------------------------------------------------------------------
/src/migrations/migrate_access_token_to_dropbox_access_token.js:
--------------------------------------------------------------------------------
1 | import { localStorageAvailable } from '../util/settings_persister';
2 |
3 | export default () => {
4 | if (!localStorageAvailable) {
5 | return;
6 | }
7 |
8 | const accessToken = localStorage.getItem('accessToken');
9 | if (!accessToken) {
10 | return;
11 | }
12 |
13 | localStorage.setItem('dropboxAccessToken', accessToken);
14 | localStorage.removeItem('accessToken');
15 | };
16 |
--------------------------------------------------------------------------------
/src/sync_backend_clients/dropbox_sync_backend_client.test.js:
--------------------------------------------------------------------------------
1 | import {
2 | dropboxDirectoryListing,
3 | dropboxDirectoryListingSorted,
4 | } from './fixtures/directory_listing';
5 |
6 | const { filterAndSortDirectoryListing } = require('./dropbox_sync_backend_client');
7 |
8 | test('Filters down to Org files and orders alphabetically', () => {
9 | expect(filterAndSortDirectoryListing(dropboxDirectoryListing)).toEqual(
10 | dropboxDirectoryListingSorted
11 | );
12 | });
13 |
--------------------------------------------------------------------------------
/src/components/UI/Switch/stylesheet.css:
--------------------------------------------------------------------------------
1 | @import '../../../colors.css';
2 |
3 | .switch {
4 | display: inline-block;
5 | border: 1px solid var(--base2);
6 | width: 90px;
7 | height: 34px;
8 | padding: 2px;
9 | box-sizing: border-box;
10 | }
11 |
12 | .switch__grabber {
13 | width: 42px;
14 | height: 28px;
15 | border: 1px solid var(--base2);
16 | box-sizing: border-box;
17 | box-shadow: 1px 1px 5px 0px var(--base0-soft);
18 | background-color: var(--base00);
19 | }
20 |
--------------------------------------------------------------------------------
/contrib/organice-k8s/README.org:
--------------------------------------------------------------------------------
1 | * Running organice a Kubernetes cluster
2 |
3 | This uses the [[https://organice.200ok.ch/documentation.html#docker][official organice Docker image]], but adds deployment on a
4 | Kubernetes cluster.
5 |
6 | Author:
7 | - Github: https://github.com/johnhamelink
8 | - Website http://johnhame.link/
9 | - Email: john@johnhamelink.com
10 | - Twitter: https://twitter.com/john_hamelink
11 |
12 | Upstream repository: https://git.sr.ht/~johnhamelink/organice-k8s
13 |
--------------------------------------------------------------------------------
/contrib/organice-k8s/deployment.yml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: apps/v1
3 | kind: Deployment
4 | metadata:
5 | name: organice
6 | spec:
7 | replicas: 1
8 | selector:
9 | matchLabels:
10 | name: organice
11 | template:
12 | metadata:
13 | labels:
14 | name: organice
15 | spec:
16 | containers:
17 | - name: organice
18 | imagePullPolicy: Always
19 | image: twohundredok/organice:latest
20 | ports:
21 | - containerPort: 5000
22 |
--------------------------------------------------------------------------------
/src/service-worker.js:
--------------------------------------------------------------------------------
1 | import { manifest, version } from '@parcel/service-worker';
2 |
3 | async function install() {
4 | const cache = await caches.open(version);
5 | await cache.addAll(manifest);
6 | }
7 | addEventListener('install', (e) => e.waitUntil(install()));
8 |
9 | async function activate() {
10 | const keys = await caches.keys();
11 | await Promise.all(keys.map((key) => key !== version && caches.delete(key)));
12 | }
13 | addEventListener('activate', (e) => e.waitUntil(activate()));
14 |
--------------------------------------------------------------------------------
/src/migrations/index.js:
--------------------------------------------------------------------------------
1 | import migrateAccessTokenToDropboxAccessToken from './migrate_access_token_to_dropbox_access_token';
2 | import migrateStoreInDropboxToStoreInSyncBackend from './migrate_store_in_dropbox_to_store_in_sync_backend';
3 | import migrateNonsenseValuesInLocalstorage from './migrate_nonsense_values_in_localstorage';
4 |
5 | export default () => {
6 | migrateAccessTokenToDropboxAccessToken();
7 | migrateStoreInDropboxToStoreInSyncBackend();
8 | migrateNonsenseValuesInLocalstorage();
9 | };
10 |
--------------------------------------------------------------------------------
/src/migrations/migrate_nonsense_values_in_localstorage.js:
--------------------------------------------------------------------------------
1 | import { localStorageAvailable } from '../util/settings_persister';
2 |
3 | export default () => {
4 | if (!localStorageAvailable) {
5 | return;
6 | }
7 |
8 | Object.entries(localStorage).forEach(([k, v], _) => {
9 | if (['null', 'undefined'].includes(v)) {
10 | console.warn(`localStorage contains a bogus entry: '${k}': '${v}'`);
11 | console.warn('Deleting the bogus entry.');
12 | localStorage.removeItem(k);
13 | }
14 | });
15 | };
16 |
--------------------------------------------------------------------------------
/test_helpers/fixtures/table.org:
--------------------------------------------------------------------------------
1 | * A table
2 | #+BEGIN: clocktable :maxlevel 25 :scope subtree :formula "$3=$2*150;t"
3 | #+CAPTION: Clock summary at [2019-09-22 Sun 11:21]
4 | | Headline | Time | |
5 | |---------------------+--------+--------|
6 | | *Total time* | *4:10* | 625.00 |
7 | |---------------------+--------+--------|
8 | | Tables | 4:10 | 625.00 |
9 | | Something todo | 2:05 | 312.50 |
10 | | Something else todo | 2:05 | 312.50 |
11 | #+TBLFM: $3=$2*150;t
12 | #+END:
13 |
--------------------------------------------------------------------------------
/src/components/OrgFile/components/TaskListModal/components/TaskListView/stylesheet.css:
--------------------------------------------------------------------------------
1 | /* Currently, the markup is the same as in the AgendaDay component. Hence */
2 | /* the CSS rules from there apply. */
3 |
4 |
5 | .task-list__header-planning-type {
6 | color: var(--base01);
7 | min-width: 8em;
8 | margin: 0 5px 0 0;
9 | display: inline-block;
10 | }
11 |
12 | .task-list__header-planning-date {
13 | display: inline-block;
14 | }
15 |
16 | .task-list__header-planning-date--overdue {
17 | color: var(--orange);
18 | }
19 |
--------------------------------------------------------------------------------
/contrib/organice-k8s/load-balancer.yml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: nginx-ingress
5 | namespace: kube-system
6 | labels:
7 | app.kubernetes.io/name: ingress-nginx
8 | app.kubernetes.io/part-of: ingress-nginx
9 | spec:
10 | type: LoadBalancer
11 | ports:
12 | - port: 80
13 | name: http
14 | targetPort: 80
15 | - port: 443
16 | name: https
17 | targetPort: 443
18 | selector:
19 | app.kubernetes.io/name: ingress-nginx
20 | app.kubernetes.io/part-of: ingress-nginx
21 |
--------------------------------------------------------------------------------
/src/components/OrgFile/components/HeaderContent/stylesheet.css:
--------------------------------------------------------------------------------
1 | @import '../../../../colors.css';
2 |
3 | .header-content-container {
4 | white-space: pre-wrap;
5 | overflow-x: auto;
6 | }
7 |
8 | .header-content__edit-icon {
9 | color: var(--base2);
10 |
11 | margin-top: 10px;
12 | margin-right: 5px;
13 | float: left;
14 | }
15 |
16 | .header-content__insert-timestamp-button {
17 | color: var(--base0);
18 |
19 | display: flex;
20 | align-items: center;
21 | }
22 |
23 | .insert-timestamp-icon {
24 | margin-right: 5px;
25 | }
26 |
--------------------------------------------------------------------------------
/contrib/organice-webdav-post/organice_inbox.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | IFS=$'\n'
4 |
5 | DESC=""
6 | DATE=$(date +%Y-%m-%d)
7 | TITLE="$(echo $1 | sed -e 's/"//g' | sed -e "s/'//g")"
8 |
9 | for line in $2
10 | do
11 | if [ "$DESC" == "" ];
12 | then
13 | DESC="$(echo $line | sed -e 's/"//g' | sed -e "s/'//g")"
14 | else
15 | DESC="$DESC\n $(echo $line | sed -e 's/"//g' | sed -e "s/'//g")"
16 | fi
17 | done
18 |
19 | echo -e "* TODO $TITLE
20 | DEADLINE: <$DATE>
21 | - $DESC" >> $3
22 |
23 | echo Added task $1 to $3
24 |
--------------------------------------------------------------------------------
/src/components/Landing/stylesheet.css:
--------------------------------------------------------------------------------
1 | .main-image {
2 | max-height: 35em;
3 | }
4 | .testimonial-brand img {
5 | height: 3em;
6 | width: auto;
7 | }
8 |
9 | /* Icons with
*/
10 | #icons img {
11 | opacity: 0.5;
12 | margin-bottom: 2em;
13 | width: 100%;
14 | max-height: 2em;
15 | }
16 |
17 | #icons img:hover {
18 | opacity: 1;
19 | }
20 |
21 | /* Icons with Fontawesome */
22 | #icons svg:not(:root).svg-inline--fa {
23 | height: 3em;
24 | width: 100%;
25 | }
26 |
27 | #false-bottom-preventor {
28 | cursor: pointer;
29 | }
30 |
--------------------------------------------------------------------------------
/src/store.js:
--------------------------------------------------------------------------------
1 | import { createStore, applyMiddleware, compose } from 'redux';
2 | import thunk from 'redux-thunk';
3 | import liveSync from './middleware/live_sync';
4 | import toggleColorScheme from './middleware/toggle_color_scheme';
5 | import rootReducer from './reducers';
6 |
7 | const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
8 |
9 | export default (initialState) =>
10 | createStore(
11 | rootReducer,
12 | initialState,
13 | composeEnhancers(applyMiddleware(thunk, liveSync, toggleColorScheme))
14 | );
15 |
--------------------------------------------------------------------------------
/src/migrations/migrate_store_in_dropbox_to_store_in_sync_backend.js:
--------------------------------------------------------------------------------
1 | import { localStorageAvailable } from '../util/settings_persister';
2 |
3 | export default () => {
4 | if (!localStorageAvailable) {
5 | return;
6 | }
7 |
8 | const shouldStoreSettingsInDropbox = localStorage.getItem('shouldStoreSettingsInDropbox');
9 | if (!shouldStoreSettingsInDropbox) {
10 | return;
11 | }
12 |
13 | localStorage.setItem('shouldStoreSettingsInSyncBackend', shouldStoreSettingsInDropbox);
14 | localStorage.removeItem('shouldStoreSettingsInDropbox');
15 | };
16 |
--------------------------------------------------------------------------------
/doc/webdav/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM debian:buster-slim
2 |
3 | RUN apt-get update -y -qq && \
4 | apt-get install -y -qq \
5 | apache2-utils \
6 | apache2
7 |
8 | ADD doc/webdav/webdav.conf /etc/apache2/sites-available/webdav.conf
9 |
10 | RUN a2enmod headers
11 | RUN a2enmod dav*
12 | RUN a2enmod rewrite
13 | RUN a2ensite webdav
14 |
15 |
16 | RUN mkdir /srv/dav
17 | # RUN echo demo | htpasswd -ci /srv/dav/.htpasswd demo
18 | RUN chmod 770 /srv/dav
19 | RUN chown www-data. /srv/dav
20 |
21 | COPY sample.org /srv/dav/demo.org
22 |
23 | CMD apachectl -D FOREGROUND
24 | EXPOSE 80
--------------------------------------------------------------------------------
/src/components/OrgFile/stylesheet.css:
--------------------------------------------------------------------------------
1 | @import '../../colors.css';
2 |
3 | .org-file__parsing-error-message {
4 | text-align: center;
5 | font-size: 16px;
6 |
7 | margin: 10px;
8 | }
9 |
10 | .org-file__btn {
11 | margin: 10px;
12 | text-align: center;
13 | }
14 |
15 | .dirty-indicator {
16 | padding: 3px;
17 | opacity: 0.6;
18 | color: var(--base2);
19 | background-color: var(--orange);
20 | position: fixed;
21 | bottom: 100px;
22 | right: 10px;
23 | font-weight: bold;
24 | }
25 |
26 | .error-message-container {
27 | padding: 10px;
28 | font-size: 20px;
29 | }
30 |
--------------------------------------------------------------------------------
/bin/transient_env_vars.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | shopt -s globstar
4 |
5 | RVARS=$(cut -d = -f 1 .env.sample)
6 |
7 | case $1 in
8 |
9 | "bait")
10 | for KEY in $RVARS; do
11 | echo "$KEY=${KEY//REACT_APP_/ORGANICE_}"
12 | done
13 | ;;
14 |
15 | "switch")
16 | SRC=$2
17 | DST=$3
18 |
19 | rm -rf "$DST"
20 | cp -r "$SRC" "$DST"
21 |
22 | OVARS=${RVARS//REACT_APP_/ORGANICE_}
23 |
24 | for KEY in $OVARS; do
25 | VALUE=${!KEY}
26 | sed -i "s/$KEY/$VALUE/" "$DST"/**/*.js
27 | done
28 | ;;
29 |
30 | *)
31 | echo "Unknown command: $1"
32 | ;;
33 | esac
34 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "organice",
3 | "name": "organice",
4 | "icons": [
5 | {
6 | "src": "./organice-512x512.png",
7 | "sizes": "512x512",
8 | "type": "image/png"
9 | },
10 | {
11 | "src": "./organice-192x192.png",
12 | "sizes": "192x192",
13 | "type": "image/png"
14 | },
15 | {
16 | "src": "./favicon.ico",
17 | "sizes": "64x64 32x32 24x24 16x16",
18 | "type": "image/x-icon"
19 | }
20 | ],
21 | "start_url": "/index.html",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/bin/compile_doc_and_upload.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Sanity check that all variables are set to upload to FTP
4 | [ -z ${FTP_HOST+x} ] && (echo "$FTP_HOST needs to be set for uploading to FTP."; exit 1)
5 | [ -z ${FTP_USER+x} ] && (echo "$FTP_USER needs to be set for uploading to FTP."; exit 1)
6 | [ -z ${FTP_PASSWD+x} ] && (echo "$FTP_PASSWD needs to be set for uploading to FTP."; exit 1)
7 |
8 |
9 | here=$(dirname $0)
10 |
11 | if $here/compile_doc.sh; then
12 | lftp -e "put documentation.html; exit" -u $FTP_USER,$FTP_PASSWD $FTP_HOST
13 | else
14 | echo >&2 "compile_doc.sh failed; skipping upload"
15 | exit 1
16 | fi
17 |
--------------------------------------------------------------------------------
/src/components/OrgFile/components/SearchModal/components/HeaderListView/stylesheet.css:
--------------------------------------------------------------------------------
1 | /* Currently, the markup is the same as in the AgendaDay component. Hence */
2 | /* the CSS rules from there apply. */
3 |
4 | .task-list__header-planning-type {
5 | color: var(--base01);
6 | min-width: 8em;
7 | margin: 0 5px 0 0;
8 | display: inline-block;
9 | }
10 |
11 | .task-list__header-planning-date {
12 | display: inline-block;
13 | }
14 |
15 | .task-list__header-planning-date--overdue {
16 | color: var(--orange);
17 | }
18 |
19 | .search__breadcrumbs {
20 | color: var(--base01);
21 | font-size: 12px;
22 | font-family: Courier;
23 | }
24 |
--------------------------------------------------------------------------------
/src/components/OrgFile/components/SyncConfirmationModal/stylesheet.css:
--------------------------------------------------------------------------------
1 | @import '../../../../colors.css';
2 |
3 | .sync-confirmation-modal__header {
4 | color: var(--base2);
5 |
6 | margin-top: 0;
7 | }
8 |
9 | .sync-confirmation-modal__last-sync-time {
10 | color: var(--base0);
11 |
12 | text-align: center;
13 | font-weight: bold;
14 | }
15 |
16 | .sync-confirmation-modal__buttons-container {
17 | display: flex;
18 | flex-direction: column;
19 | align-items: center;
20 |
21 | margin-top: 20px;
22 | margin-bottom: 10px;
23 | }
24 |
25 | .sync-confirmation-modal__button {
26 | font-size: 18px;
27 |
28 | margin-top: 15px;
29 | }
30 |
--------------------------------------------------------------------------------
/config/jest/cssTransform.js:
--------------------------------------------------------------------------------
1 | // @remove-on-eject-begin
2 | /**
3 | * Copyright (c) 2014-present, Facebook, Inc.
4 | *
5 | * This source code is licensed under the MIT license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 | // @remove-on-eject-end
9 | 'use strict';
10 |
11 | // This is a custom Jest transformer turning style imports into empty objects.
12 | // http://facebook.github.io/jest/docs/en/webpack.html
13 |
14 | module.exports = {
15 | process() {
16 | return 'module.exports = {};';
17 | },
18 | getCacheKey() {
19 | // The output is always the same.
20 | return 'cssTransform';
21 | },
22 | };
23 |
--------------------------------------------------------------------------------
/src/components/OrgFile/components/AttributedString/components/ListPart/ListActionDrawer/stylesheet.css:
--------------------------------------------------------------------------------
1 | .list-action-drawer-container {
2 | color: lightgray;
3 |
4 | padding-bottom: 10px;
5 |
6 | padding-right: 20px;
7 | }
8 |
9 | .list-action-drawer__row {
10 | display: flex;
11 | align-items: center;
12 | justify-content: space-around;
13 |
14 | padding-top: 10px;
15 | }
16 |
17 | .list-action-drawer__edit-icon-container {
18 | position: relative;
19 | }
20 |
21 | .list-action-drawer__separator {
22 | background-color: lightgray;
23 |
24 | height: 15px;
25 | width: 1px;
26 |
27 | margin-left: 10px;
28 | margin-right: 10px;
29 | }
30 |
--------------------------------------------------------------------------------
/__mocks__/fileMock.js:
--------------------------------------------------------------------------------
1 | // This is a workaround. We used to have CRA, now we have Parcel.
2 |
3 | // We used to have the raw.macro for reading files, but that's a babel
4 | // thing, so we had to switch for importing the parcel way. Now, that
5 | // code works well, again. Having said so, jest (which uses babel)
6 | // cannot read the files as parcel does. So we need a workaround.
7 | // Luckily Jest is very powerful and has moduleNameMapper
8 | // functionality where we defined in jest.config.json that we override
9 | // imports with `bundle-text` and `url` prefixes to this stubbed file.
10 |
11 | // Export a simple string stub.
12 | module.exports = 'test-file-stub';
13 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | SHELL = /bin/bash
2 |
3 | .DEFAULT_GOAL = run
4 |
5 | # ------------------------------------------------------------
6 | # dev
7 |
8 | .PHONY: setup
9 | setup:
10 | yarn install --production=false
11 |
12 | .PHONY: run
13 | run: setup
14 | yarn start
15 |
16 | .PHONY: test
17 | test: setup
18 | yarn test
19 |
20 | .PHONY: test-update-snapshots
21 | test-update-snapshots: setup
22 | yarn test -u
23 |
24 | .PHONY: docs
25 | docs:
26 | ./bin/compile_doc.sh
27 |
28 | .PHONY: deploy-docs
29 | deploy-docs: docs
30 | ./bin/compile_doc_and_upload.sh
31 |
32 | .PHONY: deploy
33 | deploy:
34 | ./bin/compile_and_upload.sh
35 | ./bin/compile_doc_and_upload.sh
36 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 | tags
19 |
20 | npm-debug.log*
21 | yarn-debug.log*
22 | yarn-error.log*
23 | /.log/
24 |
25 | *~
26 |
27 | .env
28 | /src/lib/headline_filter_parser.js
29 |
30 | /documentation.html
31 | /documentation.org
32 |
33 | .eslintcache
34 | /src/components/Landing/vendor_css/template.css
35 | /src/components/Landing/vendor_css/template.css.map
36 |
37 | .parcel-cache
38 | dist
--------------------------------------------------------------------------------
/test_helpers/fixtures/logbook.org:
--------------------------------------------------------------------------------
1 | * Spec header
2 | :LOGBOOK:
3 | CLOCK: [2019-11-13 Wed 13:15]
4 | - State "DONE" from "TODO" CLOCK: [2019-11-13 Wed 13:15]
5 |
6 | CLOCK: [2019-11-13 Wed 13:15]--[2019-11-13 Wed 13:15] => 0:00
7 |
8 | some inter-entry text
9 | CLOCK: [2019-11-12 Tue 14:15]--[2019-11-12 Tue 13:20] => -0:55
10 | CLOCK: [2019-11-12 Tue 14:15]--[2019-11-12 Tue 14:25] => 0:10
11 | :END:
12 | * another one
13 | :LOGBOOK:
14 | CLOCK: [2019-11-13 Wed 13:15]
15 | CLOCK: [2019-11-13 Wed 13:15]--[2019-11-13 Wed 13:15] => 0:00
16 | CLOCK: [2019-11-12 Tue 14:15]--[2019-11-12 Tue 13:20] => -0:55
17 | CLOCK: [2019-11-12 Tue 14:15]--[2019-11-12 Tue 14:25] => 0:10
18 | :END:
19 |
--------------------------------------------------------------------------------
/src/util/misc.js:
--------------------------------------------------------------------------------
1 | import { createBrowserHistory } from 'history';
2 |
3 | // Hard-wrap long lines - from https://stackoverflow.com/a/51506718/252585
4 | export const formatTextWrap = (text, w) => {
5 | return text.replace(new RegExp(`(?![^\\n]{1,${w}}$)([^\\n]{1,${w}})\\s`, 'g'), '$1\n');
6 | };
7 |
8 | /* See adr-002 for details.
9 | `isLandingPage` is a function that can be used to create certain
10 | safeguards, i.e. not loading some CSS where not appropriate. */
11 |
12 | export const isLandingPage = () => {
13 | const history = createBrowserHistory();
14 | return (
15 | !window.testRunner &&
16 | history.location.pathname === '/' &&
17 | !localStorage.authenticatedSyncService
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/test_helpers/fixtures/multiple_headlines_with_timestamps.org:
--------------------------------------------------------------------------------
1 | #+TODO: TODO | DONE
2 | #+TODO: START INPROGRESS STALLED | FINISHED
3 |
4 | * INPROGRESS This is a header without timestamp
5 |
6 | * DONE This is a scheduled header
7 | SCHEDULED: <2019-08-04 Sun>
8 |
9 | * START This is a deadline header
10 | DEADLINE: <2019-08-27 Tue>
11 |
12 | * START This is a header with both
13 | SCHEDULED: <2019-08-04 Sun> DEADLINE: <2019-08-27 Tue>
14 |
15 | * START This is a header with all three
16 | SCHEDULED: <2019-08-04 Sun> DEADLINE: <2019-08-27 Tue> CLOSED: [2019-08-27 Tue]
17 |
18 | * TODO <2020-01-01 Wed> This is a header with timestamp
19 |
20 | * TODO This is a header with timestamp in the text
21 | <2020-01-01 Wed 00:00>
22 |
--------------------------------------------------------------------------------
/src/components/OrgFile/components/TaskListModal/stylesheet.css:
--------------------------------------------------------------------------------
1 | @import '../../../../colors.css';
2 |
3 | /* Currently, the markup is the same as in the AgendaModal component.
4 | * Hence the CSS rules from there apply. */
5 |
6 | .task-list__modal-title {
7 | width: 100%;
8 | height: 20px;
9 | min-height: 20px;
10 | display: flex;
11 | justify-content: space-between;
12 | align-items: center;
13 | }
14 |
15 | .task-list__filter-input {
16 | box-sizing: border-box;
17 | width: 100%;
18 | }
19 |
20 | .task-list__input-container {
21 | flex-shrink: 0;
22 | display: flex;
23 | align-items: center;
24 | flex-direction: column;
25 | }
26 |
27 | .task-list__filter-input--invalid {
28 | border: 2px solid var(--red);
29 | }
30 |
--------------------------------------------------------------------------------
/src/components/OrgFile/components/AttributedString/components/TablePart/stylesheet.css:
--------------------------------------------------------------------------------
1 | @import '../../../../../../colors.css';
2 |
3 | .table-part {
4 | border-collapse: collapse;
5 | margin-top: 3px;
6 | margin-bottom: 3px;
7 | }
8 |
9 | .table-part__cell {
10 | border: 1px solid var(--base01);
11 |
12 | white-space: pre;
13 |
14 | vertical-align: top;
15 | }
16 |
17 | .table-part__cell--selected {
18 | background-color: var(--green-soft);
19 | }
20 |
21 | .table-cell__edit-container {
22 | width: 100%;
23 | }
24 |
25 | .table-cell__insert-timestamp-button {
26 | color: var(--base0);
27 |
28 | font-family: Courier;
29 |
30 | display: flex;
31 | align-items: center;
32 | }
33 |
34 | .insert-timestamp-icon {
35 | margin-right: 5px;
36 | }
--------------------------------------------------------------------------------
/src/components/OrgFile/components/TimestampEditorModal/stylesheet.css:
--------------------------------------------------------------------------------
1 | @import '../../../../colors.css';
2 |
3 | .timestamp-editor__title {
4 | color: var(--base01);
5 |
6 | margin-top: 0;
7 | }
8 |
9 | .timestamp-editor__button-container {
10 | display: flex;
11 | justify-content: center;
12 | }
13 |
14 | .timestamp-editor__add-new-button {
15 | font-size: 18px;
16 | margin-top: 15px;
17 | }
18 |
19 | .timestamp-editor__separator {
20 | display: flex;
21 | align-items: center;
22 | justify-content: space-between;
23 |
24 | margin-top: 10px;
25 | margin-bottom: 10px;
26 |
27 | font-size: 22px;
28 | }
29 |
30 | .timestamp-editor__separator__margin-line {
31 | background-color: var(--base03);
32 | height: 1px;
33 | width: 40%;
34 |
35 | margin-top: 5px;
36 | }
37 |
--------------------------------------------------------------------------------
/doc/webdav/webdav.conf:
--------------------------------------------------------------------------------
1 | Alias /webdav /srv/dav/
2 | ServerName 127.0.0.1
3 |
4 |
5 | Options Indexes
6 | DAV On
7 | # AuthType Basic
8 | # AuthName "Restricted Content"
9 | # AuthUserFile /srv/dav/.htpasswd
10 | #
11 | # Require valid-user
12 | #
13 |
14 | Header always set Access-Control-Allow-Origin "*"
15 | Header always set Access-Control-Allow-Methods "GET,POST,OPTIONS,DELETE,PUT,PROPFIND"
16 | Header always set Access-Control-Allow-Headers "Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization,X-CSRF-Token,Depth"
17 | Header always set Access-Control-Allow-Credentials true
18 |
19 | Require all granted
20 |
21 |
--------------------------------------------------------------------------------
/doc/setupfile:
--------------------------------------------------------------------------------
1 | # -*- mode: org; -*-
2 |
3 | #+HTML_HEAD:
4 | #+HTML_HEAD:
5 |
6 | #+HTML_HEAD:
7 | #+HTML_HEAD:
8 | #+HTML_HEAD:
9 | #+HTML_HEAD:
10 |
--------------------------------------------------------------------------------
/bin/compile_search_parser.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | npx pegjs -o src/lib/headline_filter_parser.{js,grammar.pegjs}
4 |
5 | # The generated code of pegjs throws eslint warnings. Since it's not
6 | # code that we're writing and we want to keep eslint warnings at 0,
7 | # we're telling eslint to ignore the generated file.
8 | PARSER_FILE=src/lib/headline_filter_parser.js
9 |
10 | # Prepend the generated parser code with a `eslint-disable` comment.
11 | # We don't use `sed` or `ex` because some Linux/UNIX distros don't
12 | # support them. For example MacOS ships with BSD sed which doesn't
13 | # support `-i` and some barebones Linux distros don't ship `ex`.
14 | # `mktemp` works under Linux and MacOS, though.
15 | tmp=$(mktemp)
16 | echo '/* eslint-disable */' > "$tmp" && cat "$PARSER_FILE" >> "$tmp" && mv "$tmp" "$PARSER_FILE"
17 |
--------------------------------------------------------------------------------
/src/components/UI/TabButtons/stylesheet.css:
--------------------------------------------------------------------------------
1 | @import '../../../colors.css';
2 |
3 | .tab-buttons {
4 | border: 1px solid var(--base2);
5 | height: 34px;
6 | box-sizing: border-box;
7 | display: inline-flex;
8 | align-items: center;
9 | }
10 |
11 | .tab-buttons--equal-width-tabs {
12 | display: grid;
13 | grid-template-columns: repeat(3, 1fr);
14 | }
15 |
16 | .tab-buttons__btn {
17 | cursor: pointer;
18 | box-sizing: border-box;
19 | height: 100%;
20 | padding: 7px;
21 | border-right: 1px solid var(--base01);
22 |
23 | text-align: center;
24 | }
25 |
26 | .tab-buttons__btn:last-of-type {
27 | border-right: none;
28 | }
29 |
30 | .entry-container--large-font .tab-buttons__btn {
31 | padding: 5px;
32 | }
33 |
34 | .tab-buttons__btn--selected {
35 | background-color: var(--base2);
36 | color: var(--base03);
37 | }
38 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | Before creating a new issue, please read the "How we work with issues" section in the documentation: https://organice.200ok.ch/documentation.html#how_we_work_with_issues
11 |
12 | **Is your feature request related to a problem? Please describe.**
13 | A clear and concise description of what the problem is.
14 |
15 | **Describe the solution you'd like**
16 | A clear and concise description of what you want to happen.
17 |
18 | **Describe alternatives you've considered**
19 | A clear and concise description of any alternative solutions or features you've considered.
20 |
21 | **Additional context**
22 | Add any other context or screenshots about the feature request here.
23 |
--------------------------------------------------------------------------------
/src/util/settings_persister.test.js:
--------------------------------------------------------------------------------
1 | import Store from '../store';
2 | import { readInitialState, subscribeToChanges } from './settings_persister';
3 |
4 | describe('Settings persister', () => {
5 | let store;
6 | beforeEach(() => {
7 | const initialState = readInitialState();
8 | store = Store(initialState);
9 | subscribeToChanges(store)();
10 | });
11 |
12 | afterEach(() => {
13 | localStorage.clear();
14 | });
15 |
16 | test('Do not persist nonsense like like "false" for settings without default', () => {
17 | expect(localStorage.getItem('showClockDisplay')).not.toBe('false');
18 | expect(localStorage.getItem('showClockDisplay')).toBe(null);
19 | });
20 |
21 | test('Does persist given default values, for example colorScheme', () => {
22 | expect(localStorage.getItem('colorScheme')).toBe('OS');
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/src/components/OrgFile/components/AgendaModal/stylesheet.css:
--------------------------------------------------------------------------------
1 | @import '../../../../colors.css';
2 |
3 | .agenda__title {
4 | color: var(--base01);
5 |
6 | margin-top: 0;
7 | }
8 |
9 | .agenda__tab-container {
10 | justify-content: center;
11 | }
12 |
13 | .agenda__timeframe-header-container {
14 | display: flex;
15 | justify-content: center;
16 | align-items: center;
17 |
18 | margin: 2em 0 1.5em 0;
19 |
20 | color: var(--base01);
21 | }
22 |
23 | .agenda__timeframe-header-container > i {
24 | cursor: pointer;
25 | }
26 |
27 | .agenda__timeframe-header {
28 | font-weight: bold;
29 | font-size: 18px;
30 |
31 | text-align: center;
32 |
33 | margin-left: 15px;
34 | margin-right: 15px;
35 |
36 | min-width: 230px;
37 | }
38 |
39 | .agenda__days-container {
40 | margin-top: 15px;
41 | padding-left: 10px;
42 | padding-right: 10px;
43 | }
44 |
--------------------------------------------------------------------------------
/src/components/OrgFile/components/AttributedString/stylesheet.css:
--------------------------------------------------------------------------------
1 | @import '../../../../colors.css';
2 |
3 | .attributed-string__cookie-part {
4 | font-weight: bold;
5 | color: var(--red);
6 | }
7 |
8 | .attributed-string__cookie-part--complete {
9 | color: var(--green);
10 | }
11 |
12 | .attributed-string__inline-markup--inline-code,
13 | .attributed-string__inline-markup--verbatim {
14 | color: var(--base03);
15 | background-color: var(--base2);
16 | border: 1px solid var(--base1);
17 | padding: 2px;
18 | }
19 |
20 | .attributed-string__inline-markup--bold {
21 | font-weight: bold;
22 | }
23 |
24 | .attributed-string__inline-markup--italic {
25 | font-style: italic;
26 | }
27 |
28 | .attributed-string__inline-markup--strikethrough {
29 | text-decoration: line-through;
30 | }
31 |
32 | .attributed-string__inline-markup--underline {
33 | text-decoration: underline;
34 | }
35 |
--------------------------------------------------------------------------------
/src/middleware/toggle_color_scheme.js:
--------------------------------------------------------------------------------
1 | import { setColorScheme } from '../actions/base';
2 |
3 | export default (store) => (next) => (action) => {
4 | // Watch if the user changes the preferred color scheme through the
5 | // OS or browser.
6 |
7 | // Returns a MediaQueryList object
8 | const prefersColorSchemeMediaQueryList = window.matchMedia('(prefers-color-scheme: dark)');
9 |
10 | // Feature detection. If there's no dark mode (i.e. iOS <14), then
11 | // the `matchMedia` query above does not resolve in anything that
12 | // can be observed.
13 | if ('addEventListener' in prefersColorSchemeMediaQueryList) {
14 | prefersColorSchemeMediaQueryList.addEventListener('change', (e) => {
15 | const selectedColorScheme = e.matches ? 'Dark' : 'Light';
16 | store.dispatch(setColorScheme(selectedColorScheme));
17 | });
18 | }
19 |
20 | return next(action);
21 | };
22 |
--------------------------------------------------------------------------------
/test_helpers/fixtures/before-first-headline.org:
--------------------------------------------------------------------------------
1 | #+SETUPFILE: orgmode-export.conf
2 | #+TITLE: Testing what happens before the first headline
3 | #+AUTHOR: \includegraphics[height=2cm]{images/organice.png}
4 | #+EMAIL:
5 | #+DATE: \today
6 | #+DESCRIPTION: Introduction
7 | #+KEYWORDS: beamer org orgmode
8 | #+LANGUAGE: en
9 | #+STARTUP: beamer showeverything
10 | #+LaTeX_CLASS: beamer
11 | #+LaTeX_CLASS_OPTIONS: [bigger]
12 | #+BEAMER_THEME: metropolis
13 | #+OPTIONS: H:2 toc:t ^:{}
14 |
15 | All this content will not be visible in organice, however, it will be
16 | properly exported back!
17 |
18 | A paragraph before the first headline, weirdly indented.
19 |
20 | Another paragraph before the first headline, not indented.
21 |
22 | A list:
23 |
24 | - 1
25 | - 2
26 | - 3
27 |
28 |
29 |
30 |
31 | * This is the first headline
32 | - 1
33 | - 2
34 | - 3
35 | * Second headline
36 |
--------------------------------------------------------------------------------
/src/lib/sample_capture_templates.js:
--------------------------------------------------------------------------------
1 | import generateId from './id_generator';
2 |
3 | import { fromJS } from 'immutable';
4 |
5 | export default fromJS([
6 | {
7 | description: 'Groceries',
8 | headerPaths: ['Capture', 'Groceries'],
9 | iconName: 'lemon',
10 | id: generateId(),
11 | isAvailableInAllOrgFiles: false,
12 | letter: '',
13 | orgFilesWhereAvailable: [],
14 | shouldPrepend: false,
15 | template: '* TODO %?',
16 | isSample: true,
17 | },
18 | {
19 | description: 'Deeply nested header',
20 | headerPaths: ['Capture', 'Deeply', 'Nested', 'Headers', 'Work', 'Too!'],
21 | iconName: 'fighter-jet',
22 | id: generateId(),
23 | isAvailableInAllOrgFiles: false,
24 | letter: '',
25 | orgFilesWhereAvailable: [],
26 | shouldPrepend: true,
27 | template: '* You can insert timestamps too! %T %?',
28 | isSample: true,
29 | },
30 | ]);
31 |
--------------------------------------------------------------------------------
/src/components/OrgFile/components/AttributedString/components/TimestampPart/index.js:
--------------------------------------------------------------------------------
1 | import React, { Fragment } from 'react';
2 |
3 | import './stylesheet.css';
4 |
5 | import { renderAsText } from '../../../../../../lib/timestamps';
6 |
7 | export default ({ part, subPartDataAndHandlers: { onTimestampClick, shouldDisableActions } }) => {
8 | const handleClick = () => (shouldDisableActions ? void 0 : onTimestampClick(part.get('id')));
9 |
10 | const firstTimestamp = part.get('firstTimestamp');
11 | const secondTimestamp = part.get('secondTimestamp');
12 |
13 | return (
14 |
15 | {!!firstTimestamp && renderAsText(firstTimestamp)}
16 | {!!secondTimestamp && (
17 |
18 | {'--'}
19 | {renderAsText(secondTimestamp)}
20 |
21 | )}
22 |
23 | );
24 | };
25 |
--------------------------------------------------------------------------------
/src/middleware/live_sync.js:
--------------------------------------------------------------------------------
1 | import { sync } from '../actions/org';
2 | import { persistIsDirty, saveFileToLocalStorage } from '../util/file_persister';
3 | import { determineAffectedFiles } from '../reducers/org';
4 |
5 | export default (store) => (next) => (action) => {
6 | // middleware is run before the reducer. to persist the result of the action,
7 | // save and sync are done in a callback so they happen after the state is changed
8 | setTimeout(() => {
9 | let dirtyFiles = determineAffectedFiles(store.getState().org.present, action);
10 |
11 | dirtyFiles.forEach((path) => saveFileToLocalStorage(store.getState(), path));
12 | dirtyFiles.forEach((path) => persistIsDirty(true, path));
13 |
14 | if (store.getState().base.get('shouldLiveSync')) {
15 | dirtyFiles.forEach((path) => store.dispatch(sync({ shouldSuppressMessages: true, path })));
16 | }
17 | }, 0);
18 |
19 | return next(action);
20 | };
21 |
--------------------------------------------------------------------------------
/config/jest/babelTransform.js:
--------------------------------------------------------------------------------
1 | // @remove-on-eject-begin
2 | /**
3 | * Copyright (c) 2014-present, Facebook, Inc.
4 | *
5 | * This source code is licensed under the MIT license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 | // @remove-on-eject-end
9 | 'use strict';
10 |
11 | const babelJest = require('babel-jest');
12 |
13 | const hasJsxRuntime = (() => {
14 | if (process.env.DISABLE_NEW_JSX_TRANSFORM === 'true') {
15 | return false;
16 | }
17 |
18 | try {
19 | require.resolve('react/jsx-runtime');
20 | return true;
21 | } catch (e) {
22 | return false;
23 | }
24 | })();
25 |
26 | module.exports = babelJest.createTransformer({
27 | presets: [
28 | [
29 | require.resolve('babel-preset-react-app'),
30 | {
31 | runtime: hasJsxRuntime ? 'automatic' : 'classic',
32 | },
33 | ],
34 | ],
35 | babelrc: false,
36 | configFile: false,
37 | });
38 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: 'bug'
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 |
30 | **Smartphone (please complete the following information):**
31 | - Device: [e.g. iPhone6]
32 | - OS: [e.g. iOS8.1]
33 | - Browser [e.g. stock browser, safari]
34 |
35 | **Additional context**
36 | Add any other context about the problem here.
37 |
--------------------------------------------------------------------------------
/.eslintrc.yml:
--------------------------------------------------------------------------------
1 | env:
2 | browser: true
3 | es6: true
4 | extends:
5 | - 'eslint:recommended'
6 | - 'plugin:jest/recommended'
7 | - 'plugin:react/recommended'
8 | - 'plugin:react-redux/recommended'
9 | globals:
10 | Atomics: readonly
11 | SharedArrayBuffer: readonly
12 | parser: babel-eslint
13 | parserOptions:
14 | ecmaFeatures:
15 | jsx: true
16 | ecmaVersion: 2018
17 | sourceType: module
18 | plugins:
19 | - jest
20 | - react
21 | - react-redux
22 | rules:
23 | no-extra-boolean-cast: off
24 | no-empty: off
25 | no-case-declarations: off
26 | no-unused-vars:
27 | - error
28 | - varsIgnorePattern: '_.+'
29 | argsIgnorePattern: '_.*|reject'
30 | react/no-unescaped-entities: off
31 | react/display-name: off
32 | react/prop-types: off
33 | react-redux/prefer-separate-component-file: off
34 | jest/no-disabled-tests: off
35 | no-redeclare:
36 | - 'error'
37 | - builtinGlobals: false
38 | settings:
39 | react:
40 | version: detect
41 |
--------------------------------------------------------------------------------
/bin/compile_and_upload.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -e
4 |
5 | # Sanity check that all variables are set to upload to FTP
6 | [ -z ${FTP_HOST+x} ] && (echo "$FTP_HOST needs to be set for uploading to FTP."; exit 1)
7 | [ -z ${FTP_USER+x} ] && (echo "$FTP_USER needs to be set for uploading to FTP."; exit 1)
8 | [ -z ${FTP_PASSWD+x} ] && (echo "$FTP_PASSWD needs to be set for uploading to FTP."; exit 1)
9 |
10 | # Configure available back-end API keys
11 | cp .env.sample .env
12 | [ -z ${REACT_APP_DROPBOX_CLIENT_ID+x} ] || sed -i "s/your_dropbox_client_id/${REACT_APP_DROPBOX_CLIENT_ID}/" .env
13 |
14 | [ -z ${REACT_APP_GITLAB_CLIENT_ID+x} ] || sed -i "s/your_gitlab_client_id/${REACT_APP_GITLAB_CLIENT_ID}/" .env
15 | [ -z ${REACT_APP_GITLAB_SECRET+x} ] || sed -i "s/your_gitlab_secret/${REACT_APP_GITLAB_SECRET}/" .env
16 |
17 | yarn install
18 | yarn run build
19 | cd dist
20 | lftp "$FTP_HOST" <