浏览代码

[FIX] angular 4 version

robert2206 7 年之前
父节点
当前提交
bc3e548100

+ 1 - 0
.gitignore

@@ -32,3 +32,4 @@ $RECYCLE.BIN/
 .DS_Store
 Thumbs.db
 UserInterfaceState.xcuserstate
+yarn.lock

+ 81 - 51
config.xml

@@ -1,60 +1,90 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <widget id="com.eiru.odoo" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
-  <name>Odoo Mobile</name>
-  <description>An awesome Ionic/Cordova app.</description>
-  <author email="robert.gauto@gmail.com" href="http://ionicframework.com/">Robert Alexis Gauto</author>
-  <content src="index.html"/>
-  <access origin="*"/>
-  <allow-navigation href="http://ionic.local/*"/>
-  <allow-intent href="http://*/*"/>
-  <allow-intent href="https://*/*"/>
-  <allow-intent href="tel:*"/>
-  <allow-intent href="sms:*"/>
-  <allow-intent href="mailto:*"/>
-  <allow-intent href="geo:*"/>
-  <platform name="android">
-    <allow-intent href="market:*"/>
-    <icon src="resources/android/icon/drawable-ldpi-icon.png" density="ldpi"/>
-    <icon src="resources/android/icon/drawable-mdpi-icon.png" density="mdpi"/>
-    <icon src="resources/android/icon/drawable-hdpi-icon.png" density="hdpi"/>
-    <icon src="resources/android/icon/drawable-xhdpi-icon.png" density="xhdpi"/>
-    <icon src="resources/android/icon/drawable-xxhdpi-icon.png" density="xxhdpi"/>
-    <icon src="resources/android/icon/drawable-xxxhdpi-icon.png" density="xxxhdpi"/>
-    <splash src="resources/android/splash/drawable-land-ldpi-screen.png" density="land-ldpi"/>
-    <splash src="resources/android/splash/drawable-land-mdpi-screen.png" density="land-mdpi"/>
-    <splash src="resources/android/splash/drawable-land-hdpi-screen.png" density="land-hdpi"/>
-    <splash src="resources/android/splash/drawable-land-xhdpi-screen.png" density="land-xhdpi"/>
-    <splash src="resources/android/splash/drawable-land-xxhdpi-screen.png" density="land-xxhdpi"/>
-    <splash src="resources/android/splash/drawable-land-xxxhdpi-screen.png" density="land-xxxhdpi"/>
-    <splash src="resources/android/splash/drawable-port-ldpi-screen.png" density="port-ldpi"/>
-    <splash src="resources/android/splash/drawable-port-mdpi-screen.png" density="port-mdpi"/>
-    <splash src="resources/android/splash/drawable-port-hdpi-screen.png" density="port-hdpi"/>
-    <splash src="resources/android/splash/drawable-port-xhdpi-screen.png" density="port-xhdpi"/>
-    <splash src="resources/android/splash/drawable-port-xxhdpi-screen.png" density="port-xxhdpi"/>
-    <splash src="resources/android/splash/drawable-port-xxxhdpi-screen.png" density="port-xxxhdpi"/>
-  </platform>
+    <name>Odoo Mobile</name>
+    <description>An awesome Ionic/Cordova app.</description>
+    <author email="robert.gauto@gmail.com" href="http://ionicframework.com/">Robert Alexis Gauto</author>
+    <content src="index.html"/>
+    <access origin="*"/>
+    <allow-navigation href="http://ionic.local/*"/>
+    <allow-intent href="http://*/*"/>
+    <allow-intent href="https://*/*"/>
+    <allow-intent href="tel:*"/>
+    <allow-intent href="sms:*"/>
+    <allow-intent href="mailto:*"/>
+    <allow-intent href="geo:*"/>
+
+    <preference name="webviewbounce" value="false"/>
+    <preference name="UIWebViewBounce" value="false"/>
+    <preference name="DisallowOverscroll" value="true"/>
+    <preference name="android-minSdkVersion" value="16"/>
+    <preference name="BackupWebStorage" value="none"/>
+    <preference name="SplashMaintainAspectRatio" value="true"/>
+    <preference name="FadeSplashScreenDuration" value="300"/>
+
+    <preference name="SplashShowOnlyFirstTime" value="false"/>
+    <preference name="SplashScreen" value="screen"/>
+    <preference name="SplashScreenDelay" value="3000"/>
+
+   <platform name="android">
+        <allow-intent href="market:*"/>
+        <icon src="resources/android/icon/drawable-ldpi-icon.png" density="ldpi"/>
+        <icon src="resources/android/icon/drawable-mdpi-icon.png" density="mdpi"/>
+        <icon src="resources/android/icon/drawable-hdpi-icon.png" density="hdpi"/>
+        <icon src="resources/android/icon/drawable-xhdpi-icon.png" density="xhdpi"/>
+        <icon src="resources/android/icon/drawable-xxhdpi-icon.png" density="xxhdpi"/>
+        <icon src="resources/android/icon/drawable-xxxhdpi-icon.png" density="xxxhdpi"/>
+        <splash src="resources/android/splash/drawable-land-ldpi-screen.png" density="land-ldpi"/>
+        <splash src="resources/android/splash/drawable-land-mdpi-screen.png" density="land-mdpi"/>
+        <splash src="resources/android/splash/drawable-land-hdpi-screen.png" density="land-hdpi"/>
+        <splash src="resources/android/splash/drawable-land-xhdpi-screen.png" density="land-xhdpi"/>
+        <splash src="resources/android/splash/drawable-land-xxhdpi-screen.png" density="land-xxhdpi"/>
+        <splash src="resources/android/splash/drawable-land-xxxhdpi-screen.png" density="land-xxxhdpi"/>
+        <splash src="resources/android/splash/drawable-port-ldpi-screen.png" density="port-ldpi"/>
+        <splash src="resources/android/splash/drawable-port-mdpi-screen.png" density="port-mdpi"/>
+        <splash src="resources/android/splash/drawable-port-hdpi-screen.png" density="port-hdpi"/>
+        <splash src="resources/android/splash/drawable-port-xhdpi-screen.png" density="port-xhdpi"/>
+        <splash src="resources/android/splash/drawable-port-xxhdpi-screen.png" density="port-xxhdpi"/>
+        <splash src="resources/android/splash/drawable-port-xxxhdpi-screen.png" density="port-xxxhdpi"/>
+    </platform>
+
   <platform name="ios">
