├── .browserslistrc ├── .env.example ├── .eslintrc.js ├── .gitignore ├── .npmrc ├── README.md ├── android ├── .gitignore ├── .idea │ ├── .gitignore │ ├── compiler.xml │ ├── jarRepositories.xml │ ├── misc.xml │ └── runConfigurations.xml ├── app │ ├── .gitignore │ ├── build.gradle │ ├── capacitor.build.gradle │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── getcapacitor │ │ │ └── myapp │ │ │ └── ExampleInstrumentedTest.java │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── assets │ │ │ ├── capacitor.config.json │ │ │ └── capacitor.plugins.json │ │ ├── java │ │ │ └── io │ │ │ │ └── ionic │ │ │ │ └── starter │ │ │ │ └── MainActivity.java │ │ └── res │ │ │ ├── drawable-land-hdpi │ │ │ └── splash.png │ │ │ ├── drawable-land-mdpi │ │ │ └── splash.png │ │ │ ├── drawable-land-xhdpi │ │ │ └── splash.png │ │ │ ├── drawable-land-xxhdpi │ │ │ └── splash.png │ │ │ ├── drawable-land-xxxhdpi │ │ │ └── splash.png │ │ │ ├── drawable-port-hdpi │ │ │ └── splash.png │ │ │ ├── drawable-port-mdpi │ │ │ └── splash.png │ │ │ ├── drawable-port-xhdpi │ │ │ └── splash.png │ │ │ ├── drawable-port-xxhdpi │ │ │ └── splash.png │ │ │ ├── drawable-port-xxxhdpi │ │ │ └── splash.png │ │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── drawable │ │ │ ├── ic_launcher_background.xml │ │ │ └── splash.png │ │ │ ├── layout │ │ │ └── activity_main.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── values │ │ │ ├── ic_launcher_background.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ │ └── xml │ │ │ ├── config.xml │ │ │ └── file_paths.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── getcapacitor │ │ └── myapp │ │ └── ExampleUnitTest.java ├── build.gradle ├── capacitor.settings.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── variables.gradle ├── babel.config.js ├── capacitor.config.json ├── cypress.json ├── db.json ├── ionic.config.json ├── jest.config.js ├── package.json ├── public ├── assets │ ├── icon │ │ ├── favicon.png │ │ └── icon.png │ └── shapes.svg └── index.html ├── src ├── App.vue ├── components │ ├── PageForm.vue │ └── PageIndex.vue ├── data │ ├── DataSource.ts │ └── Manager.ts ├── database.ts ├── main.ts ├── router │ └── index.ts ├── schemas │ ├── category.ts │ ├── contact.ts │ └── tag.ts ├── shims-vue.d.ts ├── theme │ └── variables.css └── views │ ├── categories │ ├── Form.vue │ └── Index.vue │ └── contacts │ ├── Form.vue │ └── Index.vue ├── tests ├── e2e │ ├── .eslintrc.js │ ├── plugins │ │ └── index.js │ ├── specs │ │ └── test.js │ └── support │ │ ├── commands.js │ │ └── index.js └── unit │ └── example.spec.ts └── tsconfig.json /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | not ie 11 -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | NODE_ENV=development 2 | 3 | VUE_APP_HOST=localhost 4 | VUE_APP_PORT=3000 5 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | 'node': true, 5 | 'vue/setup-compiler-macros': true 6 | }, 7 | 'extends': [ 8 | 'plugin:vue/vue3-essential', 9 | 'eslint:recommended', 10 | '@vue/typescript/recommended' 11 | ], 12 | parserOptions: { 13 | ecmaVersion: 2020 14 | }, 15 | rules: { 16 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 17 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 18 | 'vue/multi-word-component-names': 'off', 19 | 'vue/no-deprecated-slot-attribute': 'off', 20 | '@typescript-eslint/no-explicit-any': 'off', 21 | }, 22 | overrides: [ 23 | { 24 | files: [ 25 | '**/__tests__/*.{j,t}s?(x)', 26 | '**/tests/unit/**/*.spec.{j,t}s?(x)' 27 | ], 28 | env: { 29 | jest: true 30 | } 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Specifies intentionally untracked files to ignore when using Git 2 | # http://git-scm.com/docs/gitignore 3 | 4 | *~ 5 | *.sw[mnpcod] 6 | .tmp 7 | *.tmp 8 | *.tmp.* 9 | *.sublime-project 10 | *.sublime-workspace 11 | .DS_Store 12 | .env 13 | Thumbs.db 14 | UserInterfaceState.xcuserstate 15 | $RECYCLE.BIN/ 16 | 17 | *.log 18 | log.txt 19 | npm-debug.log* 20 | package-lock.json 21 | 22 | /.idea 23 | /.ionic 24 | /.sass-cache 25 | /.sourcemaps 26 | /.versions 27 | /.vscode 28 | /coverage 29 | /dist 30 | /node_modules 31 | /platforms 32 | /plugins 33 | /www 34 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ionic Vue Offline First - RxDB 2 | 3 | This is an example of Ionic Vue offline first project using [RxDB](https://rxdb.info/). 4 | 5 | ## Running 6 | 7 | `npm run serve` 8 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | # Using Android gitignore template: https://github.com/github/gitignore/blob/HEAD/Android.gitignore 2 | 3 | # Built application files 4 | *.apk 5 | *.aar 6 | *.ap_ 7 | *.aab 8 | 9 | # Files for the ART/Dalvik VM 10 | *.dex 11 | 12 | # Java class files 13 | *.class 14 | 15 | # Generated files 16 | bin/ 17 | gen/ 18 | out/ 19 | # Uncomment the following line in case you need and you don't have the release build type files in your app 20 | # release/ 21 | 22 | # Gradle files 23 | .gradle/ 24 | build/ 25 | 26 | # Local configuration file (sdk path, etc) 27 | local.properties 28 | 29 | # Proguard folder generated by Eclipse 30 | proguard/ 31 | 32 | # Log Files 33 | *.log 34 | 35 | # Android Studio Navigation editor temp files 36 | .navigation/ 37 | 38 | # Android Studio captures folder 39 | captures/ 40 | 41 | # IntelliJ 42 | *.iml 43 | .idea/workspace.xml 44 | .idea/tasks.xml 45 | .idea/gradle.xml 46 | .idea/assetWizardSettings.xml 47 | .idea/dictionaries 48 | .idea/libraries 49 | # Android Studio 3 in .gitignore file. 50 | .idea/caches 51 | .idea/modules.xml 52 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you 53 | .idea/navEditor.xml 54 | 55 | # Keystore files 56 | # Uncomment the following lines if you do not want to check your keystore files in. 57 | #*.jks 58 | #*.keystore 59 | 60 | # External native build folder generated in Android Studio 2.2 and later 61 | .externalNativeBuild 62 | .cxx/ 63 | 64 | # Google Services (e.g. APIs or Firebase) 65 | # google-services.json 66 | 67 | # Freeline 68 | freeline.py 69 | freeline/ 70 | freeline_project_description.json 71 | 72 | # fastlane 73 | fastlane/report.xml 74 | fastlane/Preview.html 75 | fastlane/screenshots 76 | fastlane/test_output 77 | fastlane/readme.md 78 | 79 | # Version control 80 | vcs.xml 81 | 82 | # lint 83 | lint/intermediates/ 84 | lint/generated/ 85 | lint/outputs/ 86 | lint/tmp/ 87 | # lint/reports/ 88 | 89 | # Android Profiling 90 | *.hprof 91 | 92 | # Cordova plugins for Capacitor 93 | capacitor-cordova-android-plugins 94 | 95 | # Copied web assets 96 | app/src/main/assets/public 97 | -------------------------------------------------------------------------------- /android/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /android/.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /android/.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | -------------------------------------------------------------------------------- /android/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /android/.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /android/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build/* 2 | !/build/.npmkeep 3 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion rootProject.ext.compileSdkVersion 5 | defaultConfig { 6 | applicationId "io.ionic.starter" 7 | minSdkVersion rootProject.ext.minSdkVersion 8 | targetSdkVersion rootProject.ext.targetSdkVersion 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 12 | aaptOptions { 13 | // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. 14 | // Default: https://android.googlesource.com/platform/frameworks/base/+/282e181b58cf72b6ca770dc7ca5f91f135444502/tools/aapt/AaptAssets.cpp#61 15 | ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~' 16 | } 17 | } 18 | buildTypes { 19 | release { 20 | minifyEnabled false 21 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 22 | } 23 | } 24 | } 25 | 26 | repositories { 27 | flatDir{ 28 | dirs '../capacitor-cordova-android-plugins/src/main/libs', 'libs' 29 | } 30 | } 31 | 32 | dependencies { 33 | implementation fileTree(include: ['*.jar'], dir: 'libs') 34 | implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion" 35 | implementation project(':capacitor-android') 36 | testImplementation "junit:junit:$junitVersion" 37 | androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion" 38 | androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion" 39 | implementation project(':capacitor-cordova-android-plugins') 40 | } 41 | 42 | apply from: 'capacitor.build.gradle' 43 | 44 | try { 45 | def servicesJSON = file('google-services.json') 46 | if (servicesJSON.text) { 47 | apply plugin: 'com.google.gms.google-services' 48 | } 49 | } catch(Exception e) { 50 | logger.info("google-services.json not found, google-services plugin not applied. Push Notifications won't work") 51 | } 52 | -------------------------------------------------------------------------------- /android/app/capacitor.build.gradle: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN 2 | 3 | android { 4 | compileOptions { 5 | sourceCompatibility JavaVersion.VERSION_1_8 6 | targetCompatibility JavaVersion.VERSION_1_8 7 | } 8 | } 9 | 10 | apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle" 11 | dependencies { 12 | implementation project(':capacitor-community-sqlite') 13 | implementation project(':capacitor-app') 14 | implementation project(':capacitor-haptics') 15 | implementation project(':capacitor-keyboard') 16 | implementation project(':capacitor-status-bar') 17 | implementation project(':capacitor-storage') 18 | 19 | } 20 | 21 | 22 | if (hasProperty('postBuildExtras')) { 23 | postBuildExtras() 24 | } 25 | -------------------------------------------------------------------------------- /android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.getcapacitor.myapp; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import android.content.Context; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | import androidx.test.platform.app.InstrumentationRegistry; 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * @see Testing documentation 15 | */ 16 | @RunWith(AndroidJUnit4.class) 17 | public class ExampleInstrumentedTest { 18 | 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 23 | 24 | assertEquals("com.getcapacitor.app", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 33 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /android/app/src/main/assets/capacitor.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "appId": "io.ionic.starter", 3 | "appName": "ionic-offline", 4 | "webDir": "dist", 5 | "bundledWebRuntime": false 6 | } 7 | -------------------------------------------------------------------------------- /android/app/src/main/assets/capacitor.plugins.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "pkg": "@capacitor-community/sqlite", 4 | "classpath": "com.getcapacitor.community.database.sqlite.CapacitorSQLitePlugin" 5 | }, 6 | { 7 | "pkg": "@capacitor/app", 8 | "classpath": "com.capacitorjs.plugins.app.AppPlugin" 9 | }, 10 | { 11 | "pkg": "@capacitor/haptics", 12 | "classpath": "com.capacitorjs.plugins.haptics.HapticsPlugin" 13 | }, 14 | { 15 | "pkg": "@capacitor/keyboard", 16 | "classpath": "com.capacitorjs.plugins.keyboard.KeyboardPlugin" 17 | }, 18 | { 19 | "pkg": "@capacitor/status-bar", 20 | "classpath": "com.capacitorjs.plugins.statusbar.StatusBarPlugin" 21 | }, 22 | { 23 | "pkg": "@capacitor/storage", 24 | "classpath": "com.capacitorjs.plugins.storage.StoragePlugin" 25 | } 26 | ] 27 | -------------------------------------------------------------------------------- /android/app/src/main/java/io/ionic/starter/MainActivity.java: -------------------------------------------------------------------------------- 1 | package io.ionic.starter; 2 | 3 | import com.getcapacitor.BridgeActivity; 4 | 5 | public class MainActivity extends BridgeActivity {} 6 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-land-hdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/drawable-land-hdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-land-mdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/drawable-land-mdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-land-xhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/drawable-land-xhdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-land-xxhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/drawable-land-xxhdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-land-xxxhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/drawable-land-xxxhdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-port-hdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/drawable-port-hdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-port-mdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/drawable-port-mdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-port-xhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/drawable-port-xhdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-port-xxhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/drawable-port-xxhdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-port-xxxhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/drawable-port-xxxhdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/drawable/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFF 4 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | ionic-offline 4 | ionic-offline 5 | io.ionic.starter 6 | io.ionic.starter 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | 12 | 17 | 18 | 19 | 22 | -------------------------------------------------------------------------------- /android/app/src/main/res/xml/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /android/app/src/main/res/xml/file_paths.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.getcapacitor.myapp; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import org.junit.Test; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | 14 | @Test 15 | public void addition_isCorrect() throws Exception { 16 | assertEquals(4, 2 + 2); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | 5 | repositories { 6 | google() 7 | jcenter() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:4.2.1' 11 | classpath 'com.google.gms:google-services:4.3.5' 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | apply from: "variables.gradle" 19 | 20 | allprojects { 21 | repositories { 22 | google() 23 | jcenter() 24 | } 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /android/capacitor.settings.gradle: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN 2 | include ':capacitor-android' 3 | project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor') 4 | 5 | include ':capacitor-community-sqlite' 6 | project(':capacitor-community-sqlite').projectDir = new File('../node_modules/@capacitor-community/sqlite/android') 7 | 8 | include ':capacitor-app' 9 | project(':capacitor-app').projectDir = new File('../node_modules/@capacitor/app/android') 10 | 11 | include ':capacitor-haptics' 12 | project(':capacitor-haptics').projectDir = new File('../node_modules/@capacitor/haptics/android') 13 | 14 | include ':capacitor-keyboard' 15 | project(':capacitor-keyboard').projectDir = new File('../node_modules/@capacitor/keyboard/android') 16 | 17 | include ':capacitor-status-bar' 18 | project(':capacitor-status-bar').projectDir = new File('../node_modules/@capacitor/status-bar/android') 19 | 20 | include ':capacitor-storage' 21 | project(':capacitor-storage').projectDir = new File('../node_modules/@capacitor/storage/android') 22 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | 19 | # AndroidX package structure to make it clearer which packages are bundled with the 20 | # Android operating system, and which are packaged with your app's APK 21 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 22 | android.useAndroidX=true 23 | # Automatically convert third-party libraries to use AndroidX 24 | android.enableJetifier=true 25 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | include ':capacitor-cordova-android-plugins' 3 | project(':capacitor-cordova-android-plugins').projectDir = new File('./capacitor-cordova-android-plugins/') 4 | 5 | apply from: 'capacitor.settings.gradle' -------------------------------------------------------------------------------- /android/variables.gradle: -------------------------------------------------------------------------------- 1 | ext { 2 | minSdkVersion = 21 3 | compileSdkVersion = 30 4 | targetSdkVersion = 30 5 | androidxActivityVersion = '1.2.0' 6 | androidxAppCompatVersion = '1.2.0' 7 | androidxCoordinatorLayoutVersion = '1.1.0' 8 | androidxCoreVersion = '1.3.2' 9 | androidxFragmentVersion = '1.3.0' 10 | junitVersion = '4.13.1' 11 | androidxJunitVersion = '1.1.2' 12 | androidxEspressoCoreVersion = '3.3.0' 13 | cordovaAndroidVersion = '7.0.0' 14 | } -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /capacitor.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "appId": "io.ionic.starter", 3 | "appName": "ionic-vue-rxdb", 4 | "webDir": "dist", 5 | "bundledWebRuntime": false 6 | } 7 | -------------------------------------------------------------------------------- /cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "pluginsFile": "tests/e2e/plugins/index.js" 3 | } 4 | -------------------------------------------------------------------------------- /ionic.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ionic-offline", 3 | "integrations": { 4 | "capacitor": {} 5 | }, 6 | "type": "vue" 7 | } 8 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: '@vue/cli-plugin-unit-jest/presets/typescript-and-babel', 3 | transformIgnorePatterns: ['/node_modules/(?!@ionic/vue|@ionic/vue-router|@ionic/core|@stencil/core|ionicons)'] 4 | } 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ionic-vue-rxdb", 3 | "version": "0.0.1", 4 | "private": true, 5 | "description": "Offline fist ionic project", 6 | "scripts": { 7 | "serve": "npm-run-all --parallel serve:json serve:app", 8 | "serve:app": "vue-cli-service serve", 9 | "serve:json": "json-server --host 0.0.0.0 --watch db.json", 10 | "build": "vue-cli-service build", 11 | "test:unit": "vue-cli-service test:unit", 12 | "test:e2e": "vue-cli-service test:e2e", 13 | "lint": "vue-cli-service lint" 14 | }, 15 | "dependencies": { 16 | "@capacitor-community/sqlite": "^5.0.4", 17 | "@capacitor/android": "5.1.1", 18 | "@capacitor/app": "5.0.5", 19 | "@capacitor/core": "^5.1.1", 20 | "@capacitor/haptics": "5.0.5", 21 | "@capacitor/keyboard": "5.0.5", 22 | "@capacitor/preferences": "^5.0.5", 23 | "@capacitor/status-bar": "5.0.5", 24 | "@ionic/vue": "^7.1.1", 25 | "@ionic/vue-router": "^7.1.1", 26 | "axios": "^1.4.0", 27 | "core-js": "^3.31.0", 28 | "dexie": "^3.2.4", 29 | "lodash": "^4.17.21", 30 | "lokijs": "^1.5.12", 31 | "luxon": "^3.3.0", 32 | "rxdb": "^14.14.1", 33 | "rxjs": "^7.8.1", 34 | "uuid": "^9.0.0", 35 | "vue": "^3.3.4", 36 | "vue-router": "^4.2.3" 37 | }, 38 | "devDependencies": { 39 | "@babel/core": "^7.12.16", 40 | "@babel/eslint-parser": "^7.12.16", 41 | "@capacitor/cli": "3.5.0", 42 | "@types/jest": "^27.0.2", 43 | "@types/lodash": "^4.14.182", 44 | "@types/lokijs": "^1.5.7", 45 | "@types/luxon": "^2.3.1", 46 | "@types/uuid": "^9.0.4", 47 | "@typescript-eslint/eslint-plugin": "^5.6.0", 48 | "@typescript-eslint/parser": "^5.6.0", 49 | "@vue/cli-plugin-babel": "~5.0.0-rc.1", 50 | "@vue/cli-plugin-e2e-cypress": "~5.0.0-rc.1", 51 | "@vue/cli-plugin-eslint": "~5.0.0-rc.1", 52 | "@vue/cli-plugin-router": "~5.0.0-rc.1", 53 | "@vue/cli-plugin-typescript": "~5.0.0-rc.1", 54 | "@vue/cli-plugin-unit-jest": "~5.0.0-rc.1", 55 | "@vue/cli-service": "~5.0.0-rc.1", 56 | "@vue/eslint-config-typescript": "^9.1.0", 57 | "@vue/test-utils": "^2.0.0-rc.16", 58 | "@vue/vue3-jest": "^27.0.0-alpha.3", 59 | "babel-jest": "^27.3.1", 60 | "cypress": "^8.7.0", 61 | "eslint": "^8.4.1", 62 | "eslint-plugin-vue": "^8.2.0", 63 | "jest": "^27.3.1", 64 | "json-server": "^0.17.0", 65 | "npm-run-all": "^4.1.5", 66 | "ts-jest": "^27.0.7", 67 | "typescript": "^4.3.5" 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /public/assets/icon/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/public/assets/icon/favicon.png -------------------------------------------------------------------------------- /public/assets/icon/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandrogehlen/ionic-vue-rxdb/1b19929ae9dcbb5d19f6d50355d035d491d22f62/public/assets/icon/icon.png -------------------------------------------------------------------------------- /public/assets/shapes.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Ionic App 6 | 7 | 8 | 9 | 10 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 82 | 83 | 204 | -------------------------------------------------------------------------------- /src/components/PageForm.vue: -------------------------------------------------------------------------------- 1 | 22 | 91 | -------------------------------------------------------------------------------- /src/components/PageIndex.vue: -------------------------------------------------------------------------------- 1 | 52 | 53 | 146 | 147 | 173 | -------------------------------------------------------------------------------- /src/data/DataSource.ts: -------------------------------------------------------------------------------- 1 | import { replicateRxCollection, RxReplicationState } from 'rxdb/plugins/replication'; 2 | import { assign, keys, pickBy } from 'lodash'; 3 | import { RxCollection } from 'rxdb'; 4 | import { DateTime } from 'luxon'; 5 | import { v4, validate } from 'uuid'; 6 | 7 | 8 | export class DataSource { 9 | 10 | _options: any; 11 | _currentPage = 1; 12 | _fieldNames: string[]; 13 | _replicator: RxReplicationState; 14 | _collection: RxCollection; 15 | _syncEndTime: DateTime; 16 | 17 | constructor(collection: RxCollection, options: any) { 18 | this._options = options || {}; 19 | this._collection = collection; 20 | this._fieldNames = keys(collection.schema.jsonSchema.properties); 21 | } 22 | 23 | async findOne(key: string): Promise { 24 | const document = await this._collection.findOne(key).exec(); 25 | return this._toPlainObject(document); 26 | } 27 | 28 | async findAll(options: any = {}): Promise { 29 | const condition = options.searchValue ? { 30 | selector: { 31 | name: { $regex: new RegExp(`.*${options.searchValue}.*`, 'i') } 32 | } 33 | } : {}; 34 | 35 | const query = this._collection.find({ 36 | ...condition, 37 | skip: options.skip, 38 | limit: options.limit, 39 | sort: [ 40 | { id: 'asc' } 41 | ], 42 | }); 43 | 44 | const results = await query.exec(); 45 | return results.map(result => this._toPlainObject(result)); 46 | } 47 | 48 | async save(key: string, data: any) { 49 | if (key) { 50 | const document = await this._collection.findOne(key).exec(); 51 | await document.atomicUpdate((doc: any) => assign(doc, data)); 52 | } else { 53 | const primaryKey = this._collection.schema.primaryPath as string; 54 | await this._collection.insert({ 55 | ...{[primaryKey]: v4()}, 56 | ...data 57 | }); 58 | } 59 | } 60 | 61 | async destroy(key: string) { 62 | const document = await this._collection.findOne(key).exec(); 63 | await document.remove(); 64 | } 65 | 66 | async start(awaitInit = true): Promise { 67 | const created = !!this._replicator; 68 | 69 | if (!created) { 70 | this._replicator = await this._createReplicator(); 71 | } 72 | 73 | if ((!created || this._replicator.isStopped()) && awaitInit) { 74 | this._currentPage = 1; 75 | this._syncEndTime = null; 76 | await this._replicator.awaitInitialReplication(); 77 | this._syncEndTime = DateTime.now(); 78 | } 79 | } 80 | 81 | async stop(): Promise { 82 | return this._replicator.cancel(); 83 | } 84 | 85 | async push(documents: any[]): Promise { 86 | const baseUrl = this._options.baseUrl; 87 | 88 | for (const doc of documents) { 89 | const isNew = validate(doc.id); 90 | const url = isNew ? baseUrl : `${baseUrl}/${doc.id}`; 91 | const method = doc._deleted ? 'DELETE' : isNew ? 'POST' : 'PUT'; 92 | 93 | await fetch(url, { 94 | method: method, 95 | headers: { 96 | 'Accept': 'application/json', 97 | 'Content-Type': 'application/json' 98 | }, 99 | body: JSON.stringify(this._toPlainObject(doc)) 100 | }); 101 | } 102 | } 103 | 104 | async pull(last: any): Promise { 105 | const documents = []; 106 | const baseUrl = this._options.baseUrl; 107 | const limit = this._options.limit || 100; 108 | const batchSize = this._options.batchSize || 1000; 109 | const isSync = this.isSyncing(); 110 | 111 | let data; 112 | let lastUpdateAt = last ? DateTime.fromMillis(last.updatedAt) : null; 113 | 114 | if (this._syncEndTime >= lastUpdateAt) { 115 | lastUpdateAt = this._syncEndTime; 116 | } 117 | 118 | do { 119 | const url = last 120 | ? `${baseUrl}?updatedAt_gte=${lastUpdateAt.toMillis()}` 121 | : `${baseUrl}?_page=${this._currentPage}&_limit=${limit}` 122 | 123 | const response = await fetch(url); 124 | data = await response.json(); 125 | documents.push(...data); 126 | 127 | if (isSync) { 128 | this._currentPage++; 129 | } 130 | 131 | } while (documents.length < batchSize && data.length == limit && isSync); 132 | 133 | return { 134 | documents: documents, 135 | hasMoreDocuments: data.length === limit 136 | }; 137 | } 138 | 139 | isSyncing() { 140 | return !this._syncEndTime; 141 | } 142 | 143 | async _createReplicator() { 144 | // eslint-disable-next-line @typescript-eslint/no-this-alias 145 | const self = this; 146 | return replicateRxCollection({ 147 | collection: this._collection, 148 | replicationIdentifier: this._createReplicationIdentifier(), 149 | live: true, 150 | pull: { 151 | async handler(lastDoc) { 152 | return self.pull(lastDoc); 153 | } 154 | }, 155 | push: { 156 | async handler(document) { 157 | console.log('pushing', document); 158 | await self.push(document); 159 | return []; 160 | } 161 | }, 162 | }); 163 | } 164 | 165 | _createReplicationIdentifier() { 166 | return `${this._collection.name}:${this._options.baseUrl}`; 167 | } 168 | 169 | _toPlainObject(data: any): any { 170 | return pickBy(data, 171 | (value, key) => this._fieldNames.includes(key) && !key.startsWith('_') 172 | ); 173 | } 174 | 175 | } 176 | -------------------------------------------------------------------------------- /src/data/Manager.ts: -------------------------------------------------------------------------------- 1 | import { RxCollection, RxDatabase } from 'rxdb'; 2 | import { DataSource } from './DataSource'; 3 | 4 | export class Manager { 5 | 6 | private _database: RxDatabase; 7 | private _instances = new Map(); 8 | 9 | constructor(database: RxDatabase) { 10 | this._database = database; 11 | } 12 | 13 | public add(collection: RxCollection, options: any): this { 14 | this._instances.set(collection, new DataSource(collection, options)); 15 | return this; 16 | } 17 | 18 | public get(finder: (database: RxDatabase) => RxCollection): DataSource { 19 | const collection = finder(this._database); 20 | return this._instances.get(collection); 21 | } 22 | 23 | public async start(awaitInit = true): Promise { 24 | const values = Array.from(this._instances.values()); 25 | await Promise.all(values.map(instance => instance.start(awaitInit))); 26 | } 27 | 28 | public async stop(): Promise { 29 | const values = Array.from(this._instances.values()); 30 | await Promise.all(values.map(instance => instance.stop())); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/database.ts: -------------------------------------------------------------------------------- 1 | import { inject, Plugin } from 'vue'; 2 | import { createRxDatabase, addRxPlugin } from 'rxdb'; 3 | import { RxDBLeaderElectionPlugin } from 'rxdb/plugins/leader-election'; 4 | import { getRxStorageDexie } from 'rxdb/plugins/storage-dexie'; 5 | import { isPlatform } from '@ionic/vue'; 6 | import contactSchema from './schemas/contact'; 7 | import categorySchema from './schemas/category'; 8 | 9 | addRxPlugin(RxDBLeaderElectionPlugin); 10 | 11 | const KEY_DATABASE = Symbol('database'); 12 | 13 | function awaitDeviceIsReady(): Promise { 14 | return new Promise(resolve => { 15 | document.addEventListener('deviceready', () => { 16 | resolve(); 17 | }); 18 | }); 19 | } 20 | 21 | export function useDatabase(): any { 22 | return inject(KEY_DATABASE); 23 | } 24 | 25 | export async function createDatabase(): Promise { 26 | 27 | if (isPlatform('mobile')) { 28 | await awaitDeviceIsReady(); 29 | } 30 | 31 | const database = await createRxDatabase({ 32 | name: 'testdb', 33 | storage: getRxStorageDexie() 34 | }); 35 | 36 | await database.addCollections({ 37 | contacts: { 38 | schema: contactSchema 39 | }, 40 | categories: { 41 | schema: categorySchema 42 | } 43 | }); 44 | 45 | 46 | return { 47 | install(app: any) { 48 | app.provide(KEY_DATABASE, database); 49 | } 50 | }; 51 | } 52 | 53 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | import router from './router'; 4 | 5 | import { IonicVue } from '@ionic/vue'; 6 | 7 | /* Core CSS required for Ionic components to work properly */ 8 | import '@ionic/vue/css/core.css'; 9 | 10 | /* Basic CSS for apps built with Ionic */ 11 | import '@ionic/vue/css/normalize.css'; 12 | import '@ionic/vue/css/structure.css'; 13 | import '@ionic/vue/css/typography.css'; 14 | 15 | /* Optional CSS utils that can be commented out */ 16 | import '@ionic/vue/css/padding.css'; 17 | import '@ionic/vue/css/float-elements.css'; 18 | import '@ionic/vue/css/text-alignment.css'; 19 | import '@ionic/vue/css/text-transformation.css'; 20 | import '@ionic/vue/css/flex-utils.css'; 21 | import '@ionic/vue/css/display.css'; 22 | 23 | /* Theme variables */ 24 | import './theme/variables.css'; 25 | import { createDatabase } from './database'; 26 | const database = createDatabase(); 27 | const app = createApp(App) 28 | 29 | database.then(db => { 30 | app.use(db) 31 | .use(IonicVue) 32 | .use(router); 33 | }) 34 | .then(() => router.isReady()) 35 | .then(() => app.mount('#app')); 36 | -------------------------------------------------------------------------------- /src/router/index.ts: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory } from '@ionic/vue-router'; 2 | import { RouteRecordRaw } from 'vue-router'; 3 | 4 | const routes: Array = [ 5 | { 6 | path: '', 7 | redirect: '/contacts' 8 | }, 9 | { 10 | path: '/contacts', 11 | name: 'contacts', 12 | component: () => import ('../views/contacts/Index.vue') 13 | }, 14 | { 15 | path: '/contacts/:id', 16 | name: 'editContact', 17 | component: () => import ('../views/contacts/Form.vue') 18 | },{ 19 | path: '/contacts/new', 20 | name: 'newContact', 21 | component: () => import ('../views/contacts/Form.vue') 22 | },{ 23 | path: '/categories', 24 | name: 'categories', 25 | component: () => import ('../views/categories/Index.vue') 26 | }, 27 | { 28 | path: '/categories/:id', 29 | name: 'editCategory', 30 | component: () => import ('../views/categories/Form.vue') 31 | },{ 32 | path: '/categories/new', 33 | name: 'newCategory', 34 | component: () => import ('../views/categories/Form.vue') 35 | } 36 | ] 37 | 38 | const router = createRouter({ 39 | history: createWebHistory(process.env.BASE_URL), 40 | routes 41 | }) 42 | 43 | export default router 44 | -------------------------------------------------------------------------------- /src/schemas/category.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | version: 0, 3 | description: "Category schema", 4 | primaryKey: "id", 5 | type: "object", 6 | properties: { 7 | id: { 8 | type: "string", 9 | maxLength: 100 10 | }, 11 | name: { 12 | type: "string" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/schemas/contact.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | version: 0, 3 | description: "Contact schema", 4 | primaryKey: "id", 5 | type: "object", 6 | properties: { 7 | id: { 8 | type: "string", 9 | maxLength: 100 10 | }, 11 | name: { 12 | type: "string" 13 | }, 14 | company_name: { 15 | type: "string" 16 | }, 17 | emails: { 18 | type: 'array', 19 | items: { 20 | type: 'string', 21 | }, 22 | }, 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/schemas/tag.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | version: 0, 3 | description: "Tag schema", 4 | primaryKey: "id", 5 | type: "object", 6 | properties: { 7 | id: { 8 | type: "string", 9 | maxLength: 100 10 | }, 11 | description: { 12 | type: "string" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | declare module '*.vue' { 3 | import type { DefineComponent } from 'vue' 4 | const component: DefineComponent<{}, {}, any> 5 | export default component 6 | } 7 | -------------------------------------------------------------------------------- /src/theme/variables.css: -------------------------------------------------------------------------------- 1 | /* Ionic Variables and Theming. For more info, please see: 2 | http://ionicframework.com/docs/theming/ */ 3 | 4 | /** Ionic CSS Variables **/ 5 | :root { 6 | /** primary **/ 7 | --ion-color-primary: #3880ff; 8 | --ion-color-primary-rgb: 56, 128, 255; 9 | --ion-color-primary-contrast: #ffffff; 10 | --ion-color-primary-contrast-rgb: 255, 255, 255; 11 | --ion-color-primary-shade: #3171e0; 12 | --ion-color-primary-tint: #4c8dff; 13 | 14 | /** secondary **/ 15 | --ion-color-secondary: #3dc2ff; 16 | --ion-color-secondary-rgb: 61, 194, 255; 17 | --ion-color-secondary-contrast: #ffffff; 18 | --ion-color-secondary-contrast-rgb: 255, 255, 255; 19 | --ion-color-secondary-shade: #36abe0; 20 | --ion-color-secondary-tint: #50c8ff; 21 | 22 | /** tertiary **/ 23 | --ion-color-tertiary: #5260ff; 24 | --ion-color-tertiary-rgb: 82, 96, 255; 25 | --ion-color-tertiary-contrast: #ffffff; 26 | --ion-color-tertiary-contrast-rgb: 255, 255, 255; 27 | --ion-color-tertiary-shade: #4854e0; 28 | --ion-color-tertiary-tint: #6370ff; 29 | 30 | /** success **/ 31 | --ion-color-success: #2dd36f; 32 | --ion-color-success-rgb: 45, 211, 111; 33 | --ion-color-success-contrast: #ffffff; 34 | --ion-color-success-contrast-rgb: 255, 255, 255; 35 | --ion-color-success-shade: #28ba62; 36 | --ion-color-success-tint: #42d77d; 37 | 38 | /** warning **/ 39 | --ion-color-warning: #ffc409; 40 | --ion-color-warning-rgb: 255, 196, 9; 41 | --ion-color-warning-contrast: #000000; 42 | --ion-color-warning-contrast-rgb: 0, 0, 0; 43 | --ion-color-warning-shade: #e0ac08; 44 | --ion-color-warning-tint: #ffca22; 45 | 46 | /** danger **/ 47 | --ion-color-danger: #eb445a; 48 | --ion-color-danger-rgb: 235, 68, 90; 49 | --ion-color-danger-contrast: #ffffff; 50 | --ion-color-danger-contrast-rgb: 255, 255, 255; 51 | --ion-color-danger-shade: #cf3c4f; 52 | --ion-color-danger-tint: #ed576b; 53 | 54 | /** dark **/ 55 | --ion-color-dark: #222428; 56 | --ion-color-dark-rgb: 34, 36, 40; 57 | --ion-color-dark-contrast: #ffffff; 58 | --ion-color-dark-contrast-rgb: 255, 255, 255; 59 | --ion-color-dark-shade: #1e2023; 60 | --ion-color-dark-tint: #383a3e; 61 | 62 | /** medium **/ 63 | --ion-color-medium: #92949c; 64 | --ion-color-medium-rgb: 146, 148, 156; 65 | --ion-color-medium-contrast: #ffffff; 66 | --ion-color-medium-contrast-rgb: 255, 255, 255; 67 | --ion-color-medium-shade: #808289; 68 | --ion-color-medium-tint: #9d9fa6; 69 | 70 | /** light **/ 71 | --ion-color-light: #f4f5f8; 72 | --ion-color-light-rgb: 244, 245, 248; 73 | --ion-color-light-contrast: #000000; 74 | --ion-color-light-contrast-rgb: 0, 0, 0; 75 | --ion-color-light-shade: #d7d8da; 76 | --ion-color-light-tint: #f5f6f9; 77 | } 78 | 79 | @media (prefers-color-scheme: dark) { 80 | /* 81 | * Dark Colors 82 | * ------------------------------------------- 83 | */ 84 | 85 | body { 86 | --ion-color-primary: #428cff; 87 | --ion-color-primary-rgb: 66,140,255; 88 | --ion-color-primary-contrast: #ffffff; 89 | --ion-color-primary-contrast-rgb: 255,255,255; 90 | --ion-color-primary-shade: #3a7be0; 91 | --ion-color-primary-tint: #5598ff; 92 | 93 | --ion-color-secondary: #50c8ff; 94 | --ion-color-secondary-rgb: 80,200,255; 95 | --ion-color-secondary-contrast: #ffffff; 96 | --ion-color-secondary-contrast-rgb: 255,255,255; 97 | --ion-color-secondary-shade: #46b0e0; 98 | --ion-color-secondary-tint: #62ceff; 99 | 100 | --ion-color-tertiary: #6a64ff; 101 | --ion-color-tertiary-rgb: 106,100,255; 102 | --ion-color-tertiary-contrast: #ffffff; 103 | --ion-color-tertiary-contrast-rgb: 255,255,255; 104 | --ion-color-tertiary-shade: #5d58e0; 105 | --ion-color-tertiary-tint: #7974ff; 106 | 107 | --ion-color-success: #2fdf75; 108 | --ion-color-success-rgb: 47,223,117; 109 | --ion-color-success-contrast: #000000; 110 | --ion-color-success-contrast-rgb: 0,0,0; 111 | --ion-color-success-shade: #29c467; 112 | --ion-color-success-tint: #44e283; 113 | 114 | --ion-color-warning: #ffd534; 115 | --ion-color-warning-rgb: 255,213,52; 116 | --ion-color-warning-contrast: #000000; 117 | --ion-color-warning-contrast-rgb: 0,0,0; 118 | --ion-color-warning-shade: #e0bb2e; 119 | --ion-color-warning-tint: #ffd948; 120 | 121 | --ion-color-danger: #ff4961; 122 | --ion-color-danger-rgb: 255,73,97; 123 | --ion-color-danger-contrast: #ffffff; 124 | --ion-color-danger-contrast-rgb: 255,255,255; 125 | --ion-color-danger-shade: #e04055; 126 | --ion-color-danger-tint: #ff5b71; 127 | 128 | --ion-color-dark: #f4f5f8; 129 | --ion-color-dark-rgb: 244,245,248; 130 | --ion-color-dark-contrast: #000000; 131 | --ion-color-dark-contrast-rgb: 0,0,0; 132 | --ion-color-dark-shade: #d7d8da; 133 | --ion-color-dark-tint: #f5f6f9; 134 | 135 | --ion-color-medium: #989aa2; 136 | --ion-color-medium-rgb: 152,154,162; 137 | --ion-color-medium-contrast: #000000; 138 | --ion-color-medium-contrast-rgb: 0,0,0; 139 | --ion-color-medium-shade: #86888f; 140 | --ion-color-medium-tint: #a2a4ab; 141 | 142 | --ion-color-light: #222428; 143 | --ion-color-light-rgb: 34,36,40; 144 | --ion-color-light-contrast: #ffffff; 145 | --ion-color-light-contrast-rgb: 255,255,255; 146 | --ion-color-light-shade: #1e2023; 147 | --ion-color-light-tint: #383a3e; 148 | } 149 | 150 | /* 151 | * iOS Dark Theme 152 | * ------------------------------------------- 153 | */ 154 | 155 | .ios body { 156 | --ion-background-color: #000000; 157 | --ion-background-color-rgb: 0,0,0; 158 | 159 | --ion-text-color: #ffffff; 160 | --ion-text-color-rgb: 255,255,255; 161 | 162 | --ion-color-step-50: #0d0d0d; 163 | --ion-color-step-100: #1a1a1a; 164 | --ion-color-step-150: #262626; 165 | --ion-color-step-200: #333333; 166 | --ion-color-step-250: #404040; 167 | --ion-color-step-300: #4d4d4d; 168 | --ion-color-step-350: #595959; 169 | --ion-color-step-400: #666666; 170 | --ion-color-step-450: #737373; 171 | --ion-color-step-500: #808080; 172 | --ion-color-step-550: #8c8c8c; 173 | --ion-color-step-600: #999999; 174 | --ion-color-step-650: #a6a6a6; 175 | --ion-color-step-700: #b3b3b3; 176 | --ion-color-step-750: #bfbfbf; 177 | --ion-color-step-800: #cccccc; 178 | --ion-color-step-850: #d9d9d9; 179 | --ion-color-step-900: #e6e6e6; 180 | --ion-color-step-950: #f2f2f2; 181 | 182 | --ion-item-background: #000000; 183 | 184 | --ion-card-background: #1c1c1d; 185 | } 186 | 187 | .ios ion-modal { 188 | --ion-background-color: var(--ion-color-step-100); 189 | --ion-toolbar-background: var(--ion-color-step-150); 190 | --ion-toolbar-border-color: var(--ion-color-step-250); 191 | } 192 | 193 | 194 | /* 195 | * Material Design Dark Theme 196 | * ------------------------------------------- 197 | */ 198 | 199 | .md body { 200 | --ion-background-color: #121212; 201 | --ion-background-color-rgb: 18,18,18; 202 | 203 | --ion-text-color: #ffffff; 204 | --ion-text-color-rgb: 255,255,255; 205 | 206 | --ion-border-color: #222222; 207 | 208 | --ion-color-step-50: #1e1e1e; 209 | --ion-color-step-100: #2a2a2a; 210 | --ion-color-step-150: #363636; 211 | --ion-color-step-200: #414141; 212 | --ion-color-step-250: #4d4d4d; 213 | --ion-color-step-300: #595959; 214 | --ion-color-step-350: #656565; 215 | --ion-color-step-400: #717171; 216 | --ion-color-step-450: #7d7d7d; 217 | --ion-color-step-500: #898989; 218 | --ion-color-step-550: #949494; 219 | --ion-color-step-600: #a0a0a0; 220 | --ion-color-step-650: #acacac; 221 | --ion-color-step-700: #b8b8b8; 222 | --ion-color-step-750: #c4c4c4; 223 | --ion-color-step-800: #d0d0d0; 224 | --ion-color-step-850: #dbdbdb; 225 | --ion-color-step-900: #e7e7e7; 226 | --ion-color-step-950: #f3f3f3; 227 | 228 | --ion-item-background: #1e1e1e; 229 | 230 | --ion-toolbar-background: #1f1f1f; 231 | 232 | --ion-tab-bar-background: #1f1f1f; 233 | 234 | --ion-card-background: #1e1e1e; 235 | } 236 | } -------------------------------------------------------------------------------- /src/views/categories/Form.vue: -------------------------------------------------------------------------------- 1 | 18 | 27 | -------------------------------------------------------------------------------- /src/views/categories/Index.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 30 | -------------------------------------------------------------------------------- /src/views/contacts/Form.vue: -------------------------------------------------------------------------------- 1 | 34 | 51 | 52 | -------------------------------------------------------------------------------- /src/views/contacts/Index.vue: -------------------------------------------------------------------------------- 1 | 14 | 30 | 31 | -------------------------------------------------------------------------------- /tests/e2e/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | 'cypress' 4 | ], 5 | env: { 6 | mocha: true, 7 | 'cypress/globals': true 8 | }, 9 | rules: { 10 | strict: 'off' 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/e2e/plugins/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable arrow-body-style */ 2 | // https://docs.cypress.io/guides/guides/plugins-guide.html 3 | 4 | // if you need a custom webpack configuration you can uncomment the following import 5 | // and then use the `file:preprocessor` event 6 | // as explained in the cypress docs 7 | // https://docs.cypress.io/api/plugins/preprocessors-api.html#Examples 8 | 9 | // /* eslint-disable import/no-extraneous-dependencies, global-require */ 10 | // const webpack = require('@cypress/webpack-preprocessor') 11 | 12 | module.exports = (on, config) => { 13 | // on('file:preprocessor', webpack({ 14 | // webpackOptions: require('@vue/cli-service/webpack.config'), 15 | // watchOptions: {} 16 | // })) 17 | 18 | return Object.assign({}, config, { 19 | fixturesFolder: 'tests/e2e/fixtures', 20 | integrationFolder: 'tests/e2e/specs', 21 | screenshotsFolder: 'tests/e2e/screenshots', 22 | videosFolder: 'tests/e2e/videos', 23 | supportFile: 'tests/e2e/support/index.js' 24 | }) 25 | } 26 | -------------------------------------------------------------------------------- /tests/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // https://docs.cypress.io/api/introduction/api.html 2 | 3 | describe('My First Test', () => { 4 | it('Visits the app root url', () => { 5 | cy.visit('/folder/Inbox') 6 | cy.contains('#container', 'Inbox') 7 | }) 8 | }) 9 | -------------------------------------------------------------------------------- /tests/e2e/support/commands.js: -------------------------------------------------------------------------------- 1 | // *********************************************** 2 | // This example commands.js shows you how to 3 | // create various custom commands and overwrite 4 | // existing commands. 5 | // 6 | // For more comprehensive examples of custom 7 | // commands please read more here: 8 | // https://on.cypress.io/custom-commands 9 | // *********************************************** 10 | // 11 | // 12 | // -- This is a parent command -- 13 | // Cypress.Commands.add("login", (email, password) => { ... }) 14 | // 15 | // 16 | // -- This is a child command -- 17 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) 18 | // 19 | // 20 | // -- This is a dual command -- 21 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) 22 | // 23 | // 24 | // -- This is will overwrite an existing command -- 25 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) 26 | -------------------------------------------------------------------------------- /tests/e2e/support/index.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands' 18 | 19 | // Alternatively you can use CommonJS syntax: 20 | // require('./commands') 21 | -------------------------------------------------------------------------------- /tests/unit/example.spec.ts: -------------------------------------------------------------------------------- 1 | import { mount } from '@vue/test-utils' 2 | import FolderPage from '@/views/ConctactIndexPage.vue' 3 | 4 | describe('FolderPage.vue', () => { 5 | it('renders folder view', () => { 6 | const mockRoute = { 7 | params: { 8 | id: 'Outbox' 9 | } 10 | } 11 | const wrapper = mount(FolderPage, { 12 | global: { 13 | mocks: { 14 | $route: mockRoute 15 | } 16 | } 17 | }) 18 | expect(wrapper.text()).toMatch('Explore UI Components') 19 | }) 20 | }) 21 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "strict": true, 6 | "jsx": "preserve", 7 | "importHelpers": true, 8 | "moduleResolution": "node", 9 | "skipLibCheck": true, 10 | "esModuleInterop": true, 11 | "allowSyntheticDefaultImports": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "strictPropertyInitialization": false, 14 | "strictNullChecks": false, 15 | "sourceMap": true, 16 | "baseUrl": ".", 17 | "types": [ 18 | "webpack-env", 19 | "jest" 20 | ], 21 | "paths": { 22 | "@/*": [ 23 | "src/*" 24 | ] 25 | }, 26 | "lib": [ 27 | "esnext", 28 | "dom", 29 | "dom.iterable", 30 | "scripthost" 31 | ] 32 | }, 33 | "include": [ 34 | "src/**/*.ts", 35 | "src/**/*.tsx", 36 | "src/**/*.vue", 37 | "tests/**/*.ts", 38 | "tests/**/*.tsx" 39 | ], 40 | "exclude": [ 41 | "node_modules" 42 | ] 43 | } 44 | --------------------------------------------------------------------------------