diff --git a/Dockerfile b/Dockerfile
index a6776c5..249acc0 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -5,11 +5,15 @@ WORKDIR /app
COPY . .
-RUN apk add build-base libffi-dev
+RUN apk add build-base libffi-dev shadow
+
+RUN \
+ addgroup -g 911 abc && \
+ adduser -D -H -u 911 -G abc abc && \
+ usermod -G users abc
RUN \
cd /app && \
- pip install gunicorn && \
pip install -r requirements.txt && \
chmod +x run.sh && \
chmod +x verify_env.py && \
@@ -17,9 +21,10 @@ RUN \
RUN \
cd /app/client && \
- npm install node-sass && \
npm ci && \
+ npm install node-sass && \
npm run build
+USER abc
EXPOSE 5000
ENTRYPOINT "./run.sh"
\ No newline at end of file
diff --git a/README.md b/README.md
index 28eaacb..d6006ba 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@
-Current version: **1.0-beta10**
+Current version: **1.0-beta11**
## About
The idea for this app came from using my Hobonichi Techo planner every morning to write down what I needed to accomplish that day & using it for scratching down random thoughts and notes as the day went on. The closest thing I've seen to an app for replacing this system is Noteplan, but I don't use a Mac or an iOS device, and it's not self-hostable, so I decided to write my own.
@@ -17,7 +17,7 @@ Since I had the need for keeping track of to-dos throughout the day, regular Mar
## Roadmap
I'd like to try add include at least of some the following features to get to a final v1.0 release:
- - CalDAV support
+ - iCal support
- HTML preview (instead of just markdown)
- Kanban board for tasks (and new syntax to attach meta info like swimlane and project for each task)
- Nested tagging
@@ -50,7 +50,10 @@ The recommended way of running is to pull the image from [Docker Hub](https://hu
| API_SECRET_KEY | Used to sign API tokens. | Will be generated automatically if not passed in. |
| DATABASE_URI | Connection string for DB. | Will create and use a SQLite DB if not passed in. |
| DB_ENCRYPTION_KEY | Secret key for encrypting data. Length must be a multiple of 16.
*Warning*: If changed data will not be able to be decrypted! | Will be generated automatically if not passed in. |
-| PREVENT_SIGNUPS | Disable signup form? Anything in this variable will prevent signups. | |
+| PREVENT_SIGNUPS | Disable signup form? Anything in this variable will prevent signups. | False |
+| BASE_URL | Used when using a subfolder on a reverse proxy | None |
+| PUID | User ID (for folder permissions) | None |
+| PGID | Group ID (for folder permissions) | None |
#### Volumes
diff --git a/app/models.py b/app/models.py
index fb22b01..e373b47 100644
--- a/app/models.py
+++ b/app/models.py
@@ -51,6 +51,7 @@ class User(db.Model):
uuid = db.Column(GUID, primary_key=True, index=True, unique=True, default=lambda: uuid.uuid4())
username = db.Column(db.String(64), unique=True, nullable=False)
password_hash = db.Column(db.String(128), nullable=False)
+ auto_save = db.Column(db.Boolean, nullable=True)
notes = db.relationship('Note', lazy='dynamic', cascade='all, delete, delete-orphan')
meta = db.relationship('Meta', lazy='dynamic', cascade='all, delete, delete-orphan')
diff --git a/app/routes.py b/app/routes.py
index 50c426c..04c8d28 100644
--- a/app/routes.py
+++ b/app/routes.py
@@ -306,8 +306,34 @@ def sidebar_data():
tags = sorted(set([a.name for a in user.meta.filter_by(kind="tag").all()]), key=lambda s: s.lower())
projects = sorted(set([a.name for a in user.meta.filter_by(kind="project").all()]), key=lambda s: s.lower())
tasks = sorted([a.serialize for a in user.meta.filter_by(kind="task").all()], key=lambda task: task['note_id'])
+ auto_save = user.auto_save
- return jsonify(tags=tags,projects=projects,notes=notes,tasks=tasks), 200
+ return jsonify(tags=tags,projects=projects,notes=notes,tasks=tasks,auto_save=auto_save), 200
+
+
+@app.route('/api/toggle_auto_save', methods=['POST'])
+@jwt_required()
+def toggle_auto_save():
+ req = request.get_json()
+ auto_save = req.get('auto_save', False)
+
+ username = get_jwt_identity()
+
+ if not username:
+ abort(401)
+
+ user = User.query.filter_by(username=username.lower()).first()
+
+ if not user:
+ abort(400)
+
+ user.auto_save = auto_save
+
+ db.session.add(user)
+ db.session.flush()
+ db.session.commit()
+
+ return jsonify({}), 200
@app.route('/api/search', methods=['POST'])
@@ -365,7 +391,9 @@ def search():
cleaned_note['projects'] = sorted(set([x.name for x in note.meta.filter_by(kind="project").all()]), key=lambda s: s.lower())
notes.append(cleaned_note)
- return jsonify(notes=notes), 200
+ sorted_nodes = sorted(notes, key=lambda s: s['title'].lower())
+
+ return jsonify(notes=sorted_nodes), 200
@app.route('/', defaults={'path': ''})
diff --git a/client/package-lock.json b/client/package-lock.json
index d56e901..5d5399c 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "daily-notes",
- "version": "0.1.0",
+ "version": "1.0.0-beta.11",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -14910,4 +14910,4 @@
}
}
}
-}
+}
\ No newline at end of file
diff --git a/client/package.json b/client/package.json
index c51f79b..055d0f7 100644
--- a/client/package.json
+++ b/client/package.json
@@ -1,7 +1,12 @@
{
"name": "daily-notes",
- "version": "0.1.0",
+ "version": "1.0.0-beta.11",
"private": true,
+ "license": "MIT",
+ "repository": {
+ "url": "https://github.com/m0ngr31/DailyNotes"
+ },
+ "readme": "https://github.com/m0ngr31/DailyNotes/blob/master/README.md",
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
@@ -55,4 +60,4 @@
"git add"
]
}
-}
+}
\ No newline at end of file
diff --git a/client/src/components/Header.vue b/client/src/components/Header.vue
index 848308d..e0d9bb1 100644
--- a/client/src/components/Header.vue
+++ b/client/src/components/Header.vue
@@ -76,14 +76,16 @@
-
-
-
-
- Settings (coming soon)
+
+
+
+
+ {{ sidebar.autoSave ? 'Disable Auto-Save' : 'Enable Auto-Save' }}
+
+
Logout
diff --git a/client/src/services/requests.ts b/client/src/services/requests.ts
index 495874f..d6a550e 100644
--- a/client/src/services/requests.ts
+++ b/client/src/services/requests.ts
@@ -4,7 +4,9 @@ import {getToken, clearToken, setToken} from './user';
import router from '../router/index';
import {SharedBuefy} from './sharedBuefy';
-axios.defaults.baseURL = '/api';
+axios.defaults.baseURL = process.env.VUE_APP_BASE_URL
+ ? process.env.VUE_APP_BASE_URL
+ : '/api';
axios.interceptors.request.use(config => {
// Get token
diff --git a/client/src/services/sidebar.ts b/client/src/services/sidebar.ts
index ea2539b..f9962ae 100644
--- a/client/src/services/sidebar.ts
+++ b/client/src/services/sidebar.ts
@@ -17,6 +17,7 @@ class SidebarSerivce {
public projects: string[] = [];
public notes: INote[] = [];
public calLoading: boolean = false;
+ public autoSave: boolean = false;
public date: any = null;
public sidebarLoading: boolean = false;
public searchLoading: boolean = false;
@@ -99,6 +100,7 @@ class SidebarSerivce {
this.tasks = res.data.tasks;
this.projects = res.data.projects;
this.notes = res.data.notes;
+ this.autoSave = res.data.auto_save;
}
if (this.selectedSearch.length && this.searchString.length) {
@@ -138,6 +140,13 @@ class SidebarSerivce {
this.getSidebarInfo();
} catch (e) {}
}
+
+ public async toggleAutoSave(autoSave: boolean) {
+ try {
+ await Requests.post('/toggle_auto_save', {auto_save: autoSave});
+ this.getSidebarInfo();
+ } catch (e) {}
+ }
}
// Make it a singleton
diff --git a/client/src/views/Day.vue b/client/src/views/Day.vue
index 7039b4c..1a37939 100644
--- a/client/src/views/Day.vue
+++ b/client/src/views/Day.vue
@@ -231,12 +231,21 @@ export default class Day extends Vue {
this.unsavedChanges = true;
this.title = `* ${this.headerOptions.title}`;
this.headerOptions.saveDisabled = false;
+
+ if (this.sidebar.autoSave) {
+ this.autoSaveThrottle();
+ }
} else {
this.title = this.headerOptions.title;
this.headerOptions.saveDisabled = true;
}
}
+ public autoSaveThrottle = _.debounce(() => this.saveDay(), 3000, {
+ leading: false,
+ trailing: true
+ });
+
unsavedAlert(e: Event) {
if (this.unsavedChanges) {
// Attempt to modify event will trigger Chrome/Firefox alert msg
diff --git a/client/src/views/Home.vue b/client/src/views/Home.vue
index 720ef7d..0c50a31 100644
--- a/client/src/views/Home.vue
+++ b/client/src/views/Home.vue
@@ -1,14 +1,22 @@