├── .bowerrc ├── .dockerignore ├── .editorconfig ├── .eslintrc ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── dependabot.yml ├── .gitignore ├── .npmignore ├── .nvmrc ├── .semaphore ├── deploy_dockerhub.yml ├── deploy_npmjs.yml └── semaphore.yml ├── .tool-versions ├── .tx └── config ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Dockerfile ├── Dockerfile-alpine-arm64 ├── Dockerfile-debian-arm64 ├── Dockerfile-debian-armhf ├── Dockerfile-debian-x86_64 ├── ISSUE_TEMPLATE.md ├── LICENSE ├── README.md ├── TESTING.md ├── bin └── stf ├── bower.json ├── doc ├── 7s_usage.gif ├── API.md ├── CREDITS.md ├── DEPLOYMENT.md ├── DONATION-TRANSPARENCY.md ├── GroupFeature.pdf ├── VNC.md ├── WHY.md ├── shelf_closeup_790x.jpg ├── sponsors │ └── headspin-wordmark-orange.png ├── topo-v1.ditaa └── topo-v1.png ├── docker-compose.yaml ├── docker ├── armv7l │ ├── Dockerfile │ ├── README.md │ ├── mkimage-alpine.sh │ ├── stf-armv7l-baseimage@.service │ ├── stf-armv7l-build@.service │ ├── stf-armv7l-clone@.service │ ├── stf-armv7l-publish-latest.service │ ├── stf-armv7l-publish-latest.timer │ └── stf-armv7l-publish@.service └── extras │ ├── README.md │ ├── docker-cleanup-dangling-images.service │ └── docker-cleanup-dangling-images.timer ├── gulpfile.js ├── lib ├── cli │ ├── api │ │ └── index.js │ ├── app │ │ └── index.js │ ├── auth-ldap │ │ └── index.js │ ├── auth-mock │ │ └── index.js │ ├── auth-oauth2 │ │ └── index.js │ ├── auth-openid │ │ └── index.js │ ├── auth-saml2 │ │ └── index.js │ ├── device │ │ └── index.js │ ├── doctor │ │ └── index.js │ ├── generate-fake-device │ │ └── index.js │ ├── generate-fake-group │ │ └── index.js │ ├── generate-fake-user │ │ └── index.js │ ├── groups-engine │ │ └── index.js │ ├── index.js │ ├── local │ │ └── index.js │ ├── log-rethinkdb │ │ └── index.js │ ├── migrate │ │ └── index.js │ ├── notify-hipchat │ │ └── index.js │ ├── notify-slack │ │ └── index.js │ ├── please.js │ ├── poorxy │ │ └── index.js │ ├── processor │ │ └── index.js │ ├── provider │ │ └── index.js │ ├── reaper │ │ └── index.js │ ├── storage-plugin-apk │ │ └── index.js │ ├── storage-plugin-image │ │ └── index.js │ ├── storage-s3 │ │ └── index.js │ ├── storage-temp │ │ └── index.js │ ├── triproxy │ │ └── index.js │ └── websocket │ │ └── index.js ├── db │ ├── api.js │ ├── index.js │ ├── setup.js │ └── tables.js ├── units │ ├── api │ │ ├── config │ │ │ └── default.yaml │ │ ├── controllers │ │ │ ├── devices.js │ │ │ ├── groups.js │ │ │ ├── user.js │ │ │ └── users.js │ │ ├── helpers │ │ │ └── securityHandlers.js │ │ ├── index.js │ │ └── swagger │ │ │ ├── api_v1.yaml │ │ │ └── api_v1_generated.json │ ├── app │ │ ├── index.js │ │ └── middleware │ │ │ ├── appstore-icons.js │ │ │ ├── auth.js │ │ │ ├── browser-icons.js │ │ │ ├── device-icons.js │ │ │ └── webpack.js │ ├── auth │ │ ├── ldap.js │ │ ├── mock.js │ │ ├── oauth2 │ │ │ ├── index.js │ │ │ └── strategy.js │ │ ├── openid.js │ │ └── saml2.js │ ├── device │ │ ├── index.js │ │ ├── plugins │ │ │ ├── account.js │ │ │ ├── bluetooth.js │ │ │ ├── browser.js │ │ │ ├── cleanup.js │ │ │ ├── clipboard.js │ │ │ ├── connect.js │ │ │ ├── filesystem.js │ │ │ ├── forward │ │ │ │ ├── index.js │ │ │ │ └── util │ │ │ │ │ ├── manager.js │ │ │ │ │ ├── reader.js │ │ │ │ │ └── writer.js │ │ │ ├── group.js │ │ │ ├── heartbeat.js │ │ │ ├── install.js │ │ │ ├── logcat.js │ │ │ ├── logger.js │ │ │ ├── mute.js │ │ │ ├── reboot.js │ │ │ ├── ringer.js │ │ │ ├── screen │ │ │ │ ├── capture.js │ │ │ │ ├── options.js │ │ │ │ ├── stream.js │ │ │ │ └── util │ │ │ │ │ ├── banner.js │ │ │ │ │ ├── broadcastset.js │ │ │ │ │ ├── frameconfig.js │ │ │ │ │ └── frameparser.js │ │ │ ├── sd.js │ │ │ ├── service.js │ │ │ ├── shell.js │ │ │ ├── solo.js │ │ │ ├── store.js │ │ │ ├── touch │ │ │ │ └── index.js │ │ │ ├── util │ │ │ │ ├── data.js │ │ │ │ ├── display.js │ │ │ │ ├── flags.js │ │ │ │ ├── identity.js │ │ │ │ ├── phone.js │ │ │ │ └── urlformat.js │ │ │ ├── vnc │ │ │ │ ├── index.js │ │ │ │ └── util │ │ │ │ │ ├── connection.js │ │ │ │ │ ├── pixelformat.js │ │ │ │ │ ├── pointertranslator.js │ │ │ │ │ └── server.js │ │ │ └── wifi.js │ │ ├── resources │ │ │ ├── minicap.js │ │ │ ├── minirev.js │ │ │ ├── minitouch.js │ │ │ ├── service.js │ │ │ └── util │ │ │ │ └── resource.js │ │ └── support │ │ │ ├── abi.js │ │ │ ├── adb.js │ │ │ ├── channels.js │ │ │ ├── properties.js │ │ │ ├── push.js │ │ │ ├── router.js │ │ │ ├── sdk.js │ │ │ ├── storage.js │ │ │ └── sub.js │ ├── groups-engine │ │ ├── index.js │ │ ├── scheduler │ │ │ └── index.js │ │ └── watchers │ │ │ ├── devices.js │ │ │ ├── groups.js │ │ │ └── users.js │ ├── log │ │ └── rethinkdb.js │ ├── notify │ │ ├── hipchat.js │ │ └── slack.js │ ├── poorxy │ │ └── index.js │ ├── processor │ │ └── index.js │ ├── provider │ │ └── index.js │ ├── reaper │ │ └── index.js │ ├── storage │ │ ├── plugins │ │ │ ├── apk │ │ │ │ ├── index.js │ │ │ │ └── task │ │ │ │ │ └── manifest.js │ │ │ └── image │ │ │ │ ├── index.js │ │ │ │ ├── param │ │ │ │ ├── crop.js │ │ │ │ └── gravity.js │ │ │ │ └── task │ │ │ │ ├── get.js │ │ │ │ └── transform.js │ │ ├── s3.js │ │ └── temp.js │ ├── triproxy │ │ └── index.js │ └── websocket │ │ ├── index.js │ │ └── middleware │ │ ├── auth.js │ │ ├── cookie-session.js │ │ └── remote-ip.js ├── util │ ├── adbutil.js │ ├── apiutil.js │ ├── bundletool.js │ ├── datautil.js │ ├── deviceutil.js │ ├── devutil.js │ ├── download.js │ ├── failcounter.js │ ├── fakedevice.js │ ├── fakegroup.js │ ├── fakeuser.js │ ├── grouputil.js │ ├── jwtutil.js │ ├── keyutil.js │ ├── ldaputil.js │ ├── lifecycle.js │ ├── lockutil.js │ ├── logger.js │ ├── pathutil.js │ ├── procutil.js │ ├── promiseutil.js │ ├── refresh.js │ ├── requtil.js │ ├── riskystream.js │ ├── srv.js │ ├── statequeue.js │ ├── storage.js │ ├── streamutil.js │ ├── timeutil.js │ ├── ttlset.js │ ├── urlutil.js │ ├── vncauth.js │ └── zmqutil.js └── wire │ ├── channelmanager.js │ ├── index.js │ ├── messagestream.js │ ├── router.js │ ├── seqqueue.js │ ├── util.js │ └── wire.proto ├── package.json ├── res ├── .eslintrc ├── app │ ├── app.js │ ├── components │ │ └── stf │ │ │ ├── admin-mode │ │ │ ├── admin-mode-directive.js │ │ │ ├── admin-mode-spec.js │ │ │ └── index.js │ │ │ ├── angular-draggabilly │ │ │ ├── angular-draggabilly-directive.js │ │ │ ├── angular-draggabilly-spec.js │ │ │ └── index.js │ │ │ ├── angular-packery │ │ │ ├── angular-packery-directive.js │ │ │ ├── angular-packery-spec.js │ │ │ ├── angular-packery.css │ │ │ └── index.js │ │ │ ├── app-state │ │ │ ├── app-state-provider.js │ │ │ └── index.js │ │ │ ├── basic-mode │ │ │ ├── basic-mode-directive.js │ │ │ ├── basic-mode-spec.js │ │ │ ├── basic-mode.css │ │ │ └── index.js │ │ │ ├── browser-info │ │ │ ├── browser-info-service.js │ │ │ ├── browser-info-spec.js │ │ │ └── index.js │ │ │ ├── column-choice │ │ │ ├── column-choice-directive.js │ │ │ ├── column-choice.css │ │ │ ├── column-choice.pug │ │ │ └── index.js │ │ │ ├── common-ui │ │ │ ├── badge-icon │ │ │ │ ├── badge-icon-directive.js │ │ │ │ ├── badge-icon-spec.js │ │ │ │ ├── badge-icon.css │ │ │ │ ├── badge-icon.pug │ │ │ │ └── index.js │ │ │ ├── blur-element │ │ │ │ ├── blur-element-directive.js │ │ │ │ ├── blur-element-spec.js │ │ │ │ └── index.js │ │ │ ├── clear-button │ │ │ │ ├── clear-button-directive.js │ │ │ │ ├── clear-button-spec.js │ │ │ │ ├── clear-button.pug │ │ │ │ └── index.js │ │ │ ├── counter │ │ │ │ ├── counter-directive.js │ │ │ │ ├── counter-spec.js │ │ │ │ └── index.js │ │ │ ├── enable-autofill │ │ │ │ ├── README.md │ │ │ │ ├── enable-autofill-directive.js │ │ │ │ ├── enable-autofill-spec.js │ │ │ │ └── index.js │ │ │ ├── error-message │ │ │ │ ├── error-message-directive.js │ │ │ │ ├── error-message-spec.js │ │ │ │ ├── error-message.css │ │ │ │ ├── error-message.pug │ │ │ │ └── index.js │ │ │ ├── fallback-image │ │ │ │ ├── fallback-image-directive.js │ │ │ │ ├── fallback-image-spec.js │ │ │ │ └── index.js │ │ │ ├── filter-button │ │ │ │ ├── filter-button-directive.js │ │ │ │ ├── filter-button-spec.js │ │ │ │ ├── filter-button.pug │ │ │ │ └── index.js │ │ │ ├── focus-element │ │ │ │ ├── focus-element-directive.js │ │ │ │ ├── focus-element-spec.js │ │ │ │ └── index.js │ │ │ ├── help-icon │ │ │ │ ├── help-icon-directive.js │ │ │ │ ├── help-icon.pug │ │ │ │ └── index.js │ │ │ ├── icon-inside-input │ │ │ │ ├── icon-inside-input-directive.js │ │ │ │ ├── icon-inside-input-spec.js │ │ │ │ └── index.js │ │ │ ├── include-cached │ │ │ │ ├── compile-cache-service.js │ │ │ │ ├── include-cached-directive.js │ │ │ │ ├── include-cached-spec.js │ │ │ │ └── index.js │ │ │ ├── index.js │ │ │ ├── modals │ │ │ │ ├── add-adb-key-modal │ │ │ │ │ ├── add-adb-key-modal-service.js │ │ │ │ │ ├── add-adb-key-modal-spec.js │ │ │ │ │ ├── add-adb-key-modal.pug │ │ │ │ │ └── index.js │ │ │ │ ├── common │ │ │ │ │ ├── index.js │ │ │ │ │ └── modals.css │ │ │ │ ├── external-url-modal │ │ │ │ │ ├── external-url-modal-service.js │ │ │ │ │ ├── external-url-modal-spec.js │ │ │ │ │ ├── external-url-modal.css │ │ │ │ │ ├── external-url-modal.pug │ │ │ │ │ ├── index.js │ │ │ │ │ └── on-load-event-directive.js │ │ │ │ ├── fatal-message │ │ │ │ │ ├── fatal-message-service.js │ │ │ │ │ ├── fatal-message-spec.js │ │ │ │ │ ├── fatal-message.pug │ │ │ │ │ └── index.js │ │ │ │ ├── generic-modal │ │ │ │ │ ├── generic-modal-service.js │ │ │ │ │ ├── generic-modal-spec.js │ │ │ │ │ ├── generic-modal.pug │ │ │ │ │ └── index.js │ │ │ │ ├── index.js │ │ │ │ ├── lightbox-image │ │ │ │ │ ├── index.js │ │ │ │ │ ├── lightbox-image-service.js │ │ │ │ │ ├── lightbox-image-spec.js │ │ │ │ │ ├── lightbox-image.css │ │ │ │ │ └── lightbox-image.pug │ │ │ │ ├── save-log-modal │ │ │ │ │ ├── index.js │ │ │ │ │ ├── save-log-service.js │ │ │ │ │ ├── save-log-spec.js │ │ │ │ │ ├── save-log.css │ │ │ │ │ └── save-log.pug │ │ │ │ ├── socket-disconnected │ │ │ │ │ ├── index.js │ │ │ │ │ ├── socket-disconnected-service.js │ │ │ │ │ ├── socket-disconnected-spec.js │ │ │ │ │ └── socket-disconnected.pug │ │ │ │ └── version-update │ │ │ │ │ ├── index.js │ │ │ │ │ ├── version-update-service.js │ │ │ │ │ ├── version-update-spec.js │ │ │ │ │ └── version-update.pug │ │ │ ├── ng-enter │ │ │ │ ├── index.js │ │ │ │ ├── ng-enter-directive.js │ │ │ │ └── ng-enter-spec.js │ │ │ ├── nice-tabs │ │ │ │ ├── README.md │ │ │ │ ├── index.js │ │ │ │ ├── nice-tab-directive.js │ │ │ │ ├── nice-tab.pug │ │ │ │ ├── nice-tabs-directive.js │ │ │ │ ├── nice-tabs-spec.js │ │ │ │ └── nice-tabs.pug │ │ │ ├── nothing-to-show │ │ │ │ ├── index.js │ │ │ │ ├── nothing-to-show-directive.js │ │ │ │ ├── nothing-to-show.css │ │ │ │ └── nothing-to-show.html │ │ │ ├── notifications │ │ │ │ ├── growl.css │ │ │ │ └── index.js │ │ │ ├── pagination │ │ │ │ ├── index.js │ │ │ │ ├── pagination-directive.js │ │ │ │ ├── pagination-filter.js │ │ │ │ ├── pagination-service.js │ │ │ │ ├── pagination.css │ │ │ │ └── pagination.pug │ │ │ ├── refresh-page │ │ │ │ ├── index.js │ │ │ │ ├── refresh-page-directive.js │ │ │ │ ├── refresh-page-spec.js │ │ │ │ └── refresh-page.pug │ │ │ ├── safe-apply │ │ │ │ └── index.js │ │ │ ├── stacked-icon │ │ │ │ ├── index.js │ │ │ │ ├── stacked-icon-directive.js │ │ │ │ ├── stacked-icon.css │ │ │ │ └── stacked-icon.pug │ │ │ ├── table │ │ │ │ ├── index.js │ │ │ │ └── table.css │ │ │ ├── text-focus-select │ │ │ │ ├── index.js │ │ │ │ ├── text-focus-select-directive.js │ │ │ │ └── text-focus-select-spec.js │ │ │ └── tooltips │ │ │ │ ├── README.md │ │ │ │ ├── index.js │ │ │ │ ├── tooltips-directive.js │ │ │ │ └── tooltips-spec.js │ │ │ ├── control │ │ │ ├── control-service.js │ │ │ └── index.js │ │ │ ├── device-context-menu │ │ │ ├── device-context-menu-directive.js │ │ │ ├── device-context-menu-spec.js │ │ │ ├── device-context-menu.css │ │ │ ├── device-context-menu.pug │ │ │ └── index.js │ │ │ ├── device │ │ │ ├── device-info-filter │ │ │ │ └── index.js │ │ │ ├── device-service.js │ │ │ ├── enhance-device │ │ │ │ ├── enhance-device-service.js │ │ │ │ └── index.js │ │ │ ├── index.js │ │ │ └── state-classes-service.js │ │ │ ├── devices │ │ │ ├── devices-service.js │ │ │ └── index.js │ │ │ ├── filter-string │ │ │ ├── filter-string-service.js │ │ │ ├── filter-string-spec.js │ │ │ └── index.js │ │ │ ├── groups │ │ │ ├── groups-service.js │ │ │ └── index.js │ │ │ ├── image-onload │ │ │ ├── image-onload-animate-directive.js │ │ │ ├── image-onload-directive.js │ │ │ ├── image-onload-spec.js │ │ │ └── index.js │ │ │ ├── install │ │ │ ├── index.js │ │ │ ├── install-error-filter.js │ │ │ ├── install-service.js │ │ │ └── install-spec.js │ │ │ ├── keycodes │ │ │ ├── android │ │ │ │ └── index.json │ │ │ ├── index.js │ │ │ ├── js │ │ │ │ └── index.json │ │ │ ├── keycodes-service.js │ │ │ ├── keycodes-spec.js │ │ │ └── mapped │ │ │ │ └── index.json │ │ │ ├── keys │ │ │ ├── add-adb-key │ │ │ │ ├── adb-keys-service.js │ │ │ │ ├── add-adb-key-directive.js │ │ │ │ ├── add-adb-key-spec.js │ │ │ │ ├── add-adb-key.css │ │ │ │ ├── add-adb-key.pug │ │ │ │ └── index.js │ │ │ └── index.js │ │ │ ├── landscape │ │ │ ├── index.js │ │ │ ├── landscape-directive.js │ │ │ └── landscape-spec.js │ │ │ ├── language │ │ │ ├── index.js │ │ │ ├── language-provider.js │ │ │ └── language-service.js │ │ │ ├── logcat-table │ │ │ ├── index.js │ │ │ ├── logcat-table-directive.js │ │ │ ├── logcat-table-spec.js │ │ │ ├── logcat-table.css │ │ │ └── logcat-table.pug │ │ │ ├── logcat │ │ │ ├── index.js │ │ │ ├── logcat-service.js │ │ │ └── logcat-spec.js │ │ │ ├── native-url │ │ │ ├── index.js │ │ │ ├── native-url-service.js │ │ │ └── native-url-spec.js │ │ │ ├── nav-menu │ │ │ ├── index.js │ │ │ ├── nav-menu-directive.js │ │ │ └── nav-menu-spec.js │ │ │ ├── page-visibility │ │ │ ├── index.js │ │ │ └── page-visibility-service.js │ │ │ ├── port-forwarding │ │ │ ├── index.js │ │ │ ├── port-forwarding-service.js │ │ │ └── port-forwarding-spec.js │ │ │ ├── scoped-hotkeys │ │ │ ├── index.js │ │ │ ├── scoped-hotkeys-service.js │ │ │ └── scoped-hotkeys-spec.js │ │ │ ├── screen │ │ │ ├── fast-image-render │ │ │ │ ├── canvas-render.js │ │ │ │ ├── index.js │ │ │ │ ├── test │ │ │ │ │ ├── images │ │ │ │ │ │ ├── screen.dds │ │ │ │ │ │ ├── screen.dds.gz │ │ │ │ │ │ ├── screen.jpg │ │ │ │ │ │ ├── screen.png │ │ │ │ │ │ ├── screen.webp │ │ │ │ │ │ └── texture24.crn │ │ │ │ │ ├── index.html │ │ │ │ │ ├── performance_test.js │ │ │ │ │ └── results.md │ │ │ │ └── webgl-render.js │ │ │ ├── imagepool.js │ │ │ ├── index.js │ │ │ ├── rotator-test.js │ │ │ ├── rotator.js │ │ │ ├── scaling │ │ │ │ ├── index.js │ │ │ │ └── scaling-service.js │ │ │ ├── screen-controller.js │ │ │ ├── screen-directive.js │ │ │ ├── screen-keyboard │ │ │ │ ├── index.js │ │ │ │ ├── screen-keyboard-directive.js │ │ │ │ ├── screen-keyboard-spec.js │ │ │ │ ├── screen-keyboard.css │ │ │ │ └── screen-keyboard.pug │ │ │ ├── screen-touch │ │ │ │ ├── index.js │ │ │ │ ├── screen-touch-directive.js │ │ │ │ └── screen-touch-spec.js │ │ │ ├── screen.css │ │ │ └── screen.pug │ │ │ ├── settings │ │ │ ├── index.js │ │ │ └── settings-service.js │ │ │ ├── socket │ │ │ ├── index.js │ │ │ ├── socket-service.js │ │ │ └── socket-state │ │ │ │ ├── index.js │ │ │ │ ├── socket-state-directive.js │ │ │ │ └── socket-state.pug │ │ │ ├── standalone │ │ │ ├── index.js │ │ │ ├── standalone-controller.js │ │ │ ├── standalone-directive.js │ │ │ ├── standalone-service.js │ │ │ ├── standalone.css │ │ │ └── standalone.pug │ │ │ ├── storage │ │ │ ├── index.js │ │ │ └── storage-service.js │ │ │ ├── text-history │ │ │ ├── index.js │ │ │ ├── text-history-directive.js │ │ │ └── text-history-spec.js │ │ │ ├── timeline │ │ │ ├── index.js │ │ │ ├── timeline-service.js │ │ │ └── timeline-spec.js │ │ │ ├── timelines │ │ │ ├── index.js │ │ │ ├── timeline-message │ │ │ │ ├── index.js │ │ │ │ ├── timeline-message-directive.js │ │ │ │ └── timeline-message-spec.js │ │ │ ├── timelines-directive.js │ │ │ ├── timelines-spec.js │ │ │ ├── timelines.css │ │ │ └── timelines.pug │ │ │ ├── tokens │ │ │ ├── access-token-service.js │ │ │ ├── generate-access-token │ │ │ │ ├── generate-access-token-directive.js │ │ │ │ ├── generate-access-token-spec.js │ │ │ │ ├── generate-access-token.css │ │ │ │ ├── generate-access-token.pug │ │ │ │ └── index.js │ │ │ └── index.js │ │ │ ├── transaction │ │ │ ├── index.js │ │ │ ├── transaction-error.js │ │ │ └── transaction-service.js │ │ │ ├── upload │ │ │ ├── index.js │ │ │ ├── upload-error-filter.js │ │ │ └── upload-spec.js │ │ │ ├── user │ │ │ ├── group │ │ │ │ ├── group-service.js │ │ │ │ └── index.js │ │ │ ├── index.js │ │ │ └── user-service.js │ │ │ ├── users │ │ │ ├── index.js │ │ │ └── users-service.js │ │ │ └── util │ │ │ ├── common │ │ │ ├── common-service.js │ │ │ └── index.js │ │ │ └── vendor │ │ │ ├── index.js │ │ │ └── vendor-util.js │ ├── control-panes │ │ ├── activity │ │ │ ├── activity-controller.js │ │ │ ├── activity-spec.js │ │ │ ├── activity.css │ │ │ ├── activity.pug │ │ │ └── index.js │ │ ├── advanced │ │ │ ├── advanced-controller.js │ │ │ ├── advanced-spec.js │ │ │ ├── advanced.css │ │ │ ├── advanced.pug │ │ │ ├── index.js │ │ │ ├── input │ │ │ │ ├── index.js │ │ │ │ ├── input-controller.js │ │ │ │ ├── input-spec.js │ │ │ │ ├── input.css │ │ │ │ └── input.pug │ │ │ ├── maintenance │ │ │ │ ├── index.js │ │ │ │ ├── maintenance-controller.js │ │ │ │ ├── maintenance-spec.js │ │ │ │ └── maintenance.pug │ │ │ ├── port-forwarding │ │ │ │ ├── index.js │ │ │ │ ├── port-forwarding-controller.js │ │ │ │ ├── port-forwarding-spec.js │ │ │ │ ├── port-forwarding.css │ │ │ │ └── port-forwarding.pug │ │ │ ├── run-js │ │ │ │ ├── index.js │ │ │ │ ├── run-js-controller.js │ │ │ │ ├── run-js-spec.js │ │ │ │ ├── run-js.css │ │ │ │ └── run-js.pug │ │ │ ├── usb │ │ │ │ ├── index.js │ │ │ │ ├── usb-controller.js │ │ │ │ ├── usb-spec.js │ │ │ │ ├── usb.css │ │ │ │ └── usb.pug │ │ │ └── vnc │ │ │ │ ├── index.js │ │ │ │ ├── vnc-controller.js │ │ │ │ ├── vnc-spec.js │ │ │ │ ├── vnc.css │ │ │ │ └── vnc.pug │ │ ├── automation │ │ │ ├── automation.pug │ │ │ ├── device-settings │ │ │ │ ├── device-settings-controller.js │ │ │ │ ├── device-settings-spec.js │ │ │ │ ├── device-settings.css │ │ │ │ ├── device-settings.pug │ │ │ │ └── index.js │ │ │ ├── index.js │ │ │ └── store-account │ │ │ │ ├── index.js │ │ │ │ ├── store-account-controller.js │ │ │ │ ├── store-account-spec.js │ │ │ │ ├── store-account.css │ │ │ │ └── store-account.pug │ │ ├── control-panes-controller.js │ │ ├── control-panes-hotkeys-controller.js │ │ ├── control-panes-no-device-controller.js │ │ ├── control-panes-service.js │ │ ├── control-panes.pug │ │ ├── cpu │ │ │ ├── cpu-controller.js │ │ │ ├── cpu-spec.js │ │ │ ├── cpu.css │ │ │ ├── cpu.pug │ │ │ └── index.js │ │ ├── dashboard │ │ │ ├── apps │ │ │ │ ├── apps-controller.js │ │ │ │ ├── apps.css │ │ │ │ ├── apps.pug │ │ │ │ └── index.js │ │ │ ├── clipboard │ │ │ │ ├── clipboard-controller.js │ │ │ │ ├── clipboard-spec.js │ │ │ │ ├── clipboard.css │ │ │ │ ├── clipboard.pug │ │ │ │ └── index.js │ │ │ ├── dashboard-controller.js │ │ │ ├── dashboard-spec.js │ │ │ ├── dashboard.pug │ │ │ ├── index.js │ │ │ ├── install │ │ │ │ ├── activities │ │ │ │ │ ├── activities-controller.js │ │ │ │ │ ├── activities-spec.js │ │ │ │ │ ├── activities.css │ │ │ │ │ ├── activities.pug │ │ │ │ │ ├── index.js │ │ │ │ │ └── test │ │ │ │ │ │ └── manifest-1.json │ │ │ │ ├── index.js │ │ │ │ ├── install-controller.js │ │ │ │ ├── install-spec.js │ │ │ │ ├── install.css │ │ │ │ └── install.pug │ │ │ ├── navigation │ │ │ │ ├── default-favicon.png │ │ │ │ ├── index.js │ │ │ │ ├── navigation-controller.js │ │ │ │ ├── navigation-spec.js │ │ │ │ ├── navigation.css │ │ │ │ └── navigation.pug │ │ │ ├── remote-debug │ │ │ │ ├── index.js │ │ │ │ ├── remote-debug-controller.js │ │ │ │ ├── remote-debug-spec.js │ │ │ │ ├── remote-debug.css │ │ │ │ └── remote-debug.pug │ │ │ └── shell │ │ │ │ ├── index.js │ │ │ │ ├── shell-controller.js │ │ │ │ ├── shell-spec.js │ │ │ │ ├── shell.css │ │ │ │ └── shell.pug │ │ ├── device-control │ │ │ ├── device-control-controller.js │ │ │ ├── device-control-key-directive.js │ │ │ ├── device-control-standalone.pug │ │ │ ├── device-control.css │ │ │ ├── device-control.pug │ │ │ └── index.js │ │ ├── explorer │ │ │ ├── explorer-controller.js │ │ │ ├── explorer-spec.js │ │ │ ├── explorer.css │ │ │ ├── explorer.pug │ │ │ └── index.js │ │ ├── index.js │ │ ├── info │ │ │ ├── index.js │ │ │ ├── info-controller.js │ │ │ ├── info-spec.js │ │ │ ├── info.css │ │ │ └── info.pug │ │ ├── inspect │ │ │ ├── index.js │ │ │ ├── inspect-controller.js │ │ │ ├── inspect-spec.js │ │ │ ├── inspect.css │ │ │ └── inspect.pug │ │ ├── logs │ │ │ ├── index.js │ │ │ ├── logs-controller.js │ │ │ ├── logs-spec.js │ │ │ ├── logs.less │ │ │ └── logs.pug │ │ ├── performance │ │ │ ├── cpu │ │ │ │ ├── cpu-controller.js │ │ │ │ ├── cpu-spec.js │ │ │ │ ├── cpu.css │ │ │ │ ├── cpu.pug │ │ │ │ └── index.js │ │ │ ├── index.js │ │ │ ├── performance-controller.js │ │ │ ├── performance-spec.js │ │ │ ├── performance.css │ │ │ └── performance.pug │ │ ├── resources │ │ │ ├── index.js │ │ │ ├── resources-controller.js │ │ │ ├── resources-spec.js │ │ │ ├── resources.css │ │ │ └── resources.pug │ │ └── screenshots │ │ │ ├── index.js │ │ │ ├── screenshots-controller.js │ │ │ ├── screenshots-spec.js │ │ │ ├── screenshots.css │ │ │ └── screenshots.pug │ ├── device-list │ │ ├── column │ │ │ ├── device-column-service.js │ │ │ └── index.js │ │ ├── customize │ │ │ ├── device-list-customize.css │ │ │ └── index.js │ │ ├── details │ │ │ ├── device-list-details-directive.js │ │ │ ├── device-list-details.css │ │ │ ├── device-list-details.pug │ │ │ └── index.js │ │ ├── device-list-controller.js │ │ ├── device-list.css │ │ ├── device-list.pug │ │ ├── empty │ │ │ ├── device-list-empty-directive.js │ │ │ ├── device-list-empty.pug │ │ │ └── index.js │ │ ├── icons │ │ │ ├── device-list-icons-directive.js │ │ │ ├── device-list-icons.css │ │ │ ├── device-list-icons.pug │ │ │ └── index.js │ │ ├── index.js │ │ ├── search │ │ │ ├── device-list-search.css │ │ │ └── index.js │ │ ├── stats │ │ │ ├── device-list-stats-directive.js │ │ │ ├── device-list-stats.css │ │ │ ├── device-list-stats.pug │ │ │ └── index.js │ │ └── util │ │ │ ├── patch-array │ │ │ ├── index.js │ │ │ └── patch-array-test.js │ │ │ └── query-parser │ │ │ ├── index.js │ │ │ └── query-parser-test.js │ ├── docs │ │ ├── docs-controller.js │ │ ├── docs.css │ │ └── index.js │ ├── group-list │ │ ├── group-list-controller.js │ │ ├── group-list.css │ │ ├── group-list.pug │ │ ├── groups │ │ │ └── groups.pug │ │ ├── index.js │ │ └── stats │ │ │ ├── group-quota-stats.pug │ │ │ └── group-stats.pug │ ├── layout │ │ ├── cursor.css │ │ ├── index.js │ │ ├── layout-controller.js │ │ ├── small.css │ │ └── stf-styles.css │ ├── menu │ │ ├── index.js │ │ ├── menu-controller.js │ │ ├── menu-spec.js │ │ ├── menu.css │ │ └── menu.pug │ ├── settings │ │ ├── devices │ │ │ ├── devices-controller.js │ │ │ ├── devices-spec.js │ │ │ ├── devices.css │ │ │ ├── devices.pug │ │ │ └── index.js │ │ ├── general │ │ │ ├── alert-message │ │ │ │ ├── alert-message-controller.js │ │ │ │ ├── alert-message.pug │ │ │ │ └── index.js │ │ │ ├── date-format │ │ │ │ ├── date-format-controller.js │ │ │ │ ├── date-format.pug │ │ │ │ └── index.js │ │ │ ├── email-address-separator │ │ │ │ ├── email-address-separator-controller.js │ │ │ │ ├── email-address-separator.pug │ │ │ │ └── index.js │ │ │ ├── general-controller.js │ │ │ ├── general-spec.js │ │ │ ├── general.css │ │ │ ├── general.pug │ │ │ ├── index.js │ │ │ ├── language │ │ │ │ ├── index.js │ │ │ │ ├── language-controller.js │ │ │ │ └── language.pug │ │ │ └── local │ │ │ │ ├── index.js │ │ │ │ ├── local-settings-controller.js │ │ │ │ └── local-settings.pug │ │ ├── groups │ │ │ ├── conflicts │ │ │ │ └── conflicts.pug │ │ │ ├── devices │ │ │ │ └── devices.pug │ │ │ ├── filters │ │ │ │ ├── available-objects-filter.js │ │ │ │ └── group-objects-filter.js │ │ │ ├── groups-controller.js │ │ │ ├── groups-spec.js │ │ │ ├── groups.css │ │ │ ├── groups.pug │ │ │ ├── index.js │ │ │ ├── schedule │ │ │ │ └── schedule.pug │ │ │ └── users │ │ │ │ └── users.pug │ │ ├── index.js │ │ ├── keys │ │ │ ├── access-tokens │ │ │ │ ├── access-tokens-controller.js │ │ │ │ ├── access-tokens-spec.js │ │ │ │ ├── access-tokens.css │ │ │ │ ├── access-tokens.pug │ │ │ │ └── index.js │ │ │ ├── adb-keys │ │ │ │ ├── adb-keys-controller.js │ │ │ │ ├── adb-keys-service.js │ │ │ │ ├── adb-keys-spec.js │ │ │ │ ├── adb-keys.css │ │ │ │ ├── adb-keys.pug │ │ │ │ └── index.js │ │ │ ├── index.js │ │ │ ├── keys-controller.js │ │ │ ├── keys-spec.js │ │ │ ├── keys.css │ │ │ └── keys.pug │ │ ├── notifications │ │ │ ├── index.js │ │ │ ├── notifications-controller.js │ │ │ ├── notifications-service.js │ │ │ └── notifications.pug │ │ ├── settings-controller.js │ │ ├── settings.css │ │ ├── settings.pug │ │ └── users │ │ │ ├── index.js │ │ │ ├── users-controller.js │ │ │ ├── users-spec.js │ │ │ ├── users.css │ │ │ └── users.pug │ ├── terminal │ │ └── terminal.css │ ├── user │ │ ├── index.js │ │ ├── user-controller.js │ │ └── user.pug │ └── views │ │ ├── docs.pug │ │ ├── index.pug │ │ └── rejected-email.pug ├── auth │ ├── ldap │ │ ├── scripts │ │ │ ├── entry.js │ │ │ └── signin │ │ │ │ ├── index.js │ │ │ │ ├── signin-controller.js │ │ │ │ ├── signin.css │ │ │ │ └── signin.pug │ │ └── views │ │ │ └── index.pug │ └── mock │ │ ├── scripts │ │ ├── entry.js │ │ └── signin │ │ │ ├── index.js │ │ │ ├── signin-controller.js │ │ │ ├── signin.css │ │ │ └── signin.pug │ │ └── views │ │ └── index.pug ├── common │ ├── lang │ │ ├── index.js │ │ ├── langs.json │ │ ├── po │ │ │ ├── stf.es.po │ │ │ ├── stf.fr.po │ │ │ ├── stf.ja.po │ │ │ ├── stf.ko_KR.po │ │ │ ├── stf.pl.po │ │ │ ├── stf.pot │ │ │ ├── stf.pt_BR.po │ │ │ ├── stf.ru_RU.po │ │ │ ├── stf.zh-Hant.po │ │ │ └── stf.zh_CN.po │ │ └── translations │ │ │ ├── stf.es.json │ │ │ ├── stf.fr.json │ │ │ ├── stf.ja.json │ │ │ ├── stf.ko_KR.json │ │ │ ├── stf.pl.json │ │ │ ├── stf.pt_BR.json │ │ │ ├── stf.ru_RU.json │ │ │ ├── stf.zh-Hant.json │ │ │ └── stf.zh_CN.json │ ├── logo │ │ ├── STF.ai │ │ └── exports │ │ │ ├── STF-128.png │ │ │ ├── STF-512.png │ │ │ └── STF-outlined.ai │ └── status │ │ ├── scripts │ │ └── entry.js │ │ ├── views │ │ ├── 404.pug │ │ ├── maintenance.pug │ │ └── partials │ │ │ └── styles.pug │ │ └── webpack.config.js ├── test │ ├── .eslintrc │ ├── e2e │ │ ├── control │ │ │ └── control-spec.js │ │ ├── devices │ │ │ ├── devices-spec.js │ │ │ └── index.js │ │ ├── help │ │ │ └── help-spec.js │ │ ├── helpers │ │ │ ├── browser-logs.js │ │ │ ├── fail-fast.js │ │ │ ├── gulp-protractor-adv.js │ │ │ └── wait-url.js │ │ ├── login │ │ │ ├── index.js │ │ │ └── login-spec.js │ │ ├── menu │ │ │ └── menu-spec.js │ │ ├── settings │ │ │ └── settings-spec.js │ │ └── widget-container │ │ │ ├── index.js │ │ │ └── widget-container-spec.js │ ├── helpers │ │ └── helper.js │ ├── karma.conf.js │ ├── protractor-appium.conf.js │ ├── protractor-multi.conf.js │ └── protractor.conf.js └── web_modules │ ├── angular-borderlayout │ ├── index.js │ └── style.css │ ├── angular-growl │ └── index.js │ ├── angular-hotkeys │ ├── hotkeys.css │ └── index.js │ ├── angular-ladda │ └── index.js │ ├── angular-xeditable │ ├── index.js │ └── style.css │ ├── epoch │ └── index.js │ ├── gettext │ └── index.js │ ├── ladda │ └── index.js │ ├── ng-context-menu │ ├── context-menu.css │ └── index.js │ ├── ng-file-upload │ └── index.js │ ├── nine-bootstrap │ ├── README.md │ ├── index.js │ └── nine-bootstrap.scss │ └── ui-bootstrap │ └── index.js ├── test ├── .eslintrc ├── fixt │ ├── Virtual.kcm │ └── Virtual.kcm.json ├── util │ ├── keyutil.js │ ├── logger.js │ └── ttlset.js └── wire │ ├── messagestream.js │ └── seqqueue.js ├── vendor ├── STFService │ ├── STFService.apk │ └── wire.proto └── minirev │ ├── arm64-v8a │ ├── minirev │ └── minirev-nopie │ ├── armeabi-v7a │ ├── minirev │ └── minirev-nopie │ ├── armeabi │ ├── minirev │ └── minirev-nopie │ ├── mips │ ├── minirev │ └── minirev-nopie │ ├── mips64 │ ├── minirev │ └── minirev-nopie │ ├── x86 │ ├── minirev │ └── minirev-nopie │ └── x86_64 │ ├── minirev │ └── minirev-nopie └── webpack.config.js /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "registry": "https://registry.bower.io", 3 | "directory": "res/bower_components" 4 | } 5 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | *.mo 2 | *.tgz 3 | .DS_Store 4 | .env 5 | .git/ 6 | .idea/ 7 | node_modules/ 8 | npm-debug.log 9 | res/bower_components/ 10 | res/build/ 11 | rethinkdb_data/ 12 | temp/ 13 | tmp/ 14 | .eslintcache 15 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org/ 2 | 3 | root = true 4 | 5 | [*] 6 | indent_style = space 7 | indent_size = 2 8 | end_of_line = lf 9 | charset = utf-8 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | ignore: 9 | - dependency-name: karma 10 | versions: 11 | - 6.0.0 12 | - 6.1.0 13 | - 6.1.2 14 | - 6.2.0 15 | - dependency-name: semver 16 | versions: 17 | - 7.3.4 18 | - dependency-name: style-loader 19 | versions: 20 | - 1.2.1 21 | - dependency-name: express-validator 22 | versions: 23 | - 6.9.2 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.mo 2 | .DS_Store 3 | .eslintcache 4 | .idea/ 5 | *.iml 6 | .python-version 7 | /*.tgz 8 | /.env 9 | /node_modules/ 10 | /res/bower_components/ 11 | /res/build/ 12 | /res/test_out/ 13 | /rethinkdb_data/ 14 | /temp/ 15 | /tmp/ 16 | package-lock.json 17 | yarn.lock 18 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | *.!sync 2 | .DS_Store 3 | /*.tgz 4 | /.bowerrc 5 | /.dockerignore 6 | /.editorconfig 7 | /.env 8 | /.gitignore 9 | /.idea/ 10 | /.jscsrc 11 | /.npmignore 12 | /.npmrc 13 | /.python-version 14 | /.travis.yml 15 | /Dockerfile 16 | /bower.json 17 | /component.json 18 | /docker 19 | /gulpfile.js 20 | /npm-debug.log 21 | /res/bower_components/ 22 | /res/test/ 23 | /res/web_modules/ 24 | /rethinkdb_data/ 25 | /temp/ 26 | /test/ 27 | /tmp/ 28 | /webpack.config.js 29 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v22.11.0 2 | -------------------------------------------------------------------------------- /.semaphore/deploy_npmjs.yml: -------------------------------------------------------------------------------- 1 | version: v1.0 2 | name: Deploy to npmjs 3 | blocks: 4 | - name: Deploy to npmjs 5 | task: 6 | jobs: 7 | - name: Deploy 8 | commands: 9 | - install-package libzmq3-dev libprotobuf-dev graphicsmagick yasm gulp python3 --update 10 | - sem-version node 20 11 | - checkout 12 | - npm install 13 | - npm publish --access=public 14 | secrets: 15 | - name: npmjs 16 | agent: 17 | machine: 18 | type: e1-standard-2 19 | os_image: ubuntu2004 20 | -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | nodejs 22.11.0 2 | -------------------------------------------------------------------------------- /.tx/config: -------------------------------------------------------------------------------- 1 | [main] 2 | host = https://www.transifex.com 3 | 4 | [stf.ui] 5 | file_filter = res/common/lang/po/stf..po 6 | source_file = res/common/lang/po/stf.pot 7 | source_lang = en 8 | type = PO 9 | 10 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | **What is the issue or idea you have?** 4 | 5 | **Does it only happen on a specific device? Please run `adb devices -l` and paste the corresponding row.** 6 | 7 | **Please provide the steps to reproduce the issue.** 8 | 9 | **What is the expected behavior?** 10 | 11 | **Do you see errors or warnings in the `stf local` output? If so, please paste them or the full log here.** 12 | 13 | **Please run `stf doctor` and paste the output here.** 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2013 CyberAgent, Inc. 2 | Copyright © 2016 The OpenSTF Project 3 | Copyright © 2019 Orange SA 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | -------------------------------------------------------------------------------- /bin/stf: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S node --no-deprecation 2 | require('../lib/cli/please') 3 | -------------------------------------------------------------------------------- /doc/7s_usage.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/doc/7s_usage.gif -------------------------------------------------------------------------------- /doc/GroupFeature.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/doc/GroupFeature.pdf -------------------------------------------------------------------------------- /doc/WHY.md: -------------------------------------------------------------------------------- 1 | # Why? 2 | 3 | This document lists reasons for various internal decisions so that we'll hopefully never forget them (again). 4 | 5 | ## Why not keep a rotation lock to prevent the screen from reverting to its natural position? 6 | 7 | Because a physical rotation would then have no effect. While STF is meant for larger device farms, we anticipate a large portion of our user base to be running STF on their local computers with the actual devices right next to them, and it would be confusing if rotation suddenly had no effect. 8 | -------------------------------------------------------------------------------- /doc/shelf_closeup_790x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/doc/shelf_closeup_790x.jpg -------------------------------------------------------------------------------- /doc/sponsors/headspin-wordmark-orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/doc/sponsors/headspin-wordmark-orange.png -------------------------------------------------------------------------------- /doc/topo-v1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/doc/topo-v1.png -------------------------------------------------------------------------------- /docker/armv7l/stf-armv7l-baseimage@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Build openstf/stf %I base image for armv7l 3 | After=docker.service 4 | Requires=docker.service 5 | ConditionArchitecture=arm 6 | Requires=stf-armv7l-clone@%i.service 7 | After=stf-armv7l-clone@%i.service 8 | 9 | [Service] 10 | Type=oneshot 11 | WorkingDirectory=/home/stf-armv7l/repo-%i 12 | Environment="ARCH=armhf" 13 | ExecStart=/bin/sh docker/armv7l/mkimage-alpine.sh -r v3.5 -i alpine-stf-armv7l-%i:3.5 14 | ExecStart=/usr/bin/sed -i.bak 's/FROM alpine:3.5/FROM alpine-stf-armv7l-%i:3.5/' docker/armv7l/Dockerfile 15 | -------------------------------------------------------------------------------- /docker/armv7l/stf-armv7l-build@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Build openstf/stf %I for armv7l 3 | After=docker.service 4 | Requires=docker.service 5 | ConditionArchitecture=arm 6 | Requires=stf-armv7l-baseimage@%i.service 7 | After=stf-armv7l-baseimage@%i.service 8 | 9 | [Service] 10 | Type=oneshot 11 | User=stf-armv7l 12 | WorkingDirectory=/home/stf-armv7l/repo-%i 13 | ExecStart=/usr/bin/docker build -f docker/armv7l/Dockerfile -t openstf/stf-armv7l:%i . 14 | -------------------------------------------------------------------------------- /docker/armv7l/stf-armv7l-clone@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Clone openstf/stf %I for armv7l 3 | After=docker.service 4 | Requires=docker.service 5 | 6 | [Service] 7 | Type=oneshot 8 | User=stf-armv7l 9 | ExecStart=/usr/bin/rm -rf /home/stf-armv7l/repo-%i 10 | ExecStart=/usr/bin/git -C /home/stf-armv7l clone --depth 1 -b "%I" https://github.com/openstf/stf.git repo-%i 11 | -------------------------------------------------------------------------------- /docker/armv7l/stf-armv7l-publish-latest.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Publish openstf/stf master as latest for armv7l 3 | After=docker.service 4 | Requires=docker.service 5 | ConditionArchitecture=arm 6 | Requires=stf-armv7l-publish@master.service 7 | After=stf-armv7l-publish@master.service 8 | 9 | [Service] 10 | Type=oneshot 11 | ExecStart=/usr/bin/docker tag openstf/stf-armv7l:master openstf/stf-armv7l:latest 12 | ExecStart=/usr/bin/docker push openstf/stf-armv7l:latest 13 | -------------------------------------------------------------------------------- /docker/armv7l/stf-armv7l-publish-latest.timer: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Run stf-armv7l-publish-latest.service daily 3 | 4 | [Timer] 5 | OnCalendar=*-*-* 18:00:00 6 | Persistent=true 7 | 8 | [Install] 9 | WantedBy=timers.target 10 | -------------------------------------------------------------------------------- /docker/armv7l/stf-armv7l-publish@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Publish openstf/stf %I for armv7l 3 | After=docker.service 4 | Requires=docker.service 5 | ConditionArchitecture=arm 6 | Requires=stf-armv7l-build@%i.service 7 | After=stf-armv7l-build@%i.service 8 | 9 | [Service] 10 | Type=oneshot 11 | ExecStart=/usr/bin/docker push openstf/stf-armv7l:%i 12 | -------------------------------------------------------------------------------- /docker/extras/docker-cleanup-dangling-images.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Clean up dangling Docker images 3 | After=docker.service 4 | Requires=docker.service 5 | 6 | [Service] 7 | Type=oneshot 8 | ExecStart=/usr/bin/env sh -c '/usr/bin/docker images -q --filter "dangling=true" | xargs -t --no-run-if-empty /usr/bin/docker rmi' 9 | -------------------------------------------------------------------------------- /docker/extras/docker-cleanup-dangling-images.timer: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Run docker-cleanup-dangling-images.service daily 3 | 4 | [Timer] 5 | OnCalendar=*-*-* 10:00:00 6 | Persistent=true 7 | 8 | [Install] 9 | WantedBy=timers.target 10 | -------------------------------------------------------------------------------- /lib/cli/please.js: -------------------------------------------------------------------------------- 1 | require('@devicefarmer/please-update-dependencies')(module) 2 | require('./') 3 | -------------------------------------------------------------------------------- /lib/units/app/middleware/appstore-icons.js: -------------------------------------------------------------------------------- 1 | var serveStatic = require('serve-static') 2 | 3 | var pathutil = require('../../../util/pathutil') 4 | 5 | module.exports = function() { 6 | return serveStatic( 7 | pathutil.root('node_modules/@devicefarmer/stf-appstore-db/dist') 8 | , { 9 | maxAge: '30d' 10 | } 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /lib/units/app/middleware/browser-icons.js: -------------------------------------------------------------------------------- 1 | var serveStatic = require('serve-static') 2 | 3 | var pathutil = require('../../../util/pathutil') 4 | 5 | module.exports = function() { 6 | return serveStatic( 7 | pathutil.root('node_modules/@devicefarmer/stf-browser-db/dist') 8 | , { 9 | maxAge: '30d' 10 | } 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /lib/units/app/middleware/device-icons.js: -------------------------------------------------------------------------------- 1 | var serveStatic = require('serve-static') 2 | 3 | var pathutil = require('../../../util/pathutil') 4 | 5 | module.exports = function() { 6 | return serveStatic( 7 | pathutil.root('node_modules/@devicefarmer/stf-device-db/dist') 8 | , { 9 | maxAge: '30d' 10 | } 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /lib/units/device/plugins/screen/options.js: -------------------------------------------------------------------------------- 1 | var syrup = require('@devicefarmer/stf-syrup') 2 | var _ = require('lodash') 3 | 4 | module.exports = syrup.serial() 5 | .define(function(options) { 6 | var plugin = Object.create(null) 7 | 8 | plugin.devicePort = 9002 9 | plugin.publicPort = options.screenPort 10 | plugin.publicUrl = _.template(options.screenWsUrlPattern)({ 11 | publicIp: options.publicIp 12 | , publicPort: plugin.publicPort 13 | , serial: options.serial 14 | }) 15 | 16 | return plugin 17 | }) 18 | -------------------------------------------------------------------------------- /lib/units/device/plugins/screen/util/frameconfig.js: -------------------------------------------------------------------------------- 1 | var util = require('util') 2 | 3 | function FrameConfig(real, virtual) { 4 | this.realWidth = real.width 5 | this.realHeight = real.height 6 | this.virtualWidth = virtual.width 7 | this.virtualHeight = virtual.height 8 | this.rotation = virtual.rotation 9 | } 10 | 11 | FrameConfig.prototype.toString = function() { 12 | return util.format( 13 | '%dx%d@%dx%d/%d' 14 | , this.realWidth 15 | , this.realHeight 16 | , this.virtualWidth 17 | , this.virtualHeight 18 | , this.rotation 19 | ) 20 | } 21 | 22 | module.exports = FrameConfig 23 | -------------------------------------------------------------------------------- /lib/units/device/plugins/util/data.js: -------------------------------------------------------------------------------- 1 | var syrup = require('@devicefarmer/stf-syrup') 2 | var deviceData = require('@devicefarmer/stf-device-db') 3 | 4 | var logger = require('../../../../util/logger') 5 | 6 | module.exports = syrup.serial() 7 | .dependency(require('./identity')) 8 | .define(function(options, identity) { 9 | var log = logger.createLogger('device:plugins:data') 10 | 11 | function find() { 12 | var data = deviceData.find(identity) 13 | if (!data) { 14 | log.warn('Unable to find device data', identity) 15 | } 16 | return data 17 | } 18 | 19 | return find() 20 | }) 21 | -------------------------------------------------------------------------------- /lib/units/device/plugins/util/flags.js: -------------------------------------------------------------------------------- 1 | var syrup = require('@devicefarmer/stf-syrup') 2 | 3 | module.exports = syrup.serial() 4 | .dependency(require('./data')) 5 | .define(function(options, data) { 6 | return { 7 | has: function(flag) { 8 | return data && data.flags && !!data.flags[flag] 9 | } 10 | , get: function(flag, defaultValue) { 11 | return data && data.flags && typeof data.flags[flag] !== 'undefined' ? 12 | data.flags[flag] : 13 | defaultValue 14 | } 15 | } 16 | }) 17 | -------------------------------------------------------------------------------- /lib/units/device/plugins/util/phone.js: -------------------------------------------------------------------------------- 1 | var syrup = require('@devicefarmer/stf-syrup') 2 | 3 | var logger = require('../../../../util/logger') 4 | 5 | module.exports = syrup.serial() 6 | .dependency(require('../service')) 7 | .define(function(options, service) { 8 | var log = logger.createLogger('device:plugins:phone') 9 | 10 | function fetch() { 11 | log.info('Fetching phone info') 12 | return service.getProperties([ 13 | 'imei' 14 | , 'imsi' 15 | , 'phoneNumber' 16 | , 'iccid' 17 | , 'network' 18 | ]) 19 | } 20 | 21 | return fetch() 22 | }) 23 | -------------------------------------------------------------------------------- /lib/units/device/plugins/vnc/util/pixelformat.js: -------------------------------------------------------------------------------- 1 | function PixelFormat(values) { 2 | this.bitsPerPixel = values.bitsPerPixel 3 | this.depth = values.depth 4 | this.bigEndianFlag = values.bigEndianFlag 5 | this.trueColorFlag = values.trueColorFlag 6 | this.redMax = values.redMax 7 | this.greenMax = values.greenMax 8 | this.blueMax = values.blueMax 9 | this.redShift = values.redShift 10 | this.greenShift = values.greenShift 11 | this.blueShift = values.blueShift 12 | } 13 | 14 | module.exports = PixelFormat 15 | -------------------------------------------------------------------------------- /lib/units/device/resources/util/resource.js: -------------------------------------------------------------------------------- 1 | var util = require('util') 2 | 3 | function Resource(options) { 4 | this.src = options.src 5 | this.dest = options.dest.shift() 6 | this.comm = options.comm 7 | this.mode = options.mode 8 | this.fallback = options.dest 9 | } 10 | 11 | Resource.prototype.shift = function() { 12 | if (this.fallback.length === 0) { 13 | throw new Error(util.format( 14 | 'Out of fallback locations for "%s"' 15 | , this.src 16 | )) 17 | } 18 | this.dest = this.fallback.shift() 19 | } 20 | 21 | module.exports = Resource 22 | -------------------------------------------------------------------------------- /lib/units/device/support/channels.js: -------------------------------------------------------------------------------- 1 | var syrup = require('@devicefarmer/stf-syrup') 2 | 3 | var logger = require('../../../util/logger') 4 | var ChannelManager = require('../../../wire/channelmanager') 5 | 6 | module.exports = syrup.serial() 7 | .define(function() { 8 | var log = logger.createLogger('device:support:channels') 9 | var channels = new ChannelManager() 10 | channels.on('timeout', function(channel) { 11 | log.info('Channel "%s" timed out', channel) 12 | }) 13 | return channels 14 | }) 15 | -------------------------------------------------------------------------------- /lib/units/device/support/properties.js: -------------------------------------------------------------------------------- 1 | var syrup = require('@devicefarmer/stf-syrup') 2 | 3 | var logger = require('../../../util/logger') 4 | 5 | module.exports = syrup.serial() 6 | .dependency(require('./adb')) 7 | .define(function(options, adb) { 8 | var log = logger.createLogger('device:support:properties') 9 | 10 | function load() { 11 | log.info('Loading properties') 12 | return adb.getProperties(options.serial) 13 | .timeout(10000) 14 | } 15 | 16 | return load() 17 | }) 18 | -------------------------------------------------------------------------------- /lib/units/device/support/router.js: -------------------------------------------------------------------------------- 1 | var syrup = require('@devicefarmer/stf-syrup') 2 | 3 | var wirerouter = require('../../../wire/router') 4 | 5 | module.exports = syrup.serial() 6 | .dependency(require('./sub')) 7 | .dependency(require('./channels')) 8 | .define(function(options, sub, channels) { 9 | var router = wirerouter() 10 | 11 | sub.on('message', router.handler()) 12 | 13 | // Special case, we're hooking into a message that's not actually routed. 14 | router.on({$code: 'message'}, function(channel) { 15 | channels.keepalive(channel) 16 | }) 17 | 18 | return router 19 | }) 20 | -------------------------------------------------------------------------------- /lib/units/storage/plugins/apk/task/manifest.js: -------------------------------------------------------------------------------- 1 | var ApkReader = require('@devicefarmer/adbkit-apkreader') 2 | 3 | module.exports = function(file) { 4 | return ApkReader.open(file.path).then(function(reader) { 5 | return reader.readManifest() 6 | }) 7 | } 8 | -------------------------------------------------------------------------------- /lib/units/storage/plugins/image/param/crop.js: -------------------------------------------------------------------------------- 1 | var RE_CROP = /^([0-9]*)x([0-9]*)$/ 2 | 3 | module.exports = function(raw) { 4 | var parsed 5 | 6 | if (raw && (parsed = RE_CROP.exec(raw))) { 7 | return { 8 | width: Number(parsed[1]) || 0 9 | , height: Number(parsed[2]) || 0 10 | } 11 | } 12 | 13 | return null 14 | } 15 | -------------------------------------------------------------------------------- /lib/units/storage/plugins/image/param/gravity.js: -------------------------------------------------------------------------------- 1 | var GRAVITY = { 2 | northwest: 'NorthWest' 3 | , north: 'North' 4 | , northeast: 'NorthEast' 5 | , west: 'West' 6 | , center: 'Center' 7 | , east: 'East' 8 | , southwest: 'SouthWest' 9 | , south: 'South' 10 | , southeast: 'SouthEast' 11 | } 12 | 13 | module.exports = function(raw) { 14 | var parsed 15 | 16 | if (raw && (parsed = GRAVITY[raw])) { 17 | return parsed 18 | } 19 | 20 | return null 21 | } 22 | -------------------------------------------------------------------------------- /lib/units/websocket/middleware/auth.js: -------------------------------------------------------------------------------- 1 | var dbapi = require('../../../db/api') 2 | 3 | module.exports = function(socket, next) { 4 | var req = socket.request 5 | var token = req.session.jwt 6 | if (token) { 7 | return dbapi.loadUser(token.email) 8 | .then(function(user) { 9 | if (user) { 10 | req.user = user 11 | next() 12 | } 13 | else { 14 | next(new Error('Invalid user')) 15 | } 16 | }) 17 | .catch(next) 18 | } 19 | else { 20 | next(new Error('Missing authorization token')) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /lib/units/websocket/middleware/cookie-session.js: -------------------------------------------------------------------------------- 1 | var cookieSession = require('cookie-session') 2 | 3 | module.exports = function(options) { 4 | var session = cookieSession(options) 5 | return function(socket, next) { 6 | var req = socket.request 7 | var res = Object.create(null) 8 | session(req, res, next) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /lib/units/websocket/middleware/remote-ip.js: -------------------------------------------------------------------------------- 1 | var proxyaddr = require('proxy-addr') 2 | 3 | module.exports = function(options) { 4 | return function(socket, next) { 5 | var req = socket.request 6 | req.ip = proxyaddr(req, options.trust) 7 | next() 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /lib/util/fakeuser.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | const util = require('util') 6 | const uuid = require('uuid') 7 | const dbapi = require('../db/api') 8 | 9 | module.exports.generate = function() { 10 | const name = 'fakeuser-' + util.format('%s', uuid.v4()).replace(/-/g, '') 11 | const email = name + '@openstf.com' 12 | 13 | return dbapi.createUser(email, name, '127.0.0.1').return(email) 14 | } 15 | -------------------------------------------------------------------------------- /lib/util/promiseutil.js: -------------------------------------------------------------------------------- 1 | var Promise = require('bluebird') 2 | 3 | module.exports.periodicNotify = function(promise, interval) { 4 | var resolver = Promise.defer() 5 | 6 | function notify() { 7 | resolver.progress() 8 | } 9 | 10 | var timer = setInterval(notify, interval) 11 | 12 | function resolve(value) { 13 | resolver.resolve(value) 14 | } 15 | 16 | function reject(err) { 17 | resolver.reject(err) 18 | } 19 | 20 | promise.then(resolve, reject) 21 | 22 | return resolver.promise.finally(function() { 23 | clearInterval(timer) 24 | }) 25 | } 26 | -------------------------------------------------------------------------------- /lib/util/refresh.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | 3 | var watchers = Object.create(null) 4 | 5 | function refresh() { 6 | process.kill('SIGHUP') 7 | } 8 | 9 | function collect() { 10 | Object.keys(require.cache).forEach(function(path) { 11 | if (!watchers[path]) { 12 | if (path.indexOf('node_modules') === -1) { 13 | watchers[path] = fs.watch(path, refresh) 14 | } 15 | } 16 | }) 17 | } 18 | 19 | module.exports = function() { 20 | collect() 21 | } 22 | -------------------------------------------------------------------------------- /lib/util/timeutil.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | const timeutil = Object.create(null) 6 | 7 | timeutil.now = function(unit) { 8 | const hrTime = process.hrtime() 9 | 10 | switch (unit) { 11 | case 'milli': 12 | return hrTime[0] * 1000 + hrTime[1] / 1000000 13 | case 'micro': 14 | return hrTime[0] * 1000000 + hrTime[1] / 1000 15 | case 'nano': 16 | return hrTime[0] * 1000000000 + hrTime[1] 17 | default: 18 | return hrTime[0] * 1000000000 + hrTime[1] 19 | } 20 | } 21 | 22 | module.exports = timeutil 23 | -------------------------------------------------------------------------------- /lib/util/urlutil.js: -------------------------------------------------------------------------------- 1 | var url = require('url') 2 | 3 | /* eslint guard-for-in:0 */ 4 | module.exports.addParams = function(originalUrl, params) { 5 | var parsed = url.parse(originalUrl, true) 6 | parsed.search = null 7 | // TODO: change to ES6 loop 8 | for (var key in params) { 9 | parsed.query[key] = params[key] 10 | } 11 | return url.format(parsed) 12 | } 13 | 14 | module.exports.removeParam = function(originalUrl, param) { 15 | var parsed = url.parse(originalUrl, true) 16 | parsed.search = null 17 | delete parsed.query[param] 18 | return url.format(parsed) 19 | } 20 | -------------------------------------------------------------------------------- /lib/wire/index.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | 3 | var ProtoBuf = require('protobufjs') 4 | 5 | var wire = ProtoBuf.loadProtoFile(path.join(__dirname, 'wire.proto')).build() 6 | 7 | wire.ReverseMessageType = Object.keys(wire.MessageType) 8 | .reduce( 9 | function(acc, type) { 10 | var code = wire.MessageType[type] 11 | if (!wire[type]) { 12 | throw new Error('wire.MessageType has unknown value "' + type + '"') 13 | } 14 | wire[type].$code = wire[type].prototype.$code = code 15 | acc[code] = type 16 | return acc 17 | } 18 | , Object.create(null) 19 | ) 20 | 21 | module.exports = wire 22 | -------------------------------------------------------------------------------- /res/app/components/stf/admin-mode/admin-mode-directive.js: -------------------------------------------------------------------------------- 1 | module.exports = function adminModeDirective($rootScope, SettingsService) { 2 | return { 3 | restrict: 'AE', 4 | link: function() { 5 | SettingsService.bind($rootScope, { 6 | target: 'adminMode', 7 | defaultValue: false 8 | }) 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /res/app/components/stf/admin-mode/admin-mode-spec.js: -------------------------------------------------------------------------------- 1 | describe('AdminModeService', function() { 2 | beforeEach(angular.mock.module(require('./').name)) 3 | }) 4 | -------------------------------------------------------------------------------- /res/app/components/stf/admin-mode/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.admin-mode', [ 2 | 3 | ]) 4 | .directive('adminMode', require('./admin-mode-directive')) 5 | -------------------------------------------------------------------------------- /res/app/components/stf/angular-draggabilly/angular-draggabilly-directive.js: -------------------------------------------------------------------------------- 1 | module.exports = 2 | function angularDraggabillyDirective(DraggabillyService, $parse) { 3 | return { 4 | restrict: 'AE', 5 | link: function(scope, element, attrs) { 6 | var parsedAttrs = $parse(attrs.angularDraggabilly)() 7 | if (typeof parsedAttrs !== 'object') { 8 | parsedAttrs = {} 9 | } 10 | 11 | var options = angular.extend({ 12 | }, parsedAttrs) 13 | 14 | /* eslint no-unused-vars: 0 */ 15 | var draggie = new DraggabillyService(element[0], options) 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /res/app/components/stf/angular-draggabilly/index.js: -------------------------------------------------------------------------------- 1 | var draggabilly = require('draggabilly') 2 | 3 | module.exports = angular.module('stf.angular-draggabilly', [ 4 | 5 | ]) 6 | .factory('DraggabillyService', function() { 7 | return draggabilly 8 | }) 9 | .directive('angularDraggabilly', require('./angular-draggabilly-directive')) 10 | -------------------------------------------------------------------------------- /res/app/components/stf/angular-packery/index.js: -------------------------------------------------------------------------------- 1 | require('./angular-packery.css') 2 | 3 | require('packery/js/rect.js') 4 | require('packery/js/packer.js') 5 | require('packery/js/item.js') 6 | var packery = require('packery/js/packery.js') 7 | 8 | module.exports = angular.module('stf.angular-packery', [ 9 | require('stf/angular-draggabilly').name 10 | ]) 11 | .factory('PackeryService', function() { 12 | return packery 13 | }) 14 | .directive('angularPackery', require('./angular-packery-directive')) 15 | -------------------------------------------------------------------------------- /res/app/components/stf/app-state/app-state-provider.js: -------------------------------------------------------------------------------- 1 | module.exports = function AppStateProvider() { 2 | var values = { 3 | config: { 4 | websocketUrl: '' 5 | }, 6 | user: { 7 | settings: {} 8 | }, 9 | device: { 10 | platform: '' 11 | } 12 | } 13 | 14 | /* global GLOBAL_APPSTATE:false */ 15 | if (typeof GLOBAL_APPSTATE !== 'undefined') { 16 | values = angular.extend(values, GLOBAL_APPSTATE) 17 | } 18 | 19 | return { 20 | set: function(constants) { 21 | angular.extend(values, constants) 22 | }, 23 | $get: function() { 24 | return values 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /res/app/components/stf/app-state/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.app-state', [ 2 | ]) 3 | .provider('AppState', require('./app-state-provider.js')) 4 | -------------------------------------------------------------------------------- /res/app/components/stf/basic-mode/basic-mode-directive.js: -------------------------------------------------------------------------------- 1 | module.exports = function basicModeDirective($rootScope, BrowserInfo) { 2 | return { 3 | restrict: 'AE', 4 | link: function(scope, element) { 5 | $rootScope.basicMode = !!BrowserInfo.mobile 6 | if ($rootScope.basicMode) { 7 | element.addClass('basic-mode') 8 | } 9 | 10 | if (BrowserInfo.mobile) { 11 | element.addClass('mobile') 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /res/app/components/stf/basic-mode/basic-mode-spec.js: -------------------------------------------------------------------------------- 1 | describe('basicMode', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, compile 6 | 7 | beforeEach(inject(function($rootScope, $compile) { 8 | scope = $rootScope.$new() 9 | compile = $compile 10 | })) 11 | 12 | it('should ...', function() { 13 | 14 | /* 15 | To test your directive, you need to create some html that would use your directive, 16 | send that through compile() then compare the results. 17 | 18 | var element = compile('
hi
')(scope); 19 | expect(element.text()).toBe('hello, world'); 20 | */ 21 | 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /res/app/components/stf/basic-mode/index.js: -------------------------------------------------------------------------------- 1 | require('./basic-mode.css') 2 | 3 | module.exports = angular.module('stf.basic-mode', [ 4 | ]) 5 | .directive('basicMode', require('./basic-mode-directive')) 6 | -------------------------------------------------------------------------------- /res/app/components/stf/browser-info/browser-info-spec.js: -------------------------------------------------------------------------------- 1 | describe('BrowserInfo', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | it('should ...', inject(function() { 6 | 7 | // expect(BrowserInfo.doSomething()).toEqual('something') 8 | 9 | })) 10 | 11 | }) 12 | -------------------------------------------------------------------------------- /res/app/components/stf/browser-info/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.browser-info', [ 2 | 3 | ]) 4 | .factory('BrowserInfo', require('./browser-info-service')) 5 | -------------------------------------------------------------------------------- /res/app/components/stf/column-choice/column-choice-directive.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | module.exports = function() { 6 | return { 7 | restrict: 'E', 8 | scope: { 9 | buttonStyle: '@?', 10 | columnData: '=', 11 | resetData: '&' 12 | }, 13 | template: require('./column-choice.pug'), 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /res/app/components/stf/column-choice/column-choice.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | .stf-column-choice .stf-column-customize { 6 | white-space: nowrap; 7 | padding: 10px; 8 | padding-bottom: 0; 9 | column-count: 2; 10 | -moz-column-count: 2; 11 | -webkit-column-count: 2; 12 | max-width: 800px; 13 | } 14 | 15 | .stf-column-choice .stf-column-customize .checkbox { 16 | margin-bottom: 10px; 17 | } 18 | 19 | .stf-column-choice .stf-column-customize .checkbox-label { 20 | margin-left: 10px; 21 | } 22 | 23 | 24 | -------------------------------------------------------------------------------- /res/app/components/stf/column-choice/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | require('./column-choice.css') 6 | 7 | module.exports = angular.module('stf.column-choice', [ 8 | require('stf/common-ui').name 9 | ]) 10 | .directive('stfColumnChoice', require('./column-choice-directive')) 11 | 12 | 13 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/badge-icon/badge-icon-directive.js: -------------------------------------------------------------------------------- 1 | module.exports = function badgeIconDirective() { 2 | return { 3 | restrict: 'EA', 4 | replace: true, 5 | scope: { 6 | }, 7 | template: require('./badge-icon.pug'), 8 | link: function() { 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/badge-icon/badge-icon.css: -------------------------------------------------------------------------------- 1 | .stf-badge-icon { 2 | 3 | } 4 | 5 | .stf-badge-icon .stf-badge-icon-warning { 6 | color: #fec42d; 7 | } 8 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/badge-icon/badge-icon.pug: -------------------------------------------------------------------------------- 1 | div.stf-badge-icon 2 | i.fa.fa-warning.stf-badge-icon-warning(tooltip-placement='bottom', uib-tooltip='An error has ocurred') 3 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/badge-icon/index.js: -------------------------------------------------------------------------------- 1 | require('./badge-icon.css') 2 | 3 | module.exports = angular.module('stf.badge-icon', [ 4 | 5 | ]) 6 | .directive('badgeIcon', require('./badge-icon-directive')) 7 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/blur-element/blur-element-directive.js: -------------------------------------------------------------------------------- 1 | module.exports = function blurElementDirective($parse, $timeout) { 2 | return { 3 | restrict: 'A', 4 | link: function(scope, element, attrs) { 5 | var model = $parse(attrs.blurElement) 6 | 7 | scope.$watch(model, function(value) { 8 | if (value === true) { 9 | $timeout(function() { 10 | element[0].blur() 11 | }) 12 | } 13 | }) 14 | 15 | element.bind('blur', function() { 16 | scope.$apply(model.assign(scope, false)) 17 | }) 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/blur-element/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.blur-element', [ 2 | 3 | ]) 4 | .directive('blurElement', require('./blur-element-directive')) 5 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/clear-button/clear-button-directive.js: -------------------------------------------------------------------------------- 1 | module.exports = function clearButtonDirective() { 2 | return { 3 | restrict: 'EA', 4 | replace: true, 5 | scope: {}, 6 | template: require('./clear-button.pug') 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/clear-button/clear-button.pug: -------------------------------------------------------------------------------- 1 | button.btn.btn-sm.btn-danger-outline.pull-right 2 | i.fa.fa-trash-o 3 | span(translate) Clear -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/clear-button/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.clear-button', []) 2 | .directive('clearButton', require('./clear-button-directive')) 3 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/counter/counter-spec.js: -------------------------------------------------------------------------------- 1 | describe('counter', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, compile 6 | 7 | beforeEach(inject(function($rootScope, $compile) { 8 | scope = $rootScope.$new() 9 | compile = $compile 10 | })) 11 | 12 | it('should ...', function() { 13 | 14 | /* 15 | To test your directive, you need to create some html that would use your directive, 16 | send that through compile() then compare the results. 17 | 18 | var element = compile('
hi
')(scope); 19 | expect(element.text()).toBe('hello, world'); 20 | */ 21 | 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/counter/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.counter', [ 2 | 3 | ]) 4 | .directive('countFrom', require('./counter-directive')) 5 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/enable-autofill/index.js: -------------------------------------------------------------------------------- 1 | require('angular-cookies') 2 | 3 | module.exports = angular.module('stf.enable-autofill', [ 4 | 'ngCookies' 5 | ]) 6 | .directive('enableAutofill', require('./enable-autofill-directive')) 7 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/error-message/error-message-directive.js: -------------------------------------------------------------------------------- 1 | module.exports = function errorMessageDirective() { 2 | return { 3 | restrict: 'EA', 4 | replace: true, 5 | scope: { 6 | message: '@' 7 | }, 8 | template: require('./error-message.pug'), 9 | link: function(scope) { 10 | scope.closeMessage = function() { 11 | scope.message = '' 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/error-message/error-message.css: -------------------------------------------------------------------------------- 1 | .stf-error-message { 2 | padding-bottom: 15px; 3 | } 4 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/error-message/error-message.pug: -------------------------------------------------------------------------------- 1 | .stf-error-message 2 | alert(type='danger', close='closeMessage()', ng-if='message') 3 | strong(translate) Oops! 4 | | 5 | span(ng-bind='message') 6 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/error-message/index.js: -------------------------------------------------------------------------------- 1 | require('./error-message.css') 2 | 3 | module.exports = angular.module('stf.error-message', [ 4 | 5 | ]) 6 | .directive('errorMessage', require('./error-message-directive')) 7 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/fallback-image/fallback-image-directive.js: -------------------------------------------------------------------------------- 1 | module.exports = function fallbackImageDirective() { 2 | return { 3 | restrict: 'A', 4 | link: function postLink(scope, element, attrs) { 5 | element.on('error', function() { 6 | angular.element(this).attr('src', attrs.fallbackImage) 7 | }) 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/fallback-image/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.fallback-image', [ 2 | 3 | ]) 4 | .directive('fallbackImage', require('./fallback-image-directive')) 5 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/filter-button/filter-button-directive.js: -------------------------------------------------------------------------------- 1 | module.exports = function filterButtonDirective() { 2 | return { 3 | require: 'ngModel', 4 | restrict: 'EA', 5 | replace: true, 6 | scope: {}, 7 | template: require('./filter-button.pug') 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/filter-button/filter-button.pug: -------------------------------------------------------------------------------- 1 | button(uib-btn-checkbox, title='{{"Filter"|translate}}').btn.btn-sm.btn-primary-outline.pull-right 2 | i.fa.fa-filter 3 | span {{"Filter"|translate}} 4 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/filter-button/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.filter-button', []) 2 | .directive('filterButton', require('./filter-button-directive')) 3 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/focus-element/focus-element-directive.js: -------------------------------------------------------------------------------- 1 | module.exports = function focusElementDirective($parse, $timeout) { 2 | return { 3 | restrict: 'A', 4 | link: function(scope, element, attrs) { 5 | var model = $parse(attrs.focusElement) 6 | 7 | scope.$watch(model, function(value) { 8 | if (value === true) { 9 | $timeout(function() { 10 | element[0].focus() 11 | }) 12 | } 13 | }) 14 | 15 | element.bind('blur', function() { 16 | if (model && model.assign) { 17 | scope.$apply(model.assign(scope, false)) 18 | } 19 | }) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/focus-element/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.focus-element', [ 2 | 3 | ]) 4 | .directive('focusElement', require('./focus-element-directive')) 5 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/help-icon/help-icon-directive.js: -------------------------------------------------------------------------------- 1 | module.exports = function clearButtonDirective() { 2 | return { 3 | restrict: 'EA', 4 | replace: true, 5 | scope: { 6 | topic: '@', 7 | tooltip: '@' 8 | }, 9 | template: require('./help-icon.pug') 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/help-icon/help-icon.pug: -------------------------------------------------------------------------------- 1 | a(ng-href='/#!/docs/{{topic}}', uib-tooltip='{{tooltip}}', tooltip-placement='left').btn.btn-xs.btn-primary-outline.pull-right.transparent-border 2 | i.fa.fa-question-circle 3 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/help-icon/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.help-icon', []) 2 | .directive('helpIcon', require('./help-icon-directive')) 3 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/icon-inside-input/icon-inside-input-directive.js: -------------------------------------------------------------------------------- 1 | module.exports = function iconInsideInputDirective() { 2 | return { 3 | restrict: 'A', 4 | link: function(scope, element, attrs) { 5 | // NOTE: this doesn't work on Chrome with auto-fill, known Chrome bug 6 | element.css({ 7 | 'background-repeat': 'no-repeat', 8 | 'background-position': '8px 8px', 9 | 'padding-left': '30px' 10 | }) 11 | 12 | attrs.$observe('iconInsideInput', function(value) { 13 | element.css({ 14 | 'background-image': 'url(' + value + ')' 15 | }) 16 | }) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/icon-inside-input/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.icon-inside-input', [ 2 | 3 | ]) 4 | .directive('iconInsideInput', require('./icon-inside-input-directive')) 5 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/include-cached/compile-cache-service.js: -------------------------------------------------------------------------------- 1 | module.exports = function($http, $templateCache, $compile) { 2 | var cache = {} 3 | 4 | return function(src, scope, cloneAttachFn) { 5 | var compileFn = cache[src] 6 | if (compileFn) { 7 | compileFn(scope, cloneAttachFn) 8 | } else { 9 | $http.get(src, {cache: $templateCache}).success(function(response) { 10 | var responseContents = angular.element('
').html(response).contents() 11 | compileFn = cache[src] = $compile(responseContents) 12 | compileFn(scope, cloneAttachFn) 13 | }) 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/include-cached/include-cached-directive.js: -------------------------------------------------------------------------------- 1 | module.exports = function includeCachedDirective(CompileCacheService) { 2 | return { 3 | restrict: 'ECA', 4 | terminal: true, 5 | compile: function(element, attrs) { 6 | var srcExp = attrs.ngIncludeCached || attrs.src 7 | 8 | return function(scope, element) { 9 | var src = scope.$eval(srcExp) 10 | var newScope = scope.$new() 11 | CompileCacheService(src, newScope, function(compiledElm) { 12 | element.append(compiledElm) 13 | }) 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/include-cached/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.include-cached', [ 2 | 3 | ]) 4 | .factory('CompileCacheService', require('./compile-cache-service')) 5 | .directive('ngIncludeCached', require('./include-cached-directive')) 6 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/add-adb-key-modal/add-adb-key-modal-spec.js: -------------------------------------------------------------------------------- 1 | describe('FatalMessageService', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | it('should ...', inject(function() { 6 | 7 | //expect(FatalMessageService.doSomething()).toEqual('something'); 8 | 9 | })) 10 | 11 | }) 12 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/add-adb-key-modal/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.add-adb-key-modal', [ 2 | require('stf/common-ui/modals/common').name 3 | ]) 4 | .factory('AddAdbKeyModalService', require('./add-adb-key-modal-service')) 5 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/common/index.js: -------------------------------------------------------------------------------- 1 | require('./modals.css') 2 | 3 | module.exports = angular.module('stf.modals.common', [ 4 | require('ui-bootstrap').name 5 | ]) 6 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/external-url-modal/external-url-modal-spec.js: -------------------------------------------------------------------------------- 1 | describe('ExternalUrlModalService', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | it('should ...', inject(function() { 6 | 7 | //expect(FatalMessageService.doSomething()).toEqual('something'); 8 | 9 | })) 10 | 11 | }) 12 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/external-url-modal/external-url-modal.css: -------------------------------------------------------------------------------- 1 | .stf-external-url-modal { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/external-url-modal/external-url-modal.pug: -------------------------------------------------------------------------------- 1 | .stf-external-url-modal.stf-modal 2 | .modal-header 3 | button(type='button', ng-click='cancel()').close × 4 | h4.modal-title(ng-show='title') 5 | i.fa.fa-fw(ng-class='icon') 6 | span(ng-bind='title') 7 | .modal-body 8 | iframe(ng-src='{{url}}', width='100%', height='100%', frameborder='0') 9 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/external-url-modal/index.js: -------------------------------------------------------------------------------- 1 | require('./external-url-modal.css') 2 | 3 | module.exports = angular.module('stf.external-url-modal', [ 4 | require('stf/common-ui/modals/common').name 5 | ]) 6 | .factory('ExternalUrlModalService', require('./external-url-modal-service')) 7 | .directive('onLoadEvent', require('./on-load-event-directive')) 8 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/external-url-modal/on-load-event-directive.js: -------------------------------------------------------------------------------- 1 | // TODO: Test this 2 | module.exports = function() { 3 | return function(scope, element, attrs) { 4 | scope.$watch(attrs.pageVisible, function() { 5 | element.bind('load', function() { 6 | scope.$apply(attrs.pageLoad) 7 | }) 8 | }) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/fatal-message/fatal-message-spec.js: -------------------------------------------------------------------------------- 1 | describe('FatalMessageService', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | it('should ...', inject(function() { 6 | 7 | //expect(FatalMessageService.doSomething()).toEqual('something'); 8 | 9 | })) 10 | 11 | }) 12 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/fatal-message/index.js: -------------------------------------------------------------------------------- 1 | require('angular-route') 2 | 3 | module.exports = angular.module('stf.fatal-message', [ 4 | require('stf/common-ui/modals/common').name, 5 | 'ngRoute' 6 | ]) 7 | .factory('FatalMessageService', require('./fatal-message-service')) 8 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/generic-modal/generic-modal-spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | describe('GenericModalService', function() { 6 | 7 | beforeEach(angular.mock.module(require('./').name)) 8 | 9 | it('should ...', inject(function() { 10 | 11 | //expect(FatalMessageService.doSomething()).toEqual('something'); 12 | 13 | })) 14 | 15 | }) 16 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/generic-modal/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | module.exports = angular.module('stf.generic-modal', [ 6 | require('stf/common-ui/modals/common').name 7 | ]) 8 | .factory('GenericModalService', require('./generic-modal-service')) 9 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 contains code contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | module.exports = angular.module('stf.modals', [ 6 | require('./generic-modal').name, 7 | require('./fatal-message').name, 8 | require('./socket-disconnected').name, 9 | require('./version-update').name, 10 | require('./add-adb-key-modal').name, 11 | require('./save-log-modal').name 12 | ]) 13 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/lightbox-image/index.js: -------------------------------------------------------------------------------- 1 | require('./lightbox-image.css') 2 | 3 | module.exports = angular.module('stf.lightbox-image', [ 4 | require('stf/common-ui/modals/common').name 5 | ]) 6 | .factory('LightboxImageService', require('./lightbox-image-service')) 7 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/lightbox-image/lightbox-image-spec.js: -------------------------------------------------------------------------------- 1 | describe('LightboxImageService', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | it('should ...', inject(function() { 6 | 7 | //expect(XLightboxImageService.doSomething()).toEqual('something'); 8 | 9 | })) 10 | 11 | }) 12 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/lightbox-image/lightbox-image.css: -------------------------------------------------------------------------------- 1 | .stf-lightbox-image .modal-body { 2 | text-align: center; 3 | background: white; 4 | } 5 | 6 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/lightbox-image/lightbox-image.pug: -------------------------------------------------------------------------------- 1 | .stf-lightbox-image.stf-modal 2 | .modal-header 3 | button(type='button', ng-click='cancel()').close × 4 | h4.modal-title 5 | i.fa.fa-mobile.fa-fw 6 | span {{ title }} 7 | .modal-body 8 | img(ng-if='imageUrl', ng-src='{{imageUrl}}') 9 | nothing-to-show(message='{{"No photo available"|translate}}', icon='fa-picture-o', ng-if='!imageUrl') 10 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/save-log-modal/index.js: -------------------------------------------------------------------------------- 1 | require('./save-log.css') 2 | 3 | require('angular-route') 4 | 5 | module.exports = angular.module('stf.save-log-message', [ 6 | require('stf/common-ui/modals/common').name, 7 | 'ngRoute' 8 | ]) 9 | .factory('SaveLogService', require('./save-log-service')) 10 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/save-log-modal/save-log-spec.js: -------------------------------------------------------------------------------- 1 | describe('SaveLogService', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | it('should ...', inject(function() { 6 | 7 | //expect(SaveLogService.doSomething()).toEqual('something'); 8 | 9 | })) 10 | 11 | }) 12 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/save-log-modal/save-log.css: -------------------------------------------------------------------------------- 1 | 2 | .save-log-textarea { 3 | resize: none; 4 | cursor: text; 5 | font-family: Monaco, Menlo, Consolas, "Courier New", monospace; 6 | font-size: 12px; 7 | width: 100%; 8 | } 9 | 10 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/socket-disconnected/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.socket-disconnected', [ 2 | require('stf/common-ui/modals/common').name 3 | ]) 4 | .factory('SocketDisconnectedService', require('./socket-disconnected-service')) 5 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/socket-disconnected/socket-disconnected-spec.js: -------------------------------------------------------------------------------- 1 | describe('SocketDisconnectedService', function() { 2 | 3 | beforeEach(angular.mock.module(require('./index').name)) 4 | 5 | it('should ...', inject(function() { 6 | 7 | //expect(SocketDisconnectedService.doSomething()).toEqual('something') 8 | 9 | })) 10 | 11 | }) 12 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/socket-disconnected/socket-disconnected.pug: -------------------------------------------------------------------------------- 1 | .stf-fatal-message.stf-modal 2 | .modal-header.dialog-header-errorX 3 | button(type='button', ng-click='cancel()').close × 4 | h4.modal-title.text-danger 5 | i.fa.fa-warning 6 | .button-spacer 7 | span(translate) Disconnected 8 | .modal-body 9 | nothing-to-show(message='{{ message | translate }}', icon='fa-plug fa-4x') 10 | 11 | .modal-footer 12 | button.btn.btn-primary-outline.pull-right(type='button', ng-click='ok()') 13 | i.fa.fa-refresh 14 | span(translate) Try to reconnect 15 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/version-update/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.version-update-service', [ 2 | require('stf/common-ui/modals/common').name, 3 | require('ui-bootstrap').name 4 | ]) 5 | .factory('VersionUpdateService', require('./version-update-service')) 6 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/version-update/version-update-spec.js: -------------------------------------------------------------------------------- 1 | describe('VersionUpdateService', function() { 2 | 3 | beforeEach(angular.mock.module(require('ui-bootstrap').name)) 4 | beforeEach(angular.mock.module(require('./').name)) 5 | 6 | it('should ...', inject(function() { 7 | 8 | //expect(VersionUpdateService.doSomething()).toEqual('something'); 9 | 10 | })) 11 | 12 | }) 13 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/modals/version-update/version-update.pug: -------------------------------------------------------------------------------- 1 | .stf-fatal-message.stf-modal 2 | .modal-header.dialog-header-notify 3 | button(type='button', ng-click='cancel()').close × 4 | h4.modal-title.text-danger 5 | i.fa.fa-exclamation-circle.fa-fw 6 | span(translate) Version Update 7 | .modal-body(translate) A new version of STF is available 8 | .modal-footer 9 | button.btn.btn-primary(type='button', ng-click='ok()') 10 | i.fa.fa-refresh 11 | span(translate) Reload 12 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/ng-enter/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.ng-enter', [ 2 | 3 | ]) 4 | .directive('ngEnter', require('./ng-enter-directive')) 5 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/ng-enter/ng-enter-directive.js: -------------------------------------------------------------------------------- 1 | module.exports = function ngEnterDirective() { 2 | return function(scope, element, attrs) { 3 | element.bind('keydown keypress', function(event) { 4 | if (event.which === 13) { 5 | scope.$apply(function() { 6 | scope.$eval(attrs.ngEnter, {event: event}) 7 | }) 8 | event.preventDefault() 9 | } 10 | }) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/ng-enter/ng-enter-spec.js: -------------------------------------------------------------------------------- 1 | describe('ngEnter', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, compile 6 | 7 | beforeEach(inject(function($rootScope, $compile) { 8 | scope = $rootScope.$new() 9 | compile = $compile 10 | })) 11 | 12 | it('should ...', function() { 13 | 14 | /* 15 | To test your directive, you need to create some html that would use your directive, 16 | send that through compile() then compare the results. 17 | 18 | var element = compile('
hi
')(scope); 19 | expect(element.text()).toBe('hello, world'); 20 | */ 21 | 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/nice-tabs/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.nice-tabs', [ 2 | 3 | ]) 4 | .directive('niceTab', require('./nice-tab-directive')) 5 | .directive('niceTabs', require('./nice-tabs-directive')) 6 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/nice-tabs/nice-tab-directive.js: -------------------------------------------------------------------------------- 1 | // Declarative syntax not implemented yet 2 | module.exports = function niceTabDirective() { 3 | return { 4 | restrict: 'E', 5 | replace: true, 6 | scope: { 7 | }, 8 | template: require('./nice-tab.pug'), 9 | link: function() { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/nice-tabs/nice-tab.pug: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/res/app/components/stf/common-ui/nice-tabs/nice-tab.pug -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/nice-tabs/nice-tabs.pug: -------------------------------------------------------------------------------- 1 | .heading-for-tabs.tabs 2 | uib-tabset 3 | uib-tab(ng-repeat='tab in tabs', active='tab.active', ng-hide='!tabFound(tab)') 4 | uib-tab-heading 5 | i.fa(ng-class='tab.icon') 6 | span {{tab.title | translate }} 7 | div(ng-if='tab.active') 8 | div(ng-include='tab.templateUrl') 9 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/nothing-to-show/index.js: -------------------------------------------------------------------------------- 1 | require('./nothing-to-show.css') 2 | 3 | module.exports = angular.module('stf/common-ui/nothing-to-show', []) 4 | .directive('nothingToShow', require('./nothing-to-show-directive')) 5 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/nothing-to-show/nothing-to-show-directive.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return { 3 | restrict: 'EA', 4 | transclude: true, 5 | scope: { 6 | icon: '@', 7 | message: '@' 8 | }, 9 | template: require('./nothing-to-show.html'), 10 | link: function(scope, element, attrs) { 11 | scope.icon = attrs.icon 12 | scope.message = attrs.message 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/nothing-to-show/nothing-to-show.css: -------------------------------------------------------------------------------- 1 | .nothing-to-show { 2 | color: #b7b7b7; 3 | min-height: 130px; 4 | text-align: center; 5 | padding: 15px 0; 6 | } 7 | 8 | .nothing-to-show p { 9 | font-size: 20px; 10 | } 11 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/nothing-to-show/nothing-to-show.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |

5 |
6 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/notifications/growl.css: -------------------------------------------------------------------------------- 1 | .growl { 2 | position: fixed; 3 | top: 60px; 4 | right: 15px; 5 | float: right; 6 | z-index: 9999; 7 | } 8 | 9 | .growl-item.ng-enter, 10 | .growl-item.ng-leave { 11 | -webkit-transition: 0.3s linear all; 12 | -moz-transition: 0.3s linear all; 13 | -o-transition: 0.3s linear all; 14 | transition: 0.3s linear all; 15 | } 16 | 17 | .growl-item.ng-enter, 18 | .growl-item.ng-leave.ng-leave-active { 19 | opacity: 0; 20 | } 21 | 22 | .growl-item.ng-leave, 23 | .growl-item.ng-enter.ng-enter-active { 24 | opacity: 1; 25 | } 26 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/notifications/index.js: -------------------------------------------------------------------------------- 1 | require('angular-animate') 2 | require('./growl.css') 3 | require('angular-growl') 4 | 5 | module.exports = angular.module('stf/common-ui/notifications', [ 6 | 'ngAnimate', 7 | 'angular-growl' 8 | ]) 9 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/pagination/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | require('./pagination.css') 6 | 7 | module.exports = angular.module('stf.pagination', [ 8 | ]) 9 | .filter('pagedObjectsFilter', require('./pagination-filter')) 10 | .directive('stfPager', require('./pagination-directive')) 11 | .factory('ItemsPerPageOptionsService', require('./pagination-service')) 12 | 13 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/pagination/pagination-filter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | module.exports = function() { 6 | return function(objects, scope, currentPage, maxItems, searchItems) { 7 | scope[searchItems] = objects 8 | if (scope[maxItems].value === 0) { 9 | return objects 10 | } 11 | return objects.slice( 12 | (scope[currentPage] - 1) * scope[maxItems].value 13 | , scope[currentPage] * scope[maxItems].value 14 | ) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/pagination/pagination-service.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | module.exports = function ItemsPerPageOptionsServiceFactory() { 6 | const service = [ 7 | {name: '1', value: 1} 8 | , {name: '5', value: 5} 9 | , {name: '10', value: 10} 10 | , {name: '20', value: 20} 11 | , {name: '50', value: 50} 12 | , {name: '100', value: 100} 13 | , {name: '200', value: 200} 14 | , {name: '500', value: 500} 15 | , {name: '1000', value: 1000} 16 | , {name: '*', value: 0} 17 | ] 18 | 19 | return service 20 | } 21 | 22 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/pagination/pagination.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/refresh-page/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.refresh-page', []) 2 | .directive('refreshPage', require('./refresh-page-directive')) 3 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/refresh-page/refresh-page-directive.js: -------------------------------------------------------------------------------- 1 | module.exports = function refreshPageDirective($window) { 2 | return { 3 | restrict: 'E', 4 | replace: true, 5 | scope: { 6 | }, 7 | template: require('./refresh-page.pug'), 8 | link: function(scope) { 9 | scope.reloadWindow = function() { 10 | $window.location.reload() 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/refresh-page/refresh-page.pug: -------------------------------------------------------------------------------- 1 | button.btn.btn-sm.btn-primary-outline(ng-click='reloadWindow()') 2 | i.fa.fa-refresh 3 | span(translate) Refresh 4 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/safe-apply/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.safe-apply', []) 2 | .config([ 3 | '$provide', function($provide) { 4 | return $provide.decorator('$rootScope', [ 5 | '$delegate', function($delegate) { 6 | $delegate.safeApply = function(fn) { 7 | var phase = $delegate.$$phase 8 | if (phase === '$apply' || phase === '$digest') { 9 | if (fn && typeof fn === 'function') { 10 | fn() 11 | } 12 | } else { 13 | $delegate.$apply(fn) 14 | } 15 | } 16 | return $delegate 17 | } 18 | ]) 19 | } 20 | ]) 21 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/stacked-icon/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.stacked-icon', []) 2 | .directive('stackedIcon', require('./stacked-icon-directive')) 3 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/stacked-icon/stacked-icon-directive.js: -------------------------------------------------------------------------------- 1 | require('./stacked-icon.css') 2 | 3 | module.exports = function clearButtonDirective() { 4 | return { 5 | restrict: 'EA', 6 | replace: true, 7 | scope: { 8 | icon: '@', 9 | color: '@' 10 | }, 11 | template: require('./stacked-icon.pug') 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/stacked-icon/stacked-icon.css: -------------------------------------------------------------------------------- 1 | .stf-stacked-icon .fa-square { 2 | font-size: 22px !important; 3 | } 4 | 5 | .stf-stacked-icon.fa-stack { 6 | height: 24px !important; 7 | width: 21px !important; 8 | } 9 | 10 | .stf-stacked-icon .fa-stack-1x { 11 | line-height: 24px !important; 12 | } 13 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/stacked-icon/stacked-icon.pug: -------------------------------------------------------------------------------- 1 | span.fa-stack.fa-lgX.stf-stacked-icon 2 | i.fa.fa-square.fa-stack-2x(ng-class='color') 3 | i.fa(ng-class='icon').fa-stack-1x.fa-inverse 4 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/table/index.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2022 contains code contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | // 4 | 5 | require('./table.css') 6 | require('script-loader!ng-table/dist/ng-table') 7 | 8 | module.exports = angular.module('stf/common-ui/table', [ 9 | 'ngTable' 10 | ]) 11 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/text-focus-select/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.text-focus-select', [ 2 | 3 | ]) 4 | .directive('textFocusSelect', require('./text-focus-select-directive')) 5 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/text-focus-select/text-focus-select-directive.js: -------------------------------------------------------------------------------- 1 | module.exports = function textFocusSelectDirective() { 2 | return { 3 | restrict: 'AC', 4 | link: function(scope, element) { 5 | // TODO: try with focus event 6 | element.bind('click', function() { 7 | this.select() 8 | }) 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/tooltips/README.md: -------------------------------------------------------------------------------- 1 | # stf-tooltips 2 | 3 | Based on Angular Bootstrap. 4 | 5 | Usage: 6 | 7 | ```html 8 | help-title='{{"Run Command"|translate}}' 9 | help-key='Enter' 10 | ``` 11 | 12 | Maps to: 13 | 14 | ```html 15 | tooltip-html-unsafe='{{"Run Command

Enter"|translate}}' 16 | ``` -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/tooltips/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.tooltips', [ 2 | 3 | ]) 4 | .directive('tooltips', require('./tooltips-directive')) 5 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/tooltips/tooltips-directive.js: -------------------------------------------------------------------------------- 1 | module.exports = function tooltipsDirective() { 2 | return { 3 | restrict: 'A', 4 | link: function() { 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /res/app/components/stf/common-ui/tooltips/tooltips-spec.js: -------------------------------------------------------------------------------- 1 | describe('tooltips', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, compile 6 | 7 | beforeEach(inject(function($rootScope, $compile) { 8 | scope = $rootScope.$new() 9 | compile = $compile 10 | })) 11 | 12 | it('should ...', function() { 13 | 14 | /* 15 | To test your directive, you need to create some html that would use your directive, 16 | send that through compile() then compare the results. 17 | 18 | var element = compile('
hi
')(scope); 19 | expect(element.text()).toBe('hello, world'); 20 | */ 21 | 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /res/app/components/stf/control/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf/control', [ 2 | require('stf/socket').name, 3 | require('stf/transaction').name, 4 | require('stf/keycodes').name 5 | ]) 6 | .factory('ControlService', require('./control-service')) 7 | -------------------------------------------------------------------------------- /res/app/components/stf/device-context-menu/device-context-menu.css: -------------------------------------------------------------------------------- 1 | .stf-device-context-menu { 2 | 3 | } -------------------------------------------------------------------------------- /res/app/components/stf/device-context-menu/index.js: -------------------------------------------------------------------------------- 1 | require('./device-context-menu.css') 2 | 3 | module.exports = angular.module('stf.device-context-menu', [ 4 | require('ng-context-menu').name 5 | ]) 6 | .directive('deviceContextMenu', require('./device-context-menu-directive')) 7 | -------------------------------------------------------------------------------- /res/app/components/stf/device/enhance-device/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf/device/enhance-device', [ 2 | require('stf/app-state').name 3 | ]) 4 | .factory('EnhanceDeviceService', require('./enhance-device-service')) 5 | -------------------------------------------------------------------------------- /res/app/components/stf/device/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf/device', [ 2 | require('./device-info-filter').name, 3 | require('./enhance-device').name 4 | ]) 5 | .factory('DeviceService', require('./device-service')) 6 | .factory('StateClassesService', require('./state-classes-service')) 7 | -------------------------------------------------------------------------------- /res/app/components/stf/devices/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | module.exports = angular.module('stf.devices', [ 6 | require('stf/util/common').name, 7 | require('stf/socket').name 8 | ]) 9 | .factory('DevicesService', require('./devices-service')) 10 | -------------------------------------------------------------------------------- /res/app/components/stf/filter-string/filter-string-spec.js: -------------------------------------------------------------------------------- 1 | describe('FilterStringService', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | it('should ...', inject(function() { 6 | 7 | //expect(FilterStringService.doSomething()).toEqual('something') 8 | 9 | })) 10 | 11 | }) 12 | -------------------------------------------------------------------------------- /res/app/components/stf/filter-string/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.filter-string', [ 2 | 3 | ]) 4 | .factory('FilterStringService', require('./filter-string-service')) 5 | -------------------------------------------------------------------------------- /res/app/components/stf/groups/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | module.exports = angular.module('stf.groups', [ 6 | require('stf/util/common').name 7 | ]) 8 | .factory('GroupsService', require('./groups-service')) 9 | -------------------------------------------------------------------------------- /res/app/components/stf/image-onload/image-onload-animate-directive.js: -------------------------------------------------------------------------------- 1 | module.exports = function imageOnloadAnimateDirective($parse, $animate) { 2 | return { 3 | restrict: 'A', 4 | link: function(scope, element) { 5 | $animate.addClass(element, 'ng-image-not-loaded') 6 | element.bind('load', function() { 7 | $animate.removeClass(element, 'ng-image-not-loaded') 8 | 9 | //if(!scope.$$phase) { 10 | // scope.$digest() 11 | //} 12 | // console.log('image is loaded') 13 | }) 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /res/app/components/stf/image-onload/image-onload-directive.js: -------------------------------------------------------------------------------- 1 | module.exports = function imageOnloadDirective() { 2 | return { 3 | restrict: 'A', 4 | link: function(scope, element, attrs) { 5 | element.bind('load', function() { 6 | scope.$eval(attrs.imageOnload) 7 | // console.log('image is loaded') 8 | }) 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /res/app/components/stf/image-onload/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.image-onload', [ 2 | 3 | ]) 4 | .directive('imageOnload', require('./image-onload-directive')) 5 | .directive('imageOnloadAnimate', require('./image-onload-animate-directive')) 6 | -------------------------------------------------------------------------------- /res/app/components/stf/install/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.install-service', [ 2 | require('gettext').name 3 | ]) 4 | .filter('installError', require('./install-error-filter')) 5 | .factory('InstallService', require('./install-service')) 6 | -------------------------------------------------------------------------------- /res/app/components/stf/install/install-spec.js: -------------------------------------------------------------------------------- 1 | describe('install', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | it('should ...', inject(function() { 6 | 7 | //var filter = $filter('installError') 8 | 9 | //expect(filter('input')).toEqual('output') 10 | 11 | })) 12 | 13 | }) 14 | -------------------------------------------------------------------------------- /res/app/components/stf/keycodes/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.keycodes', [ 2 | 3 | ]) 4 | .factory('KeycodesMapped', function() { 5 | return require('./mapped/index.json') 6 | }) 7 | 8 | // Not used for now: 9 | // 10 | // .factory('KeycodesAndroid', function () { 11 | // return require('./android/index.json') 12 | // }) 13 | // .factory('KeycodesJS', function () { 14 | // return require('./android/index.json') 15 | // }) 16 | // .factory('KeycodesService', require('./keycodes-service')) 17 | -------------------------------------------------------------------------------- /res/app/components/stf/keycodes/keycodes-spec.js: -------------------------------------------------------------------------------- 1 | //describe('KeycodesService', function() { 2 | // 3 | // beforeEach(angular.mock.module(require('./').name)); 4 | // 5 | // it('should ...', inject(function(KeycodesService) { 6 | // 7 | // //expect(KeycodesService.doSomething()).toEqual('something'); 8 | // 9 | // })); 10 | // 11 | //}) 12 | -------------------------------------------------------------------------------- /res/app/components/stf/keycodes/mapped/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "8": "del", 3 | "9": "tab", 4 | "13": "enter", 5 | "20": "caps_lock", 6 | "27": "escape", 7 | "33": "page_up", 8 | "34": "page_down", 9 | "35": "move_end", 10 | "36": "move_home", 11 | "37": "dpad_left", 12 | "38": "dpad_up", 13 | "39": "dpad_right", 14 | "40": "dpad_down", 15 | "45": "insert", 16 | "46": "forward_del", 17 | "93": "menu", 18 | "112": "f1", 19 | "113": "f2", 20 | "114": "f3", 21 | "115": "f4", 22 | "116": "f5", 23 | "117": "f6", 24 | "118": "f7", 25 | "119": "f8", 26 | "120": "f9", 27 | "121": "f10", 28 | "122": "f11", 29 | "123": "f12", 30 | "144": "num_lock" 31 | } 32 | -------------------------------------------------------------------------------- /res/app/components/stf/keys/add-adb-key/adb-keys-service.js: -------------------------------------------------------------------------------- 1 | module.exports = function AdbKeysServiceFactory() { 2 | var service = {} 3 | 4 | service.commentFromKey = function(key) { 5 | if (key.match(/.+= (.+)/)) { 6 | return key.replace(/.+= (.+)/g, '$1') 7 | } 8 | return '' 9 | } 10 | 11 | return service 12 | } 13 | -------------------------------------------------------------------------------- /res/app/components/stf/keys/add-adb-key/add-adb-key.css: -------------------------------------------------------------------------------- 1 | .stf-add-adb-key .form-adb-key { 2 | margin-bottom: 60px; 3 | } 4 | 5 | .stf-add-adb-key .clip-board { 6 | margin-bottom: 20px; 7 | } 8 | -------------------------------------------------------------------------------- /res/app/components/stf/keys/add-adb-key/index.js: -------------------------------------------------------------------------------- 1 | require('./add-adb-key.css') 2 | 3 | module.exports = angular.module('stf.add-adb-key', [ 4 | require('gettext').name, 5 | require('stf/common-ui').name 6 | ]) 7 | .directive('addAdbKey', require('./add-adb-key-directive')) 8 | .factory('AdbKeysService', require('./adb-keys-service')) 9 | 10 | -------------------------------------------------------------------------------- /res/app/components/stf/keys/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.keys', [ 2 | require('./add-adb-key').name 3 | ]) 4 | -------------------------------------------------------------------------------- /res/app/components/stf/landscape/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.landscape', [ 2 | require('stf/browser-info').name 3 | ]) 4 | .directive('landscape', require('./landscape-directive')) 5 | -------------------------------------------------------------------------------- /res/app/components/stf/landscape/landscape-spec.js: -------------------------------------------------------------------------------- 1 | describe('landscape', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, compile 6 | 7 | beforeEach(inject(function($rootScope, $compile) { 8 | scope = $rootScope.$new() 9 | compile = $compile 10 | })) 11 | 12 | it('should ...', function() { 13 | 14 | /* 15 | To test your directive, you need to create some html that would use your directive, 16 | send that through compile() then compare the results. 17 | 18 | var element = compile('
hi
')(scope); 19 | expect(element.text()).toBe('hello, world'); 20 | */ 21 | 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /res/app/components/stf/language/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf-language', [ 2 | require('stf/settings').name, 3 | require('gettext').name, 4 | require('stf/app-state').name 5 | ]) 6 | .factory('LanguageService', require('./language-service')) 7 | .provider('language', require('./language-provider')) 8 | -------------------------------------------------------------------------------- /res/app/components/stf/logcat-table/index.js: -------------------------------------------------------------------------------- 1 | require('./logcat-table.css') 2 | 3 | module.exports = angular.module('stf.logcat-table', [ 4 | 5 | ]) 6 | .directive('logcatTable', require('./logcat-table-directive')) 7 | -------------------------------------------------------------------------------- /res/app/components/stf/logcat-table/logcat-table.pug: -------------------------------------------------------------------------------- 1 | .stf-logcat-table.force-gpu 2 | table.console-message-text.tableX.table-condensed.selectable 3 | tbody 4 | -------------------------------------------------------------------------------- /res/app/components/stf/logcat/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.logcat', [ 2 | require('stf/filter-string').name, 3 | require('stf/socket').name 4 | ]) 5 | .factory('LogcatService', require('./logcat-service')) 6 | -------------------------------------------------------------------------------- /res/app/components/stf/logcat/logcat-spec.js: -------------------------------------------------------------------------------- 1 | describe('LogcatService', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | it('should ...', inject(function() { 6 | 7 | //expect(LogcatService.doSomething()).toEqual('something') 8 | 9 | })) 10 | 11 | }) 12 | -------------------------------------------------------------------------------- /res/app/components/stf/native-url/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.native-url', [ 2 | 3 | ]) 4 | .factory('NativeUrlService', require('./native-url-service')) 5 | -------------------------------------------------------------------------------- /res/app/components/stf/native-url/native-url-spec.js: -------------------------------------------------------------------------------- 1 | describe('NativeUrlService', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | it('should ...', inject(function() { 6 | 7 | //expect(NativeUrlService.doSomething()).toEqual('something') 8 | 9 | })) 10 | 11 | }) 12 | -------------------------------------------------------------------------------- /res/app/components/stf/nav-menu/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.nav-menu', []) 2 | .directive('navMenu', require('./nav-menu-directive')) 3 | -------------------------------------------------------------------------------- /res/app/components/stf/nav-menu/nav-menu-spec.js: -------------------------------------------------------------------------------- 1 | describe('navMenu', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, compile 6 | 7 | beforeEach(inject(function($rootScope, $compile) { 8 | scope = $rootScope.$new() 9 | compile = $compile 10 | })) 11 | 12 | it('should ...', function() { 13 | 14 | /* 15 | To test your directive, you need to create some html that would use your 16 | directive, send that through compile() then compare the results. 17 | 18 | var element = compile('
hi
')(scope); 19 | expect(element.text()).toBe('hello, world'); 20 | */ 21 | 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /res/app/components/stf/page-visibility/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.page-visibility', [ 2 | 3 | ]) 4 | .factory('PageVisibilityService', require('./page-visibility-service')) 5 | -------------------------------------------------------------------------------- /res/app/components/stf/page-visibility/page-visibility-service.js: -------------------------------------------------------------------------------- 1 | module.exports = function PageVisibilityServiceFactory($rootScope) { 2 | var service = { 3 | hidden: false 4 | } 5 | 6 | function visibilityChangeListener() { 7 | service.hidden = document.hidden 8 | $rootScope.$broadcast('visibilitychange', service.hidden) 9 | } 10 | 11 | document.addEventListener( 12 | 'visibilitychange' 13 | , visibilityChangeListener 14 | , false 15 | ) 16 | 17 | return service 18 | } 19 | -------------------------------------------------------------------------------- /res/app/components/stf/port-forwarding/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.port-forwarding-service', [ 2 | ]) 3 | .factory('PortForwardingService', require('./port-forwarding-service')) 4 | -------------------------------------------------------------------------------- /res/app/components/stf/port-forwarding/port-forwarding-service.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | var service = {} 3 | 4 | 5 | return service 6 | } 7 | -------------------------------------------------------------------------------- /res/app/components/stf/port-forwarding/port-forwarding-spec.js: -------------------------------------------------------------------------------- 1 | describe('PortForwardingService', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | it('should ...', inject(function() { 6 | //expect(PortForwardingService.doSomething()).toEqual('something') 7 | 8 | })) 9 | 10 | }) 11 | -------------------------------------------------------------------------------- /res/app/components/stf/scoped-hotkeys/index.js: -------------------------------------------------------------------------------- 1 | require('angular-hotkeys') 2 | module.exports = angular.module('stf.scoped-hotkeys', [ 3 | 'cfp.hotkeys' 4 | ]) 5 | .factory('ScopedHotkeysService', require('./scoped-hotkeys-service')) 6 | -------------------------------------------------------------------------------- /res/app/components/stf/scoped-hotkeys/scoped-hotkeys-spec.js: -------------------------------------------------------------------------------- 1 | describe('ScopedHotkeysService', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | it('should ...', inject(function() { 6 | 7 | //expect(ScopedHotkeysService.doSomething()).toEqual('something') 8 | 9 | })) 10 | 11 | }) 12 | -------------------------------------------------------------------------------- /res/app/components/stf/screen/fast-image-render/test/images/screen.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/res/app/components/stf/screen/fast-image-render/test/images/screen.dds -------------------------------------------------------------------------------- /res/app/components/stf/screen/fast-image-render/test/images/screen.dds.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/res/app/components/stf/screen/fast-image-render/test/images/screen.dds.gz -------------------------------------------------------------------------------- /res/app/components/stf/screen/fast-image-render/test/images/screen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/res/app/components/stf/screen/fast-image-render/test/images/screen.jpg -------------------------------------------------------------------------------- /res/app/components/stf/screen/fast-image-render/test/images/screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/res/app/components/stf/screen/fast-image-render/test/images/screen.png -------------------------------------------------------------------------------- /res/app/components/stf/screen/fast-image-render/test/images/screen.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/res/app/components/stf/screen/fast-image-render/test/images/screen.webp -------------------------------------------------------------------------------- /res/app/components/stf/screen/fast-image-render/test/images/texture24.crn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/res/app/components/stf/screen/fast-image-render/test/images/texture24.crn -------------------------------------------------------------------------------- /res/app/components/stf/screen/imagepool.js: -------------------------------------------------------------------------------- 1 | function ImagePool(size) { 2 | this.size = size 3 | this.images = [] 4 | this.counter = 0 5 | } 6 | 7 | ImagePool.prototype.next = function() { 8 | if (this.images.length < this.size) { 9 | var image = new Image() 10 | this.images.push(image) 11 | return image 12 | } 13 | else { 14 | if (this.counter >= this.size) { 15 | // Reset for unlikely but theoretically possible overflow. 16 | this.counter = 0 17 | } 18 | 19 | return this.images[this.counter++ % this.size] 20 | } 21 | } 22 | 23 | module.exports = ImagePool 24 | -------------------------------------------------------------------------------- /res/app/components/stf/screen/index.js: -------------------------------------------------------------------------------- 1 | require('./screen.css') 2 | 3 | module.exports = angular.module('stf/screen', [ 4 | require('stf/screen/scaling').name 5 | , require('stf/util/vendor').name 6 | , require('stf/page-visibility').name 7 | , require('stf/browser-info').name 8 | , require('stf/common-ui/nothing-to-show').name 9 | ]) 10 | .directive('deviceScreen', require('./screen-directive')) 11 | .controller('DeviceScreenCtrl', require('./screen-controller')) 12 | -------------------------------------------------------------------------------- /res/app/components/stf/screen/rotator.js: -------------------------------------------------------------------------------- 1 | var mapping = { 2 | 0: { 3 | 0: 0 4 | , 90: -90 5 | , 180: -180 6 | , 270: 90 7 | } 8 | , 90: { 9 | 0: 90 10 | , 90: 0 11 | , 180: -90 12 | , 270: 180 13 | } 14 | , 180: { 15 | 0: 180 16 | , 90: 90 17 | , 180: 0 18 | , 270: -90 19 | } 20 | , 270: { 21 | 0: -90 22 | , 90: -180 23 | , 180: 90 24 | , 270: 0 25 | } 26 | } 27 | 28 | module.exports = function rotator(oldRotation, newRotation) { 29 | var r1 = oldRotation < 0 ? 360 + oldRotation % 360 : oldRotation % 360 30 | var r2 = newRotation < 0 ? 360 + newRotation % 360 : newRotation % 360 31 | 32 | return mapping[r1][r2] 33 | } 34 | -------------------------------------------------------------------------------- /res/app/components/stf/screen/scaling/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf/scaling', []) 2 | .factory('ScalingService', require('./scaling-service')) 3 | -------------------------------------------------------------------------------- /res/app/components/stf/screen/screen-controller.js: -------------------------------------------------------------------------------- 1 | module.exports = function DeviceScreenCtrl( 2 | $scope 3 | , $rootScope 4 | , ScalingService 5 | , InstallService 6 | ) { 7 | $scope.displayError = false 8 | $scope.ScalingService = ScalingService 9 | 10 | $scope.installFile = function($files) { 11 | return InstallService.installFile($scope.control, $files) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /res/app/components/stf/screen/screen-keyboard/index.js: -------------------------------------------------------------------------------- 1 | require('./screen-keyboard.css') 2 | 3 | module.exports = angular.module('stf.screen-keyboard', [ 4 | 5 | ]) 6 | .directive('screenKeyboard', require('./screen-keyboard-directive')) 7 | -------------------------------------------------------------------------------- /res/app/components/stf/screen/screen-keyboard/screen-keyboard-directive.js: -------------------------------------------------------------------------------- 1 | module.exports = function screenKeyboardDirective() { 2 | return { 3 | restrict: 'E', 4 | template: require('./screen-keyboard.pug'), 5 | link: function(scope, element) { 6 | element.find('input') 7 | 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /res/app/components/stf/screen/screen-keyboard/screen-keyboard.css: -------------------------------------------------------------------------------- 1 | .stf-screen-keyboard { 2 | 3 | } -------------------------------------------------------------------------------- /res/app/components/stf/screen/screen-keyboard/screen-keyboard.pug: -------------------------------------------------------------------------------- 1 | input(type='password', tabindex='40', accesskey='C', 2 | autocorrect='off', autocapitalize='off').stf-screen-keyboard 3 | -------------------------------------------------------------------------------- /res/app/components/stf/screen/screen-touch/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.screen-touch', [ 2 | 3 | ]) 4 | .directive('screenTouch', require('./screen-touch-directive')) 5 | -------------------------------------------------------------------------------- /res/app/components/stf/screen/screen-touch/screen-touch-directive.js: -------------------------------------------------------------------------------- 1 | module.exports = function screenTouchDirective() { 2 | return { 3 | restrict: 'A', 4 | link: function() { 5 | 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /res/app/components/stf/screen/screen.css: -------------------------------------------------------------------------------- 1 | .screen-error { 2 | width: 100%; 3 | height: 100%; 4 | background: rgba(0, 0, 0, 0.7); 5 | z-index: 100; 6 | position: absolute; 7 | /*pointer-events: none; */ 8 | } 9 | 10 | .screen-error .nothing-to-show { 11 | color: #eee; 12 | } 13 | 14 | .screen-error .screen-error-message { 15 | position: relative; 16 | top: 15%; 17 | transform: translateY(-15%); 18 | text-align: center; 19 | } 20 | 21 | .screen-error .screen-error-alert { 22 | padding: 15px; 23 | margin-bottom: 20px; 24 | color: #ccc; 25 | } 26 | -------------------------------------------------------------------------------- /res/app/components/stf/settings/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf/settings', [ 2 | require('stf/user').name, 3 | require('stf/socket').name 4 | ]) 5 | .factory('SettingsService', require('./settings-service')) 6 | -------------------------------------------------------------------------------- /res/app/components/stf/socket/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.socket', [ 2 | //TODO: Refactor version update out to its own Ctrl 3 | require('stf/app-state').name, 4 | require('stf/common-ui/modals/version-update').name 5 | ]) 6 | .factory('socket', require('./socket-service')) 7 | -------------------------------------------------------------------------------- /res/app/components/stf/socket/socket-state/socket-state.pug: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/res/app/components/stf/socket/socket-state/socket-state.pug -------------------------------------------------------------------------------- /res/app/components/stf/standalone/standalone-controller.js: -------------------------------------------------------------------------------- 1 | module.exports = function StandaloneCtrl() { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /res/app/components/stf/standalone/standalone-directive.js: -------------------------------------------------------------------------------- 1 | module.exports = function standaloneDirective($rootScope, $location) { 2 | return { 3 | restrict: 'AE', 4 | link: function() { 5 | //$rootScope.standalone = $window.history.length < 2 6 | var standalone = $location.search().standalone 7 | $rootScope.standalone = standalone 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /res/app/components/stf/standalone/standalone.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/res/app/components/stf/standalone/standalone.css -------------------------------------------------------------------------------- /res/app/components/stf/standalone/standalone.pug: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/res/app/components/stf/standalone/standalone.pug -------------------------------------------------------------------------------- /res/app/components/stf/storage/index.js: -------------------------------------------------------------------------------- 1 | require('ng-file-upload') 2 | 3 | module.exports = angular.module('stf/storage', [ 4 | 'angularFileUpload' 5 | ]) 6 | .factory('StorageService', require('./storage-service')) 7 | -------------------------------------------------------------------------------- /res/app/components/stf/text-history/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.text-history', [ 2 | 3 | ]) 4 | .directive('textHistory', require('./text-history-directive')) 5 | -------------------------------------------------------------------------------- /res/app/components/stf/text-history/text-history-directive.js: -------------------------------------------------------------------------------- 1 | //input.form-control(type='text', placeholder='', ng-model='selectedAction', 2 | // typeahead='action for action in activityActions') 3 | 4 | module.exports = function textHistoryDirective() { 5 | return { 6 | restrict: 'A', 7 | template: '', 8 | link: function() { 9 | 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /res/app/components/stf/timeline/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.timeline', [ 2 | 3 | ]) 4 | .factory('TimelineService', require('./timeline-service')) 5 | -------------------------------------------------------------------------------- /res/app/components/stf/timeline/timeline-spec.js: -------------------------------------------------------------------------------- 1 | describe('TimelineService', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | it('should ...', inject(function() { 6 | 7 | //expect(TimelineService.doSomething()).toEqual('something'); 8 | 9 | })) 10 | 11 | }) 12 | -------------------------------------------------------------------------------- /res/app/components/stf/timelines/index.js: -------------------------------------------------------------------------------- 1 | require('./timelines.css') 2 | 3 | module.exports = angular.module('stf.timelines', [ 4 | 5 | ]) 6 | .directive('timelines', require('./timelines-directive')) 7 | -------------------------------------------------------------------------------- /res/app/components/stf/timelines/timeline-message/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.timeline-message', [ 2 | 3 | ]) 4 | .directive('timelineMessage', require('./timeline-message-directive')) 5 | -------------------------------------------------------------------------------- /res/app/components/stf/timelines/timelines-directive.js: -------------------------------------------------------------------------------- 1 | module.exports = function timelinesDirective(Timelines) { 2 | return { 3 | restrict: 'AE', 4 | replace: false, 5 | scope: {}, 6 | template: require('./timelines.pug'), 7 | link: function(scope) { 8 | scope.cssPrefix = Timelines.options.cssPrefix 9 | scope.notifications = Timelines.notifications 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /res/app/components/stf/timelines/timelines-spec.js: -------------------------------------------------------------------------------- 1 | describe('timelines', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, compile 6 | 7 | beforeEach(inject(function($rootScope, $compile) { 8 | scope = $rootScope.$new() 9 | compile = $compile 10 | })) 11 | 12 | it('should ...', function() { 13 | 14 | /* 15 | To test your directive, you need to create some html that would use your directive, 16 | send that through compile() then compare the results. 17 | 18 | var element = compile('
hi
')(scope); 19 | expect(element.text()).toBe('hello, world'); 20 | */ 21 | 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /res/app/components/stf/timelines/timelines.css: -------------------------------------------------------------------------------- 1 | .stf-timelines { 2 | 3 | } -------------------------------------------------------------------------------- /res/app/components/stf/timelines/timelines.pug: -------------------------------------------------------------------------------- 1 | div.stf-timelines 2 | ui.list-unstyled 3 | li(ng-repeat='(id, notification) in notifications') 4 | div(ng-class='{{cssPrefix}} {{cssPrefix}}-{{notification.type}}') 5 | div(ng-bind-html='notification.message') 6 | -------------------------------------------------------------------------------- /res/app/components/stf/tokens/generate-access-token/generate-access-token-spec.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/res/app/components/stf/tokens/generate-access-token/generate-access-token-spec.js -------------------------------------------------------------------------------- /res/app/components/stf/tokens/generate-access-token/generate-access-token.css: -------------------------------------------------------------------------------- 1 | .stf-generate-access-token { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /res/app/components/stf/tokens/generate-access-token/index.js: -------------------------------------------------------------------------------- 1 | require('./generate-access-token.css') 2 | 3 | module.exports = angular.module('stf.tokens.generate-access-token', [ 4 | 5 | ]) 6 | .directive('generateAccessToken', require('./generate-access-token-directive')) 7 | -------------------------------------------------------------------------------- /res/app/components/stf/tokens/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.tokens', [ 2 | require('./generate-access-token').name 3 | ]) 4 | .factory('AccessTokenService', require('./access-token-service')) 5 | -------------------------------------------------------------------------------- /res/app/components/stf/transaction/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf/transaction', [ 2 | require('stf/socket').name 3 | ]) 4 | .constant('TransactionError', require('./transaction-error')) 5 | .factory('TransactionService', require('./transaction-service')) 6 | -------------------------------------------------------------------------------- /res/app/components/stf/transaction/transaction-error.js: -------------------------------------------------------------------------------- 1 | function TransactionError(result) { 2 | this.code = this.message = result.error 3 | this.name = 'TransactionError' 4 | Error.captureStackTrace(this, TransactionError) 5 | } 6 | 7 | TransactionError.prototype = Object.create(Error.prototype) 8 | TransactionError.prototype.constructor = TransactionError 9 | 10 | module.exports = TransactionError 11 | -------------------------------------------------------------------------------- /res/app/components/stf/upload/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.upload-service', [ 2 | require('gettext').name 3 | ]) 4 | .filter('uploadError', require('./upload-error-filter')) 5 | -------------------------------------------------------------------------------- /res/app/components/stf/upload/upload-error-filter.js: -------------------------------------------------------------------------------- 1 | module.exports = function uploadErrorFilter(gettext) { 2 | return function(text) { 3 | return { 4 | fail_invalid_app_file: gettext('Uploaded file is not valid'), 5 | fail_download: gettext('Failed to download file'), 6 | fail_invalid_url: gettext('Cannot access specified URL'), 7 | fail: gettext('Upload failed') 8 | }[text] || gettext('Upload unknown error') 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /res/app/components/stf/upload/upload-spec.js: -------------------------------------------------------------------------------- 1 | describe('upload', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | it('should ...', inject(function() { 6 | 7 | //var filter = $filter('uploadError') 8 | 9 | //expect(filter('input')).toEqual('output') 10 | 11 | })) 12 | 13 | }) 14 | -------------------------------------------------------------------------------- /res/app/components/stf/user/group/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf/group', [ 2 | require('stf/socket').name, 3 | require('stf/user').name, 4 | require('stf/transaction').name 5 | ]) 6 | .factory('GroupService', require('./group-service')) 7 | -------------------------------------------------------------------------------- /res/app/components/stf/user/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf/user', [ 2 | require('stf/socket').name, 3 | require('stf/common-ui').name, 4 | require('stf/app-state').name 5 | ]) 6 | .factory('UserService', require('./user-service')) 7 | -------------------------------------------------------------------------------- /res/app/components/stf/users/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | module.exports = angular.module('stf.users', [ 6 | require('stf/util/common').name 7 | ]) 8 | .factory('UsersService', require('./users-service')) 9 | -------------------------------------------------------------------------------- /res/app/components/stf/util/common/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | module.exports = angular.module('stf.util.common', [ 6 | require('stf/common-ui').name 7 | ]) 8 | .factory('CommonService', require('./common-service')) 9 | -------------------------------------------------------------------------------- /res/app/components/stf/util/vendor/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf/util/vendor', []) 2 | .factory('VendorUtil', require('./vendor-util')) 3 | -------------------------------------------------------------------------------- /res/app/components/stf/util/vendor/vendor-util.js: -------------------------------------------------------------------------------- 1 | module.exports = function VendorUtilFactory() { 2 | var vendorUtil = {} 3 | 4 | vendorUtil.style = function(props) { 5 | var testee = document.createElement('span') 6 | for (var i = 0, l = props.length; i < l; ++i) { 7 | if (typeof testee.style[props[i]] !== 'undefined') { 8 | return props[i] 9 | } 10 | } 11 | return props[0] 12 | } 13 | 14 | return vendorUtil 15 | } 16 | -------------------------------------------------------------------------------- /res/app/control-panes/activity/activity-spec.js: -------------------------------------------------------------------------------- 1 | describe('ActivityCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('ActivityCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/control-panes/activity/activity.css: -------------------------------------------------------------------------------- 1 | .stf-activity .activity-list .activity-date, 2 | .stf-activity .activity-list .activity-buttons { 3 | opacity: 0; 4 | transition: opacity 0.25s ease-in-out; 5 | } 6 | 7 | .stf-activity .activity-list li:hover .activity-date, 8 | .stf-activity .activity-list li:hover .activity-buttons { 9 | opacity: 1; 10 | } 11 | 12 | .stf-activity .activity-title { 13 | display: inline-block; 14 | } 15 | 16 | .stf-activity .activity-icon { 17 | width: 30px; 18 | height: 30px; 19 | } 20 | 21 | .stf-activity { 22 | background: #e8e8e8; 23 | } 24 | -------------------------------------------------------------------------------- /res/app/control-panes/activity/index.js: -------------------------------------------------------------------------------- 1 | require('./activity.css') 2 | 3 | module.exports = angular.module('stf.activity', [ 4 | require('gettext').name, 5 | require('stf/common-ui').name, 6 | require('stf/timeline').name 7 | ]) 8 | .run(['$templateCache', function($templateCache) { 9 | $templateCache.put('control-panes/activity/activity.pug', 10 | require('./activity.pug') 11 | ) 12 | }]) 13 | .controller('ActivityCtrl', require('./activity-controller')) 14 | -------------------------------------------------------------------------------- /res/app/control-panes/advanced/advanced-controller.js: -------------------------------------------------------------------------------- 1 | module.exports = function AdvancedCtrl() { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /res/app/control-panes/advanced/advanced-spec.js: -------------------------------------------------------------------------------- 1 | describe('AdvancedCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('AdvancedCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/control-panes/advanced/advanced.css: -------------------------------------------------------------------------------- 1 | .stf-advanced { 2 | 3 | } -------------------------------------------------------------------------------- /res/app/control-panes/advanced/advanced.pug: -------------------------------------------------------------------------------- 1 | .row 2 | //.col-md-12 3 | div(ng-include='"control-panes/advanced/run-js/run-js.pug"') 4 | .col-md-6 5 | div(ng-include='"control-panes/advanced/input/input.pug"') 6 | .col-md-6 7 | div(ng-include='"control-panes/advanced/port-forwarding/port-forwarding.pug"') 8 | .row 9 | //.col-md-6 10 | // div(ng-include='"control-panes/advanced/vnc/vnc.pug"') 11 | 12 | .col-md-6 13 | div(ng-include='"control-panes/advanced/maintenance/maintenance.pug"') 14 | -------------------------------------------------------------------------------- /res/app/control-panes/advanced/index.js: -------------------------------------------------------------------------------- 1 | require('./advanced.css') 2 | 3 | module.exports = angular.module('stf.advanced', [ 4 | require('./input').name, 5 | // require('./run-js').name, 6 | // require('./usb').name, 7 | // require('./vnc').name, 8 | require('./port-forwarding').name, 9 | require('./maintenance').name 10 | ]) 11 | .run(['$templateCache', function($templateCache) { 12 | $templateCache.put('control-panes/advanced/advanced.pug', 13 | require('./advanced.pug') 14 | ) 15 | }]) 16 | .controller('AdvancedCtrl', require('./advanced-controller')) 17 | -------------------------------------------------------------------------------- /res/app/control-panes/advanced/input/index.js: -------------------------------------------------------------------------------- 1 | require('./input.css') 2 | 3 | module.exports = angular.module('stf.advanced.input', [ 4 | ]) 5 | .run(['$templateCache', function($templateCache) { 6 | $templateCache.put('control-panes/advanced/input/input.pug', 7 | require('./input.pug') 8 | ) 9 | }]) 10 | .controller('InputAdvancedCtrl', require('./input-controller')) 11 | -------------------------------------------------------------------------------- /res/app/control-panes/advanced/input/input-controller.js: -------------------------------------------------------------------------------- 1 | module.exports = function InputCtrl($scope) { 2 | 3 | $scope.press = function(key) { 4 | $scope.control.keyPress(key) 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /res/app/control-panes/advanced/input/input-spec.js: -------------------------------------------------------------------------------- 1 | describe('InputAdvancedCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('InputAdvancedCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/control-panes/advanced/input/input.css: -------------------------------------------------------------------------------- 1 | .stf-input { 2 | 3 | } -------------------------------------------------------------------------------- /res/app/control-panes/advanced/maintenance/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.advanced.maintenance', [ 2 | require('gettext').name 3 | ]) 4 | .run(['$templateCache', function($templateCache) { 5 | $templateCache.put('control-panes/advanced/maintenance/maintenance.pug', 6 | require('./maintenance.pug') 7 | ) 8 | }]) 9 | .controller('MaintenanceCtrl', require('./maintenance-controller')) 10 | -------------------------------------------------------------------------------- /res/app/control-panes/advanced/maintenance/maintenance-controller.js: -------------------------------------------------------------------------------- 1 | module.exports = function($scope, gettext, $filter) { 2 | 3 | $scope.reboot = function() { 4 | var config = { 5 | rebootEnabled: true 6 | } 7 | 8 | /* eslint no-console: 0 */ 9 | if (config.rebootEnabled) { 10 | var line1 = $filter('translate')(gettext('Are you sure you want to reboot this device?')) 11 | var line2 = $filter('translate')(gettext('The device will be unavailable for a moment.')) 12 | if (confirm(line1 + '\n' + line2)) { 13 | $scope.control.reboot().then(function(result) { 14 | console.error(result) 15 | }) 16 | } 17 | } 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /res/app/control-panes/advanced/maintenance/maintenance-spec.js: -------------------------------------------------------------------------------- 1 | describe('MaintenanceCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('MaintenanceCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/control-panes/advanced/maintenance/maintenance.pug: -------------------------------------------------------------------------------- 1 | .widget-container.fluid-height(ng-controller='MaintenanceCtrl') 2 | .heading 3 | stacked-icon(icon='fa-gears', color='color-darkgray') 4 | span(translate) Maintenance 5 | .pull-right 6 | .widget-content.padded 7 | button(ng-click='reboot()').btn.btn-sm.btn-danger 8 | i.fa.fa-refresh 9 | span(translate) Restart Device 10 | -------------------------------------------------------------------------------- /res/app/control-panes/advanced/port-forwarding/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2023 contains code contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | require('./port-forwarding.css') 6 | 7 | module.exports = angular.module('stf.port-forwarding', [ 8 | require('stf/common-ui/table').name 9 | ]) 10 | .run(['$templateCache', function($templateCache) { 11 | $templateCache.put( 12 | 'control-panes/advanced/port-forwarding/port-forwarding.pug', 13 | require('./port-forwarding.pug') 14 | ) 15 | }]) 16 | .controller('PortForwardingCtrl', require('./port-forwarding-controller')) 17 | -------------------------------------------------------------------------------- /res/app/control-panes/advanced/port-forwarding/port-forwarding-spec.js: -------------------------------------------------------------------------------- 1 | describe('PortForwardingCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('PortForwardingCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/control-panes/advanced/port-forwarding/port-forwarding.css: -------------------------------------------------------------------------------- 1 | .stf-port-forwarding { 2 | 3 | } 4 | 5 | .stf-port-forwarding .padded { 6 | padding-top: 0; 7 | } 8 | 9 | .stf-port-forwarding table { 10 | white-space: nowrap; 11 | } 12 | 13 | .stf-port-forwarding .port-forwarding-image { 14 | text-align: center; 15 | color: #b7b7b7; 16 | padding-bottom: 4px; 17 | } 18 | 19 | .stf-port-forwarding .port-forwarding-image .fa-arrow-right { 20 | vertical-align: 38%; 21 | margin-right: 6px; 22 | } 23 | -------------------------------------------------------------------------------- /res/app/control-panes/advanced/run-js/index.js: -------------------------------------------------------------------------------- 1 | require('./run-js.css') 2 | 3 | module.exports = angular.module('stf.run-js', [ 4 | 5 | ]) 6 | .run(['$templateCache', function($templateCache) { 7 | $templateCache.put('control-panes/advanced/run-js/run-js.pug', 8 | require('./run-js.pug') 9 | ) 10 | }]) 11 | .controller('RunJsCtrl', require('./run-js-controller')) 12 | -------------------------------------------------------------------------------- /res/app/control-panes/advanced/run-js/run-js-controller.js: -------------------------------------------------------------------------------- 1 | module.exports = function RunJsCtrl() { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /res/app/control-panes/advanced/run-js/run-js-spec.js: -------------------------------------------------------------------------------- 1 | describe('RunJsCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('RunJsCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/control-panes/advanced/run-js/run-js.css: -------------------------------------------------------------------------------- 1 | .stf-run-js { 2 | 3 | } -------------------------------------------------------------------------------- /res/app/control-panes/advanced/usb/index.js: -------------------------------------------------------------------------------- 1 | require('./usb.css') 2 | 3 | module.exports = angular.module('stf.usb', [ 4 | 5 | ]) 6 | .run(['$templateCache', function($templateCache) { 7 | $templateCache.put('control-panes/advanced/usb/usb.pug', 8 | require('./usb.pug') 9 | ) 10 | }]) 11 | .controller('UsbCtrl', require('./usb-controller')) 12 | -------------------------------------------------------------------------------- /res/app/control-panes/advanced/usb/usb-controller.js: -------------------------------------------------------------------------------- 1 | module.exports = function UsbCtrl() { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /res/app/control-panes/advanced/usb/usb-spec.js: -------------------------------------------------------------------------------- 1 | describe('UsbCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('UsbCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/control-panes/advanced/usb/usb.css: -------------------------------------------------------------------------------- 1 | .stf-usb { 2 | 3 | } -------------------------------------------------------------------------------- /res/app/control-panes/advanced/usb/usb.pug: -------------------------------------------------------------------------------- 1 | .widget-container.fluid-height.stf-usb 2 | .heading 3 | i.fa 4 | span(translate) Usb speed 5 | .widget-content.padded 6 | div -------------------------------------------------------------------------------- /res/app/control-panes/advanced/vnc/index.js: -------------------------------------------------------------------------------- 1 | require('./vnc.css') 2 | 3 | module.exports = angular.module('stf.vnc', [ 4 | require('gettext').name 5 | ]) 6 | .run(['$templateCache', function($templateCache) { 7 | $templateCache.put( 8 | 'control-panes/advanced/vnc/vnc.pug', 9 | require('./vnc.pug') 10 | ) 11 | }]) 12 | .controller('VNCCtrl', require('./vnc-controller')) 13 | -------------------------------------------------------------------------------- /res/app/control-panes/advanced/vnc/vnc-controller.js: -------------------------------------------------------------------------------- 1 | module.exports = function RemoteDebugCtrl($scope) { 2 | $scope.vnc = {} 3 | 4 | $scope.generateVNCLogin = function() { 5 | $scope.vnc = { 6 | serverHost: 'localhost' 7 | , serverPort: '7042' 8 | , serverPassword: '12345678' 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /res/app/control-panes/advanced/vnc/vnc-spec.js: -------------------------------------------------------------------------------- 1 | describe('VNCCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('VNCCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/control-panes/advanced/vnc/vnc.css: -------------------------------------------------------------------------------- 1 | .stf-vnc { 2 | 3 | } 4 | 5 | -------------------------------------------------------------------------------- /res/app/control-panes/automation/automation.pug: -------------------------------------------------------------------------------- 1 | .row 2 | .col-md-6 3 | div(ng-include='"control-panes/automation/store-account/store-account.pug"') 4 | .col-md-6 5 | div(ng-include='"control-panes/automation/device-settings/device-settings.pug"') 6 | -------------------------------------------------------------------------------- /res/app/control-panes/automation/device-settings/device-settings-spec.js: -------------------------------------------------------------------------------- 1 | describe('DeviceSettingsCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('DeviceSettingsCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/control-panes/automation/device-settings/device-settings.css: -------------------------------------------------------------------------------- 1 | .stf-device-settings { 2 | 3 | } -------------------------------------------------------------------------------- /res/app/control-panes/automation/device-settings/index.js: -------------------------------------------------------------------------------- 1 | require('./device-settings.css') 2 | 3 | module.exports = angular.module('stf.device-settings', [ 4 | 5 | ]) 6 | .run(['$templateCache', function($templateCache) { 7 | $templateCache.put('control-panes/automation/device-settings/device-settings.pug', 8 | require('./device-settings.pug') 9 | ) 10 | }]) 11 | .controller('DeviceSettingsCtrl', require('./device-settings-controller')) 12 | -------------------------------------------------------------------------------- /res/app/control-panes/automation/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.automation', [ 2 | require('./store-account').name, 3 | require('./device-settings').name 4 | ]) 5 | .run(['$templateCache', function($templateCache) { 6 | $templateCache.put( 7 | 'control-panes/automation/automation.pug' 8 | , require('./automation.pug') 9 | ) 10 | }]) 11 | -------------------------------------------------------------------------------- /res/app/control-panes/automation/store-account/index.js: -------------------------------------------------------------------------------- 1 | require('./store-account.css') 2 | require('angular-ladda') 3 | 4 | module.exports = angular.module('stf.store-account', [ 5 | 'angular-ladda', 6 | require('stf/common-ui/table').name 7 | ]) 8 | .run(['$templateCache', function($templateCache) { 9 | $templateCache.put('control-panes/automation/store-account/store-account.pug', 10 | require('./store-account.pug') 11 | ) 12 | }]) 13 | .controller('StoreAccountCtrl', require('./store-account-controller')) 14 | -------------------------------------------------------------------------------- /res/app/control-panes/automation/store-account/store-account-spec.js: -------------------------------------------------------------------------------- 1 | describe('StoreAccountCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('StoreAccountCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | }) 17 | -------------------------------------------------------------------------------- /res/app/control-panes/automation/store-account/store-account.css: -------------------------------------------------------------------------------- 1 | .stf-store-account { 2 | 3 | } 4 | 5 | .stf-store-account .appstore-icon { 6 | width: 16px; 7 | height: 16px; 8 | } 9 | -------------------------------------------------------------------------------- /res/app/control-panes/control-panes-no-device-controller.js: -------------------------------------------------------------------------------- 1 | module.exports = 2 | function ControlPanesNoDeviceController($location, SettingsService) { 3 | var lastUsedDevice = SettingsService.get('lastUsedDevice') 4 | 5 | if (lastUsedDevice) { 6 | $location.path('/control/' + lastUsedDevice) 7 | } else { 8 | $location.path('/') 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /res/app/control-panes/control-panes-service.js: -------------------------------------------------------------------------------- 1 | module.exports = function ControlPanesServiceFactory() { 2 | var ControlPanesService = { 3 | } 4 | 5 | 6 | return ControlPanesService 7 | } 8 | -------------------------------------------------------------------------------- /res/app/control-panes/cpu/cpu-controller.js: -------------------------------------------------------------------------------- 1 | module.exports = function CpuCtrl() { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /res/app/control-panes/cpu/cpu-spec.js: -------------------------------------------------------------------------------- 1 | describe('CpuCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('CpuCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/control-panes/cpu/cpu.css: -------------------------------------------------------------------------------- 1 | .stf-cpu { 2 | 3 | } -------------------------------------------------------------------------------- /res/app/control-panes/cpu/cpu.pug: -------------------------------------------------------------------------------- 1 | .widget-container.fluid-height.stf-cpu(ng-controller='CpuCtrl') 2 | .widget-content.padded 3 | div.overflow-x 4 | ul 5 | li(ng-repeat="(id, stats) in data") 6 | span {{ stats.deviceName }} 7 | ul 8 | li(ng-repeat="(cpu, load) in stats.loads") 9 | span {{cpu}}: {{load.user + load.nice + load.system}}% 10 | -------------------------------------------------------------------------------- /res/app/control-panes/cpu/index.js: -------------------------------------------------------------------------------- 1 | require('./cpu.css') 2 | 3 | module.exports = angular.module('stf.cpu', [ 4 | 5 | ]) 6 | .run(['$templateCache', function($templateCache) { 7 | $templateCache.put('control-panes/cpu/cpu.pug', 8 | require('./cpu.pug') 9 | ) 10 | }]) 11 | .controller('CpuCtrl', require('./cpu-controller')) 12 | -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/apps/apps.css: -------------------------------------------------------------------------------- 1 | .stf-apps .icon-title { 2 | font-size: 12px; 3 | width: 70px; 4 | } 5 | 6 | .stf-apps .icon-app { 7 | margin: 0; 8 | text-align: center; 9 | } 10 | 11 | .stf-apps .heading .icon-app { 12 | margin-top: -8px; 13 | } 14 | 15 | .stf-apps .icon-app:hover .fa { 16 | color: #fff; 17 | } 18 | 19 | .stf-apps .heading .icon-app .fa { 20 | font-size: 19px !important; 21 | line-height: 14px !important; 22 | } 23 | 24 | .stf-apps .padded { 25 | padding-bottom: 8px; 26 | } 27 | -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/apps/index.js: -------------------------------------------------------------------------------- 1 | require('./apps.css') 2 | 3 | module.exports = angular.module('stf.apps', [ 4 | require('stf/common-ui').name 5 | ]) 6 | .run(['$templateCache', function($templateCache) { 7 | $templateCache.put('control-panes/dashboard/apps/apps.pug', 8 | require('./apps.pug') 9 | ) 10 | }]) 11 | .controller('AppsCtrl', require('./apps-controller')) 12 | -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/clipboard/clipboard-spec.js: -------------------------------------------------------------------------------- 1 | describe('ClipboardCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('ClipboardCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/clipboard/clipboard.css: -------------------------------------------------------------------------------- 1 | .stf-clipboard { 2 | 3 | } 4 | 5 | .stf-clipboard .clipboard-textarea { 6 | resize: none; 7 | } 8 | -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/clipboard/clipboard.pug: -------------------------------------------------------------------------------- 1 | .widget-container.fluid-height.stf-clipboard(ng-controller='ClipboardCtrl') 2 | .heading 3 | stacked-icon(icon='fa-copy', color='color-brown') 4 | span(translate) Clipboard 5 | .widget-content.padded 6 | .input-group.form-inline 7 | textarea(rows='1', ng-model='control.clipboardContent', msd-elastic, text-focus-select, 8 | tabindex='20').form-control.clipboard-textarea 9 | span.input-group-btn 10 | button.btn.btn-primary-outline(ng-click='control.getClipboardContent()', uib-tooltip='{{ "Get clipboard contents" | translate }}') 11 | i.fa.fa-refresh 12 | -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/clipboard/index.js: -------------------------------------------------------------------------------- 1 | require('./clipboard.css') 2 | 3 | require('angular-elastic') 4 | 5 | module.exports = angular.module('stf.clipboard', [ 6 | 'monospaced.elastic', 7 | require('gettext').name 8 | ]) 9 | .run(['$templateCache', function($templateCache) { 10 | $templateCache.put('control-panes/dashboard/clipboard/clipboard.pug', 11 | require('./clipboard.pug') 12 | ) 13 | }]) 14 | .controller('ClipboardCtrl', require('./clipboard-controller')) 15 | -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/dashboard-controller.js: -------------------------------------------------------------------------------- 1 | module.exports = function DashboardCtrl() { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/dashboard-spec.js: -------------------------------------------------------------------------------- 1 | describe('DashboardCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('DashboardCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/dashboard.pug: -------------------------------------------------------------------------------- 1 | .row 2 | .col-md-6 3 | div(ng-include='"control-panes/dashboard/navigation/navigation.pug"') 4 | .col-md-6 5 | div(ng-include='"control-panes/dashboard/clipboard/clipboard.pug"') 6 | 7 | .row 8 | .col-md-6 9 | div(ng-include='"control-panes/dashboard/install/install.pug"') 10 | .col-md-6(ng-if='$root.platform == "native"') 11 | div(ng-include='"control-panes/dashboard/shell/shell.pug"') 12 | .row 13 | .col-md-6 14 | div(ng-include='"control-panes/dashboard/apps/apps.pug"') 15 | .col-md-6 16 | div(ng-include='"control-panes/advanced/remote-debug/remote-debug.pug"') 17 | -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.dashboard', [ 2 | require('./navigation/index').name, 3 | require('./shell/index').name, 4 | require('./install/index').name, 5 | require('./apps/index').name, 6 | require('./clipboard/index').name, 7 | require('./remote-debug/index').name 8 | ]) 9 | .run(['$templateCache', function($templateCache) { 10 | $templateCache.put( 11 | 'control-panes/dashboard/dashboard.pug' 12 | , require('./dashboard.pug') 13 | ) 14 | }]) 15 | .controller('DashboardCtrl', require('./dashboard-controller')) 16 | -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/install/activities/activities-spec.js: -------------------------------------------------------------------------------- 1 | describe('ActivitiesCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('ActivitiesCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/install/activities/activities.css: -------------------------------------------------------------------------------- 1 | .stf-activities { 2 | 3 | } -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/install/activities/index.js: -------------------------------------------------------------------------------- 1 | require('./activities.css') 2 | 3 | module.exports = angular.module('stf.activities', [ 4 | require('stf/common-ui').name 5 | ]) 6 | .run(['$templateCache', function($templateCache) { 7 | $templateCache.put( 8 | 'control-panes/dashboard/install/activities/activities.pug', 9 | require('./activities.pug') 10 | ) 11 | }]) 12 | .controller('ActivitiesCtrl', require('./activities-controller')) 13 | -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/install/index.js: -------------------------------------------------------------------------------- 1 | require('./install.css') 2 | 3 | require('ng-file-upload') 4 | 5 | module.exports = angular.module('stf.install', [ 6 | 'angularFileUpload', 7 | require('./activities').name, 8 | require('stf/settings').name, 9 | require('stf/storage').name, 10 | require('stf/install').name, 11 | require('stf/upload').name 12 | ]) 13 | .run(['$templateCache', function($templateCache) { 14 | $templateCache.put('control-panes/dashboard/install/install.pug', 15 | require('./install.pug') 16 | ) 17 | }]) 18 | .controller('InstallCtrl', require('./install-controller')) 19 | -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/install/install-spec.js: -------------------------------------------------------------------------------- 1 | describe('InstallCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('InstallCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/navigation/default-favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/res/app/control-panes/dashboard/navigation/default-favicon.png -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/navigation/index.js: -------------------------------------------------------------------------------- 1 | require('./navigation.css') 2 | 3 | module.exports = angular.module('stf.navigation', [ 4 | 5 | ]) 6 | .run(['$templateCache', function($templateCache) { 7 | $templateCache.put('control-panes/dashboard/navigation/navigation.pug', 8 | require('./navigation.pug') 9 | ) 10 | }]) 11 | .controller('NavigationCtrl', require('./navigation-controller')) 12 | -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/navigation/navigation-spec.js: -------------------------------------------------------------------------------- 1 | describe('NavigationCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('NavigationCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/navigation/navigation.css: -------------------------------------------------------------------------------- 1 | .stf-navigation .browser-icon { 2 | width: 18px; 3 | height: auto; 4 | } 5 | 6 | .stf-navigation .url-input-container { 7 | position: relative; 8 | padding: 0; 9 | margin: 0; 10 | } 11 | 12 | .stf-navigation .url-input-container input { 13 | margin: 0; 14 | padding-left: 30px; 15 | z-index: 0; 16 | } 17 | 18 | .stf-navigation .url-input-container img { 19 | position: absolute; 20 | bottom: 14px; 21 | left: 9px; 22 | width: 16px; 23 | height: 16px; 24 | pointer-events: none; 25 | border: none; 26 | margin:0; 27 | } 28 | 29 | .stf-navigation .browser-buttons { 30 | min-width: 44px; 31 | min-height: 35px; 32 | } 33 | -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/remote-debug/index.js: -------------------------------------------------------------------------------- 1 | require('./remote-debug.css') 2 | 3 | module.exports = angular.module('stf.remote-debug', [ 4 | require('gettext').name 5 | ]) 6 | .run(['$templateCache', function($templateCache) { 7 | $templateCache.put( 8 | 'control-panes/advanced/remote-debug/remote-debug.pug', 9 | require('./remote-debug.pug') 10 | ) 11 | }]) 12 | .controller('RemoteDebugCtrl', require('./remote-debug-controller')) 13 | -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/remote-debug/remote-debug-spec.js: -------------------------------------------------------------------------------- 1 | describe('RemoteDebugCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('RemoteDebugCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/remote-debug/remote-debug.css: -------------------------------------------------------------------------------- 1 | .stf-remote-debug { 2 | 3 | } 4 | 5 | .stf-remote-debug .remote-debug-textarea { 6 | resize: none; 7 | cursor: text; 8 | font-family: Monaco, Menlo, Consolas, "Courier New", monospace; 9 | font-size: 12px; 10 | width: 100%; 11 | } 12 | 13 | 14 | -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/remote-debug/remote-debug.pug: -------------------------------------------------------------------------------- 1 | .widget-container.fluid-height.stf-remote-debug(ng-controller='RemoteDebugCtrl') 2 | .heading 3 | stacked-icon(icon='fa-bug', color='color-darkgreen') 4 | span(translate) Remote debug 5 | help-icon(topic='Remote-Debug', uib-tooltip='{{remoteDebugTooltip | translate}}') 6 | 7 | .widget-content.padded 8 | .form-inline 9 | textarea(readonly, rows='1', ng-model='debugCommand', msd-elastic, text-focus-select).form-control.remote-debug-textarea 10 | -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/shell/index.js: -------------------------------------------------------------------------------- 1 | require('./shell.css') 2 | 3 | module.exports = angular.module('stf.shell', [ 4 | require('stf/common-ui').name, 5 | require('gettext').name 6 | ]) 7 | .run(['$templateCache', function($templateCache) { 8 | $templateCache.put('control-panes/dashboard/shell/shell.pug', 9 | require('./shell.pug') 10 | ) 11 | }]) 12 | .controller('ShellCtrl', require('./shell-controller')) 13 | -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/shell/shell-spec.js: -------------------------------------------------------------------------------- 1 | describe('ShellCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('ShellCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should clear the results', inject(function() { 13 | scope.result = ['result'] 14 | scope.run('clear') 15 | expect(scope.result).toBe(null) 16 | expect(scope.data).toBe('') 17 | expect(scope.command).toBe('') 18 | })) 19 | 20 | }) 21 | -------------------------------------------------------------------------------- /res/app/control-panes/dashboard/shell/shell.css: -------------------------------------------------------------------------------- 1 | .stf-shell .shell-results { 2 | font-size: 12px; 3 | color: #fefefe; 4 | background: #444; 5 | } 6 | 7 | .stf-shell .shell-results-empty { 8 | font-style: italic; 9 | } 10 | 11 | .stf-shell .shell-input { 12 | font-family: Monaco, Menlo, Consolas, "Courier New", monospace; 13 | font-size: 12px; 14 | } 15 | -------------------------------------------------------------------------------- /res/app/control-panes/device-control/device-control-standalone.pug: -------------------------------------------------------------------------------- 1 | .interact-control.fill-height.stf-device-control(ng-controller='DeviceControlCtrl').fill-height.fill-width 2 | div(ng-controller='DeviceScreenCtrl', ng-if='device').fill-height.fill-width 3 | div(ng-file-drop='installFile($files)', ng-file-drag-over-class='dragover').fill-height.fill-width 4 | device-context-menu(device='device', control='control') 5 | device-screen(device='device', control='control').fill-height.fill-width 6 | -------------------------------------------------------------------------------- /res/app/control-panes/explorer/explorer-spec.js: -------------------------------------------------------------------------------- 1 | describe('FsCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('ExplorerCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/control-panes/explorer/explorer.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/res/app/control-panes/explorer/explorer.css -------------------------------------------------------------------------------- /res/app/control-panes/info/index.js: -------------------------------------------------------------------------------- 1 | require('./info.css') 2 | 3 | module.exports = angular.module('stf.info', [ 4 | require('stf/angular-packery').name, 5 | require('stf/common-ui/modals/lightbox-image').name 6 | ]) 7 | .run(['$templateCache', function($templateCache) { 8 | $templateCache.put('control-panes/info/info.pug', 9 | require('./info.pug') 10 | ) 11 | }]) 12 | .controller('InfoCtrl', require('./info-controller')) 13 | -------------------------------------------------------------------------------- /res/app/control-panes/info/info-controller.js: -------------------------------------------------------------------------------- 1 | module.exports = function InfoCtrl($scope, LightboxImageService) { 2 | $scope.openDevicePhoto = function(device) { 3 | var title = device.name 4 | var enhancedPhoto800 = '/static/app/devices/photo/x800/' + device.image 5 | LightboxImageService.open(title, enhancedPhoto800) 6 | } 7 | 8 | var getSdStatus = function() { 9 | if ($scope.control) { 10 | $scope.control.getSdStatus().then(function(result) { 11 | $scope.$apply(function() { 12 | $scope.sdCardMounted = (result.lastData === 'sd_mounted') 13 | }) 14 | }) 15 | } 16 | } 17 | getSdStatus() 18 | } 19 | -------------------------------------------------------------------------------- /res/app/control-panes/info/info-spec.js: -------------------------------------------------------------------------------- 1 | describe('InfoCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('InfoCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/control-panes/info/info.css: -------------------------------------------------------------------------------- 1 | 2 | .stf-info .table.table-infocard thead > tr > th, 3 | .stf-info .table.table-infocard tbody > tr > th, 4 | .stf-info .table.table-infocard tfoot > tr > th, 5 | .stf-info .table.table-infocard thead > tr > td, 6 | .stf-info .table.table-infocard tbody > tr > td, 7 | .stf-info .table.table-infocard tfoot > tr > td { 8 | border-top: 0; 9 | } 10 | 11 | .stf-info .table-infocard tbody > tr > td:first-child { 12 | text-align: right; 13 | margin-right: 20px; 14 | font-weight: bold; 15 | white-space: nowrap; 16 | } 17 | 18 | .stf-info .progress { 19 | margin-bottom: 0; 20 | height: 15px; 21 | } 22 | -------------------------------------------------------------------------------- /res/app/control-panes/inspect/index.js: -------------------------------------------------------------------------------- 1 | require('./inspect.css') 2 | 3 | module.exports = angular.module('stf.inspect', [ 4 | 5 | ]) 6 | .run(['$templateCache', function($templateCache) { 7 | $templateCache.put('control-panes/inspect/inspect.pug', 8 | require('./inspect.pug') 9 | ) 10 | }]) 11 | .controller('InspectCtrl', require('./inspect-controller')) 12 | -------------------------------------------------------------------------------- /res/app/control-panes/inspect/inspect-controller.js: -------------------------------------------------------------------------------- 1 | module.exports = function InspectCtrl() { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /res/app/control-panes/inspect/inspect-spec.js: -------------------------------------------------------------------------------- 1 | describe('InspectCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('InspectCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/control-panes/inspect/inspect.css: -------------------------------------------------------------------------------- 1 | .stf-inspect { 2 | 3 | } -------------------------------------------------------------------------------- /res/app/control-panes/logs/index.js: -------------------------------------------------------------------------------- 1 | require('./logs.less') 2 | 3 | module.exports = angular.module('stf.logs', [ 4 | require('stf/logcat').name, 5 | require('stf/logcat-table').name 6 | ]) 7 | .run(['$templateCache', function($templateCache) { 8 | $templateCache.put('control-panes/logs/logs.pug', 9 | require('./logs.pug') 10 | ) 11 | }]) 12 | .controller('LogsCtrl', require('./logs-controller')) 13 | -------------------------------------------------------------------------------- /res/app/control-panes/logs/logs-spec.js: -------------------------------------------------------------------------------- 1 | describe('LogsCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | if (Object.keys($rootScope.LogcatService).length > 0) { 10 | scope.deviceEntries = $rootScope.LogcatService 11 | } 12 | ctrl = $controller('LogsCtrl', {$scope: scope}) 13 | })) 14 | 15 | it('should ...', inject(function() { 16 | expect(1).toEqual(1) 17 | 18 | })) 19 | 20 | }) 21 | -------------------------------------------------------------------------------- /res/app/control-panes/logs/logs.less: -------------------------------------------------------------------------------- 1 | .stf-logs { 2 | .logcat-filters-table { 3 | margin-bottom: 0; 4 | box-shadow: 0 1px 5px rgba(0, 0, 0, 0.1); 5 | } 6 | 7 | .logcat-filters-table .btn { 8 | margin: 0; 9 | } 10 | 11 | .logcat-filters-table thead > tr > th, 12 | .logcat-filters-table tbody > tr > th, 13 | .logcat-filters-table tfoot > tr > th, 14 | .logcat-filters-table thead > tr > td, 15 | .logcat-filters-table tbody > tr > td, 16 | .logcat-filters-table tfoot > tr > td { 17 | border-top: none; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /res/app/control-panes/performance/cpu/cpu-controller.js: -------------------------------------------------------------------------------- 1 | module.exports = function CpuCtrl() { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /res/app/control-panes/performance/cpu/cpu-spec.js: -------------------------------------------------------------------------------- 1 | describe('CpuCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./index').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('CpuCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/control-panes/performance/cpu/cpu.css: -------------------------------------------------------------------------------- 1 | .stf-cpu { 2 | 3 | } -------------------------------------------------------------------------------- /res/app/control-panes/performance/cpu/cpu.pug: -------------------------------------------------------------------------------- 1 | .widget-container.fluid-height.stf-cpu(ng-controller='CpuCtrl') 2 | .heading 3 | i.fa 4 | span(translate) CPU 5 | .widget-content.padded 6 | div 7 | -------------------------------------------------------------------------------- /res/app/control-panes/performance/cpu/index.js: -------------------------------------------------------------------------------- 1 | require('./cpu.css') 2 | 3 | module.exports = angular.module('stf.cpu', [ 4 | require('epoch').name 5 | ]) 6 | .run(['$templateCache', function($templateCache) { 7 | $templateCache.put('control-panes/performance/cpu/cpu.pug', 8 | require('./cpu.pug') 9 | ) 10 | }]) 11 | .controller('CpuCtrl', require('./cpu-controller')) 12 | -------------------------------------------------------------------------------- /res/app/control-panes/performance/index.js: -------------------------------------------------------------------------------- 1 | require('./performance.css') 2 | 3 | module.exports = angular.module('stf.performance', [ 4 | require('./cpu').name 5 | ]) 6 | .run(['$templateCache', function($templateCache) { 7 | $templateCache.put('control-panes/performance/performance.pug', 8 | require('./performance.pug') 9 | ) 10 | }]) 11 | .controller('PerformanceCtrl', require('./performance-controller')) 12 | -------------------------------------------------------------------------------- /res/app/control-panes/performance/performance-controller.js: -------------------------------------------------------------------------------- 1 | module.exports = function PerformanceCtrl() { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /res/app/control-panes/performance/performance-spec.js: -------------------------------------------------------------------------------- 1 | describe('PerformanceCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./index').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('PerformanceCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/control-panes/performance/performance.css: -------------------------------------------------------------------------------- 1 | .stf-performance { 2 | 3 | } -------------------------------------------------------------------------------- /res/app/control-panes/performance/performance.pug: -------------------------------------------------------------------------------- 1 | .row 2 | .col-md-12 3 | div(ng-include='"control-panes/performance/cpu/cpu.pug"') 4 | -------------------------------------------------------------------------------- /res/app/control-panes/resources/index.js: -------------------------------------------------------------------------------- 1 | require('./resources.css') 2 | 3 | module.exports = angular.module('stf.resources', [ 4 | 5 | ]) 6 | .run(['$templateCache', function($templateCache) { 7 | $templateCache.put('control-panes/resources/resources.pug', 8 | require('./resources.pug') 9 | ) 10 | }]) 11 | .controller('ResourcesCtrl', require('./resources-controller')) 12 | -------------------------------------------------------------------------------- /res/app/control-panes/resources/resources-controller.js: -------------------------------------------------------------------------------- 1 | module.exports = function ResourcesCtrl() { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /res/app/control-panes/resources/resources-spec.js: -------------------------------------------------------------------------------- 1 | describe('ResourcesCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('ResourcesCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/control-panes/resources/resources.css: -------------------------------------------------------------------------------- 1 | .stf-resources { 2 | 3 | } -------------------------------------------------------------------------------- /res/app/control-panes/screenshots/index.js: -------------------------------------------------------------------------------- 1 | require('./screenshots.css') 2 | 3 | module.exports = angular.module('stf.screenshots', [ 4 | require('stf/image-onload').name, 5 | require('stf/settings').name 6 | ]) 7 | .run(['$templateCache', function($templateCache) { 8 | $templateCache.put('control-panes/screenshots/screenshots.pug', 9 | require('./screenshots.pug') 10 | ) 11 | }]) 12 | .controller('ScreenshotsCtrl', require('./screenshots-controller')) 13 | -------------------------------------------------------------------------------- /res/app/control-panes/screenshots/screenshots-spec.js: -------------------------------------------------------------------------------- 1 | describe('ScreenshotsCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('ScreenshotsCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/control-panes/screenshots/screenshots.css: -------------------------------------------------------------------------------- 1 | .stf-screenshots { 2 | 3 | } 4 | 5 | .stf-screenshots .screenshot-image { 6 | display: block !important; 7 | } 8 | 9 | .stf-screenshots .screenshot-image { 10 | -webkit-transition: 1000ms; 11 | transition: 1000ms; 12 | } 13 | 14 | .stf-screenshots .screenshot-image.ng-image-not-loaded { 15 | opacity: 0; 16 | } 17 | 18 | .stf-screenshots .screenshot-image { 19 | opacity: 1; 20 | } 21 | 22 | .stf-screenshots .zoom-range { 23 | width: 180px; 24 | margin-right: 5px; 25 | } 26 | -------------------------------------------------------------------------------- /res/app/device-list/column/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 contains code contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | module.exports = angular.module('stf.device-list.column', [ 6 | require('gettext').name, 7 | require('stf/settings').name, 8 | require('stf/app-state').name 9 | ]) 10 | .service('DeviceColumnService', require('./device-column-service')) 11 | -------------------------------------------------------------------------------- /res/app/device-list/customize/device-list-customize.css: -------------------------------------------------------------------------------- 1 | .stf-device-list .stf-device-details-customize { 2 | white-space: nowrap; 3 | padding: 10px; 4 | padding-bottom: 0; 5 | column-count: 2; 6 | -moz-column-count: 2; 7 | -webkit-column-count: 2; 8 | max-width: 800px; 9 | } 10 | 11 | .stf-device-list .stf-device-details-customize .radio, 12 | .stf-device-list .stf-device-details-customize .checkbox { 13 | margin: 0; 14 | margin-bottom: 10px; 15 | } 16 | -------------------------------------------------------------------------------- /res/app/device-list/customize/index.js: -------------------------------------------------------------------------------- 1 | require('./device-list-customize.css') 2 | 3 | module.exports = angular.module('stf.device-list.customize', [ 4 | ]) 5 | -------------------------------------------------------------------------------- /res/app/device-list/details/device-list-details.css: -------------------------------------------------------------------------------- 1 | .device-list-details-content table { 2 | white-space: nowrap; 3 | } 4 | 5 | .device-list-details-content .device-list-product, 6 | .device-list-details-content .device-list-carrier { 7 | white-space: normal; 8 | } 9 | 10 | .device-list-details-content .progress { 11 | margin-bottom: 0 !important; 12 | height: 17px !important; 13 | } 14 | 15 | .device-list-details-content .device-status.state-available { 16 | font-weight: 600; 17 | } 18 | -------------------------------------------------------------------------------- /res/app/device-list/details/device-list-details.pug: -------------------------------------------------------------------------------- 1 | table.table.table-hover.dataTable.ng-table 2 | thead 3 | tr 4 | th.header.sortable(ng-repeat='column in columns() track by column.name', ng-if='column.selected', ng-class='["sort-" + (sortedColumns[column.name].order || "none")]', ng-click='sortBy(column, $event.shiftKey)') 5 | div(ng-bind='columnDefinitions[column.name].title | translate') 6 | device-list-empty(tracker='tracker()') 7 | -------------------------------------------------------------------------------- /res/app/device-list/details/index.js: -------------------------------------------------------------------------------- 1 | require('./device-list-details.css') 2 | 3 | module.exports = angular.module('stf.device-list.details', [ 4 | require('stf/device').name, 5 | require('stf/user/group').name, 6 | require('stf/common-ui').name, 7 | require('stf/admin-mode').name, 8 | require('../column').name, 9 | require('../empty').name 10 | ]) 11 | .directive('deviceListDetails', require('./device-list-details-directive')) 12 | -------------------------------------------------------------------------------- /res/app/device-list/empty/device-list-empty.pug: -------------------------------------------------------------------------------- 1 | nothing-to-show(message='{{"No devices connected"|translate}}', icon='fa-sitemap', ng-show='empty') 2 | -------------------------------------------------------------------------------- /res/app/device-list/empty/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.device-list.empty', [ 2 | ]) 3 | .directive('deviceListEmpty', require('./device-list-empty-directive')) 4 | -------------------------------------------------------------------------------- /res/app/device-list/icons/device-list-icons.pug: -------------------------------------------------------------------------------- 1 | ul.devices-icon-view 2 | device-list-empty(tracker='tracker()') 3 | .clear-fix 4 | .line 5 | -------------------------------------------------------------------------------- /res/app/device-list/icons/index.js: -------------------------------------------------------------------------------- 1 | require('./device-list-icons.css') 2 | 3 | module.exports = angular.module('stf.device-list.icons', [ 4 | require('gettext').name, 5 | require('stf/user/group').name, 6 | require('stf/common-ui').name, 7 | require('../column').name, 8 | require('../empty').name, 9 | require('stf/standalone').name 10 | ]) 11 | .directive('deviceListIcons', require('./device-list-icons-directive')) 12 | -------------------------------------------------------------------------------- /res/app/device-list/search/device-list-search.css: -------------------------------------------------------------------------------- 1 | .stf-device-list .device-search { 2 | width: 20em; 3 | -webkit-transition: none; 4 | transition: none; 5 | } 6 | 7 | .stf-device-list .filter-out { 8 | display: none; 9 | } 10 | -------------------------------------------------------------------------------- /res/app/device-list/search/index.js: -------------------------------------------------------------------------------- 1 | require('./device-list-search.css') 2 | 3 | module.exports = angular.module('stf.device-list.search', [ 4 | ]) 5 | -------------------------------------------------------------------------------- /res/app/device-list/stats/index.js: -------------------------------------------------------------------------------- 1 | require('./device-list-stats.css') 2 | 3 | module.exports = angular.module('stf.device-list.stats', [ 4 | require('stf/user').name 5 | ]) 6 | .directive('deviceListStats', require('./device-list-stats-directive')) 7 | -------------------------------------------------------------------------------- /res/app/group-list/group-list.pug: -------------------------------------------------------------------------------- 1 | // 2 | Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | // 4 | 5 | .stf-group-list 6 | .row.unselectable 7 | .col-md-12 8 | div(ng-include="'group-list/stats/group-stats.pug'") 9 | .row.unselectable 10 | .col-md-12 11 | div(ng-include="'group-list/stats/group-quota-stats.pug'") 12 | .row.unselectable 13 | .col-md-12 14 | div(ng-include="'group-list/groups/groups.pug'") 15 | -------------------------------------------------------------------------------- /res/app/group-list/stats/group-quota-stats.pug: -------------------------------------------------------------------------------- 1 | // 2 | Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | // 4 | 5 | .widget-container.group-quota-stats 6 | .col-xs-6 7 | uib-progressbar.bar(class='progress-striped' value='numberBar.value' type='{{numberBar.type}}') 8 | b {{numberBar.value}}% 9 | .text(translate) {{user.name}} groups number use 10 | .col-xs-6 11 | uib-progressbar.bar(class='progress-striped' value='durationBar.value' type='{{durationBar.type}}') 12 | b {{durationBar.value}}% 13 | .text(translate) {{user.name}} groups duration use 14 | 15 | -------------------------------------------------------------------------------- /res/app/layout/layout-controller.js: -------------------------------------------------------------------------------- 1 | module.exports = 2 | function LayoutCtrl(LanguageService, $rootScope, hotkeys, $filter, gettext) { 3 | LanguageService.updateLanguage() 4 | 5 | function toggleAdminMode() { 6 | var enabled = $filter('translate')(gettext('Admin mode has been enabled.')) 7 | var disabled = $filter('translate')(gettext('Admin mode has been disabled.')) 8 | 9 | $rootScope.adminMode = !$rootScope.adminMode 10 | 11 | alert($rootScope.adminMode ? enabled : disabled) 12 | } 13 | 14 | hotkeys.add({ 15 | combo: 'up up down down left right left right enter', 16 | callback: toggleAdminMode 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /res/app/menu/menu-spec.js: -------------------------------------------------------------------------------- 1 | describe('MenuCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('MenuCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/settings/devices/devices-spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | describe('DevicesCtrl', function() { 6 | 7 | beforeEach(angular.mock.module(require('./index').name)) 8 | 9 | var scope, ctrl 10 | 11 | beforeEach(inject(function($rootScope, $controller) { 12 | scope = $rootScope.$new() 13 | ctrl = $controller('DevicesCtrl', {$scope: scope}) 14 | })) 15 | 16 | it('should ...', inject(function() { 17 | expect(1).toEqual(1) 18 | 19 | })) 20 | 21 | }) 22 | -------------------------------------------------------------------------------- /res/app/settings/devices/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | require('./devices.css') 6 | 7 | module.exports = angular.module('stf.settings.devices', [ 8 | require('stf/common-ui').name, 9 | require('stf/settings').name, 10 | require('stf/util/common').name, 11 | require('stf/devices').name 12 | ]) 13 | .run(['$templateCache', function($templateCache) { 14 | $templateCache.put( 15 | 'settings/devices/devices.pug', require('./devices.pug') 16 | ) 17 | }]) 18 | .controller('DevicesCtrl', require('./devices-controller')) 19 | -------------------------------------------------------------------------------- /res/app/settings/general/alert-message/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2024 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | module.exports = angular.module('stf.settings.general.alert-message', [ 6 | require('stf/settings').name 7 | ]) 8 | .run(['$templateCache', function($templateCache) { 9 | $templateCache.put( 10 | 'settings/general/alert-message/alert-message.pug' 11 | , require('./alert-message.pug') 12 | ) 13 | }]) 14 | .controller('AlertMessageCtrl', require('./alert-message-controller')) 15 | -------------------------------------------------------------------------------- /res/app/settings/general/date-format/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | module.exports = angular.module('stf.settings.general.date-format', [ 6 | require('stf/settings').name 7 | ]) 8 | .run(['$templateCache', function($templateCache) { 9 | $templateCache.put( 10 | 'settings/general/date-format/date-format.pug', require('./date-format.pug') 11 | ) 12 | }]) 13 | .controller('DateFormatCtrl', require('./date-format-controller')) 14 | -------------------------------------------------------------------------------- /res/app/settings/general/email-address-separator/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | module.exports = angular.module('stf.settings.general.email-address-separator', [ 6 | require('stf/settings').name 7 | ]) 8 | .run(['$templateCache', function($templateCache) { 9 | $templateCache.put( 10 | 'settings/general/email-address-separator/email-address-separator.pug' 11 | , require('./email-address-separator.pug') 12 | ) 13 | }]) 14 | .controller('EmailAddressSeparatorCtrl', require('./email-address-separator-controller')) 15 | -------------------------------------------------------------------------------- /res/app/settings/general/general-controller.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2024 contains code contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | module.exports = function GeneralCtrl($scope, AppState) { 6 | $scope.isAdmin = function() { 7 | return AppState.user.privilege === 'admin' 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /res/app/settings/general/general-spec.js: -------------------------------------------------------------------------------- 1 | describe('GeneralCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./index').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('GeneralCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/settings/general/general.css: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2024 contains code contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | */ 4 | 5 | .stf-general { 6 | 7 | } 8 | 9 | .stf-general .general-item { 10 | margin: 0px 10px 15px 0px; 11 | } 12 | 13 | .stf-general .general-label { 14 | font-weight: bold; 15 | margin-right: 10px; 16 | } 17 | -------------------------------------------------------------------------------- /res/app/settings/general/language/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf-ui-language', [ 2 | require('stf/settings').name, 3 | require('stf/language').name 4 | ]) 5 | .run(['$templateCache', function($templateCache) { 6 | $templateCache.put( 7 | 'settings/general/language/language.pug', require('./language.pug') 8 | ) 9 | }]) 10 | .controller('LanguageCtrl', require('./language-controller')) 11 | -------------------------------------------------------------------------------- /res/app/settings/general/language/language-controller.js: -------------------------------------------------------------------------------- 1 | module.exports = function($scope, LanguageService, SettingsService) { 2 | SettingsService.bind($scope, { 3 | target: 'language' 4 | , source: LanguageService.settingKey 5 | , defaultValue: LanguageService.detectedLanguage 6 | }) 7 | 8 | $scope.supportedLanguages = LanguageService.supportedLanguages 9 | } 10 | -------------------------------------------------------------------------------- /res/app/settings/general/language/language.pug: -------------------------------------------------------------------------------- 1 | .widget-container.fluid-height(ng-controller='LanguageCtrl') 2 | .heading 3 | i.fa.fa-flag 4 | span(translate) Language 5 | .widget-content.padded 6 | .form-horizontal 7 | .form-group 8 | select.form-control(ng-model='language', ng-options='key as value for (key, value) in supportedLanguages') 9 | -------------------------------------------------------------------------------- /res/app/settings/general/local/index.js: -------------------------------------------------------------------------------- 1 | require('angular-bootstrap') 2 | 3 | module.exports = angular.module('ui-local-settings', [ 4 | require('stf/settings').name, 5 | require('stf/common-ui/modals/common').name, 6 | 'ui.bootstrap' 7 | ]) 8 | .run(['$templateCache', function($templateCache) { 9 | $templateCache.put( 10 | 'settings/general/local/local-settings.pug' 11 | , require('./local-settings.pug') 12 | ) 13 | }]) 14 | .controller('LocalSettingsCtrl', require('./local-settings-controller')) 15 | -------------------------------------------------------------------------------- /res/app/settings/general/local/local-settings-controller.js: -------------------------------------------------------------------------------- 1 | module.exports = function($scope, SettingsService) { 2 | $scope.resetSettings = function() { 3 | SettingsService.reset() 4 | alert('Settings cleared') 5 | } 6 | 7 | } 8 | -------------------------------------------------------------------------------- /res/app/settings/general/local/local-settings.pug: -------------------------------------------------------------------------------- 1 | .widget-container.fluid-height(ng-controller='LocalSettingsCtrl') 2 | .heading 3 | i.fa.fa-save 4 | span(translate) Local Settings 5 | .widget-content.padded 6 | button(ng-click='resetSettings()').btn.btn-danger 7 | i.fa.fa-trash-o 8 | span(translate) Reset Settings 9 | -------------------------------------------------------------------------------- /res/app/settings/groups/filters/available-objects-filter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | module.exports = function() { 6 | return function(objects, group, groupKey, objectKey) { 7 | const objectList = [] 8 | 9 | objects.forEach(function(object) { 10 | if (group[groupKey].indexOf(object[objectKey]) < 0) { 11 | objectList.push(object) 12 | } 13 | }) 14 | return objectList 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /res/app/settings/groups/filters/group-objects-filter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | module.exports = function(CommonService) { 6 | return function(keys, objects, objectsIndex) { 7 | const objectList = [] 8 | 9 | keys.forEach(function(key) { 10 | if (CommonService.isExisting(objectsIndex[key])) { 11 | objectList.push(objects[objectsIndex[key].index]) 12 | } 13 | }) 14 | return objectList 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /res/app/settings/groups/groups-spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | describe('GroupsCtrl', function() { 6 | 7 | beforeEach(angular.mock.module(require('./index').name)) 8 | 9 | var scope, ctrl 10 | 11 | beforeEach(inject(function($rootScope, $controller) { 12 | scope = $rootScope.$new() 13 | ctrl = $controller('GroupsCtrl', {$scope: scope}) 14 | })) 15 | 16 | it('should ...', inject(function() { 17 | expect(1).toEqual(1) 18 | 19 | })) 20 | 21 | }) 22 | -------------------------------------------------------------------------------- /res/app/settings/keys/access-tokens/access-tokens-spec.js: -------------------------------------------------------------------------------- 1 | describe('AccessTokensCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./index').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('AccessTokensCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/settings/keys/access-tokens/access-tokens.css: -------------------------------------------------------------------------------- 1 | .stf-access-tokens .access-token-generated-okay { 2 | display: inline-block; 3 | } 4 | 5 | .stf-access-tokens .token-id-textarea { 6 | resize: none; 7 | cursor: text; 8 | font-family: Monaco, Menlo, Consolas, "Courier New", monospace; 9 | font-size: 12px; 10 | width: 85%; 11 | } 12 | -------------------------------------------------------------------------------- /res/app/settings/keys/access-tokens/index.js: -------------------------------------------------------------------------------- 1 | require('./access-tokens.css') 2 | 3 | module.exports = angular.module('stf.settings.keys.access-tokens', [ 4 | require('stf/socket').name, 5 | require('stf/common-ui').name, 6 | require('stf/tokens').name, 7 | require('stf/tokens/generate-access-token').name 8 | ]) 9 | .run(['$templateCache', function($templateCache) { 10 | $templateCache.put( 11 | 'settings/keys/access-tokens/access-tokens.pug', require('./access-tokens.pug') 12 | ) 13 | }]) 14 | .controller('AccessTokensCtrl', require('./access-tokens-controller')) 15 | -------------------------------------------------------------------------------- /res/app/settings/keys/adb-keys/adb-keys-controller.js: -------------------------------------------------------------------------------- 1 | module.exports = 2 | function AdbKeysCtrl($scope, $http, UserService) { 3 | $scope.adbKeys = [] 4 | 5 | function updateKeys() { 6 | $scope.adbKeys = UserService.getAdbKeys() 7 | } 8 | 9 | $scope.removeKey = function(key) { 10 | UserService.removeAdbKey(key) 11 | } 12 | 13 | $scope.$on('user.keys.adb.updated', updateKeys) 14 | updateKeys() 15 | } 16 | -------------------------------------------------------------------------------- /res/app/settings/keys/adb-keys/adb-keys-service.js: -------------------------------------------------------------------------------- 1 | module.exports = function AdbKeysServiceFactory() { 2 | var service = {} 3 | 4 | service.hostNameFromKey = function(key) { 5 | if (key.match(/.+= (.+)/)) { 6 | return key.replace(/.+= (.+)/g, '$1') 7 | } 8 | return '' 9 | } 10 | 11 | return service 12 | } 13 | -------------------------------------------------------------------------------- /res/app/settings/keys/adb-keys/adb-keys-spec.js: -------------------------------------------------------------------------------- 1 | describe('AdbKeysCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./index').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('AdbKeysCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/settings/keys/adb-keys/adb-keys.css: -------------------------------------------------------------------------------- 1 | .stf-adb-keys .key-list-fingerprint { 2 | font-family: Monaco, Menlo, Consolas, "Courier New", monospace; 3 | font-size: 10px; 4 | margin-bottom: 2px; 5 | color: #999999; 6 | font-weight: 300; 7 | } 8 | -------------------------------------------------------------------------------- /res/app/settings/keys/adb-keys/index.js: -------------------------------------------------------------------------------- 1 | require('./adb-keys.css') 2 | 3 | module.exports = angular.module('stf.settings.keys.adb-keys', [ 4 | require('stf/user').name, 5 | require('stf/common-ui').name, 6 | require('stf/keys/add-adb-key').name 7 | ]) 8 | .run(['$templateCache', function($templateCache) { 9 | $templateCache.put( 10 | 'settings/keys/adb-keys/adb-keys.pug', require('./adb-keys.pug') 11 | ) 12 | }]) 13 | .controller('AdbKeysCtrl', require('./adb-keys-controller')) 14 | -------------------------------------------------------------------------------- /res/app/settings/keys/index.js: -------------------------------------------------------------------------------- 1 | require('./keys.css') 2 | 3 | module.exports = angular.module('stf.settings.keys', [ 4 | require('./adb-keys').name, 5 | require('./access-tokens').name 6 | ]) 7 | .run(['$templateCache', function($templateCache) { 8 | $templateCache.put( 9 | 'settings/keys/keys.pug', require('./keys.pug') 10 | ) 11 | }]) 12 | .controller('KeysCtrl', require('./keys-controller')) 13 | -------------------------------------------------------------------------------- /res/app/settings/keys/keys-controller.js: -------------------------------------------------------------------------------- 1 | module.exports = function KeysCtrl() { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /res/app/settings/keys/keys-spec.js: -------------------------------------------------------------------------------- 1 | describe('KeysCtrl', function() { 2 | 3 | beforeEach(angular.mock.module(require('./index').name)) 4 | 5 | var scope, ctrl 6 | 7 | beforeEach(inject(function($rootScope, $controller) { 8 | scope = $rootScope.$new() 9 | ctrl = $controller('KeysCtrl', {$scope: scope}) 10 | })) 11 | 12 | it('should ...', inject(function() { 13 | expect(1).toEqual(1) 14 | 15 | })) 16 | 17 | }) 18 | -------------------------------------------------------------------------------- /res/app/settings/keys/keys.pug: -------------------------------------------------------------------------------- 1 | .row 2 | .col-md-6 3 | div(ng-include='"settings/keys/access-tokens/access-tokens.pug"') 4 | .col-md-6 5 | div(ng-include='"settings/keys/adb-keys/adb-keys.pug"') 6 | -------------------------------------------------------------------------------- /res/app/settings/notifications/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('settings-notifications', [ 2 | require('stf/settings').name 3 | ]) 4 | .run(['$templateCache', function($templateCache) { 5 | $templateCache.put( 6 | 'settings/notifications/notifications.pug' 7 | , require('./notifications.pug') 8 | ) 9 | }]) 10 | .factory('NotificationsService', require('./notifications-service')) 11 | .controller('NotificationsCtrl', require('./notifications-controller')) 12 | -------------------------------------------------------------------------------- /res/app/settings/notifications/notifications-controller.js: -------------------------------------------------------------------------------- 1 | module.exports = function NotificationsCtrl() { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /res/app/settings/notifications/notifications-service.js: -------------------------------------------------------------------------------- 1 | module.exports = function NotificationsServiceFactory() { 2 | var NotificationsService = {} 3 | 4 | 5 | return NotificationsService 6 | } 7 | -------------------------------------------------------------------------------- /res/app/settings/notifications/notifications.pug: -------------------------------------------------------------------------------- 1 | .widget-container.fluid-height 2 | .heading 3 | i.fa.fa-exclamation-circle 4 | span(translate) Notifications 5 | .widget-content.padded 6 | label.checkbox 7 | input(type='checkbox', ng-model='notificationsEnabled', ng-click='enableNotifications()', disabled) 8 | span(translate) Enable notifications -------------------------------------------------------------------------------- /res/app/settings/settings.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | .stf-settings-tabs-device-icon { 6 | font-size: 15px; 7 | } 8 | 9 | -------------------------------------------------------------------------------- /res/app/settings/settings.pug: -------------------------------------------------------------------------------- 1 | div(pane='center', ng-controller='SettingsCtrl') 2 | .widget-container.fluid-height 3 | nice-tabs(key='SettingsTabs', tabs='settingTabs', filter='') 4 | -------------------------------------------------------------------------------- /res/app/settings/users/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | require('./users.css') 6 | 7 | module.exports = angular.module('stf.settings.users', [ 8 | require('stf/app-state').name, 9 | require('stf/settings').name, 10 | require('stf/util/common').name, 11 | require('stf/users').name 12 | ]) 13 | .run(['$templateCache', function($templateCache) { 14 | $templateCache.put( 15 | 'settings/users/users.pug', require('./users.pug') 16 | ) 17 | }]) 18 | .controller('UsersCtrl', require('./users-controller')) 19 | -------------------------------------------------------------------------------- /res/app/settings/users/users-spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 code initially contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | describe('UsersCtrl', function() { 6 | 7 | beforeEach(angular.mock.module(require('./index').name)) 8 | 9 | var scope, ctrl 10 | 11 | beforeEach(inject(function($rootScope, $controller) { 12 | scope = $rootScope.$new() 13 | ctrl = $controller('UsersCtrl', {$scope: scope}) 14 | })) 15 | 16 | it('should ...', inject(function() { 17 | expect(1).toEqual(1) 18 | 19 | })) 20 | 21 | }) 22 | -------------------------------------------------------------------------------- /res/app/terminal/terminal.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | padding: 0; 3 | margin: 0; 4 | cursor: text; 5 | background: #000; 6 | } 7 | 8 | .terminal { 9 | font-family: Monaco, FreeMono, monospace; 10 | color: #fff; 11 | font-weight: bold; 12 | font-size: 14px; 13 | line-height: 14px; 14 | -webkit-font-smoothing: antialiased; 15 | font-smoothing: antialiased; 16 | cursor: text; 17 | } 18 | -------------------------------------------------------------------------------- /res/app/user/index.js: -------------------------------------------------------------------------------- 1 | module.exports = angular.module('stf.user-profile', []) 2 | .config(function($routeProvider) { 3 | 4 | $routeProvider 5 | .when('/user/:user*', { 6 | template: require('./user.pug') 7 | }) 8 | }) 9 | .controller('UserProfileCtrl', require('./user-controller')) 10 | -------------------------------------------------------------------------------- /res/app/user/user-controller.js: -------------------------------------------------------------------------------- 1 | module.exports = 2 | function UserCtrl() { 3 | 4 | 5 | } 6 | -------------------------------------------------------------------------------- /res/app/user/user.pug: -------------------------------------------------------------------------------- 1 | h1 User 2 | -------------------------------------------------------------------------------- /res/app/views/docs.pug: -------------------------------------------------------------------------------- 1 | //extends layout 2 | block content 3 | .row.stf-docs(ng-controller='DocsCtrl') 4 | .col-md-10.col-md-offset-1 5 | .widget-container.fluid-height 6 | .stf-docs-navigation 7 | button.btn.btn-primary-outline.docs-back.transparent-border(ng-click='goBack()', 8 | ng-show='hasHistory') 9 | i.fa.fa-chevron-left.fa-fw 10 | button.btn.btn-primary-outline.docs-home.transparent-border(ng-click='goHome()') 11 | i.fa.fa-home.fa-fw 12 | .widget-content.padded 13 | .row 14 | .col-md-10.col-md-offset-1.selectable 15 | != markdownFile.parseContent() 16 | -------------------------------------------------------------------------------- /res/app/views/rejected-email.pug: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | meta(charset='utf-8') 5 | base(href='/') 6 | title("STF") 7 | body 8 | Missing or rejected email address 9 | a(href='/auth/oauth/') 10 | Retry 11 | -------------------------------------------------------------------------------- /res/auth/ldap/scripts/entry.js: -------------------------------------------------------------------------------- 1 | require.ensure([], function(require) { 2 | require('nine-bootstrap') 3 | 4 | require('angular') 5 | require('angular-route') 6 | require('angular-touch') 7 | 8 | angular.module('app', [ 9 | 'ngRoute', 10 | 'ngTouch', 11 | require('gettext').name, 12 | require('./signin').name 13 | ]) 14 | .config(function($routeProvider, $locationProvider) { 15 | $locationProvider.html5Mode(true) 16 | $routeProvider 17 | .otherwise({ 18 | redirectTo: '/auth/ldap/' 19 | }) 20 | }) 21 | 22 | }) 23 | -------------------------------------------------------------------------------- /res/auth/ldap/scripts/signin/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 contains code contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | require('./signin.css') 6 | 7 | module.exports = angular.module('stf.signin', [ 8 | require('stf/util/common').name, 9 | require('stf/common-ui').name 10 | ]) 11 | .config(function($routeProvider) { 12 | $routeProvider 13 | .when('/auth/ldap/', { 14 | template: require('./signin.pug') 15 | }) 16 | }) 17 | .controller('SignInCtrl', require('./signin-controller')) 18 | -------------------------------------------------------------------------------- /res/auth/ldap/views/index.pug: -------------------------------------------------------------------------------- 1 | // 2 | Copyright © 2024 contains code contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | // 4 | 5 | doctype html 6 | html(ng-app='app') 7 | head 8 | title STF 9 | base(href='/') 10 | meta(charset='utf-8') 11 | meta(name='viewport', content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui') 12 | body(ng-cloak) 13 | div(ng-view) 14 | script(src='static/app/build/entry/authldap.entry.js') 15 | -------------------------------------------------------------------------------- /res/auth/mock/scripts/entry.js: -------------------------------------------------------------------------------- 1 | require.ensure([], function(require) { 2 | require('nine-bootstrap') 3 | 4 | require('angular') 5 | require('angular-route') 6 | require('angular-touch') 7 | 8 | angular.module('app', [ 9 | 'ngRoute', 10 | 'ngTouch', 11 | require('gettext').name, 12 | require('./signin').name 13 | ]) 14 | .config(function($routeProvider, $locationProvider) { 15 | $locationProvider.html5Mode(true) 16 | $routeProvider 17 | .otherwise({ 18 | redirectTo: '/auth/mock/' 19 | }) 20 | }) 21 | }) 22 | -------------------------------------------------------------------------------- /res/auth/mock/scripts/signin/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2019 contains code contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | **/ 4 | 5 | require('./signin.css') 6 | 7 | module.exports = angular.module('stf.signin', [ 8 | require('stf/util/common').name, 9 | require('stf/common-ui').name 10 | ]) 11 | .config(function($routeProvider) { 12 | $routeProvider 13 | .when('/auth/mock/', { 14 | template: require('./signin.pug') 15 | }) 16 | }) 17 | .controller('SignInCtrl', require('./signin-controller')) 18 | -------------------------------------------------------------------------------- /res/auth/mock/views/index.pug: -------------------------------------------------------------------------------- 1 | // 2 | Copyright © 2024 contains code contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | // 4 | 5 | doctype html 6 | html(ng-app='app') 7 | head 8 | title STF 9 | base(href='/') 10 | meta(charset='utf-8') 11 | meta(name='viewport', content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui') 12 | body(ng-cloak) 13 | div(ng-view) 14 | script(src='static/app/build/entry/authmock.entry.js') 15 | -------------------------------------------------------------------------------- /res/common/lang/index.js: -------------------------------------------------------------------------------- 1 | angular.module('gettext').run(['gettextCatalog', function(gettextCatalog) { 2 | // Load all supported languages 3 | angular.forEach(require('./langs'), function(value, key) { 4 | if (key !== 'en') { 5 | gettextCatalog.setStrings(key, 6 | require('./translations/stf.' + key + '.json')[key]) 7 | } 8 | }) 9 | }]) 10 | 11 | module.exports = angular.module('stf/lang', [ 12 | 'gettext' 13 | ]) 14 | -------------------------------------------------------------------------------- /res/common/lang/langs.json: -------------------------------------------------------------------------------- 1 | { 2 | "en": "English", 3 | "es": "Español", 4 | "fr": "Français", 5 | "pt_BR": "Português (Brasil)", 6 | "pl": "Język polski", 7 | "ja": "日本語", 8 | "zh_CN": "简体中文", 9 | "zh-Hant": "繁體中文", 10 | "ko_KR": "한국어", 11 | "ru_RU": "Русский" 12 | } 13 | -------------------------------------------------------------------------------- /res/common/logo/STF.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/res/common/logo/STF.ai -------------------------------------------------------------------------------- /res/common/logo/exports/STF-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/res/common/logo/exports/STF-128.png -------------------------------------------------------------------------------- /res/common/logo/exports/STF-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/res/common/logo/exports/STF-512.png -------------------------------------------------------------------------------- /res/common/logo/exports/STF-outlined.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/res/common/logo/exports/STF-outlined.ai -------------------------------------------------------------------------------- /res/common/status/scripts/entry.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/res/common/status/scripts/entry.js -------------------------------------------------------------------------------- /res/common/status/views/404.pug: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | title STF Not Found 5 | meta(charset='utf-8') 6 | meta(name='viewport', content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui') 7 | include partials/styles 8 | body(ng-cloak).forofour.bg-danger 9 | div(ng-view) 10 | .forofour-container 11 | h1 12 | i.fa.fa-unlink.fa-4x 13 | h2 Page not available 14 | -------------------------------------------------------------------------------- /res/common/status/views/maintenance.pug: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | title STF Maintenance 5 | meta(charset='utf-8') 6 | meta(name='viewport', content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui') 7 | include partials/styles 8 | body(ng-cloak).forofour.bg-danger 9 | div(ng-view) 10 | .forofour-container 11 | h1 12 | i.fa.fa-unlink.fa-4x 13 | h2 STF is in maintenance mode. 14 | h3 Please wait, the system will be back up shortly. 15 | -------------------------------------------------------------------------------- /res/common/status/views/partials/styles.pug: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/res/common/status/views/partials/styles.pug -------------------------------------------------------------------------------- /res/common/status/webpack.config.js: -------------------------------------------------------------------------------- 1 | var pathutil = require('./../../../lib/util/pathutil') 2 | var options = require('./../../../webpack.config').webpack 3 | var _ = require('lodash') 4 | 5 | module.exports = _.defaults(options, { 6 | entry: pathutil.resource('common/status/scripts/entry.js'), 7 | output: { 8 | path: pathutil.resource('build'), 9 | publicPath: '/static/build/', 10 | filename: 'bundle-status.js' 11 | } 12 | }) 13 | -------------------------------------------------------------------------------- /res/test/.eslintrc: -------------------------------------------------------------------------------- 1 | // TODO: Some day use eslint-plugin-angular 2 | // https://github.com/Gillespie59/eslint-plugin-angular 3 | { 4 | "env": { 5 | "browser": true, 6 | "node": true, 7 | "protractor": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /res/test/e2e/help/help-spec.js: -------------------------------------------------------------------------------- 1 | describe('Help Page', function() { 2 | //var HelpPage = function () { 3 | // this.get = function () { 4 | // browser.get(protractor.getInstance().baseUrl + 'help') 5 | // } 6 | //} 7 | }) 8 | -------------------------------------------------------------------------------- /res/test/e2e/helpers/fail-fast.js: -------------------------------------------------------------------------------- 1 | // https://github.com/angular/protractor/issues/499 2 | 3 | module.exports = function FailFast() { 4 | var passed = jasmine.getEnv().currentSpec.results().passed() 5 | if (!passed) { 6 | jasmine.getEnv().specFilter = function() { 7 | return false 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /res/test/e2e/menu/menu-spec.js: -------------------------------------------------------------------------------- 1 | describe('Menu', function() { 2 | it('should display the STF version', function() { 3 | // Navigate to the device list page 4 | browser.get('/#!/devices') 5 | 6 | // Find the version display element 7 | var versionElement = element(by.css('.stf-menu .version-text')) 8 | 9 | // Assert that the element is present 10 | expect(versionElement.isPresent()).toBe(true) 11 | 12 | // Assert that the text matches 'v' + version from package.json 13 | // Using a regex to be more flexible with the exact version number. 14 | expect(versionElement.getText()).toMatch(/^v\d+\.\d+\.\d+$/) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /res/test/e2e/settings/settings-spec.js: -------------------------------------------------------------------------------- 1 | describe('Settings Page', function() { 2 | //var SettingsPage = function () { 3 | // this.get = function () { 4 | // browser.get(protractor.getInstance().baseUrl + 'settings') 5 | // } 6 | //} 7 | }) 8 | -------------------------------------------------------------------------------- /res/test/e2e/widget-container/index.js: -------------------------------------------------------------------------------- 1 | module.exports = function WidgetContainerPage() { 2 | 3 | this.get = function() { 4 | browser.get(browser.baseUrl + 'devices') 5 | browser.wait(waitUrl(/devices/), 5000) 6 | } 7 | 8 | this.userName = element(by.binding('currentUser.name')) 9 | this.amountOfAssignedToUserDevices = element(by.xpath('//*[@class="number color-orange"]/span')) 10 | 11 | this.getUserNameFromWidget = function() { 12 | return this.userName.getText() 13 | } 14 | 15 | this.getAmountOfAssignedToUserDevices = function() { 16 | return this.amountOfAssignedToUserDevices.getText() 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /res/test/helpers/helper.js: -------------------------------------------------------------------------------- 1 | require('angular') 2 | require('angular-mocks') 3 | -------------------------------------------------------------------------------- /res/test/protractor-appium.conf.js: -------------------------------------------------------------------------------- 1 | var config = require('./protractor.conf').config 2 | 3 | config.seleniumAddress = 'http://localhost:4723/wd/hub' 4 | config.chromeOnly = false 5 | //config.capabilities = { 6 | // platformName: 'iOS', 7 | // deviceName: 'iPhone Simulator', 8 | // browserName: 'Safari' 9 | //} 10 | 11 | config.capabilities = { 12 | platformName: 'Android', 13 | deviceName: '', 14 | browserName: 'Chrome' 15 | } 16 | 17 | module.exports.config = config 18 | -------------------------------------------------------------------------------- /res/web_modules/angular-borderlayout/index.js: -------------------------------------------------------------------------------- 1 | require('angular-borderlayout/src/borderLayout.js') 2 | require('angular-borderlayout/src/borderLayout.css') 3 | require('./style.css') 4 | 5 | module.exports = { 6 | name: 'fa.directive.borderLayout' 7 | } 8 | -------------------------------------------------------------------------------- /res/web_modules/angular-growl/index.js: -------------------------------------------------------------------------------- 1 | require('angular-growl-v2/build/angular-growl.js') 2 | // Using custom CSS 3 | //require('angular-growl-v2/build/angular-growl.min.css') 4 | 5 | module.exports = { 6 | name: 'angular-growl' 7 | } 8 | -------------------------------------------------------------------------------- /res/web_modules/angular-hotkeys/hotkeys.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/res/web_modules/angular-hotkeys/hotkeys.css -------------------------------------------------------------------------------- /res/web_modules/angular-hotkeys/index.js: -------------------------------------------------------------------------------- 1 | require('angular-hotkeys/build/hotkeys.css') 2 | //require('./hotkeys.css') 3 | require('angular-hotkeys/build/hotkeys.js') 4 | 5 | module.exports = { 6 | name: 'cfp.hotkeys' 7 | } 8 | -------------------------------------------------------------------------------- /res/web_modules/angular-ladda/index.js: -------------------------------------------------------------------------------- 1 | 2 | //window.Ladda = require('ladda/js/ladda') 3 | require('angular-ladda/src/angular-ladda') 4 | 5 | module.exports = { 6 | //Ladda: window.Ladda, 7 | name: 'angular-ladda' 8 | } 9 | -------------------------------------------------------------------------------- /res/web_modules/angular-xeditable/index.js: -------------------------------------------------------------------------------- 1 | require('angular-xeditable/dist/js/xeditable.js') 2 | require('angular-xeditable/dist/css/xeditable.css') 3 | require('./style.css') 4 | 5 | module.exports = { 6 | name: 'xeditable' 7 | } 8 | -------------------------------------------------------------------------------- /res/web_modules/epoch/index.js: -------------------------------------------------------------------------------- 1 | require('jquery') 2 | 3 | require('d3') 4 | require('epoch/dist/css/epoch.min.css') 5 | require('epoch/dist/js/epoch.min.js') 6 | require('ng-epoch') 7 | 8 | module.exports = { 9 | name: 'ng.epoch' 10 | } 11 | -------------------------------------------------------------------------------- /res/web_modules/gettext/index.js: -------------------------------------------------------------------------------- 1 | require('angular-gettext') 2 | 3 | module.exports = { 4 | name: 'gettext' 5 | } 6 | -------------------------------------------------------------------------------- /res/web_modules/ladda/index.js: -------------------------------------------------------------------------------- 1 | require('ladda/dist/ladda-themeless.min.css') 2 | require('ladda/dist/spin.min.js') 3 | require('ladda/dist/ladda.min.js') 4 | -------------------------------------------------------------------------------- /res/web_modules/ng-context-menu/context-menu.css: -------------------------------------------------------------------------------- 1 | .context-menu { 2 | position: fixed; 3 | z-index: 1000; 4 | } 5 | -------------------------------------------------------------------------------- /res/web_modules/ng-context-menu/index.js: -------------------------------------------------------------------------------- 1 | require('ng-context-menu/dist/ng-context-menu') 2 | require('./context-menu.css') 3 | 4 | module.exports = { 5 | name: 'ng-context-menu' 6 | } 7 | -------------------------------------------------------------------------------- /res/web_modules/ng-file-upload/index.js: -------------------------------------------------------------------------------- 1 | require('ng-file-upload/angular-file-upload-shim') 2 | require('ng-file-upload/angular-file-upload') 3 | 4 | module.exports = { 5 | name: 'angularFileUpload' 6 | } 7 | -------------------------------------------------------------------------------- /res/web_modules/nine-bootstrap/README.md: -------------------------------------------------------------------------------- 1 | nine-bootstrap 2 | ============== 3 | 4 | Bootstrap 3 theme inspired on iOS 9 flat design. 5 | It's being used by [STF](https://github.com/openstf/stf). 6 | 7 | ## Building and Usage 8 | 9 | Compile to CSS using [sass](http://sass-lang.com/documentation/). 10 | 11 | ``` 12 | sass nine-bootstrap.scss 13 | ``` 14 | 15 | Or use with a module bundler like [Webpack](http://webpack.github.io) directly. 16 | 17 | ``` 18 | require('nine-bootstrap') 19 | ``` 20 | -------------------------------------------------------------------------------- /res/web_modules/nine-bootstrap/index.js: -------------------------------------------------------------------------------- 1 | require('bootstrap/dist/css/bootstrap.css') 2 | 3 | require('nine-bootstrap/nine-bootstrap.scss') 4 | 5 | require('components-font-awesome/css/font-awesome.css') 6 | 7 | require('font-lato-2-subset') 8 | -------------------------------------------------------------------------------- /res/web_modules/ui-bootstrap/index.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2022 contains code contributed by Orange SA, authors: Denis Barbaron - Licensed under the Apache license 2.0 3 | // 4 | 5 | require('script-loader!angular-bootstrap/ui-bootstrap-tpls') 6 | 7 | module.exports = { 8 | name: 'ui.bootstrap' 9 | } 10 | -------------------------------------------------------------------------------- /test/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | }, 5 | "rules": { 6 | "no-unused-expressions": 0 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /test/util/logger.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai') 2 | var expect = chai.expect 3 | 4 | var logger = require('../../lib/util/logger') 5 | 6 | describe('Logger', function() { 7 | it('should have a createLogger method', function() { 8 | expect(logger).itself.to.respondTo('createLogger') 9 | }) 10 | 11 | it('should have a setGlobalIdentifier method', function() { 12 | expect(logger).itself.to.respondTo('setGlobalIdentifier') 13 | }) 14 | }) 15 | -------------------------------------------------------------------------------- /vendor/STFService/STFService.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/vendor/STFService/STFService.apk -------------------------------------------------------------------------------- /vendor/minirev/arm64-v8a/minirev: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/vendor/minirev/arm64-v8a/minirev -------------------------------------------------------------------------------- /vendor/minirev/arm64-v8a/minirev-nopie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/vendor/minirev/arm64-v8a/minirev-nopie -------------------------------------------------------------------------------- /vendor/minirev/armeabi-v7a/minirev: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/vendor/minirev/armeabi-v7a/minirev -------------------------------------------------------------------------------- /vendor/minirev/armeabi-v7a/minirev-nopie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/vendor/minirev/armeabi-v7a/minirev-nopie -------------------------------------------------------------------------------- /vendor/minirev/armeabi/minirev: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/vendor/minirev/armeabi/minirev -------------------------------------------------------------------------------- /vendor/minirev/armeabi/minirev-nopie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/vendor/minirev/armeabi/minirev-nopie -------------------------------------------------------------------------------- /vendor/minirev/mips/minirev: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/vendor/minirev/mips/minirev -------------------------------------------------------------------------------- /vendor/minirev/mips/minirev-nopie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/vendor/minirev/mips/minirev-nopie -------------------------------------------------------------------------------- /vendor/minirev/mips64/minirev: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/vendor/minirev/mips64/minirev -------------------------------------------------------------------------------- /vendor/minirev/mips64/minirev-nopie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/vendor/minirev/mips64/minirev-nopie -------------------------------------------------------------------------------- /vendor/minirev/x86/minirev: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/vendor/minirev/x86/minirev -------------------------------------------------------------------------------- /vendor/minirev/x86/minirev-nopie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/vendor/minirev/x86/minirev-nopie -------------------------------------------------------------------------------- /vendor/minirev/x86_64/minirev: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/vendor/minirev/x86_64/minirev -------------------------------------------------------------------------------- /vendor/minirev/x86_64/minirev-nopie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeviceFarmer/stf/4192eb3ea1084039ebe29c585931a570840af03e/vendor/minirev/x86_64/minirev-nopie --------------------------------------------------------------------------------