-    <allow-intent href="itms:*"/>
-    <allow-intent href="itms-apps:*"/>
-  </platform>
-  <preference name="webviewbounce" value="false"/>
-  <preference name="UIWebViewBounce" value="false"/>
-  <preference name="DisallowOverscroll" value="true"/>
-  <preference name="android-minSdkVersion" value="16"/>
-  <preference name="BackupWebStorage" value="none"/>
-  <preference name="SplashMaintainAspectRatio" value="true"/>
-  <preference name="FadeSplashScreenDuration" value="300"/>
-  <preference name="SplashShowOnlyFirstTime" value="false"/>
-  <preference name="SplashScreen" value="screen"/>
-  <preference name="SplashScreenDelay" value="3000"/>
-  <feature name="StatusBar">
-    <param name="ios-package" onload="true" value="CDVStatusBar"/>
-  </feature>
+        <allow-intent href="itms:*"/>
+        <allow-intent href="itms-apps:*"/>
+        <icon src="resources/ios/icon/icon.png" width="57" height="57"/>
+        <icon src="resources/ios/icon/icon@2x.png" width="114" height="114"/>
+        <icon src="resources/ios/icon/icon-40.png" width="40" height="40"/>
+        <icon src="resources/ios/icon/icon-40@2x.png" width="80" height="80"/>
+        <icon src="resources/ios/icon/icon-40@3x.png" width="120" height="120"/>
+        <icon src="resources/ios/icon/icon-50.png" width="50" height="50"/>
+        <icon src="resources/ios/icon/icon-50@2x.png" width="100" height="100"/>
+        <icon src="resources/ios/icon/icon-60.png" width="60" height="60"/>
+        <icon src="resources/ios/icon/icon-60@2x.png" width="120" height="120"/>
+        <icon src="resources/ios/icon/icon-60@3x.png" width="180" height="180"/>
+        <icon src="resources/ios/icon/icon-72.png" width="72" height="72"/>
+        <icon src="resources/ios/icon/icon-72@2x.png" width="144" height="144"/>
+        <icon src="resources/ios/icon/icon-76.png" width="76" height="76"/>
+        <icon src="resources/ios/icon/icon-76@2x.png" width="152" height="152"/>
+        <icon src="resources/ios/icon/icon-83.5@2x.png" width="167" height="167"/>
+        <icon src="resources/ios/icon/icon-small.png" width="29" height="29"/>
+        <icon src="resources/ios/icon/icon-small@2x.png" width="58" height="58"/>
+        <icon src="resources/ios/icon/icon-small@3x.png" width="87" height="87"/>
+        <splash src="resources/ios/splash/Default-568h@2x~iphone.png" width="640" height="1136"/>
+        <splash src="resources/ios/splash/Default-667h.png" width="750" height="1334"/>
+        <splash src="resources/ios/splash/Default-736h.png" width="1242" height="2208"/>
+        <splash src="resources/ios/splash/Default-Landscape-736h.png" width="2208" height="1242"/>
+        <splash src="resources/ios/splash/Default-Landscape@2x~ipad.png" width="2048" height="1536"/>
+        <splash src="resources/ios/splash/Default-Landscape@~ipadpro.png" width="2732" height="2048"/>
+        <splash src="resources/ios/splash/Default-Landscape~ipad.png" width="1024" height="768"/>
+        <splash src="resources/ios/splash/Default-Portrait@2x~ipad.png" width="1536" height="2048"/>
+        <splash src="resources/ios/splash/Default-Portrait@~ipadpro.png" width="2048" height="2732"/>
+        <splash src="resources/ios/splash/Default-Portrait~ipad.png" width="768" height="1024"/>
+        <splash src="resources/ios/splash/Default@2x~iphone.png" width="640" height="960"/>
+        <splash src="resources/ios/splash/Default~iphone.png" width="320" height="480"/>
+    </platform>
   <plugin name="ionic-plugin-keyboard" spec="~2.2.1"/>
   <plugin name="cordova-plugin-whitelist" spec="1.3.1"/>
   <plugin name="cordova-plugin-console" spec="1.0.5"/>
