Initial commmit

This commit is contained in:
Marcel Kapfer (mmk2410) 2016-06-02 12:01:32 +02:00
commit ff749d68b6
18 changed files with 534 additions and 0 deletions

35
.gitignore vendored Normal file
View File

@ -0,0 +1,35 @@
node_modules
# See https://www.dartlang.org/tools/private-files.html
# Files and directories created by pub
.buildlog
.packages
.project
.pub/
build/
**/packages/
# Files created by dart2js
# (Most Dart developers will use pub build to compile Dart, use/modify these
# rules if you intend to use dart2js directly
# Convention is to use extension '.dart.js' for Dart compiled to Javascript to
# differentiate from explicit Javascript files)
*.dart.js
*.part.js
*.js.deps
*.js.map
*.info.json
# Directory created by dartdoc
doc/api/
# Don't commit pubspec lock file
# (Library packages only! Remove pattern if developing an application package)
pubspec.lock
web/packages
# IDE files
.idea/
*.iml
.atom/
completer.hist

3
.jshintrc Normal file
View File

@ -0,0 +1,3 @@
{
"esversion": 6
}

6
AUTHORS Normal file
View File

@ -0,0 +1,6 @@
# Here is a list of people that have contributed to this project
# Please keep this form:
#
# Name / Organization <email address>
Marcel Kapfer <marcelmichaelkapfer@yahoo.co.nz>

17
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,17 @@
# Contributing
If you want to contribute have a look at the project board at [phab.mmk2410.org](https://phab.mmk2410.org/project/view/19/) to see what you should do.
## Workflow
While there is no stable release this project will follow the feature workflow. As soon as there is a stable release I will switch to the Gitflow workflow.
If your unfamiliar with these workflows I recommend reading [this article](https://www.atlassian.com/git/tutorials/comparing-workflows/forking-workflow/).
## Contact
If you want to ask me some questions, feel free to contact me at (marcelmichaelkapfer@yahoo.co.nz)[mailto:marcelmichaelkapfer@yahoo.co.nz].
## Honor
Please add yourself to the AUTHORS file.

22
LICENSE.txt Normal file
View File

@ -0,0 +1,22 @@
COPYRIGHT (c) 2016 Marcel Kapfer (mmk2410)
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

7
README.md Normal file
View File

@ -0,0 +1,7 @@
# Rangitaki Desktop Client
This is the Rangitaki desktop client made with Dart, Polymer and Electron.
***It is not fully developed and misses many features. The content of this repository is right now only for development purposes, but not for any productive usage.***
For contributing see the CONTRIBUTING.md.

3
bcli.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/bash
rlwrap /bin/bash ./run.sh

20
pubspec.yaml Normal file
View File

@ -0,0 +1,20 @@
name: rangitakidesktop
version: 0.0.1
description: >
Desktop app for Rangitaki
author: Marcel Kapfer (mmk2410) <marcelmichaelkapfer@yahoo.co.nz>
homepage: https://mmk2410.org/rangitaki/rangitaki-desktop/
documentation: https://mmk2410.org/rangitaki/rangitaki-lib/docs/
dependencies:
browser: '>=0.10.0 <0.11.0'
http: '^0.11.3+7'
polymer_elements: ^1.0.0-rc.8
polymer: ^1.0.0-rc.2
web_components: ^0.12.0
test: "^0.12.13+4"
transformers:
- polymer:
entry_points:
- web/index.html

44
run.sh Normal file
View File

@ -0,0 +1,44 @@
#!/bin/bash
while true; do
echo -n " (BCLI) > "
read -r command
case $command in
build | b ) pub build & ;;
run | r )
killall -q electron
electron build/web/ &
;;
bar | br )
killall -q electron
pub build
electron build/web/ &
;;
get | g) pub get ;;
close | c) killall -q electron ;;
test | t) pub run test;;
lint | l)
jshint web/main.js
jshint web/renderer.js
dartanalyzer web/
;;
exit | quit | q | x | e)
exit ;;
about ) echo "mmk2410 - Build CLI script - MIT License" ;;
help | h | ? )
echo """
run, r Close running instances and run Electron in background
build, b Build app in background
bar, br Short for build and run
test, t Run tests.
close, c Exit running Electron instances
exit, quit, q, x, e Exit the script
about About text
get, g Get updates.
help, h, ? Prints this help
"""
;;
* ) echo "Command $command not found." ;;
esac
done

119
web/api.dart Normal file
View File

