API Implemented in javascript. Currently just readonly functionality. No possibility to set user credentials

This commit is contained in:
Scharel Clemens 2018-10-16 23:52:28 +02:00
parent 4b9a83cfb8
commit 53b94e99e2
17 changed files with 195 additions and 93 deletions

View file

@ -0,0 +1,13 @@
[Desktop Entry]
Type=Application
X-Nemo-Application-Type=silica-qt5
Icon=harbour-nextcloudnotes
Exec=harbour-nextcloudnotes
Name=harbour-nextcloudnotes
# translation example:
# your app name in German locale (de)
#
# Remember to comment out the following line, if you do not want to use
# a different app name in German locale (de).
Name[de]=harbour-nextcloudnotes
Name[de_DE]=harbour-nextcloudnotes.desktop

View file

@ -0,0 +1,43 @@
# NOTICE:
#
# Application name defined in TARGET has a corresponding QML filename.
# If name defined in TARGET is changed, the following needs to be done
# to match new name:
# - corresponding QML filename must be changed
# - desktop icon filename must be changed
# - desktop filename must be changed
# - icon definition filename in desktop file must be changed
# - translation filenames have to be changed
# The name of your application
TARGET = harbour-nextcloudnotes
CONFIG += sailfishapp
SOURCES += src/harbour-nextcloudnotes.cpp
DISTFILES += qml/harbour-nextcloudnotes.qml \
qml/cover/CoverPage.qml \
qml/pages/FirstPage.qml \
qml/pages/NotesApi.qml \
rpm/harbour-nextcloudnotes.changes.in \
rpm/harbour-nextcloudnotes.changes.run.in \
rpm/harbour-nextcloudnotes.spec \
rpm/harbour-nextcloudnotes.yaml \
translations/*.ts \
harbour-nextcloudnotes.desktop \
qml/pages/NotePage.qml
SAILFISHAPP_ICONS = 86x86 108x108 128x128 172x172
# to disable building translations every time, comment out the
# following CONFIG line
CONFIG += sailfishapp_i18n
# German translation is enabled as an example. If you aren't
# planning to localize your app, remember to comment out the
# following TRANSLATIONS line. And also do not forget to
# modify the localized app name in the the .desktop file.
TRANSLATIONS += translations/harbour-nextcloudnotes-de.ts
HEADERS +=

View file

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

View file

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

View file

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View file

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View file

@ -9,21 +9,20 @@ ApplicationWindow
ConfigurationGroup {
id: appSettings
path: "/apps/harbour-nextcloud-notes/settings"
path: "/apps/harbour-nextcloudnotes/settings"
property string lastUpdate: qsTr("never")
property url nextcloudServer: "https://cloud.scharel.name"
property string username: "scharel"
property string password: ""
property url server: "https://cloud.scharel.name" + "/index.php/apps/notes/api/v0.2/notes"
property string username: "test"
property string password // TODO provide password before testing
}
property var notesModel: JSONListModel {
url: appSettings.nextcloudServer + "/index.php/apps/notes/api/v0.2/notes"
property var notes: NotesApi {
name: "notes"
saveFile: false
}
Connections {
target: notesModel
onLastUpdateChanged: appSettings.lastUpdate = notesModel.lastUpdate
target: notes
onLastUpdateChanged: appSettings.lastUpdate = notes.lastUpdate
}
initialPage: Component { FirstPage { } }

View file

@ -1,6 +1,5 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
//import harbour.nextcloudnotes 0.1
Page {
id: page
@ -10,7 +9,7 @@ Page {
anchors.fill: parent
PullDownMenu {
busy: notesModel.busy
busy: notes.busy
MenuItem {
text: qsTr("Settings")
onClicked: pageStack.push(Qt.resolvedUrl("Settings.qml"))
@ -20,42 +19,33 @@ Page {
onClicked: console.log("Add note")
}
MenuLabel {
text: qsTr("Last update") + ": " + appSettings.lastUpdate
text: qsTr("Last update") + ": " + new Date(appSettings.lastUpdate).toLocaleString(Qt.locale(), Locale.ShortFormat)
}
}
header: SearchField {
width: parent.width
placeholderText: qsTr("Nextcloud Notes")
onTextChanged: notesModel.search(text.toLowerCase())
onTextChanged: notes.search(text.toLowerCase())
EnterKey.iconSource: "image://theme/icon-m-enter-close"
EnterKey.onClicked: focus = false
enabled: notesModel.json.length > 0
enabled: notes.json.length > 0
}
currentIndex: -1
Component.onCompleted: notesModel.update()
Component.onCompleted: notes.getNotes()
//Component.onCompleted: notes.getNote("1212725")
//Component.onCompleted: notes.createNote("Hello World!", "Test")
//Component.onCompleted: notes.updateNote(1212725, "# Hello World!\nIs this working?", "Test")
//Component.onCompleted: notes.deleteNote(1212725)
model: notesModel
model: notes.model
delegate: ListItem {
id: note
contentHeight: Theme.itemSizeMedium
onClicked: {
pageStack.push(Qt.resolvedUrl("NotePage.qml"),
{id: id,
etag: etag,
modified: modified,
title: title,
category: category,
favorite: favorite,
content: content,
error: error,
errorMessage: errorMessage})
}
IconButton {
id: isFavoriteIcon
x: Theme.horizontalPageMargin
@ -66,6 +56,7 @@ Page {
onClicked: {
console.log("Toggle favorite")
favorite = !favorite
notes.updateNote(id, {'favorite': favorite} )
}
}
@ -86,11 +77,13 @@ Page {
anchors.leftMargin: Theme.paddingSmall
anchors.right: parent.right
anchors.top: parent.verticalCenter
text: new Date(modified * 1000).toLocaleDateString()
text: new Date(modified * 1000).toLocaleString(Qt.locale(), Locale.ShortFormat)
font.pixelSize: Theme.fontSizeExtraSmall
color: note.highlighted ? Theme.highlightColor : Theme.primaryColor
}
onClicked: pageStack.push(Qt.resolvedUrl("NotePage.qml"), { note: notesList.model.get(index) } )
menu: ContextMenu {
Text {
id: descriptionText
@ -114,17 +107,23 @@ Page {
section.criteria: ViewSection.FullString
section.labelPositioning: ViewSection.InlineLabels
section.delegate: SectionHeader {
text: section.empty ? qsTr("No category") : section
text: section
}
BusyIndicator {
id: busyIndicator
anchors.centerIn: parent
size: BusyIndicatorSize.Large
visible: notesList.count === 0
visible: notesList.count === 0 && notes.busy
running: visible
}
ViewPlaceholder {
enabled: notesList.count === 0 && !notes.busy
text: qsTr("No notes yet")
hintText: qsTr("Pull down to add a note")
}
VerticalScrollDecorator { flickable: notesList }
}
}

View file

@ -4,6 +4,8 @@ import Sailfish.Silica 1.0
Page {
id: page
property var note
property int id
property string etag
property date modified
@ -29,14 +31,13 @@ Page {
width: parent.width// - 2*x
PageHeader {
title: page.title
title: note.title
}
TextArea {
id: note
width: parent.width
readOnly: true
text: page.content
text: note.content
}
}
VerticalScrollDecorator {}

View file

@ -1,17 +1,87 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
import Nemo.Configuration 1.0
ListModel {
property url url
property string json
Item {
property string name
property var model: ListModel { }
property string json
property string file: StandardPaths.data + "/" + name + ".json"
property bool saveFile: false
property bool busy: false
property int status: 200
property date lastUpdate: new Date(0)
function callApi(method, data) {
busy = true
var endpoint = ""
if (data && (method === "GET" || method === "PUT" || method === "DELETE"))
if (data.id)
endpoint = "/" + data.id
var apiReq = new XMLHttpRequest
apiReq.open(method, appSettings.server + endpoint, true)
apiReq.setRequestHeader('User-Agent', 'SailfishOS/harbour-lidderbuch')
apiReq.setRequestHeader('OCS-APIRequest', 'true')
apiReq.setRequestHeader("Content-Type", "application/json");
apiReq.setRequestHeader("Authorization", "Basic " + Qt.btoa(appSettings.username + ":" + appSettings.password))
apiReq.onreadystatechange = function() {
if (apiReq.readyState === XMLHttpRequest.DONE) {
if (apiReq.status === 200) {
console.log("Successfull request!")
console.log(apiReq.responseText)
// TODO handle non arrays
var elements = JSON.parse(apiReq.responseText)
for (var element in elements) {
model.append(elements[element])
}
}
else if (apiReq.status === 404) {
console.log("Note does not exist!")
}
else {
console.log("Unknown error: " + apiReq.statusText + " (" + apiReq.status + ")")
}
busy = false
}
}
if (method === "GET") {
apiReq.send()
}
else if (method === "POST" || method === "PUT" || method === "DELETE") {
apiReq.send(JSON.stringify(data))
}
else {
console.log("Unsupported method: " + method)
apiReq.abort()
}
}
function getNotes() {
callApi("GET")
}
function getNote(id) {
if (id)
callApi("GET", { 'id': id } )
}
function createNote(data) {
callApi("POST", data)
}
function updateNote(id, data) {
if (id) {
data.id = id
callApi("PUT", data)
}
}
function deleteNote(id) {
if (id)
callApi("DELETE", { 'id': id } )
}
onJsonChanged: refresh()
function flush() {
@ -19,7 +89,7 @@ ListModel {
var filePut = new XMLHttpRequest
filePut.open("PUT", file)
filePut.send(json)
clear()
model.clear()
lastUpdate = new Date(0)
status = 200
}
@ -29,7 +99,7 @@ ListModel {
}
function search(query) {
clear()
model.clear()
var elements = parseJson()
for (var element in elements) {
elements[element].section = ""
@ -40,7 +110,7 @@ ListModel {
}
}
if (query === "" || match)
append(elements[element])
model.append(elements[element])
}
}
@ -53,43 +123,12 @@ ListModel {
return null
}
else {
clear()
model.clear()
return elements
}
}
function update() {
busy = true
var apiReq = new XMLHttpRequest
apiReq.open("GET", url, true)//, appSettings.username, appSettings.password)
apiReq.setRequestHeader('User-Agent', 'SailfishOS/harbour-lidderbuch')
apiReq.setRequestHeader('OCS-APIRequest', 'true')
apiReq.setRequestHeader("Authorization", "Basic " + Qt.btoa(appSettings.username + ":" + appSettings.password))
apiReq.onreadystatechange = function() {
if (apiReq.readyState === XMLHttpRequest.DONE) {
if (apiReq.status === 200) {
console.log("Successfully loaded " + url)
json = apiReq.responseText
//console.log(json)
if (saveFile) {
var filePut = new XMLHttpRequest
filePut.open("PUT", file)
filePut.send(json)
}
lastUpdate = new Date()
}
else {
console.log("Error loading " + url + " - " + apiReq.status)
//lastUpdate = new Date(0)
}
status = apiReq.status
busy = false
}
}
apiReq.send()
}
Component.onCompleted: {
/*Component.onCompleted: {
if (saveFile) {
if (name === "") {
saveFile = false
@ -113,5 +152,5 @@ ListModel {
fileReq.send()
}
}
}
}*/
}

