From 1dc2c1a2476d154ffe2032d031445b3553aa560f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20Norman=20Hauk=C3=A5s?= Date: Sun, 7 Aug 2016 13:49:33 +0200 Subject: [PATCH] Add material design and settings page. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Squashed commit of the following: commit 8eaac39b94663e32659e41dde211a197cfdf567f Author: Nils Norman Haukås Date: Sun Aug 7 13:46:56 2016 +0200 Prepare new feature for plugification Menu.tpl.html now references chrome plugin file resources for material design. Adjusted build step to copy material design styles and such. Whitelisted web accessible resources in manifest.json. Bump version number. commit a2662042904ee69613b75fc1bebb188c9783f414 Author: Nils Norman Haukås Date: Sun Aug 7 12:54:27 2016 +0200 Use parameter properties commit 888e3511212eca705585651f4d9286502b5c05b6 Author: Nils Norman Haukås Date: Sun Aug 7 12:45:51 2016 +0200 Post tags to configurable endpoint User can now specify the url where tags should be posted. commit f4adda15223bba3044184d4a0780387051828958 Author: Nils Norman Haukås Date: Sun Aug 7 07:06:30 2016 +0200 Rename to settings service commit 5646a8dabab740267181d0d87ec369bbdabe42e5 Author: Nils Norman Haukås Date: Sun Aug 7 07:02:36 2016 +0200 Reworked settings Replaced index.Appconfig.ts with appConfig.service. This paves way for an adjustable settingspage. commit 63c7d5bfa2029702ba5e4eafa462436f5e547afa Author: Nils Norman Haukås Date: Sun Aug 7 07:01:57 2016 +0200 Update angular.js version to 1.5.8 commit bcee26ccda036abdb90a98121dab3bd1e0e39fcc Author: Nils Norman Haukås Date: Thu Jul 14 22:00:26 2016 +0200 removed browsersync notification commit 71b0c3a1c735c1b2293c21a756f0bf05f85ccacc Author: Nils Norman Haukås Date: Thu Jul 14 21:58:12 2016 +0200 Added spinner, started settings page commit fd0b16a146c7f633f354ed4f8c69754d9b66cfdd Author: Nils Norman Haukås Date: Mon Jun 27 21:50:50 2016 +0200 Include material-design-lite, started building settings page. --- build.sh | 4 + config.js | 2 +- package.json | 5 +- src/app/index.appConfig.ts | 9 -- src/app/main.ts | 16 ++-- src/app/menu/menu.controller.ts | 63 +++++++------- src/app/menu/menu.tpl.html | 115 +++++++++++++++++++------ src/app/menu/settings.controller.ts | 51 +++++++++++ src/app/services/backend.service.ts | 36 ++------ src/app/services/file.service.ts | 7 +- src/app/services/index.ts | 1 + src/app/services/settings.service.ts | 93 ++++++++++++++++++++ src/app/services/tagStorage.service.ts | 9 +- src/app/services/webpage.service.ts | 19 ++-- src/plugin-specific/manifest.json | 5 +- test/index.html | 3 +- 16 files changed, 301 insertions(+), 137 deletions(-) delete mode 100644 src/app/index.appConfig.ts create mode 100644 src/app/menu/settings.controller.ts create mode 100644 src/app/services/settings.service.ts diff --git a/build.sh b/build.sh index bb7b11e..e8fee15 100755 --- a/build.sh +++ b/build.sh @@ -3,8 +3,12 @@ # Note: The javascript is generated by the # package.json before calling this script. +mkdir dist #ensure there's a folder + #copy styles cp -v src/app/style.css dist/ +cp -v node_modules/material-design-lite/dist/material.css dist/ +cp -v node_modules/material-design-lite/dist/material.js dist/ #copy html menu cp -v src/app/menu/menu.tpl.html dist/ diff --git a/config.js b/config.js index 4dadddd..d9eff6f 100644 --- a/config.js +++ b/config.js @@ -14,7 +14,7 @@ System.config({ }, map: { - "angular": "github:angular/bower-angular@1.5.5", + "angular": "github:angular/bower-angular@1.5.8", "jquery": "npm:jquery@2.2.4", "lodash": "npm:lodash@4.12.0", "ngstorage": "npm:ngstorage@0.3.10", diff --git a/package.json b/package.json index e722887..55f9c6b 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "scripts": { "clean": "rm -r dist", "build": "jspm bundle-sfx src/app/main.ts dist/app.js && ./build.sh", - "start": "browser-sync start -b google-chrome --startPath test/ --server --files 'src/**/*'", + "start": "browser-sync start --no-notify -b google-chrome --startPath test/ --server --files 'src/**/*'", "postinstall": "typings install && jspm install" }, "repository": { @@ -28,11 +28,12 @@ "dependencies": { "browser-sync": "^2.9.6", "jspm": "^0.16.39", + "material-design-lite": "^1.1.3", "typings": "^1.3.0" }, "jspm": { "dependencies": { - "angular": "github:angular/bower-angular@^1.5.5", + "angular": "github:angular/bower-angular@^1.5.8", "jquery": "npm:jquery@^2.2.4", "lodash": "npm:lodash@^4.12.0", "ngstorage": "npm:ngstorage@^0.3.10", diff --git a/src/app/index.appConfig.ts b/src/app/index.appConfig.ts deleted file mode 100644 index 08de000..0000000 --- a/src/app/index.appConfig.ts +++ /dev/null @@ -1,9 +0,0 @@ - -export function AppConfigInitializer ($logProvider: ng.ILogProvider) { - $logProvider.debugEnabled(true); -} - -export class AppConfigService { - serverUrl = 'https://imdb.uib.no/lexitags/lexitags/'; -} - diff --git a/src/app/main.ts b/src/app/main.ts index 754fb96..00c136c 100644 --- a/src/app/main.ts +++ b/src/app/main.ts @@ -5,9 +5,10 @@ import { BackendService, WebPageService, TagStorageService, - FileService} from './services/index'; -import {AppConfigInitializer, AppConfigService} from "./index.appConfig"; + FileService, + SettingsService} from './services/index'; import {MenuCtrl} from './menu/menu.controller'; +import {SettingsCtrl} from './menu/settings.controller'; import {preparePage} from './pageRebuilder'; import angular from 'angular'; import 'rangy'; @@ -25,20 +26,13 @@ else { function loadAngular() { angular.module('tagit', ['ngStorage']) - .config(AppConfigInitializer) - .service('AppConfigService', AppConfigService) + .service('SettingsService', SettingsService) .service('BackendService', BackendService) .service('WebPageService', WebPageService) .service('TagStorageService', TagStorageService) .service('FileService', FileService) + .controller('SettingsCtrl', SettingsCtrl) .controller('MenuCtrl', MenuCtrl) - .controller('TestCtrl', function () { - var vm = this; - vm.test = 'hello world'; - vm.alert = function () { - alert('test alert'); - } - }); angular.bootstrap( (document.getElementById("tagit-iframe")) diff --git a/src/app/menu/menu.controller.ts b/src/app/menu/menu.controller.ts index d1e3bf6..e11696a 100644 --- a/src/app/menu/menu.controller.ts +++ b/src/app/menu/menu.controller.ts @@ -13,26 +13,15 @@ export class MenuCtrl { selectedWord = ""; senses: Object[]; - backendService: BackendService; - webPageService: WebPageService; - tagStorageService: TagStorageService; - fileService: FileService; - $log: ng.ILogService; - $scope: ng.IScope; - /* @ngInject */ - constructor($scope: IVMScope, $log: angular.ILogService, - BackendService: BackendService, - WebPageService: WebPageService, - TagStorageService: TagStorageService, - FileService: FileService) { + constructor( + private $scope: IVMScope, + private $log: angular.ILogService, + private BackendService: BackendService, + private WebPageService: WebPageService, + private TagStorageService: TagStorageService, + private FileService: FileService) { $scope.vm = this; - this.$log = $log; - this.$scope = $scope; - this.backendService = BackendService; - this.webPageService = WebPageService; - this.tagStorageService = TagStorageService; - this.fileService = FileService; this.$scope.$on('wordWasSelected', (event, selectedWord) => { this.$log.debug(`Menucontroller received wordWasSelected event for: ${selectedWord}`); @@ -45,12 +34,12 @@ export class MenuCtrl { }); // Reload existing tags - var tagsToLoad = this.tagStorageService.loadTagsForCurrentPage(); + var tagsToLoad = this.TagStorageService.loadTagsForCurrentPage(); this.$log.debug('these tags were found in storage'); this.$log.debug(tagsToLoad); - this.webPageService.readdTagsToPage(tagsToLoad); + this.WebPageService.readdTagsToPage(tagsToLoad); } /** @@ -60,17 +49,17 @@ export class MenuCtrl { onSenseSelect(sense: ISense) { //remove all tags so that new tag range is serialized //based on a document without any highlights - this.webPageService.removeAllTagsFromPage(() => { + this.WebPageService.removeAllTagsFromPage(() => { //initialize and save the new tag - var senseTag = this.webPageService.initializeNewTag(sense); - this.tagStorageService.saveTag(senseTag); + var senseTag = this.WebPageService.initializeNewTag(sense); + this.TagStorageService.saveTag(senseTag); - // deactivate backendService for now. - // this.backendService.sendTaggedDataToServer(senseTag); + // deactivate BackendService for now. + this.BackendService.sendTaggedDataToServer(senseTag); //re-add tags, with new tag. Clear menu options. - this.webPageService.readdTagsToPage( - this.tagStorageService.loadTagsForCurrentPage() + this.WebPageService.readdTagsToPage( + this.TagStorageService.loadTagsForCurrentPage() ); this.clearMenuVariables(); }); @@ -84,7 +73,7 @@ export class MenuCtrl { this.$log.debug('Did not find chrome facilities. Can\'t download.') return; //do nothing } - this.fileService.saveFile(this.tagStorageService.loadTagsForCurrentPage()); + this.FileService.saveFile(this.TagStorageService.loadTagsForCurrentPage()); } downloadAllTagsForDomain() { @@ -92,7 +81,7 @@ export class MenuCtrl { this.$log.debug('Did not find chrome facilities. Can\'t download.') return; //do nothing } - this.fileService.saveFile(this.tagStorageService.loadAllTagsInLocalStorage()); + this.FileService.saveFile(this.TagStorageService.loadAllTagsInLocalStorage()); } /** @@ -100,23 +89,24 @@ export class MenuCtrl { */ removeTagsFromLocalStorage() { if (confirm('Really delete tags from the current page?')) { - this.webPageService.removeAllTagsFromPage(() => { - this.tagStorageService.deleteTagsFromCurrentPage() + this.WebPageService.removeAllTagsFromPage(() => { + this.TagStorageService.deleteTagsFromCurrentPage() }) } } onWordSelectedEvent = (newWord: string) => { if (countWords(newWord) > 2) { - this.selectedWord = "Wops! Plugin can't handle more than two words."; - this.senses = []; + this.selectedWord = "Wops! Plugin can't handle more than two words." + this.senses = [] } else if (newWord.length === 0) { this.clearMenuVariables(); } else { this.selectedWord = newWord; - this.backendService.callServer(newWord) + this.senses = [] + this.BackendService.callServer(newWord) .then((synsets: any) => { this.$log.debug(synsets); this.senses = synsets.data.senses; @@ -138,4 +128,9 @@ export class MenuCtrl { this.senses = []; } + isLoadingSenses() { + // if senses var has initialized, we check length to see if they've been loaded. + return this.senses && this.senses.length == 0 && this.selectedWord + } + } diff --git a/src/app/menu/menu.tpl.html b/src/app/menu/menu.tpl.html index c61557c..03f983b 100644 --- a/src/app/menu/menu.tpl.html +++ b/src/app/menu/menu.tpl.html @@ -3,9 +3,19 @@ - - - + -
-