@ -0,0 +1,119 @@
import 'dart:async';
import 'dart:html';
import 'dart:convert';
import 'package:polymer_elements/paper_item.dart';
import 'article-view.dart';
/**
* Easily connects with the Rangitaki API and does also a part of the frontend.
*/
class RangitakiConnect {
String baseurl;
String _username;
String _password;
String _auth;
/**
* Initializer for RangitaiConnect.
* @value baseurl Root URL of your Rangitaki installation.
* @value username Username for authentication.
* @value password Password for authentication.
*/
RangitakiConnect(this.baseurl, this._username, this._password) {
_auth = BASE64.encode(UTF8.encode("$_username:$_password"));
}
/**
* Fetch all blogs from the server and list them in the #list element.
*/
Future addBlogs() async {
var data = await _getBlogs();
data = JSON.decode(data);
for (String blog in data) {
blog = blog.substring(0, blog.length - 3);
PaperItem item = new PaperItem();
item.text = blog;
item.id = blog;
querySelector("#main-list").children.add(item);
}
}
/**
* Fetch all articles of a blog from the server and list the in the #list
* element.
* @value blog Blog for which the articles shoul be fetched.
*/
Future addArticles(String blog) async {
var data = await _getArticles(blog);
data = JSON.decode(data);
for (String article in data) {
article = article.substring(0, article.length - 3);
PaperItem item = new PaperItem();
item.text = article;
item.id = article;
querySelector("#main-list").children.add(item);
}
}
Future showArticle(String blog, String post, ArticleView articleView) async {
var data = await _getArticle(blog, post);
print(data);
data = JSON.decode(data);
List tags = data['tags'];
String tag = tags.join(", ");
print("Tags: $tag");
print("ArticleView: $articleView");
articleView
..title = data['title']
..author = data['author']
..date = data['date']
..tags = tag
..text = data['text'];
}
/**
* Internal method for fetching blogs from the server.
*/
Future _getBlogs() async {
String _url = "$baseurl/rcc/api/list/";
return (await
HttpRequest.request(
_url, withCredentials: true,
requestHeaders: {'authorization' : 'Basic $_auth'}
)).responseText;
}
/**
* Internal method for fetching articles of blog from the server.
*/
Future _getArticles(String blog) async {
String _url = "$baseurl/rcc/api/list/?blog=$blog";
return (await
HttpRequest.request(
_url, withCredentials: true,
requestHeaders: {'authorization' : 'Basic $_auth'}
)).responseText;
}
Future _getArticle(blog, post) async {
print("Blog: $blog");
print("Post: $post");
String _url = "$baseurl/rcc/api/post/?blog=$blog&post=$post.md";
print("URL: $_url");
return (await
HttpRequest.request(_url, withCredentials: true,
requestHeaders: {'authorization' : 'Basic $_auth'}
)).responseText;
}
}

18
web/article-view.dart Normal file
View File

@ -0,0 +1,18 @@
@HtmlImport('article_view.html')
library mmk2410_rangitaki_app.article_view;
import 'package:polymer/polymer.dart';
import 'package:web_components/web_components.dart' show HtmlImport;
@PolymerRegister('article-view')
class ArticleView extends PolymerElement {
ArticleView.created() : super.created();
@property
String title;
String author;
String date;
String text;
String tags;
}

16
web/article_view.html Normal file
View File

@ -0,0 +1,16 @@
<dom-module id="article-view">
<style>
/* css rules */
</style>
<template>
<paper-material elevation="1">
<paper-input label="Title" value="{{title}}"></paper-input>
<paper-input label="Date" value="{{date}}"></paper-input>
<paper-input label="Author" value="{{author}}"></paper-input>
<paper-input label="Tags" value="{{tags}}"></paper-input>
<paper-autogrow-textarea id="a1">
<textarea id="t1" value="{{text}}"></textarea>
<paper-autogrow-textarea>
</paper-material>
</template>
</dom-module>

61
web/index.dart Normal file
View File

@ -0,0 +1,61 @@
/**
* @author Marcel Kapfer (mmk2410) <marcelmichaelkapfer@yahoo.co.nz>
* Library for easily working with the Rangitaki API in your browswer.
*/
library mmk2410_rangitaki_app.index;
import 'dart:html';
import 'dart:async';
import 'package:polymer/polymer.dart';
import 'api.dart';
import 'article-view.dart';
export 'article-view.dart';
export 'package:polymer/init.dart';
final String username = "";
final String pwd = "";
final String baseurl = "";
RangitakiConnect rcc;
Element itemList;
ArticleView articleView;
String currentBlog;
main() async {
await initPolymer();
print("Starting...");
rcc = new RangitakiConnect(baseurl, username, pwd);
await rcc.addBlogs();
itemList = querySelector("#main-list");
for (Element item in itemList.children) {
item.onClick.listen(blogSelected);
}
articleView = querySelector("articlev-iew");
}
Future blogSelected(Event e) async {
Element element = e.target;
itemList.children.clear();
currentBlog = element.id;
await rcc.addArticles(element.id);
for (Element item in itemList.children) {
item.onClick.listen(articleSelected);
}
}
Future articleSelected(Event e) async {
Element element = e.target;
await rcc.showArticle(currentBlog, element.id, articleView);
itemList.hidden = true;
articleView.hidden = false;
}