View file

@ -1,4 +1,4 @@
# Rename this file as harbour-nextcloud-notes.changes to include changelog
# Rename this file as harbour-nextcloudnotes.changes to include changelog
# entries in your RPM file.
#
# Add new changelog entries following the format below.
@ -7,7 +7,7 @@
#
# Alternatively, if your changelog is automatically generated (e.g. with
# the git-change-log command provided with Sailfish OS SDK), create a
# harbour-nextcloud-notes.changes.run script to let mb2 run the required commands for you.
# harbour-nextcloudnotes.changes.run script to let mb2 run the required commands for you.
# * date Author's Name <author's email> version-release
# - Summary of changes

View file

@ -1,6 +1,6 @@
#!/bin/bash
#
# Rename this file as harbour-nextcloud-notes.changes.run to let mb2 automatically
# Rename this file as harbour-nextcloudnotes.changes.run to let mb2 automatically
# generate changelog from well formatted Git commit messages and tag
# annotations.

View file

@ -3,7 +3,7 @@
# Generated by: spectacle version 0.27
#
Name: harbour-nextcloud-notes
Name: harbour-nextcloudnotes
# >> macros
# << macros
@ -19,7 +19,7 @@ Group: Qt/Qt
License: LICENSE
URL: http://example.org/
Source0: %{name}-%{version}.tar.bz2
Source100: harbour-nextcloud-notes.yaml
Source100: harbour-nextcloudnotes.yaml
Requires: sailfishsilica-qt5 >= 0.10.9
BuildRequires: pkgconfig(sailfishapp) >= 1.0.2
BuildRequires: pkgconfig(Qt5Core)

