シェルスクリプトを利用して、tsファイルの先頭にimport文を差し込む
tsファイル内に文字列angular
が存在する場合、ファイルの先頭にimport * as angular from 'angular;
を追加。
# 改行コード LF=$'\\\x0A' # 結果を配列に files=(`find ./client/{app,components} -type f -name "*.ts" -print0 | xargs -0 grep "angular" -l`) for i in "${files[@]}" # 各ファイルの1行目に差し込む do sed -i '' -e "1s/^/import * as angular from 'angular';"$LF"/" $i; # 終了 done;
参考
GithubのLabel設定 Export, Import
Getting Started | GitHub Developer Guide
Create an OAuth token
2段階認証をしている場合。
curl -i -u ${your_username} -H "X-GitHub-OTP: ${your_2fa_OTP_code}" -d '{"scopes": ["repo"], "note": "labels"}' https://api.github.com/authorizations
https://github.com/settings/tokens からでもおk
Export
curl -i -H "Authorization: token ${token}" https://api.github.com/repos/:owner/:repo/labels
https://developer.github.com/v3/issues/labels/#list-all-labels-for-this-repository
Import
curl -i -H "Authorization: token ${token}" -d '{ "name": "foo", "color": "ff0000" }' https://api.github.com/repos/${owner}/${repo}/labels ...
https://developer.github.com/v3/issues/labels/#create-a-label
テーブルとデータ
これは何か
データテーブルを表示する場合、どのようなデータの型が利用しやすいか、について整理してみました。
参考にしたのは以下2つのライブラリ
例
以下のようなテーブルを表示したい。
ID | Date | Name | Age |
---|---|---|---|
1 | March 5, 2017 | Foo | 26 |
2 | March 6, 2017 | Bar | 31 |
データのみ用意
配列
const data = [ [1, 'March 5, 2017', 'Foo', 26], [2, 'March 6, 2017', 'Bar', 31] ];
- 一番シンプル
- カラムタイトルなどは別途用意する必要がある(Htmlのテンプレート内など)
オブジェクト
const data = [ { id: 1, date: 'March 5, 2017', name: 'foo', age: 26}, { id: 2, date: 'March 6, 2017', name: 'bar', age: 31}, ];
- 1行目を利用して、カラムタイトルを作成
- オブジェクトだからカラム項目の順番は保証できないはず
データとカラム用の設定データ
- 汎用性が高いのはこっち
配列
const data = [ [1, 'March 5, 2017', 'Foo', 26], [2, 'March 6, 2017', 'Bar', 31] ]; const columns = [ { name: 'ID'}, { name: 'Date'}, { name: 'Name'}, { name: 'Age'} ];
オブジェクト
const data = [ { id: 1, date: 'March 5, 2017', name: 'foo', age: 26}, { id: 2, date: 'March 6, 2017', name: 'bar', age: 31}, ]; const columns = [ { field: 'id', name: 'ID' }, { field: 'date', name: 'Date' }, { field: 'name', name: 'Name' }, { field: 'age', name: 'Age' } ];
- カラムタイトル(name)とプロパティ名(field)を別にできる
const data = [ { id: 1, date: 'March 5, 2017', customer: { name: 'foo', age: 26 } }, { id: 2, date: 'March 6, 2017', customer: { name: 'bar', age: 31} }, ]; const columns = [ { field: 'id', name: 'ID' }, { field: 'date', name: 'Date' }, { field: 'customer.name', name: 'Name' }, { field: 'customer.age', name: 'Age' } ];
- データのネストなども対応可能
複雑なテーブル
カラム設定データを用意する場合、以下の機能の実現も汎用的にできそう。
- ソート機能のオンオフ
- 合計値の表示
- 平均値の表示
- データと表示内容の変更
2017-03-05
->March 5, 2017
or2017年3月5日
UI-Gridだとこのような感じで設定を追加しています。
// http://ui-grid.info/docs/#/tutorial/105_footer $scope.gridOptions = { showGridFooter: true, showColumnFooter: true, enableFiltering: true, columnDefs: [ { field: 'name', width: '13%' }, { field: 'address.street',aggregationType: uiGridConstants.aggregationTypes.sum, width: '13%' }, { field: 'age', aggregationType: uiGridConstants.aggregationTypes.avg, aggregationHideLabel: true, width: '13%' }, { name: 'ageMin', field: 'age', aggregationType: uiGridConstants.aggregationTypes.min, width: '13%', displayName: 'Age for min' }, { name: 'ageMax', field: 'age', aggregationType: uiGridConstants.aggregationTypes.max, width: '13%', displayName: 'Age for max' }, { name: 'customCellTemplate', field: 'age', width: '14%', footerCellTemplate: '<div class="ui-grid-cell-contents" style="background-color: Red;color: White">custom template</div>' }, { name: 'registered', field: 'registered', width: '20%', cellFilter: 'date', footerCellFilter: 'date', aggregationType: uiGridConstants.aggregationTypes.max } ], data: data, onRegisterApi: function(gridApi) { $scope.gridApi = gridApi; } };
angular-translate読み直し
半年前にまとめたもの。こっちに転載。
これは何か
- 実際に仕事でi18n対応した時に調べたことのメモと設定例
- https://angular-translate.github.io/docs/#/guide を読んで、必要そうな情報を逆引きっぽくまとめたもの
設定例
/*@ngInject*/ export function translateConfig($translateProvider) { $translateProvider // angular-translate-loader-static-files // assets/lang/[langKey].json から非同期で言語ファイルを読み込む .useStaticFilesLoader({ prefix: 'assets/lang/', suffix: '.json' }) // 言語keyの設定 .registerAvailableLanguageKeys(['en', 'ja'], { // en_US などは en と認識させる 'en_*': 'en', 'ja_*': 'ja', // そのほかの言語keyは全て en にする '*': 'en' }) // ブラウザ環境から優先言語を自動取得 // (以前に設定されたkeyがあれば、そちらを優先する <- angular-translate-storage-local利用時) .determinePreferredLanguage() // enable escaping of HTML // https://angular-translate.github.io/docs/#/guide/19_security .useSanitizeValueStrategy('escape') // angular-translate-handler-log .useMissingTranslationHandlerLog() // angular-translate-storage-local .useLocalStorage(); }
以下3つのextensionを利用している
- angular-translate-loader-static-files
- 非同期読み込み
- angular-translate-handler-log
- 対応するメッセージがない場合にエラーを表示
- angular-translate-storage-local
逆引き
言語ファイル(JSON)の書き方
- 通常:
{ "TRANSLATION_ID": "This is a concrete translation for a specific language." }
- ショートカット:
// bar.foo でアクセス可 { "bar": { "foo": { "foo": "This is my text." } } }
- リンク(いい機能だなあ):
{ "SOME_NAMESPACE": { "OK_TEXT": "OK" }, "ANOTHER_NAMESPACE": { "OK_TEXT": "@:SOME_NAMESPACE.OK_TEXT" } }
参考: https://angular-translate.github.io/docs/#/guide/02_getting-started
$translate利用時に、非同期読み込みされたメッセージを反映
- Two-way binding されないので 明示的に処理を書く必要がある
$translateChangeSuccess
を利用
/*@ngInject*/ app.controller('Ctrl', ($scope, $translate, $rootScope) => { $rootScope.$on('$translateChangeSuccess', () => { $translate('HEADLINE').then( // 成功 translation => $scope.headline = translation, // 失敗 translationId => $scope.headline = translationId ); }); });
参考: https://angular-translate.github.io/docs/#/guide/03_using-translate-service
変数を利用
言語JSONファイル:
{ "TRANSLATION_ID": "{{username}} is logged in." }
$translate利用時
$translate('TRANSLATION_ID', { username: 'PascalPrecht' });
$filter利用時
パターン1:
<div>{{ 'TRANSLATION_ID' | translate:'{ username: "PascalPrecht" }' }}</div>
パターン2:
<div>{{ 'TRANSLATION_ID' | translate:translationData }}</div>
angular.module('myApp') /*@ngInject*/ .controller('Ctrl', ($scope) => { $scope.translationData = { username: 'PascalPrecht' }; });
そのほかの方法もある
参考: https://angular-translate.github.io/docs/#/guide/06_variable-replacement
設定されている言語を取得
$rootScope.$on('$translateChangeEnd', (event, args) => { // args.language }); // or $translate.proposedLanguage() || $translate.use() // proposedLanguage() -> 非同期読み込み中の言語keyを取得
利用言語を設定する
preferredLanguage
を利用- ブラウザ環境から優先言語を自動取得する場合は
determinePreferredLanguage
を利用- (内部的に
navigator.languages[0]
navigator.language
などを利用している)
- (内部的に
参考: https://angular-translate.github.io/docs/#/guide/07_multi-language
en_US
en_SG
などをen
として扱う
registerAvailableLanguageKeys
を利用
参考: https://angular-translate.github.io/docs/#/guide/09_language-negotiation
Unit Testing
非同期読み込みをしている場合、ローダー書き換える
beforeEach(module('app', ($provide, $translateProvider) => { $provide.factory('customLoader', $q => () => $q.resolve() ); $translateProvider.useLoader('customLoader'); }));
アプリを起動させる時の流れ
- we register a asynchronous loader
- we define our preferred language
- $translate service is instantiated the first time it gets injected
- angular-translate notices that there’s no language locally available
- it looks if there’s a registered asynchronous loader
- the asynchronous loader is called with the preferred language locale
- the translation data is loaded and ready to be used
参考: https://angular-translate.github.io/docs/#/guide/22_unit-testing-with-angular-translate
タイピングの練習
最近はじめた。仕事の前のウォーミングアップにちょうどよかったりする。
webpack2にした
今の開発環境ではwebpackに任せているタスクが少ないため、かなり簡単に移行できた。
grunt-webpack
を利用してるのでこれもv2に変更。
GitHub - webpack-contrib/grunt-webpack: integrate webpack into grunt build process
webpackで処理が止まってしまったので、keepalive: true
を追加して完了。
(以前から必要だったような気もしないではない)
ユニットテスト(Karma)もTypeScriptで: karma-webpack編
以前の記事
ユニットテスト(Karma)もTypeScriptで - ryotah’s blog
これだと、モジュールのimportができないねえ。
というわけでkarma-webpackを試そうと思います。
GitHub - webpack-contrib/karma-webpack: Use webpack with karma.
テスト環境は Karma Chrome Jasmine。
// karma.conf.js var webpackConfig = require('./webpack.config'); module.exports = function(config) { config.set({ mime: { 'text/x-typescript': ['ts','tsx'] }, basePath: '', frameworks: ['jasmine'], patterns to load in the browser files: [ 'test/**/*.spec.ts' ], exclude: [ ], preprocessors: { 'test/**/*.spec.ts': ['webpack'], }, webpack: { module: webpackConfig.module, resolve: webpackConfig.resolve }, reporters: ['progress'], port: 9876, colors: true, logLevel: config.LOG_INFO, autoWatch: true, browsers: ['Chrome'], singleRun: false, concurrency: Infinity }) }
基本的にはkarm init
でkarma.conf.jsを生成した後、 preprocessors
とwebpack
の部分を追加するだけでおk。
これに加えて、Chromeでテストが実行されなかったので mime: {'text/x-typescript': ['ts','tsx']}
の設定も追加しています。
ng test ends with "Executed 0 of 0 ERROR" · Issue #2838 · angular/angular-cli · GitHub
他のファイルも参考程度に。
. ├── karma.conf.js ├── node_modules ├── package.json ├── src ├── test ├── tsconfig.json └── webpack.config.js
// package.json { "name": "webpack2-karm", // (省略) "devDependencies": { "@types/jasmine": "^2.5.43", "jasmine-core": "^2.5.2", "karma": "^1.5.0", "karma-chrome-launcher": "^2.0.0", "karma-jasmine": "^1.1.0", "karma-webpack": "^2.0.2", "ts-loader": "^2.0.1", "typescript": "^2.2.1", "webpack": "^2.2.1" } }
// tsconfig.json { "compilerOptions": { "target": "es5", "module": "commonjs" }, "exclude": [ "node_modules" ] }
// webpack.config.js var path = require('path'); module.exports = { entry: './src/foo', output: { path: path.resolve(__dirname, 'dist'), filename: 'foo.bundle.js' }, resolve: { extensions: ['.ts', '.tsx', '.js'] }, module: { rules: [ { test: /\.tsx?$/, use: 'ts-loader' } ] } }