Skip to content

Commit

Permalink
Merge pull request #173 from jniles/feature-language-service
Browse files Browse the repository at this point in the history
chore(languages): implement a LanguageService
  • Loading branch information
DedrickEnc committed Mar 9, 2016
2 parents 9dabe60 + 5c1727b commit e6d44cd
Show file tree
Hide file tree
Showing 9 changed files with 159 additions and 83 deletions.
104 changes: 104 additions & 0 deletions client/src/js/services/LanguageService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
angular.module('bhima.services')
.service('LanguageService', LanguageService);

LanguageService.$inject = [
'$http', '$q', 'util', 'AppCache', '$translate', 'tmhDynamicLocale', 'amMoment'
];

/**
* Language Service
*
* A cross-controller service to manage lanuages throughout the application.
* Supports getter and setter methods.
* @constructor
*/
function LanguageService($http, $q, util, AppCache, $translate, Locale, Moment) {
var service = this;

/** language settings are stored in the application settings */
var cache = AppCache('settings');

/** object to cache the list of supported languages */
var languages = {};

/** sets the current language */
service.set = set;

/** retrieves the current language */
service.get = get;

/** retrieves the languages from the backend */
service.read = read;

/**
* set the current application language to the key passed in and caches the
* language key for later lookups. Finally, it sets the translate
*
* @param {string} key - the language key to set the language
*/
function set(key) {

// retrieve the language object
var language = languages[key];

// cache the key
cache.key = key;

// set the language key
service.key = key;

// translate the application using the key
$translate.use(language.key);

// change the date/time locale using the localeKey
Locale.set(language.localeKey);

// change angular-moment's language based on the key
Moment.changeLocale(language.key);
}

/** returns the current application language object */
function get() {
return languages[service.key];
}

/**
* Reads the languages from the database table and populates the internal
* languages object.
*
* @method read
* @public
* @param {boolean} refresh - refreshes the languages if necessary
* @returns {promise} languages - the langauge object
*/
function read(refresh) {

var loadCachedData =
!(angular.equals(languages, {}) || refresh);

// if we have
if (loadCachedData) {
return $q.when(languages);
}

// load languages from the database
return $http.get('/languages')
.then(util.unwrapHttpResponse)
.then(function (langs) {

// bind langauges to service in the form of { key : languageObject }
languages = langs.reduce(function (map, lang) {
map[lang.key] = lang;
return map;
}, {});

// load the initial language and preferences based on the cache key
// defaults to 'fr'
set(cache.key || 'fr');

return languages;
});
}

return service;
}
15 changes: 6 additions & 9 deletions client/src/partials/bhima/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ angular.module('bhima.controllers')
.controller('ApplicationController', ApplicationController);

ApplicationController.$inject = [
'$location', '$timeout', '$translate', 'AppCache', 'appstate',
'connect', 'util', 'SessionService', 'tmhDynamicLocale', 'amMoment'
'$location', '$timeout', 'AppCache', 'appstate',
'connect', 'util', 'SessionService', 'LanguageService'
];