View file

@ -1,4 +1,4 @@
Name: harbour-nextcloud-notes
Name: harbour-nextcloudnotes
Summary: Nextcloud Notes
Version: 0.1
Release: 1

View file

@ -8,16 +8,16 @@ int main(int argc, char *argv[])
{
QGuiApplication* app = SailfishApp::application(argc, argv);
app->setApplicationDisplayName("Nextcloud Notes");
app->setApplicationName("harbour-nextcloud-notes");
app->setApplicationName("harbour-nextcloudnotes");
app->setApplicationVersion("0.1");
app->setOrganizationDomain("https://github.com/scharel");
app->setOrganizationName("harbour-nextcloud-notes");
app->setOrganizationName("harbour-nextcloudnotes");
qDebug() << app->applicationDisplayName() << app->applicationVersion();
QQuickView* view = SailfishApp::createView();
view->setSource(SailfishApp::pathTo("qml/harbour-nextcloud-notes.qml"));
view->setSource(SailfishApp::pathTo("qml/harbour-nextcloudnotes.qml"));
view->show();
return app->exec();

View file

@ -18,6 +18,10 @@
<source>Add note</source>
<translation>Neue Notiz</translation>
</message>
<message>
<source>Last update</source>
<translation>Zuletzt aktualisiert</translation>
</message>
<message>
<source>Nextcloud Notes</source>
<translation>Nextcloud Notizen</translation>
@ -27,16 +31,16 @@
<translation>Löschen</translation>
</message>
<message>
<source>No category</source>
<translation>Ohne Kategorie</translation>
<source>No notes yet</source>
<translatio>Noch keine Notizen</translation>
</message>
<message>
<source>Last update</source>
<translation>Zuletzt aktualisiert</translation>
<source>Pull down to add a note</source>
<translation>Herunterziehen um eine neue Notiz zu erzeugen</translation>
</message>
</context>
<context>
<name>harbour-nextcloud-notes</name>
<name>harbour-nextcloudnotes</name>
<message>
<source>never</source>
<translation>noch nie</translation>

View file

@ -18,6 +18,10 @@
<source>Add note</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Last update</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Nextcloud Notes</source>
<translation type="unfinished"></translation>
@ -27,16 +31,16 @@
<translation type="unfinished"></translation>
</message>
<message>
<source>No category</source>
<source>No notes yet</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Last update</source>
<source>Pull down to add a note</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>harbour-nextcloud-notes</name>
<name>harbour-nextcloudnotes</name>
<message>
<source>never</source>
<translation type="unfinished"></translation>