├── demo ├── lang │ └── en.json ├── icon.png ├── icon-apple.png ├── images │ ├── flag-de.png │ ├── flag-en.png │ ├── firebase.png │ ├── theme-ios.png │ ├── theme-material.png │ └── standard-js-sticker-small.png ├── design │ ├── firebase.pxd │ ├── theme-ios.pxd │ └── theme-material.pxd ├── firebase-storage.txt ├── pages │ ├── panel-left.vue │ ├── panel-right.vue │ ├── f7ios │ │ ├── bars-no-navbar.vue │ │ ├── bars-no-navbar-toolbar.vue │ │ ├── bars-no-toolbar.vue │ │ ├── panel-right2.vue │ │ ├── panel-right3.vue │ │ ├── animation.vue │ │ ├── bars-deep-navbar.vue │ │ ├── login-screen.vue │ │ ├── notifications.vue │ │ ├── swiper-fade.vue │ │ ├── panels.vue │ │ ├── swiper-loop.vue │ │ ├── swiper-horizontal.vue │ │ ├── floating-button.vue │ │ ├── swiper-pagination-fraction.vue │ │ ├── swiper-pagination-progress.vue │ │ ├── swiper-scrollbar.vue │ │ ├── swiper-vertical.vue │ │ ├── timeline.vue │ │ ├── swiper-space-between.vue │ │ ├── login-screen-embedded.vue │ │ ├── swiper-nested.vue │ │ ├── virtual-list.vue │ │ ├── tabs.vue │ │ ├── about.vue │ │ ├── swiper-3d-cube.vue │ │ ├── swiper-3d-flip.vue │ │ ├── swiper-custom.vue │ │ ├── swiper-3d-coverflow.vue │ │ ├── transitions.vue │ │ ├── bars-hide.vue │ │ ├── photo-browser.vue │ │ ├── color-themes.vue │ │ ├── pull-to-refresh.vue │ │ ├── bars-deep-navbar-3.vue │ │ ├── bars-deep-navbar-2.vue │ │ ├── swiper-zoom.vue │ │ └── preloader.vue │ ├── f7material │ │ ├── bars-no-navbar.vue │ │ ├── bars-no-navbar-toolbar.vue │ │ ├── animation.vue │ │ ├── panel-right2.vue │ │ ├── panel-right3.vue │ │ ├── bars-no-toolbar.vue │ │ ├── bars-deep-navbar.vue │ │ ├── login-screen.vue │ │ ├── notifications.vue │ │ ├── swiper-fade.vue │ │ ├── panels.vue │ │ ├── swiper-loop.vue │ │ ├── swiper-horizontal.vue │ │ ├── swiper-vertical.vue │ │ ├── swiper-scrollbar.vue │ │ ├── swiper-pagination-fraction.vue │ │ ├── swiper-pagination-progress.vue │ │ ├── timeline.vue │ │ ├── swiper-space-between.vue │ │ ├── login-screen-embedded.vue │ │ ├── virtual-list.vue │ │ ├── swiper-nested.vue │ │ ├── about.vue │ │ ├── floating-button.vue │ │ ├── tabs.vue │ │ ├── swiper-3d-cube.vue │ │ ├── swiper-3d-flip.vue │ │ ├── swiper-custom.vue │ │ ├── swiper-3d-coverflow.vue │ │ ├── bars-hide.vue │ │ ├── photo-browser.vue │ │ ├── pull-to-refresh.vue │ │ ├── bars-deep-navbar-3.vue │ │ ├── bars-deep-navbar-2.vue │ │ ├── swiper-zoom.vue │ │ ├── preloader.vue │ │ └── modals.vue │ ├── flexible-routing.vue │ └── firebase-private.vue ├── firebase-database.json ├── config.json └── app.vue ├── client ├── icon.png ├── ios.js ├── material.js ├── login-popup.vue ├── workarounds.css ├── sort-object.js ├── theme-colors.json ├── application-frame.css ├── init.css └── index.ejs ├── media ├── process.png ├── process.pptx ├── screenshots.png ├── cli-commands.png ├── cli-commands.pptx ├── documentation.png ├── web-app-visit.png ├── web-app-visit.pxd ├── documentation.pptx ├── app-store-download.png ├── app-store-download.pxd ├── google-play-download.png ├── google-play-download.pxd └── Untitled Diagram.xml ├── design ├── icon-template.pdf ├── icon-template.pptx ├── smartphone-template.pdf └── smartphone-template.pptx ├── .babelrc ├── vendor ├── framework7 │ └── img │ │ ├── i-f7-ios.png │ │ └── i-f7-material.png └── material-icons │ ├── MaterialIcons-Regular.eot │ ├── MaterialIcons-Regular.ttf │ ├── MaterialIcons-Regular.woff │ ├── MaterialIcons-Regular.woff2 │ └── material-icons.css ├── scripts ├── deprecated.js ├── reset-cache.js ├── dev-client.js ├── cache-version.js ├── found.js ├── type.js ├── applyConfiguration.js ├── config.json ├── jobs │ ├── updateEditorconfigFile.js │ ├── updateEslintrcFile.js │ └── updateIgnoreFiles.js ├── addLoginPopup.js ├── path.js ├── alert.js ├── snapshot.js ├── code-check.js ├── create-snapshot.js ├── modifications14.js ├── backup.js ├── modifications16plus.js ├── cmd.js └── checkLanguageFiles.js ├── .gitignore ├── .npmignore ├── docs ├── cordova-preferences.md ├── backup.md ├── ignoreFiles.md ├── eslintrcFile.md ├── dev-requirements.md ├── editorconfigFile.md ├── build.md ├── dev-trouble-shooting.md ├── design.md ├── knowledge.md ├── image-upload-component.md ├── icon-fonts.md ├── sort-object.md ├── cli-commands.md ├── setup.md ├── dev-folder-structure.md ├── cordova-plugins.md ├── page-components.md ├── language-files.md ├── modules-and-scripts.md ├── folder-structure.md ├── app-component.md ├── application-style.md ├── dev-update-vendor-folder.md ├── status-bar-style.md ├── state-restoration.md ├── dev-way-of-working.md ├── data-object.md └── images.md └── LICENSE /demo/lang/en.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /demo/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/demo/icon.png -------------------------------------------------------------------------------- /client/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/client/icon.png -------------------------------------------------------------------------------- /media/process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/media/process.png -------------------------------------------------------------------------------- /media/process.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/media/process.pptx -------------------------------------------------------------------------------- /demo/icon-apple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/demo/icon-apple.png -------------------------------------------------------------------------------- /media/screenshots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/media/screenshots.png -------------------------------------------------------------------------------- /demo/images/flag-de.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/demo/images/flag-de.png -------------------------------------------------------------------------------- /demo/images/flag-en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/demo/images/flag-en.png -------------------------------------------------------------------------------- /media/cli-commands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/media/cli-commands.png -------------------------------------------------------------------------------- /media/cli-commands.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/media/cli-commands.pptx -------------------------------------------------------------------------------- /media/documentation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/media/documentation.png -------------------------------------------------------------------------------- /media/web-app-visit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/media/web-app-visit.png -------------------------------------------------------------------------------- /media/web-app-visit.pxd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/media/web-app-visit.pxd -------------------------------------------------------------------------------- /demo/design/firebase.pxd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/demo/design/firebase.pxd -------------------------------------------------------------------------------- /demo/design/theme-ios.pxd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/demo/design/theme-ios.pxd -------------------------------------------------------------------------------- /demo/images/firebase.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/demo/images/firebase.png -------------------------------------------------------------------------------- /demo/images/theme-ios.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/demo/images/theme-ios.png -------------------------------------------------------------------------------- /design/icon-template.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/design/icon-template.pdf -------------------------------------------------------------------------------- /design/icon-template.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/design/icon-template.pptx -------------------------------------------------------------------------------- /media/documentation.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/media/documentation.pptx -------------------------------------------------------------------------------- /media/app-store-download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/media/app-store-download.png -------------------------------------------------------------------------------- /media/app-store-download.pxd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/media/app-store-download.pxd -------------------------------------------------------------------------------- /demo/design/theme-material.pxd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/demo/design/theme-material.pxd -------------------------------------------------------------------------------- /demo/images/theme-material.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/demo/images/theme-material.png -------------------------------------------------------------------------------- /design/smartphone-template.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/design/smartphone-template.pdf -------------------------------------------------------------------------------- /design/smartphone-template.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/design/smartphone-template.pptx -------------------------------------------------------------------------------- /media/google-play-download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/media/google-play-download.png -------------------------------------------------------------------------------- /media/google-play-download.pxd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/media/google-play-download.pxd -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-2"], 3 | "plugins": ["transform-runtime"], 4 | "comments": false 5 | } 6 | -------------------------------------------------------------------------------- /vendor/framework7/img/i-f7-ios.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/vendor/framework7/img/i-f7-ios.png -------------------------------------------------------------------------------- /client/ios.js: -------------------------------------------------------------------------------- 1 | require('../vendor/framework7/css/framework7.ios.css') 2 | require('../vendor/framework7/css/framework7.ios.colors.css') 3 | -------------------------------------------------------------------------------- /demo/images/standard-js-sticker-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/demo/images/standard-js-sticker-small.png -------------------------------------------------------------------------------- /vendor/framework7/img/i-f7-material.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/vendor/framework7/img/i-f7-material.png -------------------------------------------------------------------------------- /client/material.js: -------------------------------------------------------------------------------- 1 | require('../vendor/framework7/css/framework7.material.css') 2 | require('../vendor/framework7/css/framework7.material.colors.css') 3 | -------------------------------------------------------------------------------- /vendor/material-icons/MaterialIcons-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/vendor/material-icons/MaterialIcons-Regular.eot -------------------------------------------------------------------------------- /vendor/material-icons/MaterialIcons-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/vendor/material-icons/MaterialIcons-Regular.ttf -------------------------------------------------------------------------------- /vendor/material-icons/MaterialIcons-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/vendor/material-icons/MaterialIcons-Regular.woff -------------------------------------------------------------------------------- /vendor/material-icons/MaterialIcons-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scriptPilot/app-framework/HEAD/vendor/material-icons/MaterialIcons-Regular.woff2 -------------------------------------------------------------------------------- /demo/firebase-storage.txt: -------------------------------------------------------------------------------- 1 | service firebase.storage { 2 | match /b/app-framework-9045a.appspot.com/o { 3 | match /privateData/{uid} { 4 | allow read, write: if uid == request.auth.uid; 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /scripts/deprecated.js: -------------------------------------------------------------------------------- 1 | /* Purpose: Inform user about deprecated scripts */ 2 | 3 | let alert = require('./alert') 4 | 5 | alert('The script you have called is deprecated.\nPlease check our documentation on GitHub.') 6 | -------------------------------------------------------------------------------- /demo/pages/panel-left.vue: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /demo/pages/panel-right.vue: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /client/login-popup.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /client/workarounds.css: -------------------------------------------------------------------------------- 1 | /* Smart select option images shown to big */ 2 | .smart-select-page .item-media img { 3 | max-width: 29px; 4 | max-height: 29px; 5 | } 6 | 7 | /* Switch in item-after to low */ 8 | .item-after .label-switch { 9 | margin-top: -3px; 10 | } 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # This file is updated automatically, please add or remove files in the configuration file. 2 | 3 | *.log* 4 | *.zip 5 | .DS_Store 6 | .editorconfig 7 | .enable-dev-mode 8 | .eslintrc 9 | .git/ 10 | _SYNCAPP/ 11 | database-backup.json 12 | ftp-config.json 13 | node_modules/ 14 | snapshots/ 15 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # This file is updated automatically, please add or remove files in the configuration file. 2 | 3 | *.log* 4 | *.zip 5 | .DS_Store 6 | .editorconfig 7 | .enable-dev-mode 8 | .eslintrc 9 | .git/ 10 | DOCUMENTATION.md 11 | _SYNCAPP/ 12 | build/ 13 | database-backup.json 14 | demo/ 15 | docs/ 16 | ftp-config.json 17 | media/ 18 | node_modules/ 19 | snapshots/ 20 | -------------------------------------------------------------------------------- /demo/firebase-database.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "privateData": { 4 | "$uid": { 5 | ".read": "$uid === auth.uid", 6 | ".write": "$uid === auth.uid" 7 | } 8 | }, 9 | "publicData": { 10 | "todos": { 11 | ".read": "true", 12 | ".write": "true", 13 | ".indexOn": "created" 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /scripts/reset-cache.js: -------------------------------------------------------------------------------- 1 | /* Purpose: Clear cache folder */ 2 | 3 | 'use strict' 4 | 5 | let env = require('./env') 6 | let alert = require('./alert') 7 | let fs = require('fs-extra') 8 | 9 | alert('Cache reset ongoing - please wait ...') 10 | fs.remove(env.cache, function (err) { 11 | if (err) { 12 | alert('Failed to reset cache.', 'error') 13 | } else { 14 | alert('Cache reset done.') 15 | } 16 | }) 17 | -------------------------------------------------------------------------------- /scripts/dev-client.js: -------------------------------------------------------------------------------- 1 | /* Purpose: Provide client module for webpack development server */ 2 | 3 | 'use strict' 4 | 5 | // Load packages 6 | require('eventsource-polyfill') // needed for IE 7 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 8 | 9 | // Subscribe to webpack development server 10 | hotClient.subscribe(function (event) { 11 | if (event.action === 'reload') { 12 | window.location.reload() 13 | } 14 | }) 15 | -------------------------------------------------------------------------------- /docs/cordova-preferences.md: -------------------------------------------------------------------------------- 1 | # Cordova preferences 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | In the configuration file, you can apply custom Cordova preferences: 8 | 9 | ``` 10 | "cordovaPreferences": { 11 | "DisallowOverscroll": true 12 | } 13 | ``` 14 | 15 | You find an overview of available preferences at the [Cordova documentation](https://cordova.apache.org/docs/en/7.x/config_ref/index.html#preference). 16 | -------------------------------------------------------------------------------- /demo/pages/f7ios/bars-no-navbar.vue: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /demo/pages/f7material/bars-no-navbar.vue: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /demo/pages/f7ios/bars-no-navbar-toolbar.vue: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /demo/pages/f7material/bars-no-navbar-toolbar.vue: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /scripts/cache-version.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Purpose: Cache build version to cache. 4 | 5 | */ 6 | 7 | 'use strict' 8 | 9 | // Include modules 10 | let env = require('./env') 11 | let alert = require('./alert') 12 | let cmd = require('./cmd') 13 | 14 | // Check version 15 | if (/^(dev|(([0-9]+)\.([0-9]+)\.([0-9]+)))$/.test(env.arg.version) !== true) { 16 | alert('Version argument not valid.', 'error') 17 | // Cache version 18 | } else { 19 | cmd(__dirname, 'node cache-snapshot --name build-' + env.arg.version, function () { 20 | alert('Version ' + env.arg.version + ' cached.') 21 | }) 22 | } 23 | -------------------------------------------------------------------------------- /scripts/found.js: -------------------------------------------------------------------------------- 1 | /* Purpose: Check if file or folder exists (input string or array of path fragments; case-sensitive) */ 2 | 3 | 'use strict' 4 | 5 | // Include modules 6 | let fs = require('fs-extra') 7 | let path = require('path') 8 | 9 | // Export function 10 | module.exports = function () { 11 | try { 12 | let pathToCheck = path.resolve.apply(null, arguments) 13 | let dirname = path.dirname(pathToCheck) 14 | let basename = path.basename(pathToCheck) 15 | let files = fs.readdirSync(dirname) 16 | return files.indexOf(basename) > -1 17 | } catch (err) { 18 | return false 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /docs/backup.md: -------------------------------------------------------------------------------- 1 | # Backup your project 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | ## Backup Firebase data 8 | 9 | Run `npm run backup` to save the Firebase database content and user list as JSON files to the *snapshots* folder. 10 | 11 | ## Backup project folder 12 | 13 | Run `npm run snapshot` to create a snapshot of all important project files to the *snapshots* folder. 14 | 15 | ## Backup frequently 16 | 17 | Backup your project folder frequently by copying the *snapshots* folder to any external drive or cloud and/or pushing and synchronizing your changes to GitHub. 18 | -------------------------------------------------------------------------------- /scripts/type.js: -------------------------------------------------------------------------------- 1 | /* Purpose: Return type of input as string */ 2 | 3 | 'use strict' 4 | 5 | // Export function 6 | module.exports = function (inp) { 7 | if (inp === undefined) return 'undefined' 8 | else if (inp === null) return 'null' 9 | else if (Array.isArray(inp) === true) return 'array' 10 | else if (typeof inp === 'object') return 'object' 11 | else if (typeof inp === 'string') return 'string' 12 | else if (typeof inp === 'boolean') return 'boolean' 13 | else if (typeof inp === 'function') return 'function' 14 | else if (typeof inp === 'number') return 'number' 15 | else throw new Error('Unknown input type.') 16 | } 17 | -------------------------------------------------------------------------------- /docs/ignoreFiles.md: -------------------------------------------------------------------------------- 1 | # Configure .gitignore and .npmignore files 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | The *.gitignore* and *.npmignore* files are updated automatically, based on a default configuration. 8 | 9 | You can overwrite this configuration in `gitignore` and `npmignore` objects in the *app/config.json* file. 10 | 11 | Example: Add a custom folder to the *.npmignore* file and remove the *.editorconfig* file 12 | 13 | ``` 14 | "npmignore": { 15 | "customFolder/": true, 16 | ".editorconfig": false 17 | } 18 | ``` 19 | 20 | `true` means, the path will be listed in the ignore file. 21 | -------------------------------------------------------------------------------- /scripts/applyConfiguration.js: -------------------------------------------------------------------------------- 1 | // Purpose: Apply configuration to the project files 2 | 3 | // Import modules 4 | const alert = require('./alert') 5 | 6 | // Import jobs 7 | const updateIgnoreFiles = require('./jobs/updateIgnoreFiles') 8 | const updateEditorconfigFile = require('./jobs/updateEditorconfigFile') 9 | const updateEslintrcFile = require('./jobs/updateEslintrcFile') 10 | 11 | // Run jobs 12 | updateEditorconfigFile 13 | .then(updateEslintrcFile) 14 | .then(updateIgnoreFiles) 15 | .then(() => { 16 | alert('Configuration applied successfully.') 17 | }) 18 | .catch(() => { 19 | alert('Failed to apply the configuration.', 'issue') 20 | }) 21 | -------------------------------------------------------------------------------- /docs/eslintrcFile.md: -------------------------------------------------------------------------------- 1 | # Configure .eslintrc file 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | The *.eslintrc* file will be updated automatically. 8 | 9 | You can configure it in the `eslint` object in the *app/config.json* file. 10 | 11 | Example: 12 | 13 | ``` 14 | "eslint": { 15 | "extends": "airbnb", 16 | "rules": { 17 | "semi": [ 18 | "error", 19 | "never" 20 | ] 21 | } 22 | } 23 | ``` 24 | 25 | Currently, `airbnb` and `standard` are available to extend - if you wish to extend another shared configuration, please ask for it in our [issue list](https://github.com/scriptPilot/app-framework/issues). 26 | -------------------------------------------------------------------------------- /docs/dev-requirements.md: -------------------------------------------------------------------------------- 1 | # Requirements 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | ## App Framework 8 | 9 | Before you develop for App Framework itself, you should be familiar how to work with App Framework in your own application. So, please follow the [end user documentation](../DOCUMENTATION.md) first. 10 | 11 | ## Enable development mode 12 | 13 | To inform end users about wrong App Framework usage (forking instead of installing as a module), there is an error message on each script call. 14 | 15 | For App Framework development, you have to create an empty file *.enable-dev-mode* in the project folder to suppress this warning. 16 | -------------------------------------------------------------------------------- /docs/editorconfigFile.md: -------------------------------------------------------------------------------- 1 | # Configure .editorconfig file 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | The *.editorconfig* file will be updated automatically. You can configure it in the `editorConfig` item in the *app/config.json* file. 8 | 9 | To write a line without value, for example `[*]`, assign value `null`, else assign the value as string or number. 10 | 11 | Example: 12 | 13 | ``` 14 | "editorConfig": { 15 | "root": "true", 16 | "[*]": null, 17 | "indent_style": "space", 18 | "indent_size": 2, 19 | "charset": "utf-8", 20 | "trim_trailing_whitespace": "true", 21 | "insert_final_newline": "true", 22 | "end_of_line": "lf", 23 | "max_line_length": "null" 24 | } 25 | ``` 26 | -------------------------------------------------------------------------------- /demo/pages/f7material/animation.vue: -------------------------------------------------------------------------------- 1 | 18 | -------------------------------------------------------------------------------- /demo/pages/f7ios/bars-no-toolbar.vue: -------------------------------------------------------------------------------- 1 | 19 | -------------------------------------------------------------------------------- /demo/pages/f7material/panel-right2.vue: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /demo/pages/f7material/panel-right3.vue: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /demo/pages/f7material/bars-no-toolbar.vue: -------------------------------------------------------------------------------- 1 | 19 | -------------------------------------------------------------------------------- /demo/pages/f7ios/panel-right2.vue: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /demo/pages/f7ios/panel-right3.vue: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /docs/build.md: -------------------------------------------------------------------------------- 1 | # Build your application 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | To deploy your application you need to build it before. App Framework makes it quite easy for you, bumps the version, compiles the scripts and merges them together. Your logo is used to create many icons and launch screen graphics and at the end all files are compressed to save bandwidth. 8 | 9 | GZIP compression will be done in addition after deployment to Firebase hosting. 10 | 11 | Each build command will update the *build* folder on success. 12 | 13 | - Run `npm run patch` after bug-fixes and improvements (version bump to x.y.z+1) 14 | - Run `npm run minor` after adding new functionality (version bump to x.y+1.0) 15 | - Run `npm run major` after breaking backward-capability (version bump to x+1.0.0) 16 | -------------------------------------------------------------------------------- /demo/pages/f7ios/animation.vue: -------------------------------------------------------------------------------- 1 | 20 | -------------------------------------------------------------------------------- /demo/pages/f7ios/bars-deep-navbar.vue: -------------------------------------------------------------------------------- 1 | 19 | -------------------------------------------------------------------------------- /docs/dev-trouble-shooting.md: -------------------------------------------------------------------------------- 1 | # Trouble shooting 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | The following points should be checked for trouble shooting: 8 | 9 | - Cache is reset (could be done with `npm run reset`) 10 | - No interferences with other files 11 | - Only absolute paths used 12 | - process.env allways considered as object with strings (`process.env.ANY === 'true'`) 13 | - All `require()` commands contain only strings and/or `process.env[...]` as variable 14 | - Values from `window.localStorage` are parsed with `JSON.parse()` before usage 15 | 16 | Let us know if you have points to add. 17 | 18 | ## Debug mode 19 | 20 | Debug mode could be enabled with `debug: true` in the app config file. In code, whenever `env.debug(...)` is called, the input will be logged to debug.log file in the project folder. 21 | -------------------------------------------------------------------------------- /demo/pages/f7material/bars-deep-navbar.vue: -------------------------------------------------------------------------------- 1 | 19 | -------------------------------------------------------------------------------- /scripts/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "gitignore": { 3 | "_SYNCAPP/": true, 4 | ".git/": true, 5 | "node_modules/": true, 6 | "snapshots/": true, 7 | ".DS_Store": true, 8 | ".enable-dev-mode": true, 9 | "*.log*": true, 10 | "*.zip": true, 11 | "database-backup.json": true, 12 | "ftp-config.json": true, 13 | ".eslintrc": true, 14 | ".editorconfig": true 15 | }, 16 | "npmignore": { 17 | "_SYNCAPP/": true, 18 | ".git/": true, 19 | "node_modules/": true, 20 | "snapshots/": true, 21 | ".DS_Store": true, 22 | ".enable-dev-mode": true, 23 | "*.log*": true, 24 | "*.zip": true, 25 | "database-backup.json": true, 26 | "ftp-config.json": true, 27 | ".eslintrc": true, 28 | ".editorconfig": true, 29 | "build/": true, 30 | "demo/": true, 31 | "docs/": true, 32 | "DOCUMENTATION.md": true, 33 | "media/": true 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /docs/design.md: -------------------------------------------------------------------------------- 1 | # Design your application 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | ## Paper and pencil 8 | 9 | - Use our printable [smartphone template](../design/smartphone-template.pdf) to sketch your application 10 | - Use our printable [icon template](../design/icon-template.pdf) to sketch your application icon 11 | 12 | ## Icon creation 13 | 14 | Use our Power Point [icon template](../design/icon-template.pptx) to create your application icon. Select all elements, right click, save as image, save as *app/icon.png*. 15 | 16 | ## Design guidelines 17 | 18 | - For UI components: [http://v1.framework7.io/vue](http://v1.framework7.io/vue) 19 | - For iOS: [https://developer.apple.com/ios/human-interface-guidelines](https://developer.apple.com/ios/human-interface-guidelines) 20 | - For Material: [https://material.io/guidelines/](https://material.io/guidelines) 21 | -------------------------------------------------------------------------------- /scripts/jobs/updateEditorconfigFile.js: -------------------------------------------------------------------------------- 1 | // Purpose: Update .gitignore and .npmignore files bases on the scripts and app configuration 2 | 3 | // Load modules 4 | const path = require('../path') 5 | const fs = require('fs-extra') 6 | const _ = require('lodash') 7 | 8 | // Export promise 9 | module.exports = new Promise((resolve, reject) => { 10 | 11 | // Load configuration file 12 | const appConfig = fs.readJsonSync(path.app('config.json')) 13 | 14 | // Create file content 15 | let content = '' 16 | 17 | // Loop config options 18 | for (let item in appConfig.editorConfig) { 19 | content = content + item + (appConfig.editorConfig[item] ? ' = ' + appConfig.editorConfig[item] : '') + '\n' 20 | } 21 | 22 | // Create/update .editorconfig file 23 | fs.writeFile(path.pkg('.editorconfig'), content, (err) => { 24 | if (err) throw err 25 | 26 | // Resolve promise 27 | resolve() 28 | 29 | }) 30 | 31 | }) 32 | -------------------------------------------------------------------------------- /demo/pages/f7ios/login-screen.vue: -------------------------------------------------------------------------------- 1 | 20 | -------------------------------------------------------------------------------- /demo/pages/f7material/login-screen.vue: -------------------------------------------------------------------------------- 1 | 20 | -------------------------------------------------------------------------------- /scripts/addLoginPopup.js: -------------------------------------------------------------------------------- 1 | // Purpose: Add missing login popup to app.vue file 2 | 3 | // Import modules 4 | const env = require('./env') 5 | const alert = require('./alert') 6 | const abs = require('path').resolve 7 | const fs = require('fs-extra') 8 | 9 | // Run 10 | fs.readFile(abs(env.app, 'app.vue'), {encoding: 'utf8'}, (err, str) => { 11 | if (err) alert('Failed to read app.vue file', 'issue') 12 | const appElementFound = str.match(//) 13 | const loginPopupElementFound = str.match(//) 14 | if (!appElementFound) { 15 | alert('No #app element found in the app.vue file. Please read the documentation.', 'error') 16 | } else if (!loginPopupElementFound) { 17 | const newStr = str.replace(//, '\n ') 18 | fs.writeFile(abs(env.app, 'app.vue'), newStr, (err) => { 19 | if (err) alert('Failed to write app.vue file.', 'issue') 20 | alert('Updated app.vue file.') 21 | }) 22 | } 23 | }) 24 | -------------------------------------------------------------------------------- /client/sort-object.js: -------------------------------------------------------------------------------- 1 | /* Purpose: Exports function to sort an object by any property in ascending or descending order */ 2 | 3 | 'use strict' 4 | 5 | module.exports = function (obj, sortBy, sortDesc) { 6 | sortDesc = sortDesc === true || sortDesc === 'desc' || sortDesc === 'DESC' 7 | let arr = [] 8 | for (let el in obj) { 9 | arr.push({ 10 | '.key': el, 11 | '.sort': obj[el][sortBy] ? obj[el][sortBy] : '' 12 | }) 13 | } 14 | arr.sort(function (a, b) { 15 | let result = null 16 | if (a['.sort'] === b['.sort'] === '') { 17 | result = 0 18 | } else if (a['.sort'] === '') { 19 | result = -1 20 | } else if (b['.sort'] === '') { 21 | result = 1 22 | } else { 23 | result = a['.sort'] - b['.sort'] 24 | } 25 | result = sortDesc ? -1 * result : result 26 | return result 27 | }) 28 | let sortedObj = {} 29 | for (let e = 0; e < arr.length; e++) { 30 | sortedObj[arr[e]['.key']] = obj[arr[e]['.key']] 31 | } 32 | return sortedObj 33 | } 34 | -------------------------------------------------------------------------------- /client/theme-colors.json: -------------------------------------------------------------------------------- 1 | { 2 | "ios": { 3 | "blue": "007aff", 4 | "red": "ff3b30", 5 | "white": "ffffff", 6 | "black": "000000", 7 | "lightblue": "5ac8fa", 8 | "yellow": "ffcc00", 9 | "orange": "ff9500", 10 | "pink": "ff2d55", 11 | "green": "4cd964", 12 | "gray": "8e8e93" 13 | }, 14 | "material": { 15 | "red": "f44336", 16 | "pink": "e91e63", 17 | "purple": "9c27b0", 18 | "deeppurple": "673ab7", 19 | "indigo": "3f51b5", 20 | "blue": "2196f3", 21 | "lightblue": "03a9f4", 22 | "cyan": "00bcd4", 23 | "teal": "009688", 24 | "green": "4caf50", 25 | "lightgreen": "8bc34a", 26 | "lime": "cddc39", 27 | "yellow": "ffeb3b", 28 | "amber": "ffc107", 29 | "orange": "ff9800", 30 | "deeporange": "ff5722", 31 | "brown": "795548", 32 | "gray": "9e9e9e", 33 | "bluegray": "607d8b", 34 | "white": "ffffff", 35 | "black": "000000" 36 | }, 37 | "default": { 38 | "ios": "blue", 39 | "material": "blue" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /demo/pages/f7ios/notifications.vue: -------------------------------------------------------------------------------- 1 | 20 | -------------------------------------------------------------------------------- /docs/knowledge.md: -------------------------------------------------------------------------------- 1 | # Knowledge requirements 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | Before you start to work with App Framework, you should be familiar with the following documentation. 8 | 9 | ## Essentiell 10 | 11 | - [Node.js and npm](https://docs.npmjs.com/getting-started/what-is-npm) for command line interface handling 12 | - [Framework7](https://v1.framework7.io/docs/) and [Framework7-Vue](https://v1.framework7.io/vue/) to develop with HTML and JavaScript 13 | 14 | ## Optional 15 | 16 | - [Vue.js](https://vuejs.org/v2/guide/) to make your application state-based and reactive 17 | - [Firebase](https://firebase.google.com/docs/web/setup) to use the reliable backend service provider 18 | - [Cordova/PhoneGap](https://cordova.apache.org/docs/en/latest/) to use device hardware API plugins 19 | - [iOS design guidelines](https://developer.apple.com/ios/human-interface-guidelines/overview/design-principles/) and [Material design guidelines](https://material.io/guidelines/) 20 | -------------------------------------------------------------------------------- /scripts/jobs/updateEslintrcFile.js: -------------------------------------------------------------------------------- 1 | // Purpose: Update .eslintrc file according the app config file 2 | 3 | // Load modules 4 | const path = require('../path') 5 | const fs = require('fs-extra') 6 | 7 | // Export promise 8 | module.exports = new Promise((resolve, reject) => { 9 | 10 | // Load configuration file 11 | const appConfig = fs.readJsonSync(path.app('config.json')) 12 | 13 | // Create configuration object 14 | const eslintConfig = appConfig.eslint 15 | 16 | // Rewrite airbnb to airbnb-base 17 | if (eslintConfig.extends === 'airbnb') { 18 | eslintConfig.extends = 'airbnb-base' 19 | } 20 | 21 | // Add Vue plugin 22 | eslintConfig.plugins = ['vue'] 23 | 24 | // Add Node and browser environments 25 | eslintConfig.env = { 26 | browser: true, 27 | node: true 28 | } 29 | 30 | // Create/update .eslintrc file 31 | fs.writeJson(path.pkg('.eslintrc'), eslintConfig, { spaces: 2 }, (err) => { 32 | if (err) { 33 | reject('Failed to update the ESLint configuration file.') 34 | } else { 35 | resolve() 36 | } 37 | }) 38 | 39 | }) 40 | -------------------------------------------------------------------------------- /demo/pages/f7material/notifications.vue: -------------------------------------------------------------------------------- 1 | 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 scriptPilot 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/material-icons/material-icons.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Material Icons'; 3 | font-style: normal; 4 | font-weight: 400; 5 | src: url(MaterialIcons-Regular.eot); /* For IE6-8 */ 6 | src: local('Material Icons'), 7 | local('MaterialIcons-Regular'), 8 | url(MaterialIcons-Regular.woff2) format('woff2'), 9 | url(MaterialIcons-Regular.woff) format('woff'), 10 | url(MaterialIcons-Regular.ttf) format('truetype'); 11 | } 12 | 13 | .material-icons { 14 | font-family: 'Material Icons'; 15 | font-weight: normal; 16 | font-style: normal; 17 | font-size: 24px; /* Preferred icon size */ 18 | display: inline-block; 19 | line-height: 1; 20 | text-transform: none; 21 | letter-spacing: normal; 22 | word-wrap: normal; 23 | white-space: nowrap; 24 | direction: ltr; 25 | 26 | /* Support for all WebKit browsers. */ 27 | -webkit-font-smoothing: antialiased; 28 | /* Support for Safari and Chrome. */ 29 | text-rendering: optimizeLegibility; 30 | 31 | /* Support for Firefox. */ 32 | -moz-osx-font-smoothing: grayscale; 33 | 34 | /* Support for IE. */ 35 | font-feature-settings: 'liga'; 36 | } 37 | -------------------------------------------------------------------------------- /docs/image-upload-component.md: -------------------------------------------------------------------------------- 1 | # Image upload component 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | In native iOS or Android applications, the `` element does not work. 8 | 9 | App Framework provides you a component, to upload an image to Firebase storage and save the image URI to the Firebase database. 10 | 11 | ## Configuration 12 | 13 | In the configuration file, you have to add the following Cordova plugins: 14 | 15 | ``` 16 | "useCordovaPlugins": [ 17 | "cordova-plugin-camera", 18 | "cordova-plugin-file" 19 | ] 20 | ``` 21 | 22 | ## Usage 23 | 24 | Just add the following component to any of your page components: 25 | 26 | ``` 27 | 28 | 29 | 30 | ``` 31 | 32 | - `store` is the Firebase storage path to your image (string, no extension) 33 | - `db` is the Firebase database path to save the image URI (string, optional) 34 | - `size` is the maximum image width or height (number, optional, ratio kept) 35 | 36 | Please take care that the storage rules and database rules are correctly configured. 37 | -------------------------------------------------------------------------------- /demo/pages/f7material/swiper-fade.vue: -------------------------------------------------------------------------------- 1 | 22 | -------------------------------------------------------------------------------- /client/application-frame.css: -------------------------------------------------------------------------------- 1 | /* Body background color */ 2 | .limitHeight, 3 | .limitWidth { 4 | background: #333333; 5 | } 6 | .phoneFrame { 7 | background: #fafafa; 8 | } 9 | 10 | /* Default frame size and position */ 11 | #frame { 12 | position: absolute; 13 | height: 100%; 14 | width: 100%; 15 | } 16 | 17 | /* Phone frame */ 18 | .phoneFrame #frame { 19 | background: #111; 20 | border-radius: 55px; 21 | box-shadow: 0px 0px 0px 2px #aaa; 22 | margin: -105px -25px; 23 | padding: 105px 25px; 24 | } 25 | 26 | /* Display */ 27 | .phoneFrame #frame .framework7-root { 28 | background: #191919; 29 | } 30 | 31 | /* Speaker */ 32 | .phoneFrame #frame:after { 33 | content: ''; 34 | position: absolute; 35 | width: 60px; 36 | height: 60px; 37 | left: 50%; 38 | margin-left: -30px; 39 | bottom: 20px; 40 | border-radius: 100%; 41 | box-sizing: border-box; 42 | border: 5px solid #333; 43 | } 44 | 45 | /* Home button */ 46 | .phoneFrame #frame:before { 47 | position: absolute; 48 | left: 50%; 49 | margin-left: -30px; 50 | top: 50px; 51 | content: ''; 52 | background: #333; 53 | width: 60px; 54 | height: 10px; 55 | border-radius: 10px; 56 | } 57 | -------------------------------------------------------------------------------- /demo/pages/f7ios/swiper-fade.vue: -------------------------------------------------------------------------------- 1 | 22 | -------------------------------------------------------------------------------- /demo/pages/f7ios/panels.vue: -------------------------------------------------------------------------------- 1 | 23 | -------------------------------------------------------------------------------- /demo/pages/flexible-routing.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 33 | -------------------------------------------------------------------------------- /demo/pages/f7material/panels.vue: -------------------------------------------------------------------------------- 1 | 23 | -------------------------------------------------------------------------------- /demo/pages/f7material/swiper-loop.vue: -------------------------------------------------------------------------------- 1 | 28 | -------------------------------------------------------------------------------- /demo/pages/f7ios/swiper-loop.vue: -------------------------------------------------------------------------------- 1 | 28 | -------------------------------------------------------------------------------- /demo/pages/f7material/swiper-horizontal.vue: -------------------------------------------------------------------------------- 1 | 28 | -------------------------------------------------------------------------------- /demo/pages/f7ios/swiper-horizontal.vue: -------------------------------------------------------------------------------- 1 | 28 | -------------------------------------------------------------------------------- /demo/pages/f7material/swiper-vertical.vue: -------------------------------------------------------------------------------- 1 | 28 | -------------------------------------------------------------------------------- /demo/pages/f7material/swiper-scrollbar.vue: -------------------------------------------------------------------------------- 1 | 29 | -------------------------------------------------------------------------------- /demo/pages/f7material/swiper-pagination-fraction.vue: -------------------------------------------------------------------------------- 1 | 28 | -------------------------------------------------------------------------------- /demo/pages/f7material/swiper-pagination-progress.vue: -------------------------------------------------------------------------------- 1 | 28 | -------------------------------------------------------------------------------- /demo/pages/f7ios/floating-button.vue: -------------------------------------------------------------------------------- 1 | 33 | -------------------------------------------------------------------------------- /demo/pages/f7ios/swiper-pagination-fraction.vue: -------------------------------------------------------------------------------- 1 | 28 | -------------------------------------------------------------------------------- /demo/pages/f7ios/swiper-pagination-progress.vue: -------------------------------------------------------------------------------- 1 | 28 | -------------------------------------------------------------------------------- /demo/pages/f7ios/swiper-scrollbar.vue: -------------------------------------------------------------------------------- 1 | 29 | -------------------------------------------------------------------------------- /demo/pages/f7ios/swiper-vertical.vue: -------------------------------------------------------------------------------- 1 | 28 | -------------------------------------------------------------------------------- /docs/icon-fonts.md: -------------------------------------------------------------------------------- 1 | # Icon fonts 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | ## Configuration 8 | 9 | App Framework is well prepared to use comprehensive icon fonts for your application. 10 | 11 | To use an icon font, you have to set `true` in the configuration: 12 | 13 | ``` 14 | "useIconFonts": { 15 | "framework7": false, 16 | "material": true, 17 | "ion": false, 18 | "fontawesome": false 19 | } 20 | ``` 21 | 22 | After you changed the configuration, you have to restart the development server. 23 | 24 | Each additional icon font will increase your build size. 25 | 26 | ## Usage 27 | 28 | As an example with Material Design Icons: 29 | 30 | - HTML: `done` 31 | - Framework7-Vue: `` 32 | 33 | ## Icon overview 34 | 35 | - [Framework7 Icons](https://framework7.io/icons/) 36 | - [Material Design Icons](https://material.io/icons/) 37 | - [Ion Icons](http://ionicons.com/) 38 | - [FontAwesome Icons](http://fontawesome.io/icons/) 39 | 40 | ## Legacy support 41 | 42 | To display icon fonts in older browsers and Android versions, App Framework will automatically replace ligatures to code. Currently, this works only for the Material icon fonts. 43 | 44 | Example: `` will generate `` 45 | -------------------------------------------------------------------------------- /scripts/path.js: -------------------------------------------------------------------------------- 1 | // Purpose: Provide function to get absolute path 2 | 3 | // Load modules 4 | const fs = require('fs') 5 | const path = require('path') 6 | 7 | // Check if App Framework is installed as a module or not 8 | const isInstalled = fs.existsSync(path.resolve(__dirname, '../../../package.json')) 9 | 10 | // Export functions to get absolute path 11 | module.exports = { 12 | // Package 13 | pkg (...args) { 14 | return isInstalled ? path.resolve(__dirname, '../../../', ...args) : path.resolve(__dirname, '../', ...args) 15 | }, 16 | // App folder 17 | app (...args) { 18 | return isInstalled ? path.resolve(__dirname, '../../../app', ...args) : path.resolve(__dirname, '../demo', ...args) 19 | }, 20 | // Node modules folder 21 | modules (...args) { 22 | return isInstalled ? path.resolve(__dirname, '../../../node_modules/', ...args) : path.resolve(__dirname, '../node_modules/', ...args) 23 | }, 24 | // Cache folder 25 | cache (...args) { 26 | return isInstalled ? path.resolve(__dirname, '../../../node_modules/.app-framework-cache/', ...args) : path.resolve(__dirname, '../node_modules/.app-framework-cache/', ...args) 27 | }, 28 | // Scripts folder 29 | scripts (...args) { 30 | return isInstalled ? path.resolve(__dirname, '../../../node_modules/app-framework/scripts/', ...args) : path.resolve(__dirname, '../scripts/', ...args) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /scripts/alert.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Purpose: Clear console, show message and exit script optionally. 4 | 5 | Usage: alert(message , [type <"error"/"issue"/"exit">]) 6 | 7 | Type argument: 8 | - "error" to show "Error: " and exit script with error status 9 | - "issue" as above plus a request to open an issue on GitHub 10 | - "exit" ro show "" and exit without error status 11 | 12 | */ 13 | 14 | 'use strict' 15 | 16 | module.exports = function (message, type) { 17 | // Set default values for missing message 18 | if (message === undefined) { 19 | message = 'Missing argument "message" for function alert().' 20 | type = 'issue' 21 | } 22 | // Prefix error keyword 23 | if (type === 'error' || type === 'issue') { 24 | message = 'Error: ' + message 25 | } 26 | // Append GitHub information 27 | if (type === 'issue') { 28 | message = message + '\n\nPlease open an incident on GitHub:\nhttps://github.com/scriptPilot/app-framework/issues' 29 | } 30 | // Reset console window, show message and line breaks 31 | process.stdout.write('\x1bc' + message + '\n\n') 32 | // Exit script 33 | if (type === 'error' || type === 'issue' || type === 'exit') { 34 | // Define exit code 35 | let exitCode = (type === 'error' || type === 'issue') && process.env.subProcess === 'true' ? 1 : 0 36 | // Exit 37 | process.exit(exitCode) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /demo/pages/f7ios/timeline.vue: -------------------------------------------------------------------------------- 1 | 38 | -------------------------------------------------------------------------------- /demo/pages/f7material/timeline.vue: -------------------------------------------------------------------------------- 1 | 38 | -------------------------------------------------------------------------------- /demo/pages/f7material/swiper-space-between.vue: -------------------------------------------------------------------------------- 1 | 28 | -------------------------------------------------------------------------------- /demo/pages/f7material/login-screen-embedded.vue: -------------------------------------------------------------------------------- 1 | 34 | -------------------------------------------------------------------------------- /demo/pages/f7ios/swiper-space-between.vue: -------------------------------------------------------------------------------- 1 | 28 | -------------------------------------------------------------------------------- /docs/sort-object.md: -------------------------------------------------------------------------------- 1 | # sortObject function 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | To sort an object, for example the result of a Firebase query, you can use the following function, which is attached to the window object. 8 | 9 | `window.sortObject(obj, sortBy, sortDesc)` 10 | 11 | - obj: Object to sort 12 | - sortBy: Property to take for sorting 13 | - sortDesc: undefined or 'desc' 14 | 15 | ``` 16 | let objUnsorted = { 17 | keyA: { 18 | name: 'Berta', 19 | age: 25 20 | }, 21 | keyB: { 22 | name: 'Aaron', 23 | age: 40 24 | }, 25 | keyC: { 26 | name: `Charlie`, 27 | age: 30 28 | } 29 | } 30 | ``` 31 | 32 | Sort by name ascending: 33 | 34 | ``` 35 | let objSortedByName = window.sortObject(objUnsorted, 'name') 36 | { 37 | keyB: { name: 'Aaron', age: 40 }, 38 | keyA: { name: 'Berta', age: 25 }, 39 | keyC: { name: `Charlie`, age: 30 } 40 | } 41 | ``` 42 | 43 | Sort by age descending: 44 | 45 | ``` 46 | let objSortedByAgeDesc = window.sortObject(objectUnsorted, 'age', 'desc') 47 | { 48 |  keyB: { name: 'Aaron', age: 40 }, 49 | keyC: { name: `Charlie`, age: 30 }, 50 | keyA: { name: 'Berta', age: 25 }  51 | } 52 | ``` 53 | 54 | For more complex data manipulation you can think about the integration of [Underscore.js](http://underscorejs.org/) or [Lodash](https://lodash.com/). Please see the chapter [Modules and Scripts](modules-and-scripts.md) for details 55 | -------------------------------------------------------------------------------- /client/init.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | height: 100%; 3 | margin: 0; 4 | line-height: 1.5; 5 | } 6 | #hiddenOverlay: { 7 | z-index: 1 8 | } 9 | #loadingOverlay: { 10 | z-index: 2 11 | } 12 | #loadingOverlay, 13 | #errorOverlay { 14 | position: fixed; 15 | top: 0; 16 | left: 0; 17 | height: 100%; 18 | width: 100%; 19 | } 20 | #loadingOverlay .inner, 21 | #errorOverlay .inner { 22 | position: relative; 23 | top: calc(50% - 50px - 30px - 25px - 5px); 24 | } 25 | #loadingOverlay .icon, 26 | #errorOverlay .icon { 27 | height: 100px; 28 | text-align: center; 29 | } 30 | #loadingOverlay .icon img, 31 | #errorOverlay .icon img { 32 | width: 100px; 33 | height: 100px; 34 | } 35 | #loadingOverlay .title, 36 | #errorOverlay .title { 37 | padding: 20px 0 20px; 38 | font-size: 20px; 39 | font-family: Verdana, sans-serif; 40 | color: #848484; 41 | text-align: center; 42 | } 43 | #loadingOverlay .progressBar { 44 | margin: 0 auto; 45 | height: 6px; 46 | width: 100px; 47 | padding: 1px; 48 | border: 1px solid #4caf50; 49 | border-radius: 5px; 50 | background: #ffffff; 51 | } 52 | #loadingOverlay .progressBarInner { 53 | width: 0; 54 | height: 6px; 55 | background-color: #4caf50; 56 | border-radius: 3px; 57 | } 58 | #loadingOverlay .spinner { 59 | position: relative; 60 | height: 50px; 61 | } 62 | #errorOverlay .error { 63 | font-size: 10px; 64 | font-family: Verdana, sans-serif; 65 | color: #ff3b30; 66 | text-align: center; 67 | } 68 | -------------------------------------------------------------------------------- /scripts/jobs/updateIgnoreFiles.js: -------------------------------------------------------------------------------- 1 | // Purpose: Update .gitignore and .npmignore files bases on the scripts and app configuration 2 | 3 | // Load modules 4 | const path = require('../path') 5 | const fs = require('fs-extra') 6 | const _ = require('lodash') 7 | 8 | // Export promise 9 | module.exports = new Promise((resolve, reject) => { 10 | 11 | // Load configuration files 12 | const scriptConfig = fs.readJsonSync(path.scripts('config.json')) 13 | const appConfig = fs.readJsonSync(path.app('config.json')) 14 | 15 | // Define function to update file 16 | const updateFile = (type) => { 17 | // Check parameters 18 | if (type !== 'git' && type !== 'npm') throw new Error('Type must be either "git" or "npm".') 19 | // Merge configurations 20 | const mergedConfig = _.merge(scriptConfig[`${type}ignore`], appConfig[`${type}ignore`]) 21 | // Filter and sort config 22 | const sortedConfig = _(mergedConfig).toPairs().filter([1, true]).sortBy(0).fromPairs().value() 23 | // Create file content 24 | let fileContent = '# This file is updated automatically, please add or remove files in the configuration file.\n\n' 25 | _.forEach(sortedConfig, (toBeIgnored, filePath) => fileContent += filePath + '\n') 26 | // Create/update file 27 | fs.writeFileSync(path.pkg('.' + type + 'ignore'), fileContent) 28 | } 29 | 30 | // Run function 31 | updateFile('git') 32 | updateFile('npm') 33 | 34 | // Resolve Promise 35 | resolve() 36 | 37 | }) 38 | -------------------------------------------------------------------------------- /demo/pages/f7ios/login-screen-embedded.vue: -------------------------------------------------------------------------------- 1 | 36 | -------------------------------------------------------------------------------- /docs/cli-commands.md: -------------------------------------------------------------------------------- 1 | # CLI commands 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | ![Process](../media/cli-commands.png) 8 | 9 | - Setup 10 | - `npm install` to install App Framework and setup the project folder 11 | - `npm update` to update App Framework to the latest sub version 12 | 13 | - Testing 14 | - `npm run dev` to start the development server 15 | - `CTRL + C` to stop the development server 16 | - `npm run ios` to open an iOS emulator with a development build 17 | - `npm run android` to open an Android emulator with a development build 18 | 19 | - Building 20 | - `npm run patch` to build after bug-fixes and improvements 21 | - `npm run minor` to build after adding new functionality 22 | - `npm run major` to build after backward-capability breaking changes 23 | 24 | - Deployment 25 | - `npm run firebase` to deploy rules and static files to Firebase 26 | - `npm run database` to deploy database rules to Firebase 27 | - `npm run storage` to deploy storage rules to Firebase 28 | - `npm run hosting` to deploy static files to Firebase 29 | - `npm run ftp` to deploy static files to your FTP server 30 | - `npm run xcode` to deploy static files as iOS Xcode project 31 | - `npm run studio` to deploy static files as Android Studio project 32 | 33 | - Backup 34 | - `npm run backup` to create snapshots of the Firebase database and user list 35 | - `npm run snapshot` to create a snapshot of your project folder 36 | -------------------------------------------------------------------------------- /docs/setup.md: -------------------------------------------------------------------------------- 1 | # Setup your project 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | ## Installation 8 | 9 | Creating a new application project *my-app* is easily done in the following four steps: 10 | 11 | 1. Run `mkdir my-app` to create a new folder *my-app* 12 | 2. Run `cd my-app` to open the folder *my-app* 13 | 3. Run `echo {} > package.json` to create a *package.json* file 14 | 4. Run `npm install --save-dev app-framework@1` to 15 | - install App Framework and its dependencies 16 | - create the project folder structure 17 | - complete the *package.json* file 18 | 19 | After the installation process finished, you should see [this folder structure](folder-structure.md). 20 | 21 | You can run `npm run dev` to see if your new app opens in the browser. 22 | 23 | ## Update 24 | 25 | If there is a newer version of App Framework available at the [npm repository](https://www.npmjs.com/package/app-framework), there will be an alert at the development server. 26 | 27 | You have to update App Framework per application project by running `npm update --save-dev app-framework`. 28 | 29 | ## Notes 30 | 31 | The proper way to install the App Framework is to include it as a dev-dependency in your app's *package.json* file, i.e. it must be installed as a module, and not cloned as a repo. The *npm install* command will generate the appropriate directories in your app's root directory, and will add the relevant scripts to your app's *package.json* file. 32 | -------------------------------------------------------------------------------- /demo/pages/f7material/virtual-list.vue: -------------------------------------------------------------------------------- 1 | 33 | -------------------------------------------------------------------------------- /docs/dev-folder-structure.md: -------------------------------------------------------------------------------- 1 | # Folder structure 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | ``` 8 | ├── .git/ # Git managed folder (do not modify) 9 | ├── build/ # Latest build files 10 | ├── client/ # Client code files 11 | ├── demo/ # Demo App files 12 | ├── design/ # Design templates (PDF and PPTX) 13 | ├── docs/ # Documentation files (configuration.md is updated on each build) 14 | ├── media/ # Graphics for documentation and promotion 15 | ├── node_modules/ # Installed node modules (do not modify) 16 | ├── scripts/ # Scripts and supporting files 17 | ├── snapshots/ # Snapshot files 18 | ├── vendor/ # Vendor files 19 | ├── .babelrc # Babel configuration file 20 | ├── .gitignore # List of ignored files for Git commits 21 | ├── CHANGELOG.md # Release changelog 22 | ├── config-scheme.json # Scheme for any application configuration file 23 | ├── DEVELOPMENT.md # Development documentation main page 24 | ├── DOCUMENTATION # End user documentation main page 25 | ├── LICENSE # App Framework license file (year is updated on each build) 26 | ├── package.json # App Framework project information 27 | └── README.md # Introduction, Features, Demo App, Documentation link 28 | ``` 29 | -------------------------------------------------------------------------------- /demo/pages/f7material/swiper-nested.vue: -------------------------------------------------------------------------------- 1 | 31 | -------------------------------------------------------------------------------- /docs/cordova-plugins.md: -------------------------------------------------------------------------------- 1 | # Cordova plugins 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | ## Configuration 8 | 9 | App Framework supports well the usage of Cordova / PhoneGap plugins. You just have to add them in the configuration file. Example with [cordova-plugin-badge](https://github.com/katzer/cordova-plugin-badge): 10 | 11 | ``` 12 | useCordovaPlugins: [ 13 | "cordova-plugin-badge" 14 | ] 15 | ``` 16 | 17 | ## Usage 18 | 19 | You can use the plugin now in any of your components. Example: 20 | 21 | ``` 22 | 30 | ``` 31 | 32 | Take care to use `window.` to access any plugin. 33 | 34 | ## Plugin repository 35 | 36 | You find a list of available plugins here: [https://cordova.apache.org/plugins](https://cordova.apache.org/plugins) 37 | 38 | ## Default plugins 39 | 40 | By default, [cordova-plugin-whitelist](https://github.com/apache/cordova-plugin-whitelist) and [cordova-plugin-statusbar](https://github.com/apache/cordova-plugin-statusbar) are included in the build. 41 | 42 | To simplify the usage, App Framework provides you an easier way to manipulate the status bar - please read the chapter [Status bar style](status-bar-style.md) for details. 43 | 44 | ## Availability 45 | 46 | Cordova plugins are only available in native applications or emulators, in the browser, they are undefined. 47 | -------------------------------------------------------------------------------- /demo/pages/f7ios/swiper-nested.vue: -------------------------------------------------------------------------------- 1 | 31 | -------------------------------------------------------------------------------- /scripts/snapshot.js: -------------------------------------------------------------------------------- 1 | /* Purpose: Creates snapshot with current day as name, increase with character in case there are more than one snapshots per day */ 2 | 3 | 'use strict' 4 | 5 | // Include modules 6 | let env = require('./env') 7 | let alert = require('./alert') 8 | let cmd = require('./cmd') 9 | let found = require('./found') 10 | let fs = require('fs-extra') 11 | let abs = require('path').resolve 12 | 13 | // Define filename 14 | let now = new Date() 15 | let name = 'snapshot-' + now.getFullYear() + '-' + (now.getMonth() < 9 ? '0' : '') + (now.getMonth() + 1) + '-' + (now.getDate() < 10 ? '0' : '') + now.getDate() 16 | 17 | // Define filename and create snapshot 18 | let createSnapshot = function (name, char) { 19 | // Start empty 20 | char = char || '' 21 | // Check if file exists 22 | if (char !== '' && char > 122) { 23 | alert('More than ' + (char - 97) + ' snapshots per day are not supported.', 'error') 24 | } else if (!found(env.proj, 'snapshots', name + (char === '' ? '' : String.fromCharCode(char)) + '.zip') && (char !== '' || !found(env.proj, 'snapshots', name + 'a.zip'))) { 25 | // Extend first one with a 26 | if (char === 98) { 27 | fs.renameSync(abs(env.proj, 'snapshots', name + '.zip'), abs(env.proj, 'snapshots', name + 'a.zip')) 28 | } 29 | name = name + (char === '' ? '' : String.fromCharCode(char)) 30 | // Create snapshot 31 | cmd(__dirname, 'node create-snapshot --name ' + name) 32 | } else { 33 | return createSnapshot(name, char === '' ? 98 : char + 1) 34 | } 35 | } 36 | createSnapshot(name) 37 | -------------------------------------------------------------------------------- /demo/pages/f7ios/virtual-list.vue: -------------------------------------------------------------------------------- 1 | 33 | -------------------------------------------------------------------------------- /docs/page-components.md: -------------------------------------------------------------------------------- 1 | # Page components 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | The structure of each page component is defined in a Framework7-Vue component, so you should be familar with [Vue.js single file components](https://vuejs.org/v2/guide/single-file-components.html) as well as [Framework7-Vue](http://v1.framework7.io/vue/). 8 | 9 | ## File naming 10 | 11 | For page component naming, please read the chapter [Routing](routing.md). 12 | 13 | ## Structure 14 | 15 | A basic page component could look like this *app/pages/home.vue* file: 16 | 17 | ``` 18 | 26 | ``` 27 | 28 | Please read the [Framework7-Vue documentation](http://v1.framework7.io/vue/page.html) for page component structure details. 29 | 30 | To add CSS, you use the *style* block: 31 | 32 | ``` 33 | ... 34 | 35 | 40 | ``` 41 | 42 | To scope the style only for that page component, use ` 31 | ``` 32 | 33 | And to add functionality, you use the *script* block: 34 | 35 | ``` 36 | ... 37 | 46 | ``` 47 | 48 | In [Framework7-Vue documentation](http://v1.framework7.io/vue/app-layout.html), the app component is described as the *#app* div - you will find all details there. 49 | 50 | [Babel / ES2015](https://babeljs.io/learn-es2015/) is supported in the app component. 51 | 52 | You can pass custom Framework7 parameters to your application in the configuration file. Example: 53 | 54 | ``` 55 | "framework7parameters": { 56 | "swipePanel": "left" 57 | } 58 | ``` 59 | -------------------------------------------------------------------------------- /demo/pages/f7material/swiper-3d-cube.vue: -------------------------------------------------------------------------------- 1 | 26 | -------------------------------------------------------------------------------- /demo/pages/f7material/swiper-3d-flip.vue: -------------------------------------------------------------------------------- 1 | 26 | -------------------------------------------------------------------------------- /demo/pages/f7ios/swiper-3d-cube.vue: -------------------------------------------------------------------------------- 1 | 26 | -------------------------------------------------------------------------------- /demo/pages/f7ios/swiper-3d-flip.vue: -------------------------------------------------------------------------------- 1 | 26 | -------------------------------------------------------------------------------- /scripts/code-check.js: -------------------------------------------------------------------------------- 1 | /* Purpose: Check or fix scripts according Standard JS and create log file with remaining findings. */ 2 | 3 | // Load packages 4 | const env = require('./env') 5 | const alert = require('./alert') 6 | const cmd = require('./cmd') 7 | const fs = require('fs-extra') 8 | const abs = require('path').resolve 9 | 10 | // Show message 11 | alert(`Code ${env.arg.fix === true ? 'fix' : 'check'} ongoing - please wait ...`) 12 | 13 | // Define log file 14 | const logFile = 'code-unconformities.log' 15 | 16 | // Define Standard parameters 17 | const params = [ 18 | 'node', 19 | 'node_modules/eslint/bin/eslint.js', 20 | // Find app.vue, pages/*.vue and pages/sub/*.vue 21 | `"${abs(env.app, '**/*.vue')}"`, 22 | `"${abs(env.app, '**/*.js')}"` 23 | ] 24 | if (!env.installed) { 25 | params.push(`"${abs(__dirname, '../client/*.js')}"`) 26 | params.push(`"${abs(__dirname, '../scripts/*.js')}"`) 27 | } 28 | // Print to log file 29 | params.push('>') 30 | params.push(`"${abs(env.proj, logFile)}"`) 31 | if (env.arg.fix === true) { 32 | params.push('--fix') 33 | } 34 | 35 | // Define error alert 36 | const errorAlert = `${env.arg.fix !== true ? 'Code unconformities found.' : 'Some unconformities must be fixed manually.'}\n` + 37 | `Please check "${logFile}" for detailed information.\n${ 38 | env.arg.fix !== true ? 'You can run "npm run fix" first for automatic fix.' : ''}` 39 | 40 | // Do the fix 41 | cmd(__dirname, 'node applyConfiguration', () => { 42 | cmd([env.proj], params, () => { 43 | fs.removeSync(abs(env.proj, logFile)) 44 | alert(`Code ${env.arg.fix === true ? 'fix' : 'check'} done without findings.`) 45 | }, () => { 46 | alert(errorAlert, 'error') 47 | }) 48 | }) 49 | -------------------------------------------------------------------------------- /media/Untitled Diagram.xml: -------------------------------------------------------------------------------- 1 | 5VpNc6M4EP01VO0e4gLxYfs4ziS7h9mqrcphZ44yyKAZQJSQY3t//bZAMsLCs0lsY085h0Q0LSReP71uiTj+Y7H9g+Mq+4slJHeQm2wd/7OD0HQWwW9p2LWGIPJaQ8pp0poMwwv9lyijq6xrmpC65ygYywWt+saYlSWJRc+GOWebvtuK5f1RK5wSy/AS49y2/kMTkbXWGZp29j8JTTM1cjjz2xtLHP9IOVuXajgH+avmp71dYP0o9Z51hhO2MUz+k+M/csZE2yq2jySXyGrU2n7PR+7up81JKd7SIQjUPMROvzpJAAl1ybjIWMpKnD911kXzfkQ+wYWrTBQ5ND1owqB891XaJ6G+/KbcvhMhdirQeC0YmLqnf2GsUs9YsVIoNw/gWLTzk5M6+orKVLM1j5UXUpzBPCXKK9rDC6QlrCAwOXDhJMeCvvafjhV90r1fhyE0FIzDkKqhX3G+Vg+lgNZ20uCEohyms0joKzRT2dxQoAT0LqmYfK+1Awxi+FgxAtpUspmweF00OCw2GRXkpcINAhtYlP3QLNuYfVlqg5ol4YJsf46sjZnu4KouapF7vloFG2PJKKJnxmqJ3NNRDj0L5pKdlctbKgwqw9W3m2N5aLPcRyPRPIysAOxAsS8QAc/A34D8q+rR4d/cu34EgrEiYAWgylhJZLrjuJB/2WRAcHBVyZeQr47cnBYUjM9v1B2esWK5rv9fbs6gLvvcpNQF5MVSF88dkJe98RRwA3RvYhJdUUyC+aXF5ApYnoCb6vo3ozBIl2+Dfr71db7Vj2hjp3odoL+fxtu0xR0pvd6yuA+siPCnkvXgTlAQqqC8L9ifOMc7w6GSQayPcwF5fS6gyDdD/l5/aLQzOOitp8NWq5qcSiq7YjArY5fWjbiLjJby6rlJYjI1fTQJDbPgpKQ0P0Bx1JwUnnezNpiTXHMFev0ViMZfgnN7CY5W4Nr1FdRFuJAkK5e1/JMznDR7N5PFBnkP3K3oAQ9FPyicQGGGl42DDIWSAfAOF074WZZvOU1LMMQAG+FgkHymMc4/qRsFTZIm8jleknyxP5B4ZDnjzbj6SOIdK0Sds6iZOfvzCzN84ZHCtxNHDwWz3vp58D6ilZa4PUxn/S5nkSu7JsFJYgTXBfIjd8mSnRVYvT+vOItJfR2pCnVRpbVqYHfuoQttz4Po3oqFwfrZHY7Q+c+c7NSqtKnZCm4Y/2EcLpmbwbJhNCxv6cuakuNdJ1DXZDgA3GO4r2Wgx3DvQgyf3hvDfXeA4UcidHaG+/aGRDEcV1XD7RskqB9FbyDopSR4dncE1V+KTIL6YxHUPpCWZ/otQW+SnaE7vSI7w7Oy83Y4iGwOjvbpSQ9ucLDO2GYg79dVjmv53amOOSHlL5T0ZwdnYGOSVlfQBr4ZTcgAvh+H/JcJRHSwvxg1EvqQ7Y6SW2ALy3wsXQks3rdb4d80X+sKl5qtzVeo353uM5SxT96z2+xwk/T252GP3pfcPsNl9y8f7UlF9181/tN/ -------------------------------------------------------------------------------- /scripts/create-snapshot.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Purpose: Create snapshot of current project folder, exclude files specified in .gitignore 4 | 5 | Arguments: --name must be string 6 | 7 | */ 8 | 9 | 'use strict' 10 | 11 | // Load modules 12 | let env = require('./env') 13 | let alert = require('./alert') 14 | let found = require('./found') 15 | let fs = require('fs-extra') 16 | let path = require('path') 17 | let zip = require('zip-dir') 18 | 19 | // Create no snapshot on initial installation 20 | if (env.pkg.devDependencies && 21 | env.pkg.devDependencies['app-framework'] && 22 | env.pkg.devDependencies['app-framework'] !== '*') { 23 | // Alert 24 | alert('Snapshot creation ongoing - please wait ...') 25 | 26 | // Check snapshot name 27 | if (env.arg.name === undefined) { 28 | alert('Snapshot must have argument "name".', 'error') 29 | } else if (env.arg.name.length < 3) { 30 | alert('Snapshot name must have three characters or more.', 'error') 31 | } 32 | 33 | // Check snapshot files 34 | let snapshotFile = path.resolve(env.proj, 'snapshots', env.arg.name + '.zip') 35 | if (found(snapshotFile) === true) { 36 | alert('Snapshot file already exists. Please choose a different name.', 'error') 37 | } 38 | 39 | // Ensure snapshot folder 40 | fs.ensureDirSync(path.dirname(snapshotFile)) 41 | 42 | // Create snapshot 43 | zip(env.proj, { 44 | saveTo: snapshotFile, 45 | filter: function (path, stat) { 46 | path = path.substr(env.proj.length + 1) 47 | return !env.ignored(path) && /^node_modules/.test(path) === false 48 | }}, 49 | function (err) { 50 | if (err) { 51 | alert('Snapshot creation failed.', 'issue') 52 | } else { 53 | alert('Snapshot creation done.') 54 | } 55 | } 56 | ) 57 | } 58 | -------------------------------------------------------------------------------- /client/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | <%= htmlWebpackPlugin.options.iconTags %> 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 27 | 28 | 29 | 36 | 37 | 38 | 39 | 40 | 41 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /docs/application-style.md: -------------------------------------------------------------------------------- 1 | # Application style 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | ## Configuration 8 | 9 | You can set the following style options in the configuration file: 10 | 11 | ``` 12 | theme: 'material', // 'ios', 'material', 'ios-material' or 'material-ios' 13 | color: 'indigo', // Any theme color name 14 | layout: 'default' // 'default', 'white' or 'dark' 15 | limitApplicationWidth: 320, // Pixel 16 | limitApplicationHeight: 570, // Pixel 17 | limitedSizeBodyBackgroundColor: '#333333', // HEX color code 18 | showPhoneFrameOnDesktop: true, // true or false 19 | phoneFrameBodyBackgroundColor: '#fafafa', // HEX color code 20 | framework7parameters: {} // Object, see Framework7 documentation 21 | ``` 22 | 23 | If you want to change the theme during runtime, you need to use `ios-material` or `material-ios` as value in the configuration. With `ios-material`, the default theme will be ios, but you are able to change the theme to `material`, with `material-ios` in the configuration vice versa. 24 | 25 | You will reduce the build size if you configure either `ios` or `material`. 26 | 27 | Find more information about all theme color and layout options [here](http://v1.framework7.io/docs/color-themes.html). 28 | 29 | ## Runtime modification 30 | 31 | You can modify the style options during runtime in any Vue hook `created` or later: 32 | 33 | ``` 34 | created: function () { 35 | this.$root.theme = 'material' 36 | this.$root.color = 'indigo' 37 | this.$root.layout = 'default' 38 | } 39 | ``` 40 | The current style is restored after application restart and overwrites the configuration. 41 | -------------------------------------------------------------------------------- /demo/pages/f7material/swiper-custom.vue: -------------------------------------------------------------------------------- 1 | 29 | -------------------------------------------------------------------------------- /demo/pages/f7ios/swiper-custom.vue: -------------------------------------------------------------------------------- 1 | 29 | -------------------------------------------------------------------------------- /docs/dev-update-vendor-folder.md: -------------------------------------------------------------------------------- 1 | # Update vendor folder 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | ## Framework7 8 | 9 | To be able to use the newest master branch of Framework7 and let developers use their modified Framework7 build, it is shipped directly with App Framework in the *vendor* folder. 10 | 11 | To update Framework7 in the vendor folder: 12 | 13 | 1. Clone [Framework7 repo](https://github.com/nolimits4web/Framework7) in *Framework7* folder next to *app-framework* folder 14 | 2. Run `npm install` in *Framework7* folder 15 | 3. Run `npm run f7` in *app-framework* folder 16 | 17 | The kitchen sink files in the *demo* folder and the *client/theme-colors.json* file are updated as well. 18 | 19 | ## Framework7-Vue 20 | 21 | To be able to use the newest master branch of Framework7-Vue and let developers use their modified Framework7-Vue build, it is shipped directly with App Framework in the *vendor* folder. 22 | 23 | To update Framework7-Vue in the vendor folder: 24 | 25 | 1. Clone [Framework7-Vue repo](https://github.com/nolimits4web/Framework7-Vue) in *Framework7-Vue* folder next to *app-framework* folder 26 | 2. Run `npm install` in *Framework7-Vue* folder 27 | 3. Run `npm run f7vue` in *app-framework* folder 28 | 29 | ## Material Design Icons 30 | 31 | To avoid the need to install the huge Material Design Icons archive and to get the mapping between ligatures and codepoints, it is shipped directly with App Framework in the *vendor* folder. 32 | 33 | To update Material Design Icons in the vendor folder: 34 | 35 | 1. Clone [Material Design Icons repo](https://github.com/google/material-design-icons) in *material-design-icons* folder next to *app-framework* folder 36 | 2. Run `npm run iconfonts` in *app-framework* folder 37 | 38 | The *client/material-codepoints.json* file is updated as well. 39 | -------------------------------------------------------------------------------- /demo/pages/f7material/swiper-3d-coverflow.vue: -------------------------------------------------------------------------------- 1 | 27 | -------------------------------------------------------------------------------- /docs/status-bar-style.md: -------------------------------------------------------------------------------- 1 | # Status bar style 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | ## Configuration 8 | 9 | You can configure the application status bar style in the configuration file: 10 | 11 | ``` 12 | statusbarVisibility: true, // true or false 13 | statusbarTextColor: 'white', // 'black' or 'white' 14 | statusbarBackgroundColor: '#3f51b5', // Hex color code 15 | ``` 16 | 17 | **changeStatusbarBackgroundColorOnThemeColorChange** 18 | 19 | This configuration option was removed with App Framework 1.9.15. You can apply the following code to your *app.vue* file to have the same behavior: 20 | 21 | ``` 22 | created() { 23 | // Update status bar background and text color after theme color change 24 | this.$watch(() => { 25 | return this.$root.color 26 | }, (newColor, oldColor) => { 27 | this.$root.statusbarTextColor = newColor === 'white' ? 'black' : 'white' 28 | this.$root.statusbarBackgroundColor = newColor === 'white' && window.cordova === undefined ? '000000' : this.$root.colors[this.$root.theme][newColor] 29 | }) 30 | } 31 | ``` 32 | 33 | ## Runtime modification 34 | 35 | You can modify the application status bar style in any Vue hook `created` or later: 36 | 37 | ``` 38 | created: function () { 39 | this.$root.statusbarVisibility = true 40 | this.$root.statusbarTextColor = 'white' 41 | this.$root.statusbarBackgroundColor = '#3f51b5' 42 | } 43 | ``` 44 | 45 | The current style is restored after application restart and overwrites the configuration. 46 | 47 | ## Limitations 48 | 49 | - Changing the status bar visibility is limited to native applications 50 | - Changing the status bar text color is limited to iOS native applications 51 | - Changing the status bar background color is limited to native or homescreen applications 52 | -------------------------------------------------------------------------------- /demo/pages/f7ios/swiper-3d-coverflow.vue: -------------------------------------------------------------------------------- 1 | 27 | -------------------------------------------------------------------------------- /scripts/modifications14.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Purpose: Apply necessary modifications to older versions to prepare version 1.4 4 | 5 | */ 6 | 7 | 'use strict' 8 | 9 | // Include modules 10 | let env = require('./env') 11 | let alert = require('./alert') 12 | let found = require('./found') 13 | let fs = require('fs-extra') 14 | let abs = require('path').resolve 15 | let rec = require('recursive-readdir') 16 | 17 | if (env.installed) { 18 | alert('Release modifications of v1.4 ongoing - please wait ...') 19 | try { 20 | // Configuration update 21 | // ... done in upgrade-config.js 22 | // Remove login-screen.vue 23 | if (found(env.app, 'pages/login-screen.vue')) { 24 | fs.removeSync(abs(env.app, 'pages/login-screen.vue')) 25 | } 26 | if (found(env.app, 'routes.json')) { 27 | let routes = fs.readJsonSync(abs(env.app, 'routes.json')) 28 | let newRoutes = [] 29 | for (let r in routes) { 30 | if (routes[r].component !== 'login-screen.vue' && routes[r].component !== 'login-screen') { 31 | newRoutes.push(routes[r]) 32 | } 33 | } 34 | fs.writeJsonSync(abs(env.app, 'routes.json'), newRoutes) 35 | } 36 | // Update strings in files 37 | rec(env.app, function (err, files) { 38 | if (err) alert('Release file modifications of v1.4 failed.', 'issue') 39 | files.map(function (file) { 40 | if (/\.(js|vue)$/.test(file)) { 41 | let content = fs.readFileSync(file, 'utf8') 42 | content = content.replace(/\$root\.title/g, '$root.config.title') 43 | content = content.replace(/\$root\.packageVersion/g, '$root.framework.version') 44 | content = content.replace(/\$root\.version/g, '$root.project.version') 45 | fs.writeFileSync(file, content) 46 | } 47 | }) 48 | alert('Release modifications of v1.4 done.') 49 | }) 50 | } catch (err) { 51 | alert('Release modifications of v1.4 failed.', 'issue') 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /demo/pages/firebase-private.vue: -------------------------------------------------------------------------------- 1 | 33 | 64 | -------------------------------------------------------------------------------- /scripts/backup.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Purpose: Create snapshots of the Firebase database and user list. 4 | 5 | */ 6 | 7 | 'use strict' 8 | 9 | // Include modules 10 | let env = require('./env') 11 | let alert = require('./alert') 12 | let cmd = require('./cmd') 13 | let fs = require('fs-extra') 14 | let abs = require('path').resolve 15 | 16 | // Define Firebase bin folder 17 | let binFolder = abs(env.proj, 'node_modules/firebase-tools/bin') 18 | 19 | // Define project 20 | let project = env.cfg.firebase.authDomain.substr(0, env.cfg.firebase.authDomain.indexOf('.firebaseapp.com')) 21 | 22 | // Define filename 23 | let now = new Date() 24 | let dateStr = now.getFullYear() + '-' + (now.getMonth() < 9 ? '0' : '') + (now.getMonth() + 1) + '-' + (now.getDate() < 10 ? '0' : '') + now.getDate() 25 | 26 | // Run 27 | alert('Firebase backup ongoing - please wait ...') 28 | cmd(binFolder, 'firebase login', function () { 29 | alert('Firebase database backup ongoing - please wait ...') 30 | cmd(binFolder, 'firebase database:get / >"' + abs(env.proj, 'snapshots/firebase-database-' + dateStr + '.json') + '" --project ' + project, function () { 31 | alert('Firebase user backup ongoing - please wait ...') 32 | cmd(binFolder, 'firebase auth:export "' + abs(env.proj, 'snapshots/firebase-users-' + dateStr + '.json') + '" --format=json --project ' + project, function () { 33 | try { 34 | let dbFile = fs.readJsonSync(abs(env.proj, 'snapshots/firebase-database-' + dateStr + '.json')) 35 | fs.writeJsonSync(abs(env.proj, 'snapshots/firebase-database-' + dateStr + '.json'), dbFile) 36 | let userFile = fs.readJsonSync(abs(env.proj, 'snapshots/firebase-users-' + dateStr + '.json')) 37 | fs.writeJsonSync(abs(env.proj, 'snapshots/firebase-users-' + dateStr + '.json'), userFile) 38 | alert('Firebase backup done.') 39 | } catch (err) { 40 | alert('Failed to beautify database backup files.', 'issue') 41 | } 42 | }, 'Firebase user backup failed.') 43 | }, 'Firebase login failed.') 44 | }) 45 | -------------------------------------------------------------------------------- /demo/pages/f7ios/transitions.vue: -------------------------------------------------------------------------------- 1 | 34 | -------------------------------------------------------------------------------- /demo/pages/f7ios/bars-hide.vue: -------------------------------------------------------------------------------- 1 | 52 | -------------------------------------------------------------------------------- /demo/pages/f7ios/photo-browser.vue: -------------------------------------------------------------------------------- 1 | 39 | -------------------------------------------------------------------------------- /demo/pages/f7material/bars-hide.vue: -------------------------------------------------------------------------------- 1 | 52 | -------------------------------------------------------------------------------- /demo/pages/f7ios/color-themes.vue: -------------------------------------------------------------------------------- 1 | 41 | -------------------------------------------------------------------------------- /docs/state-restoration.md: -------------------------------------------------------------------------------- 1 | # State restoration 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | After an application switch or closure, the application state may be reset. This means, if your user changed the page or tab, scrolled, opened modals, put in some data before - everything will be gone. 8 | 9 | App Framework has an automatic state restoration on each application restart, to let your users continue with the same application state they have had before they left the application. 10 | 11 | This restoration includes the following elements: 12 | 13 | - URL history per view (requires unique class or ID attribute per view) 14 | - Selected tabs (requires unique ID attribute per page) 15 | - Scroll positions 16 | - Side panels 17 | - Action sheets (requires unique ID attribute) 18 | - Login screens (requires unique ID attribute) 19 | - Pickers (requires unique ID attribute) 20 | - Popups (requires unique ID attribute) 21 | - Form inputs (requires unique form ID attribute and unique NAME attributes per form) 22 | - Focus on form input (requires unique form ID attribute and unique NAME attributes per form) 23 | - Page component data 24 | 25 | The state is not restored for standard modals, popovers and code-generated modals. 26 | 27 | If you use `v-model` on an input, the state will be restored by page component data, you can use a name attribute to restore the form focus, but it is not required in this case to restore form input. 28 | 29 | ## URL history per view 30 | 31 | With App Framework > 1.9.0. and configuration setting `restoreHistory: false`, only the last URL per view will be restored. 32 | 33 | This solves issues where pages have been loaded several times in the DOM. 34 | 35 | But you have to take care now to assign a `href` or `back-link-url` property to each backlink, as described in the Framework7-Vue documentation for [links](http://v1.framework7.io/vue/link.html) or [navbars](http://v1.framework7.io/vue/navbar.html). 36 | 37 | ## Page component data 38 | 39 | With App Framework > 1.11.0 you can disable the page component data restoration with `restoreComponentData: false` in the configuration file. 40 | -------------------------------------------------------------------------------- /demo/pages/f7material/photo-browser.vue: -------------------------------------------------------------------------------- 1 | 39 | -------------------------------------------------------------------------------- /demo/pages/f7material/pull-to-refresh.vue: -------------------------------------------------------------------------------- 1 | 51 | -------------------------------------------------------------------------------- /scripts/modifications16plus.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Purpose: Apply necessary modifications to older versions to prepare version 1.6+ 4 | 5 | */ 6 | 7 | 'use strict' 8 | 9 | // Include modules 10 | let env = require('./env') 11 | let alert = require('./alert') 12 | let found = require('./found') 13 | let fs = require('fs-extra') 14 | let path = require('path') 15 | let rec = require('recursive-readdir') 16 | 17 | if (env.installed) { 18 | alert('Release modifications of v1.6+ ongoing - please wait ...') 19 | // Update strings in files 20 | rec(env.app, function (err, files) { 21 | if (err) alert('Release file modifications of v1.6+ failed.', 'issue') 22 | files.map(function (file) { 23 | if (/\.(js|vue)$/.test(file)) { 24 | let content = fs.readFileSync(file, 'utf8') 25 | content = content.replace(/\$root\.framework\.version/g, '$root.frameworkVersion') 26 | content = content.replace(/\$root\.project\.version/g, '$root.version') 27 | fs.writeFileSync(file, content) 28 | } 29 | }) 30 | // Add missing language folder 31 | if (found(env.app) && !found(env.app, 'lang')) { 32 | fs.readdir(env.app, function (err, files) { 33 | if (err) alert('Failed to add language folder modification.', 'issue') 34 | if (files.length > 1) { 35 | try { 36 | fs.ensureDirSync(path.resolve(env.app, 'lang')) 37 | fs.writeJsonSync(path.resolve(env.app, 'lang/' + (env.cfg.language || env.cfg.defaultLanguage || 'en') + '.json'), {}, { spaces: 2 }) 38 | } catch (err) { 39 | alert('Failed to create languages folder.', 'issue') 40 | } 41 | } 42 | }) 43 | } 44 | // Rename storage-rules.txt 45 | if (found(env.app, 'storage-rules.txt') && !found(env.app, 'firebase-storage.txt')) { 46 | fs.renameSync(path.resolve(env.app, 'storage-rules.txt'), path.resolve(env.app, 'firebase-storage.txt')) 47 | } 48 | // Rename database-rules.json 49 | if (found(env.app, 'database-rules.json') && !found(env.app, 'firebase-database.json')) { 50 | fs.renameSync(path.resolve(env.app, 'database-rules.json'), path.resolve(env.app, 'firebase-database.json')) 51 | } 52 | // Alert 53 | alert('Release modifications of v1.6+ done.') 54 | }) 55 | } 56 | -------------------------------------------------------------------------------- /demo/pages/f7ios/pull-to-refresh.vue: -------------------------------------------------------------------------------- 1 | 51 | -------------------------------------------------------------------------------- /demo/pages/f7ios/bars-deep-navbar-3.vue: -------------------------------------------------------------------------------- 1 | 24 | -------------------------------------------------------------------------------- /demo/pages/f7ios/bars-deep-navbar-2.vue: -------------------------------------------------------------------------------- 1 | 24 | -------------------------------------------------------------------------------- /demo/pages/f7material/bars-deep-navbar-3.vue: -------------------------------------------------------------------------------- 1 | 24 | -------------------------------------------------------------------------------- /demo/pages/f7ios/swiper-zoom.vue: -------------------------------------------------------------------------------- 1 | 47 | -------------------------------------------------------------------------------- /demo/pages/f7material/bars-deep-navbar-2.vue: -------------------------------------------------------------------------------- 1 | 24 | -------------------------------------------------------------------------------- /demo/pages/f7material/swiper-zoom.vue: -------------------------------------------------------------------------------- 1 | 47 | -------------------------------------------------------------------------------- /demo/pages/f7ios/preloader.vue: -------------------------------------------------------------------------------- 1 | 37 | -------------------------------------------------------------------------------- /demo/pages/f7material/preloader.vue: -------------------------------------------------------------------------------- 1 | 37 | -------------------------------------------------------------------------------- /demo/pages/f7material/modals.vue: -------------------------------------------------------------------------------- 1 | 34 | -------------------------------------------------------------------------------- /docs/dev-way-of-working.md: -------------------------------------------------------------------------------- 1 | # Way of working 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | ## Changes 8 | 9 | For each change to App Framework code, please follow these steps: 10 | 11 | 1. Create an issue 12 | - Will be categorized as "new feature", "bug" or "improvement" 13 | - Should be discussed for new features 14 | 2. Create a branch 15 | - Should be named "feature-123", "fix-123" or "enhancement-123" where 123 is the issue number 16 | 3. Develop the solution 17 | - Update the postinstall routine to apply changes to previous versions 18 | - On variables change, check dependencies in source code 19 | - On file change, check dependencies in source code 20 | 4. Test the solution 21 | - On macOS / Windows / Linux after changes to *scripts* folder 22 | - On iOS / Android / Web after changes to *client* or *demo* folder 23 | - With a new / updated project after changes to the postinstall routine 24 | 5. Update the documentation 25 | - Features in file *README.md* 26 | - Documentation in folder *docs* 27 | 6. Commit the branch as a pull request 28 | 29 | ## Pull requests 30 | 31 | For each new pull request, please follow these steps: 32 | 33 | 1. Verify the testing 34 | - Discuss findings in the pull request 35 | 2. Verify the documentation update 36 | - Discuss findings in the pull request 37 | 3. Merge the pull request and delete the branch 38 | 4. Add the issue in file *CHANGELOG.md* for the next version 39 | 6. Close the issue with reference to the pull request 40 | 41 | ## Releases 42 | 43 | For each release, please follow these steps: 44 | 45 | 1. Build a new App Framework version and commit it to GitHub 46 | - Run `npm run patch` after bug-fixes and improvements (version bump to x.y.z+1) 47 | - Run `npm run minor` after adding new functionality (version bump to x.y+1.0) 48 | - Run `npm run major` after breaking backward-capability (version bump to x+1.0.0) 49 | 2. Update the version with release date in file *CHANGELOG.md* and commit it to GitHub 50 | 3. Publish to the [npm repository](https://www.npmjs.com/package/app-framework) with `npm publish` 51 | 4. Deploy new Demo App version 52 | - to Firebase hosting with `npm run firebase` 53 | - to Google Play Store, update all information before commit ([read documentation](deploy.md)) 54 | - to Apple App Store, update all information before commit ([read documentation](deploy.md)) 55 | 5. Update external documentation 56 | - [Framework7-Vue: Overview](https://v1.framework7.io/vue/) 57 | - [Framework7-Vue: Starter App Templates](https://v1.framework7.io/vue/templates.html) 58 | 6. Promote new version 59 | -------------------------------------------------------------------------------- /scripts/cmd.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Purpose: Run a child process and, depending on the result, run onSuccess() or onError() callbacks. 4 | 5 | cmd(workingDirectory , commands , [onSuccess , [onError ]]) 6 | 7 | */ 8 | 9 | 'use strict' 10 | 11 | // Import modules 12 | let alert = require('./alert') 13 | let type = require('./type') 14 | let cp = require('child_process') 15 | let path = require('path') 16 | 17 | // Export function 18 | module.exports = function (workingDirectory, commands, onSuccess, onError) { 19 | // Check number of argument 20 | if (arguments.length < 2 < arguments.length > 4) { 21 | alert('cmd() funtions needs two to four arguments.', 'issue') 22 | } 23 | // Check working directory 24 | if (type(workingDirectory) === 'array') { 25 | workingDirectory = path.resolve.apply(null, workingDirectory) 26 | } else if (type(workingDirectory) !== 'string') { 27 | alert('cmd() functions needs string as first argument.', 'issue') 28 | } 29 | // Check commands 30 | if (type(commands) === 'string') { 31 | commands = commands.split(' ') 32 | } else if (type(commands) !== 'array') { 33 | alert('cmd() functions needs string or array as second argument.', 'issue') 34 | } 35 | // Check onSuccess 36 | if (type(onSuccess) === 'string') { 37 | let msg = onSuccess 38 | onSuccess = function () { 39 | alert(msg) 40 | } 41 | } else if (onSuccess === undefined || type(onSuccess) === 'null') { 42 | onSuccess = function () {} 43 | } else if (type(onSuccess) !== 'function') { 44 | alert('cmd() functions needs null, string or function as third argument.', 'issue') 45 | } 46 | // Check onError 47 | if (type(onError) === 'string') { 48 | let msg = onError 49 | onError = function () { 50 | alert(msg, 'error') 51 | } 52 | } else if (onError === undefined) { 53 | onError = function () { 54 | process.exit(process.env.subProcess === 'true' ? 1 : 0) 55 | } 56 | } else if (type(onError) !== 'function') { 57 | alert('cmd() functions needs string or function as fourth argument.', 'issue') 58 | } 59 | // Define child process environment variables, set subProcess to "true" 60 | let env = JSON.parse(JSON.stringify(process.env)) 61 | env.subProcess = true 62 | // Run sub process 63 | cp.spawn(commands.shift(), commands, { 64 | cwd: workingDirectory, 65 | env: env, 66 | stdio: 'inherit', 67 | shell: true 68 | }) 69 | // Callback on sub process closure 70 | .on('close', function (exitCode) { 71 | if (exitCode === 0) { 72 | onSuccess() 73 | } else { 74 | onError() 75 | } 76 | }) 77 | } 78 | -------------------------------------------------------------------------------- /demo/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "App Framework", 3 | "defaultLanguage": "en", 4 | "defaultLanguageFallback": false, 5 | "theme": "material-ios", 6 | "color": "indigo", 7 | "layout": "default", 8 | "statusbarVisibility": false, 9 | "statusbarTextColor": "white", 10 | "statusbarBackgroundColor": "#3f51b5", 11 | "iconBackgroundColor": "#ffffff", 12 | "useIconFonts": { 13 | "framework7": true, 14 | "material": true, 15 | "ion": false, 16 | "fontawesome": false 17 | }, 18 | "limitApplicationWidth": 320, 19 | "limitApplicationHeight": 570, 20 | "limitedSizeBodyBackgroundColor": "#333333", 21 | "showPhoneFrameOnDesktop": true, 22 | "phoneFrameBodyBackgroundColor": "#fafafa", 23 | "framework7parameters": {}, 24 | "materialSubnavbarFix": true, 25 | "restoreHistory": true, 26 | "restoreComponentData": true, 27 | "completeRoutesFile": true, 28 | "firebase": { 29 | "apiKey": "AIzaSyAvzTiqd9fKR-h47Uxl4iXwqSMU1VjGdII", 30 | "authDomain": "app-framework-9045a.firebaseapp.com", 31 | "databaseURL": "https://app-framework-9045a.firebaseio.com", 32 | "storageBucket": "app-framework-9045a.appspot.com", 33 | "projectId": "app-framework-9045a", 34 | "allowEmailLogin": true, 35 | "allowEmailRegistration": true 36 | }, 37 | "devFirebase": { 38 | "deployDevRulesOnTesting": false, 39 | "apiKey": "AIzaSyBL0Xxsc-jFZ2BnmQV08T4O9B56HJVpwXk", 40 | "authDomain": "dev-app-framework.firebaseapp.com", 41 | "databaseURL": "https://dev-app-framework.firebaseio.com", 42 | "storageBucket": "dev-app-framework.appspot.com", 43 | "projectId": "app-framework-9045a", 44 | "allowEmailLogin": true, 45 | "allowEmailRegistration": false 46 | }, 47 | "loginRequiredForAllPages": false, 48 | "appStoreId": "de.scriptpilot.app-framework", 49 | "playStoreId": "de.scriptpilot.appframework", 50 | "useCordovaPlugins": [ 51 | "cordova-plugin-camera", 52 | "cordova-plugin-file" 53 | ], 54 | "cordovaPreferences": { 55 | "DisallowOverscroll": true 56 | }, 57 | "resetLocalStorageOnVersionChange": false, 58 | "preloadImages": true, 59 | "buildSourcemaps": false, 60 | "editorConfig": { 61 | "root": "true", 62 | "[*]": null, 63 | "indent_style": "space", 64 | "indent_size": 2, 65 | "charset": "utf-8", 66 | "trim_trailing_whitespace": "true", 67 | "insert_final_newline": "true", 68 | "end_of_line": "lf", 69 | "max_line_length": "null" 70 | }, 71 | "eslint": { 72 | "extends": "standard", 73 | "rules": {} 74 | }, 75 | "fixCodeOnTest": true, 76 | "fixCodeOnBuild": true, 77 | "devServerPort": "8080", 78 | "gitignore": {}, 79 | "npmignore": {}, 80 | "debug": false 81 | } 82 | -------------------------------------------------------------------------------- /docs/data-object.md: -------------------------------------------------------------------------------- 1 | # Global data object 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | App Framework provides a global persistent data object for common used data or settings. 8 | 9 | The data object will be restored on each application reload and is accessible in any Vue hook `created` or later. 10 | 11 | ## With App Framework v1.13.2 or later 12 | 13 | **Save data** 14 | - Template: `Save data` 15 | - Script: `this.$db('main.sub', 'value')` 16 | 17 | **Get data** 18 | - Template: `{{$db('main.sub')}}` 19 | - Script: `this.$db('main.sub')` 20 | 21 | **Remove data** 22 | - Template: `Remove data` 23 | - Script: `this.$db('main.sub', null)` 24 | 25 | **Notes** 26 | 27 | `main.sub` mean the paths within the data object. With a point, you can realize nested objects. Example: 28 | 29 | ``` 30 | { 31 | "main": { 32 | "sub": "value" 33 | } 34 | } 35 | ``` 36 | 37 | ## With App Framework v1.12 or later 38 | 39 | **Save data** 40 | 41 | - Template: ```Save data``` 42 | - Script: ```this.$save('main.sub', 'value')``` 43 | 44 | **Get data** 45 | 46 | - Template: ```{{$get.main.sub}}``` 47 | - Script: ```this.$get.main.sub``` 48 | 49 | **Remove data** 50 | 51 | - Template: ```Remove data``` 52 | - Script: ```this.$remove('main.sub')``` 53 | 54 | ## With App Framework v1.11 or before 55 | 56 | - To save data, use `this.$root.saveData(path, value)` 57 | - To remove data, use `this.$root.removeData(path)` 58 | - To retrieve data, use `this.$root.data.path` 59 | 60 | The *path* must be a string, use a a point to nest data. Example: 61 | 62 | ``` 63 | created: function () { 64 | this.$root.saveData('greeting', 'Hello!') 65 | this.$root.saveData('names', {first: 'Jan', second: 'Tom', third: 'Sophie'}) 66 | this.$root.removeData('names.second') 67 | } 68 | ``` 69 | 70 | Now, the data object will look like following: 71 | 72 | ``` 73 | { 74 | greeting: 'Hello!', 75 | names: { 76 | first: 'Jan', 77 | third: 'Sophie' 78 | } 79 | } 80 | ``` 81 | 82 | Example for the usage in templates: 83 | 84 | ``` 85 | 86 |

