Remove /api/notes endpoint
authorAdam Dullage <redacted>
Fri, 23 Sep 2022 11:33:45 +0000 (12:33 +0100)
committerAdam Dullage <redacted>
Fri, 23 Sep 2022 11:33:45 +0000 (12:33 +0100)
flatnotes/flatnotes.py
flatnotes/main.py
flatnotes/src/components/App.js
flatnotes/src/components/App.vue
flatnotes/src/components/NoteList.vue [deleted file]
flatnotes/src/components/RecentlyModified.vue [new file with mode: 0644]

index d514f1aa3a1c647abed9c6a4e713fac23780c8ec..2ea1bd43fa74cbffc1db3c4c9f7047b96e33abc8 100644 (file)
@@ -223,7 +223,7 @@ class Flatnotes(object):
             tags=tag_string,
         )
 
-    def get_notes(self) -> List[Note]:
+    def _get_notes(self) -> List[Note]:
         """Return a list containing a Note object for every file in the notes
         directory."""
         return [
@@ -262,7 +262,7 @@ class Flatnotes(object):
                 else:
                     indexed.add(idx_filename)
         # Add new
-        for note in self.get_notes():
+        for note in self._get_notes():
             if note.filename not in indexed:
                 self._add_note_to_index(writer, note)
                 logging.info(f"'{note.filename}' added to index")
index 8b29ac5dc33f47e87fc334d7615ff3c4136e3997..9c46a88500dbfe540aa1c032e2bb16bc77272bf0 100644 (file)
@@ -59,29 +59,6 @@ async def root(title: str = ""):
     return HTMLResponse(content=html)
 
 
-@app.get("/api/notes", response_model=List[NoteModel])
-async def get_notes(
-    start: int = 0,
-    limit: int = None,
-    sort: Literal["title", "lastModified"] = "title",
-    order: Literal["asc", "desc"] = "asc",
-    include_content: bool = False,
-    _: str = Depends(validate_token),
-):
-    """Get all notes."""
-    notes = flatnotes.get_notes()
-    notes.sort(
-        key=lambda note: note.last_modified
-        if sort == "lastModified"
-        else note.title,
-        reverse=order == "desc",
-    )
-    return [
-        NoteModel.dump(note, include_content=include_content)
-        for note in notes[start : None if limit is None else start + limit]
-    ]
-
-
 @app.post("/api/notes", response_model=NoteModel)
 async def post_note(data: NoteModel, _: str = Depends(validate_token)):
     """Create a new note."""
index 7644cf4f0c798895a942e6937e317f53481277d0..a3f3d1784e97c905f99abe6e40125a814e49aafe 100644 (file)
@@ -7,8 +7,8 @@ import Login from "./Login";
 import Logo from "./Logo";
 import Mousetrap from "mousetrap";
 import NavBar from "./NavBar";
-import NoteList from "./NoteList";
 import NoteViewerEditor from "./NoteViewerEditor";
+import RecentlyModified from "./RecentlyModified"
 import SearchInput from "./SearchInput";
 import SearchResults from "./SearchResults";
 
@@ -16,7 +16,6 @@ export default {
   name: "App",
 
   components: {
-    NoteList,
     LoadingIndicator,
     Login,
     NavBar,
@@ -24,6 +23,7 @@ export default {
     Logo,
     NoteViewerEditor,
     SearchResults,
+    RecentlyModified,
   },
 
   data: function() {
index fc3419a4ef83836e817502fdfea2bf847512bb37..71f84a74b39df4b62a5032999e9c56f0439860bb 100644 (file)
         :initial-value="searchTerm"
         class="search-input mb-4"
       ></SearchInput>
-      <NoteList
+      <RecentlyModified
         class="recently-modified"
-        mini-header="Recently Modified"
-        :num-recently-modified="5"
-        :show-loader="false"
-        centered
-      ></NoteList>
+        :max-notes="5"
+      ></RecentlyModified>
     </div>
 
     <!-- Search Results -->
diff --git a/flatnotes/src/components/NoteList.vue b/flatnotes/src/components/NoteList.vue
deleted file mode 100644 (file)
index 1a32b40..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-<template>
-  <div>
-    <!-- Loading -->
-    <div
-      v-if="notes == null || notes.length == 0"
-      class="h-100 d-flex flex-column justify-content-center"
-    >
-      <LoadingIndicator
-        :failed="loadingFailed"
-        :failedMessage="loadingFailedMessage"
-        :failedBootstrapIcon="loadingFailedIcon"
-        :show-loader="showLoader"
-      />
-    </div>
-
-    <!-- Notes Loaded -->
-    <div v-else>
-      <p
-        v-if="miniHeader"
-        class="mini-header mb-1"
-        :class="{ centered: centered }"
-      >
-        {{ miniHeader }}
-      </p>
-      <div
-        v-for="group in notesGrouped"
-        :key="group.name"
-        :class="{ centered: centered, 'mb-5': grouped }"
-      >
-        <p v-if="grouped" class="group-name">{{ group.name }}</p>
-        <a
-          v-for="note in group.notes"
-          :key="note.title"
-          class="d-flex justify-content-between align-items-center note-row"
-          :href="note.href"
-          @click.prevent="openNote(note.href, $event)"
-        >
-          <span>{{ note.title }}</span>
-          <span v-if="showLastModified" class="last-modified d-none d-md-block">
-            {{ note.lastModifiedAsString }}
-          </span>
-        </a>
-      </div>
-    </div>
-  </div>
-</template>
-
-<style lang="scss" scoped>
-@import "../colours";
-
-.centered {
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-}
-
-.mini-header {
-  text-transform: uppercase;
-  font-size: 12px;
-  font-weight: bold;
-  color: $very-muted-text;
-}
-
-.group-name {
-  padding-left: 8px;
-  font-weight: bold;
-  font-size: 32px;
-  color: $very-muted-text;
-}
-
-.note-row {
-  padding: 4px 8px;
-  margin: 2px 0;
-  border-radius: 4px;
-  &:hover {
-    background-color: $button-background;
-  }
-}
-
-a {
-  &:hover {
-    filter: none;
-    cursor: pointer;
-  }
-}
-
-.last-modified {
-  color: $muted-text;
-  font-size: 12px;
-}
-</style>
-
-<script>
-import * as constants from "../constants";
-
-import EventBus from "../eventBus";
-import LoadingIndicator from "./LoadingIndicator.vue";
-import { Note } from "../classes";
-import api from "../api";
-
-const alphaGroups = ["#", ...constants.alphabet];
-
-export default {
-  components: {
-    LoadingIndicator,
-  },
-
-  props: {
-    numRecentlyModified: { type: Number },
-    grouped: { type: Boolean, default: false },
-    showLastModified: { type: Boolean, default: false },
-    centered: { type: Boolean, default: false },
-    miniHeader: { type: String },
-    showLoader: { type: Boolean, default: true },
-  },
-
-  data: function () {
-    return {
-      notes: null,
-      loadingFailed: false,
-      loadingFailedMessage: "Failed to load notes",
-      loadingFailedIcon: null,
-    };
-  },
-
-  computed: {
-    notesGrouped: function () {
-      if (!this.grouped) {
-        return [{ name: "all", notes: this.notes }];
-      }
-
-      let notesGroupedDict = {};
-      alphaGroups.forEach(function (group) {
-        notesGroupedDict[group] = [];
-      });
-
-      this.notes.forEach(function (note) {
-        let firstCharUpper = note.title[0].toUpperCase();
-        if (constants.alphabet.includes(firstCharUpper)) {
-          notesGroupedDict[firstCharUpper].push(note);
-        } else {
-          notesGroupedDict["#"].push(note);
-        }
-      });
-
-      // Convert dict to an array skipping empty groups
-      let notesGroupedArray = [];
-      Object.entries(notesGroupedDict).forEach(function (item) {
-        if (item[1].length) {
-          notesGroupedArray.push({
-            name: item[0],
-            notes: item[1].sort(function (noteA, noteB) {
-              return noteA.title.localeCompare(noteB.title);
-            }),
-          });
-        }
-      });
-
-      // Ensure the array is ordered correctly
-      notesGroupedArray.sort(function (groupA, groupB) {
-        return groupA.name.localeCompare(groupB.name);
-      });
-
-      return notesGroupedArray;
-    },
-  },
-
-  methods: {
-    getNotes: function () {
-      let parent = this;
-      api
-        .get("/api/notes", {
-          params: {
-            limit: this.numRecentlyModified,
-            sort: "lastModified",
-            order: "desc",
-          },
-        })
-        .then(function (response) {
-          parent.notes = [];
-          if (response.data.length) {
-            response.data.forEach(function (note) {
-              parent.notes.push(new Note(note.title, note.lastModified));
-            });
-          } else {
-            parent.loadingFailedMessage =
-              "Click the 'New' button at the top of the page to add your first note";
-            parent.loadingFailedIcon = "pencil";
-            parent.loadingFailed = true;
-          }
-        })
-        .catch(function (error) {
-          parent.loadingFailed = true;
-          if (!error.handled) {
-            EventBus.$emit("unhandledServerError");
-          }
-        });
-    },
-
-    notesByTitle: function () {
-      return null;
-    },
-
-    openNote: function (href, event) {
-      EventBus.$emit("navigate", href, event);
-    },
-  },
-
-  created: function () {
-    this.getNotes();
-  },
-};
-</script>
diff --git a/flatnotes/src/components/RecentlyModified.vue b/flatnotes/src/components/RecentlyModified.vue
new file mode 100644 (file)
index 0000000..de23658
--- /dev/null
@@ -0,0 +1,109 @@
+<template>
+  <div>
+    <!-- Loading -->
+    <div
+      v-if="notes == null || notes.length == 0"
+      class="h-100 d-flex flex-column justify-content-center"
+    >
+      <LoadingIndicator
+        :failed="loadingFailed"
+        :failedMessage="loadingFailedMessage"
+        :failedBootstrapIcon="loadingFailedIcon"
+        :show-loader="showLoader"
+      />
+    </div>
+
+    <!-- Notes Loaded -->
+    <div v-else class="d-flex flex-column align-items-center">
+      <p class="mini-header mb-1">RECENTLY MODIFIED</p>
+      <a
+        v-for="note in notes"
+        :key="note.title"
+        class="bttn"
+        :href="note.href"
+        @click.prevent="openNote(note.href, $event)"
+      >
+        {{ note.title }}
+      </a>
+    </div>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+@import "../colours";
+
+.mini-header {
+  font-size: 12px;
+  font-weight: bold;
+  color: $very-muted-text;
+}
+</style>
+
+<script>
+import EventBus from "../eventBus";
+import LoadingIndicator from "./LoadingIndicator.vue";
+import { SearchResult } from "../classes";
+import api from "../api";
+
+export default {
+  components: {
+    LoadingIndicator,
+  },
+
+  props: {
+    maxNotes: { type: Number },
+  },
+
+  data: function () {
+    return {
+      notes: null,
+      loadingFailed: false,
+      loadingFailedMessage: "Failed to load notes",
+      loadingFailedIcon: null,
+    };
+  },
+
+  methods: {
+    getNotes: function () {
+      let parent = this;
+      this.loadingFailed = false;
+      api
+        .get("/api/search", {
+          params: {
+            term: "*",
+            sort: "lastModified",
+            order: "desc",
+            limit: this.maxNotes,
+          },
+        })
+        .then(function (response) {
+          parent.notes = [];
+          if (response.data.length) {
+            response.data.forEach(function (searchResult) {
+              parent.notes.push(new SearchResult(searchResult));
+            });
+          } else {
+            parent.loadingFailedMessage =
+              "Click the 'New' button at the top of the page to add your first note";
+            parent.loadingFailedIcon = "pencil";
+            parent.loadingFailed = true;
+          }
+        })
+        .catch(function (error) {
+          parent.loadingFailed = true;
+          if (!error.handled) {
+            EventBus.$emit("unhandledServerError");
+          }
+        });
+    },
+
+    openNote: function (href, event) {
+      EventBus.$emit("navigate", href, event);
+    },
+  },
+
+  created: function () {
+    this.getNotes();
+  },
+};
+</script>
git clone https://git.99rst.org/PROJECT