-  <plugin name="cordova-plugin-statusbar" spec="2.2.1"/>
+  <plugin name="cordova-plugin-statusbar" spec="2.2.2"/>
   <plugin name="cordova-plugin-device" spec="1.1.4"/>
   <plugin name="cordova-plugin-splashscreen" spec="~4.0.1"/>
-  <icon src="resources/android/icon/drawable-xhdpi-icon.png"/>
 </widget>

文件差异内容过多而无法显示
+ 81 - 1417
package-lock.json


+ 22 - 32
package.json

@@ -6,47 +6,37 @@
   "scripts": {
     "clean": "ionic-app-scripts clean",
     "build": "ionic-app-scripts build",
+    "lint": "ionic-app-scripts lint",
     "ionic:build": "ionic-app-scripts build",
     "ionic:serve": "ionic-app-scripts serve"
   },
   "dependencies": {
-    "@angular/common": "2.4.8",
-    "@angular/compiler": "2.4.8",
-    "@angular/compiler-cli": "2.4.8",
-    "@angular/core": "2.4.8",
-    "@angular/forms": "2.4.8",
-    "@angular/http": "2.4.8",
-    "@angular/platform-browser": "2.4.8",
-    "@angular/platform-browser-dynamic": "2.4.8",
-    "@angular/platform-server": "2.4.8",
-    "@ionic-native/core": "3.1.0",
-    "@ionic-native/splash-screen": "3.1.0",
-    "@ionic-native/status-bar": "3.1.0",
-    "@ionic/storage": "2.0.0",
-    "angular2-odoo-jsonrpc": "0.0.7",
-    "font-awesome": "^4.7.0",
-    "ionic-angular": "2.3.0",
+    "@angular/common": "4.1.3",
+    "@angular/compiler": "4.1.3",
+    "@angular/compiler-cli": "4.1.3",
+    "@angular/core": "4.1.3",
+    "@angular/forms": "4.1.3",
+    "@angular/http": "4.1.3",
+    "@angular/platform-browser": "4.1.3",
+    "@angular/platform-browser-dynamic": "4.1.3",
+    "@ionic-native/core": "3.12.1",
+    "@ionic-native/splash-screen": "3.12.1",
+    "@ionic-native/status-bar": "3.12.1",
+    "@ionic/storage": "2.0.1",
+    "ionic-angular": "3.5.0",
     "ionicons": "3.0.0",
     "moment": "^2.18.1",
-    "pouchdb": "^6.1.2",
-    "pouchdb-find": "^0.10.5",
-    "rxjs": "5.0.1",
+    "pouchdb": "^6.2.0",
+    "pouchdb-find": "^6.2.0",
+    "rxjs": "5.4.0",
     "slugid": "^1.1.0",
-    "sw-toolbox": "3.4.0",
-    "zone.js": "0.7.2"
+    "sw-toolbox": "3.6.0",
+    "zone.js": "0.8.12"
   },
   "devDependencies": {
-    "@ionic/app-scripts": "1.1.4",
-    "typescript": "2.0.9"
+    "@ionic/app-scripts": "^1.3.12",
+    "@ionic/cli-plugin-ionic-angular": "^1.3.1",
+    "typescript": "2.3.4"
   },