UTC date: {{$root.data.dateString}}

87 | 88 | Update date 89 | Remove date 90 | 91 |
92 | ``` 93 | 94 | Do not modify `$root.data` directly, because there wont be any update triggered. 95 | -------------------------------------------------------------------------------- /scripts/checkLanguageFiles.js: -------------------------------------------------------------------------------- 1 | // Purpose: Check language files, compare to default language file and sort each file by keys 2 | 3 | // Load modules 4 | const env = require('./env') 5 | const alert = require('./alert') 6 | const found = require('./found') 7 | const fs = require('fs-extra') 8 | const path = require('path') 9 | const abs = require('path').resolve 10 | const rec = require('recursive-readdir-sync') 11 | const sort = require('sort-keys-recursive') 12 | 13 | // Define language folder 14 | const langFolder = abs(env.app, 'lang') 15 | 16 | // Check if default language file exists 17 | const defaultLangFile = abs(langFolder, env.cfg.defaultLanguage + '.json') 18 | if (!found(defaultLangFile)) { 19 | alert(`Default language file lang/${env.cfg.defaultLanguage}.json not found.`, 'error') 20 | } 21 | 22 | // Check if all language files are valid and sort each by key 23 | const langPatterns = {} 24 | try { 25 | const files = rec(langFolder) 26 | files.forEach((file) => { 27 | const patterns = fs.readJsonSync(file) 28 | const language = path.basename(file).slice(0, -5) 29 | langPatterns[language] = patterns 30 | fs.writeJsonSync(file, sort(patterns), { spaces: 2 }) 31 | }) 32 | } catch (err) { 33 | alert('Failed to read language files.', 'issue') 34 | } 35 | 36 | // Check all files if they have flat key:string pairs 37 | for (let lang in langPatterns) { 38 | let errors = 0 39 | for (let key in langPatterns[lang]) { 40 | if (typeof langPatterns[lang][key] !== 'string') { 41 | errors++ 42 | } 43 | } 44 | if (errors > 0) { 45 | alert(`Language file lang/${lang}.json should contain plain key:string pairs.`, 'error') 46 | } 47 | } 48 | 49 | // Compare languages files to default language file 50 | // Loop all languages 51 | for (let lang in langPatterns) { 52 | // It's not the default language 53 | if (lang !== env.cfg.defaultLanguage) { 54 | const diffs = [] 55 | // Loop all items of the default language 56 | if (env.cfg.defaultLanguageFallback === false) { 57 | for (let key in langPatterns[env.cfg.defaultLanguage]) { 58 | // Missing items 59 | if (langPatterns[lang][key] === undefined) { 60 | diffs.push(`"${key}" is missing`) 61 | } 62 | } 63 | } 64 | // Loop all items of the second language 65 | for (let key in langPatterns[lang]) { 66 | // Too much items 67 | if (langPatterns[env.cfg.defaultLanguage][key] === undefined) { 68 | diffs.push(`"${key}" is too much`) 69 | } 70 | } 71 | // Differences found 72 | if (diffs.length > 0) { 73 | alert(`Language file lang/${lang}.json is different to the default one:\n- ` + diffs.join('\n- '), 'error') 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /docs/images.md: -------------------------------------------------------------------------------- 1 | # Images 2 | 3 | > This page is part of the [App Framework Documentation](../DOCUMENTATION.md) 4 | 5 |
6 | 7 | ## Image usage 8 | 9 | To use images in your application, you have to save them first in the `app/images` folder and point to them with a relative path in the *src* attribute. 10 | 11 | ``` 12 | 19 | ``` 20 | 21 | To remove images, you should remove the image tag first and delete the file afterwards. 22 | 23 | ## Dynamic image usage 24 | 25 | During the build process, all *src* attributes are parsed by Webpack and mapped to the hashed image files. This does only work, if the *src* contains a string only - no variables. 26 | 27 | So, for dynamic images, you should use single *img* elements and display them or not. 28 | 29 | The following example shows *imageA.png* initially and after five seconds *imageB.png*. 30 | 31 | ``` 32 | 40 | 54 | ``` 55 | 56 | Another solution is, that you require all images in the script: 57 | 58 | ``` 59 | 66 | 80 | ``` 81 | 82 | ## Image preloading 83 | 84 | App Framework provides image preloading by default. This means, all files in the folder `app/images` are loaded while the preloading page is shown and before the application is initialized. 85 | 86 | This could increase the initial loading time, but will improve the behavior of your application because all images are immediately visible. 87 | 88 | To disable image preloading, set `preloadImages: false` in the configuration file. To use the updated setting, you have to restart the development server. 89 | 90 | To update the preloader after adding new images to your application, you have to restart the development server as well. 91 | -------------------------------------------------------------------------------- /demo/app.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 77 | 78 | 83 | --------------------------------------------------------------------------------