function ApplicationController($location, $timeout, $translate, AppCache, appstate, connect, util, Session, tmhDynamicLocale, amMoment) {
function ApplicationController($location, $timeout, AppCache, appstate, connect, util, Session, Languages) {
var vm = this;

// load in the application cache
Expand All @@ -16,12 +16,9 @@ function ApplicationController($location, $timeout, $translate, AppCache, appsta
/** @todo Load sidebar state before angular is bootstraped to remove 'flicker' */
vm.sidebarExpanded = false;

// setup the language
if (cache.language) {
var language = cache.language;
$translate.use(language.translateKey);
tmhDynamicLocale.set(language.localeKey);
}
// set up the languages for the application, including default languages
// the 'true' parameter forces refresh
Languages.read(true);

vm.isLoggedIn = function isLoggedIn() {
return Session.user;
Expand Down
8 changes: 4 additions & 4 deletions client/src/partials/login/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
<span class="caret"></span>
</button>
<ul role="menu" uib-dropdown-menu>
<li role="menuitem" ng-repeat="lang in LoginCtrl.languages track by lang.key">
<a ng-click="LoginCtrl.setLanguage(lang)">{{ lang.name }}</a>
<li role="menuitem" ng-repeat="(key, lang) in LoginCtrl.languages">
<a ng-click="LoginCtrl.languageService.set(key)">{{ lang.name }}</a>
</li>
</ul>
</div>
Expand Down Expand Up @@ -57,11 +57,11 @@ <h4>{{ "AUTH.LOGIN" | translate }}</h4>
<i class="glyphicon glyphicon-home"></i>
</span>
<select name="project" class="form-control" ng-model="LoginCtrl.credentials.project" ng-options="proj.id as proj.name for proj in LoginCtrl.projects">
<option value="" disabled="disabled"> -- {{ "SELECT.PROJECT" | translate }} --</option>
<option value="" disabled="disabled">{{ "SELECT.PROJECT" | translate }}</option>
</select>
</div>
</div>

<div class="form-group">
<button id="submit" class="btn btn-default" type="submit">
{{ "FORM.LOGIN" | translate }}
Expand Down
21 changes: 7 additions & 14 deletions client/src/partials/login/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ angular.module('bhima.controllers')
.controller('LoginController', LoginController);

LoginController.$inject = [
'$scope', '$translate', '$location', '$http', '$timeout', 'appcache', 'appstate', 'SessionService',
'$scope', '$location', '$http', '$timeout', 'appcache', 'appstate', 'SessionService', 'LanguageService'
];

// The login conroller
function LoginController($scope, $translate, $location, $http, $timeout, AppCache, appstate, SessionService) {
function LoginController($scope, $location, $http, $timeout, AppCache, appstate, Session, Languages) {

// this is the View-Model (angular style guide).
var vm = this;
Expand All @@ -18,12 +18,11 @@ function LoginController($scope, $translate, $location, $http, $timeout, AppCach
vm.credentials = {};
vm.error = false;
vm.login = login;
vm.setLanguage = setLanguage;
vm.languageService = Languages;

// load language dependencies
$http.get('/languages')
.then(function (response) {
vm.languages = response.data;
Languages.read()
.then(function (languages) {
vm.languages = languages;
});

// load project dependencies
Expand Down Expand Up @@ -65,7 +64,7 @@ function LoginController($scope, $translate, $location, $http, $timeout, AppCach
.then(function (response) {

// Yay! We are authenticated. Create the user session.
SessionService.create(response.data.user, response.data.enterprise, response.data.project);
Session.create(response.data.user, response.data.enterprise, response.data.project);

cache.project = credentials.project.id;

Expand All @@ -92,10 +91,4 @@ function LoginController($scope, $translate, $location, $http, $timeout, AppCach
$scope.LoginForm.$setPristine();
});
}

// switches languages
function setLanguage(lang) {
$translate.use(lang.key);
cache.language = lang;
}
}
22 changes: 12 additions & 10 deletions client/src/partials/settings/settings.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
<div class="flex-header">
<div class="bhima-title">

<ol class="headercrumb">
<li class="static">{{ "HOME.BHIMA" | translate }}</li>
<li class="title">{{ "SETTINGS.TITLE" | translate }}</li>
</ol>

</div>
</div>

Expand All @@ -15,24 +13,28 @@
<div class="col-md-5">
<div class="form-group">
<label for="select-language">{{ "SETTINGS.LANGUAGE" | translate }}</label>
<select id="select-language" ng-model="SettingsCtrl.settings.language" ng-change="SettingsCtrl.updateLanguage(SettingsCtrl.settings.language)" class="form-control">
<select
id="select-language"
ng-model="SettingsCtrl.settings.language"
ng-change="SettingsCtrl.languageService.set(SettingsCtrl.settings.language)"
ng-options="key as lang.name for (key, lang) in SettingsCtrl.languages"
class="form-control">
<option value="" disabled="disabled" selected>{{ "SELECT.LANGUAGE" | translate }}</option>
<option value="en">{{ "LANGUAGES.ENGLISH" | translate }}</option>
<option value="fr">{{ "LANGUAGES.FRENCH" | translate }}</option>
<option value="ln">{{ "LANGUAGES.LINGALA" | translate }}</option>
</select>
</div>

<div class="form-group">
<label for="select-default"></span> {{ "SETTINGS.HOME_PAGE" | translate }}</label>
<label for="select-default">{{ "SETTINGS.HOME_PAGE" | translate }}</label>
<select id="select-default" class="form-control">
<option selected>{{ "SETTINGS.LAST_PAGE" | translate }}</option>
</select>
</div>
<button

<button
class="btn btn-default"
ng-click="SettingsCtrl.logout()"><span class="glyphicon glyphicon-log-out"></span> {{ "SETTINGS.LOGOUT" | translate }}</button>
ng-click="SettingsCtrl.logout()">
<span class="glyphicon glyphicon-log-out"></span> {{ "SETTINGS.LOGOUT" | translate }}
</button>

</div>
</div>
Expand Down
58 changes: 18 additions & 40 deletions client/src/partials/settings/settings.js
Original file line number Diff line number Diff line change
@@ -1,61 +1,39 @@
angular.module('bhima.controllers')
.controller('settings', Settings);
.controller('settings', SettingsController);

Settings.$inject = [
'$http','$routeParams','$translate','$location','AppCache',
'tmhDynamicLocale','amMoment', 'SessionService', 'store'
SettingsController.$inject = [
'$http', '$routeParams', '$location', 'LanguageService', 'SessionService'
];

function Settings($http, $routeParams, $translate, $location, AppCache, tmhDynamicLocale, amMoment, SessionService, Store) {
function SettingsController($http, $routeParams, $location, Languages, Session) {
var vm = this;

// set up a new appcache namespace
var cache = AppCache('preferences');

// TODO issue discussing DB modelling of languages, quick suggestion (id, label, translateKey, localeKey)
var languageStore = new Store({identifier : 'translateKey'});
var languages = [{
translateKey : 'en',
localeKey : 'en-us',
label : 'English'
}, {
translateKey : 'fr',
localeKey : 'fr-be',
label : 'French'
}, {
translateKey : 'ln',
localeKey : 'fr-cd',
label : 'Lingala'
}];

languageStore.setData(languages);

// the url to return to (using the back button)
vm.url = $routeParams.url || '';

// load settings from the cache
vm.settings = { language : cache.language };

vm.updateLanguage = function updateLanuage(key) {
var language = languageStore.get(key);
// load settings from services
vm.settings = { language : Languages.key };

$translate.use(language.translateKey);
tmhDynamicLocale.set(language.localeKey);
amMoment.changeLocale(language.translateKey);
/** bind the language service for use in the view */
Languages.read()
.then(function (languages) {
vm.languages = languages;
});

cache.language = language;
vm.languageService = Languages;

console.log('Cache:', cache);
};
/** returns a user to the previous url */
vm.back = back;

vm.back = function back() {
function back() {
$location.url(vm.url);
};
}

/** @todo Wrap logout call in a service */
vm.logout = function logout() {
$http.get('/logout')
.then(function () {
SessionService.destroy();
Session.destroy();
$location.url('/login');
});
};
Expand Down
5 changes: 3 additions & 2 deletions server/controllers/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -398,11 +398,12 @@ exports.delete = function del(req, res, next) {

// GET /languages
// TODO - where does this actually belong?
exports.getLanguages = function getLanguages(req, res, next) {
exports.getLanguages = function languages(req, res, next) {
'use strict';

var sql =
'SELECT lang.id, lang.name, lang.key FROM language AS lang;';
'SELECT lang.id, lang.name, lang.key, lang.locale_key AS localeKey ' +
'FROM language AS lang;';

db.exec(sql)
.then(function (rows) {
Expand Down
7 changes: 4 additions & 3 deletions server/models/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -958,9 +958,10 @@ CREATE TABLE `journal_log` (
DROP TABLE IF EXISTS `language`;

CREATE TABLE `language` (
`id` tinyint(3) unsigned NOT NULL,
`name` text NOT NULL,
`key` text NOT NULL,
`id` TINYINT UNSIGNED NOT NULL,
`name` TEXT NOT NULL,
`key` VARCHAR(5) NOT NULL,
`locale_key` VARCHAR(5) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Expand Down
2 changes: 1 addition & 1 deletion server/models/test/data.sql
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ INSERT INTO unit VALUES
(106, 'Depot Management', 'TREE.DEPOTS_MANAGEMENT', 'Depot Management module', 1, '/partials/depots_management/', '/depots_management');

INSERT INTO account_type VALUES (1,'income/expense'),(2,'balance'),(3,'title');
INSERT INTO language VALUES (1,'Francais','fr'),(2,'English','en'),(3,'Lingala','lg');
INSERT INTO language VALUES (1,'Francais','fr', 'fr-be'), (2,'English','en', 'en-us'), (3,'Lingala','lg', 'fr-cd');
INSERT INTO `currency` (`id`, `name`, `format_key`, `symbol`, `note`, `min_monentary_unit`) VALUES (1,'Congolese Francs','fc','Fc',NULL,50.00),(2,'United States Dollars','usd','$',NULL,0.01);

-- locations
Expand Down

0 comments on commit e6d44cd

Please sign in to comment.