Tag you're it

- -

Menu: - Download tags (current page) | - Download all tags (domain) | - Delete tags from current page -

+
-

- Mark one or two words on the page to the right. And we'll supply you with possible definitions. Select a definition and the - word will be tagged. -

+
+ +
-

- Currently selected word: {{vm.selectedWord}} -

+
- +
-
    -
  • - {{sense.word}} {{sense.explanation}} -
  • -
+
+ +

Actions: + Download tags (current page) | + Download all tags (domain) | + Delete tags from current page +

+ +

+ Mark one or two words on the page to the right. And we'll supply you with possible definitions. Select a definition and the + word will be tagged. +

+ +

+ Currently selected word: {{vm.selectedWord}} +

+ +

+ Currently selected word: No word selected. +

+ +
+
+
+ +
    + +
  • + Available sense tags: +
  • + +
  • + {{sense.word}} {{sense.explanation}} +
  • +
+ +
+ +
+ +
+ +

Changes will be automatically saved.

+ +
+ +

+ + +
+ As you go about tagging pages the tags will be posted to this server endpoint. +

+ +

+ + +
+ The email that will be included in the tag when it's sent to the server. +

+ +
+ +

Reset to default settings

+ +
+
+ \ No newline at end of file diff --git a/src/app/menu/settings.controller.ts b/src/app/menu/settings.controller.ts new file mode 100644 index 0000000..9ea678e --- /dev/null +++ b/src/app/menu/settings.controller.ts @@ -0,0 +1,51 @@ +'use strict'; + +import { + BackendService, + WebPageService, + TagStorageService, + FileService, + SettingsService} from '../services/index' +import {IVMScope, ISense} from '../index.interfaces' + +/** + * Responsible for making settings user editable + * and communicating those settings changes to + * chrome extension background page. + */ +export class SettingsCtrl { + + serverToSendTo + senseQueryUrl + + constructor( + private $scope: IVMScope, + $log: angular.ILogService, + BackendService: BackendService, + WebPageService: WebPageService, + TagStorageService: TagStorageService, + private SettingsService: SettingsService) { + + $scope.vm = this; + this.serverToSendTo = SettingsService.senseDestinationUrl + this.senseQueryUrl = SettingsService.senseQueryUrl + + $scope.$watch('vm.serverToSendTo', (newValue: string, oldValue) => { + SettingsService.senseDestinationUrl = newValue; + }) + + } + + resetDefaults() { + + if (!confirm('Reset settings to default values?')) { + return //exit if user says 'no' + } + + this.SettingsService.resetSettings(() => { + this.serverToSendTo = this.SettingsService.senseDestinationUrl + }); + } + + +} \ No newline at end of file diff --git a/src/app/services/backend.service.ts b/src/app/services/backend.service.ts index e584046..6ba2837 100644 --- a/src/app/services/backend.service.ts +++ b/src/app/services/backend.service.ts @@ -1,6 +1,6 @@ 'use strict'; -import {AppConfigService} from '../index.appConfig'; +import {SettingsService} from '../services/index'; import {ISenseTag} from '../index.interfaces'; /** @@ -9,18 +9,13 @@ import {ISenseTag} from '../index.interfaces'; */ export class BackendService { - $http: ng.IHttpService; - $log: ng.ILogService; - $q: ng.IQService; - private serverUrl: string = null; - private previousCall: string; + private previousCall: string - /* @ngInject */ - constructor($http: ng.IHttpService, $q: ng.IQService, $log: ng.ILogService, AppConfigService: AppConfigService) { - this.$http = $http; - this.$log = $log; - this.$q = $q; - this.serverUrl = AppConfigService.serverUrl; + constructor( + private $http: ng.IHttpService, + private $q: ng.IQService, + private $log: ng.ILogService, + private SettingsService: SettingsService) { } callServer(word: string) { @@ -34,25 +29,12 @@ export class BackendService { //alright let's make this query! this.previousCall = word; - return this.$http.get(this.serverUrl + word); + return this.$http.get(`${this.SettingsService.senseQueryUrl}/${word}`); } sendTaggedDataToServer(senseTag: ISenseTag) { this.$log.debug('sendTaggedDataToServer() was called'); - - this.$log.debug('would have sent this to the server:'); - this.$log.debug(senseTag); - this.$log.debug('please uncomment code for actually sending to server'); - - // this.$http.post("example.org", senseTag) - // .then((response) => { - // this.$log.debug('successfully posted to server. Response:'); - // this.$log.debug(response); - // }) - // .catch((error) => { - // this.$log.error('something went wrong when posting to server'); - // this.$log.error(error); - // }); + return this.$http.post(this.SettingsService.senseDestinationUrl, senseTag) } } \ No newline at end of file diff --git a/src/app/services/file.service.ts b/src/app/services/file.service.ts index 4116aa1..2512afb 100644 --- a/src/app/services/file.service.ts +++ b/src/app/services/file.service.ts @@ -5,12 +5,7 @@ import {ISenseTag} from '../index.interfaces'; //Responsible for saving. export class FileService { - $log: ng.ILogService; - - /* @ngInject */ - constructor($log: ng.ILogService) { - this.$log = $log; - } + constructor(private $log: ng.ILogService) {} saveFile(content: ISenseTag[]) { var json = JSON.stringify(content, null, 2); diff --git a/src/app/services/index.ts b/src/app/services/index.ts index a08e074..6a606fc 100644 --- a/src/app/services/index.ts +++ b/src/app/services/index.ts @@ -2,3 +2,4 @@ export * from './backend.service'; export * from './file.service'; export * from './tagStorage.service'; export * from './webpage.service'; +export * from './settings.service'; diff --git a/src/app/services/settings.service.ts b/src/app/services/settings.service.ts new file mode 100644 index 0000000..2961f63 --- /dev/null +++ b/src/app/services/settings.service.ts @@ -0,0 +1,93 @@ +/** + * Responsible for handling persisting and retrieving + * *select* user settings. Some settings might not be user + * editable. + */ +export class SettingsService { + + // where to query for senses + private _senseQueryUrl = 'https://imdb.uib.no/lexitags/lexitags' + private _defaultSenseQueryUrl = 'https://imdb.uib.no/lexitags/lexitags' + + // where to send the senses + private _senseDestinationUrl = 'https://www.example.org/somewhere' + private _defaultSenseDestinationUrl = 'https://www.example.org/somewhere' + + private _emailToTagWith = '' + + constructor(private $log: ng.ILogService) { + + // fall back to default value if no user defined setting + this.loadSetting('tagitSenseQueryUrl', (loadedSetting) => { + if (loadedSetting) this._senseQueryUrl = loadedSetting + else this._senseQueryUrl = this._defaultSenseQueryUrl + }) + + this.loadSetting('tagitSenseDestinationUrl', (loadedSetting) => { + if (loadedSetting) this._senseDestinationUrl = loadedSetting + else this._senseDestinationUrl = this._defaultSenseDestinationUrl + }) + + } + + resetSettings(callback) { + + // reset to default values + this._defaultSenseQueryUrl = this._defaultSenseQueryUrl + this._senseDestinationUrl = this._defaultSenseDestinationUrl + + // delete from chrome storage + if (typeof chrome.storage !== 'undefined') { + const done = _.after(2, callback); + chrome.storage.sync.remove('tagitSenseDestinationUrl', done) + chrome.storage.sync.remove('tagitSenseQueryUrl', done) + } + // delete from localstorage (dev mode) + else { + localStorage.removeItem('tagitSenseQueryUrl') + localStorage.removeItem('tagitSenseDestinationUrl') + callback() + } + } + + private loadSetting(whatToFind: string, callback) { + // support for dev mode (when not loaded as a proper chrome plugin). + if (typeof chrome.storage === 'undefined') { + callback(localStorage.getItem(whatToFind)) + return // exit function + } + + const syncStorage = chrome.storage.sync + syncStorage.get(whatToFind, callback) + } + + private saveSetting(nameOfThingToSave: string, valueToSave) { + // support for dev mode (when not loaded as a proper chrome plugin). + if (typeof chrome.storage === 'undefined') { + localStorage.setItem(nameOfThingToSave, valueToSave) + return // exit function + } + + const syncStorage = chrome.storage.sync + syncStorage.set({ nameOfThingToSave: valueToSave }) + } + + get senseQueryUrl() { + return this._senseQueryUrl + } + + set senseQueryUrl(newUrl: string) { + this._senseQueryUrl = newUrl + } + + get senseDestinationUrl() { + return this._senseDestinationUrl + } + + set senseDestinationUrl(newUrl: string) { + this._senseDestinationUrl = newUrl + this.saveSetting('tagitSenseDestinationUrl', newUrl) + } + +} + diff --git a/src/app/services/tagStorage.service.ts b/src/app/services/tagStorage.service.ts index c6e2ecb..5357a09 100644 --- a/src/app/services/tagStorage.service.ts +++ b/src/app/services/tagStorage.service.ts @@ -6,15 +6,12 @@ import {ISenseTag} from '../index.interfaces'; // any tags related to the current page export class TagStorageService { - $http: ng.IHttpService; - $log: ng.ILogService; $localStorage: { tagStorage: ISenseTag[] }; - /* @ngInject */ - constructor($http: ng.IHttpService, $log: ng.ILogService, + constructor( + private $http: ng.IHttpService, + private $log: ng.ILogService, $localStorage: any) { - this.$http = $http; - this.$log = $log; this.$localStorage = $localStorage; if (window.location.href.indexOf("tagitreset") !== -1) { diff --git a/src/app/services/webpage.service.ts b/src/app/services/webpage.service.ts index 997c608..d4f8914 100644 --- a/src/app/services/webpage.service.ts +++ b/src/app/services/webpage.service.ts @@ -14,20 +14,17 @@ import rangy from 'rangy'; */ export class WebPageService { - $log: ng.ILogService; // when clicking the menu to select a synset // we need to remember what the currently selected word was - tagStorageService: TagStorageService; - rootScopeService: ng.IRootScopeService; savedSelection: Object; savedText: string; listOfFramesWithContent: (HTMLFrameElement | HTMLIFrameElement)[] = []; - /* @ngInject */ - constructor($log: ng.ILogService, TagStorageService: TagStorageService, $rootScope: ng.IRootScopeService) { - this.$log = $log; - this.tagStorageService = TagStorageService; - this.rootScopeService = $rootScope; + constructor( + private $log: ng.ILogService, + private TagStorageService: TagStorageService, + private $rootScope: ng.IRootScopeService) { + this.wireUpListener(); rangy.init(); } @@ -45,17 +42,17 @@ export class WebPageService { } else if (wasRemoveTagButtonClicked(evt)) { this.$log.debug('remove tag button was clicked'); - removeTagFromWebAndStorage(evt, this.tagStorageService); + removeTagFromWebAndStorage(evt, this.TagStorageService); } else if (documentThatWasClicked.getSelection().toString() !== '') { resetSavedSelection(this.savedSelection); this.savedSelection = rangy.saveSelection(documentThatWasClicked); this.savedText = joinLongWords(documentThatWasClicked.getSelection().toString()); - this.rootScopeService.$broadcast('wordWasSelected', this.savedText); + this.$rootScope.$broadcast('wordWasSelected', this.savedText); } else { resetSavedSelection(this.savedSelection); this.savedText = ''; - this.rootScopeService.$broadcast('wordWasDeSelected', null); + this.$rootScope.$broadcast('wordWasDeSelected', null); } /** diff --git a/src/plugin-specific/manifest.json b/src/plugin-specific/manifest.json index bc26b98..4d18b81 100644 --- a/src/plugin-specific/manifest.json +++ b/src/plugin-specific/manifest.json @@ -1,7 +1,7 @@ { "name": "Tag you're it", "description": "A browser tool for tagging words with exact definitions.", - "version": "0.0.9", + "version": "1.0.0", "manifest_version": 2, "icons": { "16": "icon16.png", @@ -20,8 +20,7 @@ "web_accessible_resources": [ "*.html", "*.css", - "vendor/**/*.js", - "bundle.js" + "*.js" ], "browser_action": { "default_icon": "icon48.png" diff --git a/test/index.html b/test/index.html index 25df4db..1a26639 100644 --- a/test/index.html +++ b/test/index.html @@ -8,12 +8,11 @@ -