57
web/index.html Normal file
View File

@ -0,0 +1,57 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Rangitaki</title>
<!--Polymer-->
<link rel="import" href="packages/polymer_elements/paper_header_panel.html">
<link rel="import" href="packages/polymer_elements/paper_drawer_panel.html">
<link rel="import" href="packages/polymer_elements/paper_toolbar.html">
<link rel="import"
href="packages/polymer_elements/paper_icon_button.html">
<link rel="import"
href="packages/polymer_elements/paper_material.html">
<link rel="import" href="packages/polymer_elements/paper_menu.html">
<link rel="import" href="packages/polymer_elements/paper_item.html">
<link rel="import" href="packages/polymer_elements/iron_icons.html">
<link rel="import" href="packages/polymer_elements/paper_textarea.html"
<link rel="import" href="article_view.html">
</head>
<body unresolved class="fullbleed layout vertical">
<paper-drawer-panel>
<paper-header-panel drawer>
<paper-toolbar class="medium-tall">
<span>Menu</span>
</paper-toolbar>
<paper-menu selected="0">
<paper-item>Blogs</paper-item>
<paper-item>Articles</paper-item>
<paper-item>Media</paper-item>
<paper-item>Settings</paper-item>
</paper-menu>
</paper-header-panel>
<paper-header-panel main>
<paper-toolbar>
<paper-icon-button icon="menu" paper-drawer-toggle></paper-icon-button>
<div class="appname title">Rangitaki</div>
</paper-toolbar>
<paper-material elevation="1">
<div role="listbox" id="main-list"></div>
</paper-material>
<article-view hidden></article-view>
</paper-header-panel>
</paper-drawer-panel>
<script type="application/dart" src="index.dart"></script>
<!-- support for non-Dart browsers -->
<link rel="import" href="style.html" />
<script src="packages/browser/dart.js"></script>
</body>
</html>

53
web/main.js Normal file
View File

@ -0,0 +1,53 @@
const electron = require('electron');
// Module to control application life.
const app = electron.app;
// Module to create native browser window.
const BrowserWindow = electron.BrowserWindow;
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({width: 1000, height: 800});
// and load the index.html of the app.
mainWindow.loadURL(`file://${__dirname}/index.html`);
// Open the DevTools.
mainWindow.webContents.openDevTools();
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null;
});
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow);
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow();
}
});
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

23
web/package.json Normal file
View File

@ -0,0 +1,23 @@
{
"name": "rangitaki-desktop",
"version": "0.0.1",
"description": "Rangtaki desktop app made with Dart, Polymer and Electron",
"main": "main.js",
"scripts": {
"start": "electron main.js"
},
"repository": {
"type": "git",
"url": "git+https://gitlab.com/mmk2410/rangitaki-desktop.git"
},
"keywords": [
"Rangitaki",
"desktop"
],
"author": "Marcel Kapfer (mmk2410)",
"license": "MIT",
"homepage": "https://gitlab.com/mmk2410/rangitaki-desktop",
"devDependencies": {
"electron-prebuilt": "^1.0.1"
}
}

3
web/renderer.js Normal file
View File

@ -0,0 +1,3 @@
// This file is required by the index.html file and will
// be executed in the renderer process for that window.
// All of the Node.js APIs are available in this process.

27
web/style.html Normal file
View File

@ -0,0 +1,27 @@
<style is="custom-style">
:root {
--primary-text-color: var(--paper-grey-900);
--primary-background-color: #ffffff;
--secondary-text-color: #737373;
--disabled-text-color: #9b9b9b;
--divider-color: #dbdbdb;
--primary-color: #ff4415;
--light-primary-color: #ff4415;
--dark-primary-color: #ff4415;
--accent-color: var(--paper-pink-a200);
--light-accent-color: var(--paper-pink-a100);
--dark-accent-color: var(--paper-pink-a400);
/* Components */
/* paper-drawer-panel */
--drawer-menu-color: #ffffff;
--drawer-border-color: 1px solid #ccc;
--drawer-toolbar-border-color: 1px solid rgba(0, 0, 0, 0.22);
/* paper-menu */
--paper-menu-background-color: #fff;
--menu-link-color: #111111;
}
paper-toolbar {
background-color: var(--primary-color);
}
</style>