-  "cordovaPlugins": [
-    "cordova-plugin-console",
-    "cordova-plugin-statusbar",
-    "cordova-plugin-whitelist",
-    "cordova-plugin-device",
-    "cordova-plugin-splashscreen",
-    "ionic-plugin-keyboard"
-  ],
-  "cordovaPlatforms": [],
   "description": "myApp: An Ionic project"
 }

+ 6 - 3
src/app/app.component.ts

@@ -1,6 +1,7 @@
 import { Component, ViewChild } from '@angular/core';
 import { Nav, Platform, Loading, LoadingController, AlertController } from 'ionic-angular';
-import { StatusBar, Splashscreen } from 'ionic-native';
+import { StatusBar } from '@ionic-native/status-bar';
+import { SplashScreen } from '@ionic-native/splash-screen';
 
 import { LoginPage } from "../pages/login/login";
 import { HomePage } from "../pages/home/home";
@@ -29,6 +30,8 @@ export class MyApp {
 
     constructor(
         public platform: Platform,
+        public statusBar: StatusBar,
+        public splashScreen: SplashScreen,
         public loadingCtrl: LoadingController,
         public alertCtrl: AlertController
     ) {
@@ -146,8 +149,8 @@ export class MyApp {
      */
     initializeApp() {
         this.platform.ready().then(() => {
-            StatusBar.styleDefault();
-            Splashscreen.hide();
+            this.statusBar.styleDefault();
+            this.statusBar.hide();
 
             EventsManager.subscribe("app:loading", data => { 
                 if (data) {

+ 12 - 3
src/app/app.module.ts

@@ -1,6 +1,11 @@
+import { BrowserModule } from "@angular/platform-browser";
 import { NgModule, ErrorHandler } from "@angular/core";
+import { HttpModule } from "@angular/http";
 import { ReactiveFormsModule } from "@angular/forms";
 import { IonicApp, IonicModule, IonicErrorHandler } from "ionic-angular";
+import { StatusBar } from '@ionic-native/status-bar';
+import { SplashScreen } from '@ionic-native/splash-screen';
+
 import { MyApp } from "./app.component";
 
 // Components
@@ -28,7 +33,7 @@ import { LeadPage } from "../pages/lead/lead";
 import { PhonecallPage } from "../pages/phonecall/phonecall";
 
 // Services
-import { OdooRPCService } from "angular2-odoo-jsonrpc";
+import { RPCService } from "../services/rpc-service";
 import { AuthService } from "../services/auth-service";
 import { OdooService } from "../services/odoo-service";
 import { PouchService } from "../services/pouch-service";
@@ -72,8 +77,10 @@ import { DoubleTap } from "../directives/double-tap";
         DoubleTap
     ],
     imports: [
+        BrowserModule,
+        HttpModule,
+        ReactiveFormsModule,
         IonicModule.forRoot(MyApp),
-        ReactiveFormsModule
     ],
     bootstrap: [IonicApp],
     entryComponents: [
@@ -98,7 +105,9 @@ import { DoubleTap } from "../directives/double-tap";
         AboutPage,
     ],
     providers: [
-        OdooRPCService,
+        StatusBar,
+        SplashScreen,
+        RPCService,
         AuthService,
         OdooService,
         PouchService,

+ 2 - 1
src/declarations.d.ts

@@ -11,4 +11,5 @@
   For more info on type definition files, check out the Typescript docs here:
   https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html
 */
-declare module '*';
+declare module '*';
+declare var global: any;

+ 2 - 2
src/services/auth-service.ts

@@ -1,7 +1,7 @@
 import { Injectable } from "@angular/core";
 import { Observable } from "rxjs/Observable";
 
-import { OdooRPCService } from "angular2-odoo-jsonrpc";
+import { RPCService } from "./rpc-service";
 import { PouchService } from "./pouch-service";
 import { SyncService } from "./sync-service";
 
@@ -13,7 +13,7 @@ import "rxjs/add/operator/concat"
 export class AuthService {
 
     constructor(
-        public odooRPC: OdooRPCService,
+        public odooRPC: RPCService,
         public pouch: PouchService,
         public sync: SyncService
     ) { }

+ 40 - 0
src/services/cookies.ts

@@ -0,0 +1,40 @@
+export class Cookies {
+    private sessionId: string;
+
+    constructor() {
+        this.sessionId = null;
+    }
+
+    /**
+     * 
+     */
+    deleteSessionId(): void {
+        this.sessionId = null;
+        document.cookie = "session_id=; expires=Wed, 29 Jun 2016 00:00:00 UTC";
+    }
+
+    /**
+     * 
+     */
+    getSessionId(): string {
+        return document
+            .cookie
+            .split("; ")
+            .filter(x => {
+                return x.indexOf("session_id") === 0;
+            })
+            .map(x => {
+                return x.split("=")[1];
+            })
+            .pop() || this.sessionId || "";
+    }
+
+    /**
+     * 
+     */
+    setSessionId(value: string): void {
+        document.cookie = `session_id=${value}`;
+        this.sessionId = value
+    }
+
+}

+ 2 - 2
src/services/odoo-service.ts

@@ -1,6 +1,6 @@
 import { Injectable } from "@angular/core";
-import { OdooRPCService } from "angular2-odoo-jsonrpc";
 import { Observable } from "rxjs/Observable";
+import { RPCService } from "./rpc-service";
 
 import "rxjs/add/observable/fromPromise";
 
@@ -8,7 +8,7 @@ import "rxjs/add/observable/fromPromise";
 export class OdooService {
 
     constructor(
-        private odooRPC: OdooRPCService
+        private odooRPC: RPCService
     ) { }
 
     /**

+ 7 - 3
src/services/pouch-service.ts

@@ -1,16 +1,16 @@
 import { Injectable } from "@angular/core";
 import { Observable } from "rxjs/Observable";
 import { Observer } from "rxjs/Observer";
-import PouchDB from "pouchdb";
-
+import * as PouchDB from "pouchdb";
 import * as PouchFind from "pouchdb-find";
 
+PouchDB.plugin(PouchFind);
+
 import "rxjs/add/observable/throw";
 import "rxjs/add/observable/fromPromise";
 import "rxjs/add/observable/from";
 import "rxjs/add/operator/concatMap";
 
-PouchDB.plugin(PouchFind);
 
 @Injectable()
 export class PouchService {
@@ -30,6 +30,10 @@ export class PouchService {
             auto_compaction: true
         });
 
+        console.log(this.pouchDB);
+        
+        
+
         return Observable.fromPromise(this.pouchDB.createIndex({
             index: {
                 fields: ['odoo_model']

+ 295 - 0
src/services/rpc-service.ts

@@ -0,0 +1,295 @@
+import { Injectable, Inject } from "@angular/core"
+import { Http, Headers } from "@angular/http"
+import { Cookies } from "./cookies"
+
+import "rxjs/add/operator/toPromise";
+
+@Injectable()
+export class RPCService {
+    private server: string;
+    private httpAuth: string;
+    private cookies: Cookies;
+    private uniqueId: number;
+    private shouldManageSessionId: boolean;
+    private context: Object;
+    private headers: Headers;
+
+    constructor(@Inject(Http) private http: Http) {
+        this.cookies = new Cookies();
+        this.uniqueId = 0;
+        this.shouldManageSessionId = false;
+        this.context = JSON.parse(localStorage.getItem("user_context")) || {
+            "lang": "en_US"
+        };
+    }
+
+    /**
+     * 
+     * @param url 
+     * @param params 
+     */
+    private createRequest(url: string, params: any): any {
+        this.uniqueId += 1;
+
+        if (this.shouldManageSessionId) {
+            params.session_id = this.cookies.getSessionId();
+        }
+
+        this.headers = new Headers({
+            "Content-Type": "application/json",
+            "X-Openerp-Session-Id": this.cookies.getSessionId(),
+            "Authorization": "Basic " + btoa(`${this.httpAuth}`)
+        });
+
+        let data = {
+            jsonrpc: "2.0",
+            method: "call",
+            params
+        }
+
+        return JSON.stringify(data);
+    }
+
+    /**
+     * 
+     * @param response 
+     */
+    private handleResponse(response: any): Promise<any> {
+        response = response.json();
+
+        if (!response.error) {
+            return response.result;
+        }
+
+        let error = response.error;
+        let trace = {
+            title: "   ",
+            message: "",
+            fultrace: error
+        }
+
+        if (error.code === 200 && error.message === "Odoo Server Error" && error.data.name === "werkzeug.exceptions.NotFound") {
+            trace.title = "page_not_found";
+            trace.message = "HTTP Error";
+        } else if ( (error.code === 100 && error.message === "Odoo Session Expired") || (error.code === 300 && error.message === "OpenERP WebClient Error" && error.data.debug.match("SessionExpiredException"))) {
+            trace.title = "session_expired";
+            this.cookies.deleteSessionId();
+        } else if ( (error.message === "Odoo Server Error" && /FATAL:  database "(.+)" does not exist/.test(error.data.message))) {
+            trace.title = "database_not_found";
+            trace.message = error.data.message;
+        } else if (error.data.name === "openerp.exceptions.AccessError") {
+            trace.title = "AccessError";
+            trace.message = error.data.message;
+        } else {
+            let split = ("" + error.data.fault_code).split("\n")[0].split(" -- ");
+            if (split.length > 1) {
+                error.type = split.shift();
+                error.data.fault_code = error.data.fault_code.substr(error.type.length + 4);
+            }
+
+            if (error.code === 200 && error.type) {
+                trace.title = error.type;
+                trace.message = error.data.fault_code.replace(/\n/g, "<br />");
+            } else {
+                trace.title = error.message;
+                trace.message = error.data.debug.replace(/\n/g, "<br />");
+            }
+        }
+
+        return Promise.reject(trace);
+    }
+
+    /**
+     * 
+     * @param error 
+     */
+    private handleErrors(error: any): Promise<any> {
+        return Promise.reject(error.message || error);
+    }
+
+    /**
+     * 
+     * @param configuration 
+     */
+    public init(configuration: any): void {
+        this.server = configuration.server;
+        this.httpAuth = configuration.http_auth || null;
+    }
+
+    /**
+     * 
+     * @param server 
+     */
+    public setServer(server: string): void {
+        this.server = server;
+    }
+
+    /**
+     * 
+     * @param httpAuth 
+     */
+    public setHttpAuth(httpAuth: string): void {
+        this.httpAuth = httpAuth;
+    }
+
+    /**
+     * 
+     * @param url 
+     * @param params 
+     */
+    public sendRequest(url: string, params: Object): Promise<any> {
+        let options = this.createRequest(url, params);
+
+        return this.http.post(this.server + url, options, { headers: this.headers })
+            .toPromise()
+            .then(this.handleResponse)
+            .catch(this.handleErrors);
+    }
+
+    /**
+     * 
+     */
+    public getServerInfo(): Promise<any> {
+        return this.sendRequest("/web/webclient/version_info", {});
+    }
+
+    /**
+     * 
+     */
+    public getSessionInfo(): Promise<any> {
+        return this.sendRequest("/web/session/get_session_info", {});
+    }
+
+    /**
+     * 
+     * @param db 
+     * @param login 
+     * @param password 
+     */
+    public login(db: string, login: string, password: string): any {
+        let params = {
+            db,
+            login,
+            password
+        }
+
+        return this.sendRequest("/web/session/authenticate", params).then(result => {
+            if (!result.uid) {
+                this.cookies.deleteSessionId();
+
+                return Promise.reject({
+                    title: "wrong_login",
+                    message: "Username and password don't match",
+                    fulltrace: result
+                });
+            }
+
+            this.context = result.user_context;
+            localStorage.setItem("user_context", JSON.stringify(this.context));
+
+            this.cookies.setSessionId(result.session_id);
+
+            return result;
+        });    
+    }
+
+    /**
+     * 
+     * @param force 
+     */
+    public isLoggedIn(force: boolean = true): Promise<any> {
+        if (!force) {
+            return Promise.resolve(this.cookies.getSessionId.length > 0);
+        }
+
+        return this.getSessionInfo().then(result => {
+            this.cookies.setSessionId(result.session_id);
+            return !!result.uid;
+        });
+    }
+
+    /**
+     * 
+     * @param force 
+     */
+    public logout(force: boolean = true): Promise<any> {
+        this.cookies.deleteSessionId();
+
+        if (force) {
+            return this.getServerInfo().then(response => {
+                if (!!response.db) {
+                    return this.login(response.db, "", "");
+                }
+            })
+        }
+
+        return Promise.resolve();
+    }
+
+    /**
+     * 
+     */
+    public databaseList(): Promise<any> {
+        return this.sendRequest("/web/database/get_list", {});
+    }
+
+    /**
+     * 
+     * @param model 
+     * @param domain 
+     * @param fields 
+     * @param limit 
+     */
+    public searchRead(model: string, domain: any, fields: any, limit?: number): Promise<any> {
+        let params = {
+            model,
+            domain,
+            fields,
+            limit,
+            context: this.context
+        }
+
+        return this.sendRequest("/web/dataset/search_read", params);
+    }
+
+    /**
+     * 
+     * @param context 
+     */
+    public updateContext(context: any): void {
+        localStorage.setItem("user_context", JSON.stringify(context));
+        let args = [[(<any>this.context).uid], context];
+        this.call("res.users", "write", args, {})
+            .then( () => this.context = context)
+            .catch((err: any) => this.context = context);
+    }
+
+    /**
+     * 
+     */
+    public getContext(): any {
+        return this.context;
+    }
+
+    /**
+     * 
+     * @param model 
+     * @param method 
+     * @param args 
+     * @param kwargs 
+     */
+    public call(model: string, method: string, args: any, kwargs?: any): Promise<any> {
+        kwargs = kwargs || {};
+        kwargs.context = kwargs.context || {};
+        Object.assign(kwargs.context, this.context);
+
+        let params = {
+            model,
+            method,
+            args,
+            kwargs
+        }
+
+        return this.sendRequest("/web/dataset/call_kw", params);
+    }
+}

+ 0 - 1
src/services/sync-service.ts

@@ -1,6 +1,5 @@
 import { Injectable } from "@angular/core";
 import { Observable } from "rxjs/Observable";
-// import { Observer } from "rxjs/Observer";
 
 import { PouchService } from "./pouch-service";
 import { OdooService } from "../services/odoo-service";

+ 0 - 1
src/theme/variables.scss

@@ -14,4 +14,3 @@ $colors: (
 @import "ionic.ionicons";
 @import "roboto";
 @import "noto-sans";
-@import "font-awesome";

部分文件因为文件数量过多而无法显示