dackdive's blog

新米webエンジニアによる技術ブログ。JavaScript(React), Salesforce, Python など

[Salesforce]ApexでPermissionSetの"PermissionsXXX"項目の一覧を取得

ちょいメモ。

参考:PermissionSet | SOAP API 開発者ガイド | Salesforce Developers

f:id:dackdive:20180324030725p:plain

Permissions... から始まる項目がいくつかあるらしいので、Apex で項目一覧を取得してみる。

調べ方

以下を開発者コンソールの Execute Anonymous で実行。ログをダウンロードして USER_DEBUG だけ抽出。

Map<String, Schema.SObjectField> M = Schema.SObjectType.PermissionSet.fields.getMap();

SObjectType t = Schema.getGlobalDescribe().get('PermissionSet');
Map<String,Schema.SObjectField> fields = t.getDescribe().fields.getMap();

for (Schema.SObjectField field : fields.values()) {
    Schema.DescribeFieldResult dfr = field.getDescribe();
    if (dfr.getName().contains('Permissions')) {
        System.debug(dfr.getName() + ' | ' + dfr.getLabel());
    }
}

結果

API 参照名 ラベル
PermissionsEmailSingle メールの送信
PermissionsEmailMass 一括メール送信
PermissionsEditTask ToDo の編集
PermissionsEditEvent 行動の編集
PermissionsExportReport レポートのエクスポート
PermissionsImportPersonal 個人データのインポート
PermissionsDataExport ウィークリーデータのエクスポート
PermissionsManageUsers ユーザの管理
PermissionsEditPublicFilters 公開リストビューの管理
PermissionsEditPublicTemplates 公開テンプレートの管理
PermissionsModifyAllData すべてのデータの編集
PermissionsManageCases ケースの管理
PermissionsMassInlineEdit リストからの一括編集
PermissionsEditKnowledge 記事の管理
PermissionsManageKnowledge Salesforce ナレッジの管理
PermissionsManageSolutions 公開ソリューションの管理
PermissionsCustomizeApplication アプリケーションのカスタマイズ
PermissionsEditReadonlyFields 参照のみ項目の編集
PermissionsRunReports レポート実行
PermissionsViewSetup 設定・定義を参照する
PermissionsTransferAnyEntity 所有権の移行
PermissionsNewReportBuilder レポートビルダー
PermissionsActivateContract 契約の有効化
PermissionsActivateOrder 注文の有効化
PermissionsImportLeads リードのインポート
PermissionsManageLeads リードの管理
PermissionsTransferAnyLead リード所有者の移行
PermissionsViewAllData すべてのデータの参照
PermissionsEditPublicDocuments 公開ドキュメントの管理
PermissionsViewEncryptedData 暗号化されたデータの参照
PermissionsEditBrandTemplates レターヘッドの管理
PermissionsEditHtmlTemplates HTML テンプレートの編集
PermissionsChatterInternalUser Chatter 内部ユーザ
PermissionsManageTranslation 翻訳の管理
PermissionsDeleteActivatedContract 有効契約の削除
PermissionsChatterInviteExternalUsers Chatter に顧客を招待する
PermissionsSendSitRequests 登録情報照会要求の送信
PermissionsManageRemoteAccess 接続アプリケーションを管理する
PermissionsCanUseNewDashboardBuilder ドラッグアンドドロップ ダッシュボードビルダー
PermissionsManageCategories カテゴリの管理
PermissionsConvertLeads リードの取引の開始
PermissionsPasswordNeverExpires パスワード無期限
PermissionsUseTeamReassignWizards チーム再割り当てウィザードの使用
PermissionsEditActivatedOrders 有効化された注文の編集
PermissionsInstallPackaging AppExchange パッケージのダウンロード
PermissionsPublishPackaging AppExchange パッケージのアップロード
PermissionsChatterOwnGroups 新規 Chatter グループの作成および所有
PermissionsEditOppLineItemUnitPrice 商談商品の販売価格の編集
PermissionsCreatePackaging AppExchange パッケージの作成
PermissionsBulkApiHardDelete Bulk API の物理削除
PermissionsSolutionImport ソリューションのインポート
PermissionsManageCallCenters コールセンターの管理
PermissionsManageSynonyms シノニムの管理
PermissionsViewContent ポータルのコンテンツの参照
PermissionsManageEmailClientConfig メールクライアント設定の管理
PermissionsEnableNotifications アウトバウンドメッセージの送信
PermissionsManageDataIntegrations データインテグレーションの管理
PermissionsDistributeFromPersWksp コンテンツ配信の作成
PermissionsViewDataCategories データカテゴリの表示
PermissionsManageDataCategories データカテゴリの管理
PermissionsAuthorApex Apex 開発
PermissionsManageMobile モバイル設定を管理する
PermissionsApiEnabled API の有効化
PermissionsManageCustomReportTypes カスタムレポートタイプの管理
PermissionsEditCaseComments ケースコメントの編集
PermissionsTransferAnyCase ケース所有者の移行
PermissionsContentAdministrator Salesforce CRM Content の管理
PermissionsCreateWorkspaces ライブラリの作成
PermissionsManageContentPermissions コンテンツ権限の管理
PermissionsManageContentProperties コンテンツプロパティの管理
PermissionsManageContentTypes ファイルのレコードタイプおよびレイアウトの管理
PermissionsManageExchangeConfig Lightning Sync を管理
PermissionsManageAnalyticSnapshots レポート作成スナップショットを管理
PermissionsScheduleReports レポートのスケジュール
PermissionsManageBusinessHourHolidays 営業時間の休日の管理
PermissionsManageDynamicDashboards 動的ダッシュボードの管理
PermissionsCustomSidebarOnAllPages すべてのページにカスタムサイドバーを表示
PermissionsManageInteraction フローの管理
PermissionsViewMyTeamsDashboards 私のチームのダッシュボードの参照
PermissionsModerateChatter Chatter のモデレート
PermissionsResetPasswords ユーザパスワードのリセットおよびユーザのロック解除
PermissionsFlowUFLRequired フローユーザ機能ライセンスが必要
PermissionsCanInsertFeedSystemFields Chatter フィードにシステム項目値を挿入
PermissionsManageKnowledgeImportExport ナレッジ記事のインポート/エクスポートの管理
PermissionsEmailTemplateManagement メールテンプレートの管理
PermissionsEmailAdministration メール管理
PermissionsManageChatterMessages Chatter メッセージとダイレクトメッセージを管理
PermissionsAllowEmailIC メールベースの ID 検証オプション
PermissionsChatterFileLink 公開リンクの作成
PermissionsForceTwoFactor ユーザインターフェースログインの 2 要素認証
PermissionsViewEventLogFiles イベントログファイルを参照
PermissionsManageNetworks コミュニティを作成および設定
PermissionsManageAuthProviders 認証プロバイダの管理
PermissionsRunFlow フローを実行
PermissionsCreateCustomizeDashboards ダッシュボードの作成とカスタマイズ
PermissionsCreateDashboardFolders ダッシュボードフォルダを作成
PermissionsViewPublicDashboards 公開フォルダのダッシュボードを参照
PermissionsManageDashbdsInPubFolders 公開フォルダのダッシュボードを管理
PermissionsCreateCustomizeReports レポートの作成とカスタマイズ
PermissionsCreateReportFolders レポートフォルダを作成
PermissionsViewPublicReports 公開フォルダのレポートを参照
PermissionsManageReportsInPubFolders 公開フォルダのレポートを管理
PermissionsEditMyDashboards 私のダッシュボードを編集
PermissionsEditMyReports 私のレポートを編集
PermissionsViewAllUsers すべてのユーザの参照
PermissionsAllowUniversalSearch Knowledge One
PermissionsConnectOrgToEnvironmentHub 環境ハブに組織を接続
PermissionsWorkCalibrationUser Work.com 調整を有効化
PermissionsCreateCustomizeFilters リストビューを作成およびカスタマイズ
PermissionsWorkDotComUserPerm Work.com を有効化
PermissionsGovernNetworks コミュニティを管理する
PermissionsSalesConsole セールスコンソール
PermissionsTwoFactorApi API ログインの 2 要素認証
PermissionsDeleteTopics トピックを削除
PermissionsEditTopics トピックを編集
PermissionsCreateTopics トピックを作成
PermissionsAssignTopics トピックを割り当てる
PermissionsIdentityEnabled Identity 機能を使用
PermissionsIdentityConnect Identity Connect を使用
PermissionsAllowViewKnowledge ナレッジの参照を許可
PermissionsContentWorkspaces ライブラリへのアクセス
PermissionsManageSearchPromotionRules 昇格済み検索語の管理
PermissionsCustomMobileAppsAccess カスタムモバイルアプリケーションにアクセス
PermissionsViewHelpLink ヘルプリンクを参照
PermissionsManageProfilesPermissionsets プロファイルおよび権限セットを管理
PermissionsAssignPermissionSets 権限セットの割り当て
PermissionsManageRoles ロールを管理
PermissionsManageIpAddresses IP アドレスを管理
PermissionsManageSharing 共有を管理
PermissionsManageInternalUsers 内部ユーザを管理
PermissionsManagePasswordPolicies パスワードポリシーを管理
PermissionsManageLoginAccessPolicies ログインアクセスポリシーを管理
PermissionsManageCustomPermissions カスタム権限を管理
PermissionsCanVerifyComment Chatter の質問への回答の確認
PermissionsManageUnlistedGroups 「リストに記載しない」グループを管理
PermissionsModifySecureAgents セキュアエージェントを変更
PermissionsManageTwoFactor API で 2 要素認証を管理
PermissionsChatterForSharePoint Chatter For SharePoint へのアクセス
PermissionsLightningExperienceUser Lightning Experience ユーザ
PermissionsConfigCustomRecs カスタムおすすめの設定
PermissionsSubmitMacrosAllowed ユーザが元に戻せないマクロを管理
PermissionsBulkMacrosAllowed 複数のレコードに対してマクロを実行
PermissionsShareInternalArticles 内部のナレッジ記事を外部と共有
PermissionsManageSessionPermissionSets セッション権限セットの有効化を管理
PermissionsSendAnnouncementEmails お知らせメールを送信
PermissionsChatterEditOwnPost 自分の投稿を編集
PermissionsChatterEditOwnRecordPost 自分の所有レコードへの投稿を編集
PermissionsImportCustomObjects カスタムオブジェクトのインポート
PermissionsDelegatedTwoFactor ユーザインターフェースで 2 要素認証を管理
PermissionsChatterComposeUiCodesnippet UI からのコードスニペットの挿入を許可
PermissionsSelectFilesFromSalesforce Salesforce からファイルを選択
PermissionsModerateNetworkUsers コミュニティユーザモデレート
PermissionsMergeTopics トピックのマージ
PermissionsSubscribeToLightningReports レポートを登録
PermissionsManagePvtRptsAndDashbds すべての非公開レポートおよびダッシュボードを管理
PermissionsAllowLightningLogin Lightning Login ユーザ
PermissionsCampaignInfluence2 キャンペーンインフルエンス
PermissionsViewDataAssessment データ評価の参照アクセス権
PermissionsRemoveDirectMessageMembers ダイレクトメッセージから人を削除
PermissionsCanApproveFeedPost フィード投稿とコメントを承認可能
PermissionsAddDirectMessageMembers ダイレクトメッセージに人を追加
PermissionsAllowViewEditConvertedLeads 取引開始済みのリードを表示および編集
PermissionsShowCompanyNameAsUserBadge コミュニティロールとして会社名を表示
PermissionsAccessCMC コミュニティ管理にアクセス
PermissionsViewHealthCheck 状態チェックを表示
PermissionsManageHealthCheck 状態チェックを管理
PermissionsPackaging2 第二世代パッケージの作成と更新
PermissionsManageCertificates 証明書を管理
PermissionsCreateReportInLightning レポートビルダー (Lightning Experience)
PermissionsPreventClassicExperience Salesforce Classic に切り替えるオプションを非表示
PermissionsHideReadByList [表示先] リストを非表示
PermissionsListEmailSend リストメールの送信を許可
PermissionsFeedPinning フィードでの投稿の固定
PermissionsChangeDashboardColors ダッシュボードの色を変更
PermissionsIotUser IoT ユーザ
PermissionsUseWebLink カスタマイズしたアクションへのアクセスを許可
PermissionsViewAllActivities すべての活動を表示
PermissionsSubscribeReportToOtherUsers レポートを登録: 受信者を追加
PermissionsLightningConsoleAllowedForUser Lightning コンソールユーザ
PermissionsSubscribeReportsRunAsUser レポートを登録: 実行ユーザを設定
PermissionsSubscribeToLightningDashboards ダッシュボードへの登録
PermissionsApexRestServices Apex REST サービス
PermissionsEnableCommunityAppLauncher コミュニティでアプリケーションランチャーを表示
PermissionsManageSurveys アンケートを管理
PermissionsViewRoles ロールおよびロール階層を表示

いっぱいある。

[Salesforce]代理承認者機能の使い方

まとまってるドキュメントが見つからなかったのでメモ。


代理承認者とは

  • Salesforce の承認プロセス機能において、承認者の代わりに申請を承認/却下できる人を設定できる機能
  • ユーザに対して一人だけ代理承認者を設定しておくことができる
  • また承認プロセスの各承認ステップごとに代理承認者による承認を許可するかどうかが設定できる

承認プロセスそのものについては以下の Trailhead モジュールをやるといい。


設定手順

ユーザ設定より代理承認者を設定する

代理承認者を設定したいユーザのユーザ設定画面を開き、下の方の「承認者の設定」セクションに移動する。
「代理承認者」項目に代理承認者にしたいユーザを検索してセットする。

f:id:dackdive:20180317025929p:plain:w320

また、代理承認者自身のユーザ設定で、「承認申請メールを受信」項目を「自分が承認者である場合のみ」から「承認者または代理承認者である場合」に変更しておくとよい。理由は後述。

f:id:dackdive:20180317025925p:plain:w320


承認プロセス設定より、承認ステップで代理承認を許可する

今度は承認プロセスの設定画面を開き、任意の承認ステップの編集画面を開く。

f:id:dackdive:20180317031300p:plain

ステップ 3/3 で、一番下に「代理承認者もこの申請を承認可能にする」という項目があるのでチェックする。

f:id:dackdive:20180317031303p:plain


結果

自分が代理承認者になっている承認ステップに申請が回ってきたとき、承認者同様にメールが届く。
メールの件名には「(◯◯の代理承認者)」と書かれているよう。

f:id:dackdive:20180317032513p:plain


制限事項

自身が代理承認可能な申請は今のところ「未承認申請一覧」には表示されない。メール以外に確認する手段がないのでつらい。
これについてはずいぶん前から Idea に投稿されてるよう。

また、以下のヘルプ記事ではメール以外のワークアラウンドも紹介されてる(英語)。

Why can't a delegated approver see anything in the Items to approve list?

どうやら「レコードが現在承認プロセスの申請中かどうか」を表すチェックボックス項目をオブジェクトに追加し、それを条件にリストビューを作るという方法らしい。
チェックボックスの ON/OFF は承認プロセスの開始時や最終承認/却下時のアクションとして項目自動更新により自動的に制御できる。

が、これは別に「自身が代理承認になっているものリスト」ではないし、もっと言うと自分が承認者じゃないやつも含まれるのでは。。。

(2018/3/23追記)

と思ったら、標準レポートに「代理承認申請一覧」というのがあった。。。

f:id:dackdive:20180323234404p:plain

これで一覧表示できます。

f:id:dackdive:20180326143254p:plain

※ただし、標準フォルダは LEX では表示されないため、コピーする必要あり
(参考:レポートおよびダッシュボード: Lightning Experience で使用できない機能とその新機能


「代理承認者」に設定する以外に、他人の申請を承認/却下する方法

「代理承認者」はユーザにつき一人しか指定できない。もう少し柔軟に代理承認可能なユーザを増やすにはどうするか。

代理承認ではないが、申請を行うオブジェクトに対して「すべての編集」権限があれば任意の申請を承認/却下することができる。
(「すべてのデータの編集」権限もそう)

参考:承認の管理に関する考慮事項

管理者権限
次の権限のいずれかを持つユーザは承認管理者とみなされます。

  • 指定のオブジェクトに対するオブジェクトレベルでの「すべての編集」権限
  • 「すべてのデータの編集」ユーザ権限

承認管理者には次の権限があります。

  • 承認プロセスの一環としてではなく、未承認申請を承認または却下
  • 承認がロックされたレコードの編集


わかっていないこと

  • 承認者としてキューやグループを指定したときにどういう挙動になるのか

electron-react-boilerplateでCSSフレームワーク(Lightning Design System)をインストールするとエラー

Chatter Desktop という Electron アプリ を作っていて真っ先にハマったところのメモ。

Lightning Design System という CSS フレームワークを入れようとしたところ、以下のエラーとなった。

$ git clone --depth=1 https://github.com/chentsulin/electron-react-boilerplate.git your-project-name
$ cd your-project-name
$ yarn
$ yarn add @salesforce-ux/design-system
...
ERROR in dll renderer
Module not found: Error: Can't resolve '@salesforce-ux/design-system' in '/Users/yamazaki/workspace/electron/electron-react-boilerplate'
 @ dll renderer

ERROR in ./node_modules/bootstrap/dist/js/bootstrap.js
Module not found: Error: Can't resolve 'jquery' in '/Users/yamazaki/workspace/electron/electron-react-boilerplate/node_modules/bootstrap/dist/js'
 @ ./node_modules/bootstrap/dist/js/bootstrap.js 7:81-98
 @ dll renderer

ERROR in ./node_modules/bootstrap/dist/js/bootstrap.js
Module not found: Error: Can't resolve 'popper.js' in '/Users/yamazaki/workspace/electron/electron-react-boilerplate/node_modules/bootstrap/dist/js'
 @ ./node_modules/bootstrap/dist/js/bootstrap.js 7:100-120
 @ dll renderer
npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! electron-react-boilerplate@0.13.2 build-dll: `cross-env NODE_ENV=development node --trace-warnings -r babel-register ./node_modules/webpack/bin/webpack --config webpack.config.renderer.dev.dll.js --colors`
npm ERR! Exit status 2
npm ERR!
npm ERR! Failed at the electron-react-boilerplate@0.13.2 build-dll script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/yamazaki/.npm/_logs/2018-03-04T21_19_46_858Z-debug.log
error Command failed with exit code 2.
info Visit https://yarnpkg.com/en/docs/cli/add for documentation about this command.

https://github.com/chentsulin/electron-react-boilerplate/blob/master/package.json#L23
どうやら postinstall スクリプトが走っており、この中で build-dll という DLL ファイルの生成処理をやろうとして失敗しているよう。

また build-dllwebpack.config.renderer.dev.dll.js を見て webpack によるビルドを行っているので、設定ファイルの中身を見る。そうすると

https://github.com/chentsulin/electron-react-boilerplate/blob/master/webpack.config.renderer.dev.dll.js#L175-L181

entry: {
  renderer: (
    Object
      .keys(dependencies || {})
      .filter(dependency => dependency !== 'font-awesome')
  )
},

ここで、元から入っていた font-awesome については明示的にビルド対象から外しているようだ。
なので手動で

entry: {
  renderer: (
    Object
      .keys(dependencies || {})
      .filter(dependency => {
        // also ignore installed CSS library
        return dependency !== 'font-awesome' && dependency !== '@salesforce-ux/design-system';
      })
  )
},

というふうにインストールする CSS フレームワークをビルド対象から除外してやると、ビルドに成功するようになった。

が、正しい手順なのかがよくわからず、Issue で質問してみることにした。


おまけ: webpack.config.renderer.dev.dll.js がやっていること

開発時のビルドパフォーマンス向上のために webpack.DLLPlugin というのを使っている。
DLLPlugin についてはきちんと理解したわけではないが、外部ライブラリなど毎回毎回ビルドする必要がないモジュールを DLL バンドルという形で別ファイルに切り出し、require() 時に読み込むらしい。
こちらの記事が非常に参考になった。

LDSとdesign-system-reactをBabel&webpackな環境に導入する

メモ。
ちょっと前から Lightning Design System(LDS)の React 実装が公式から出てます。

Lightning Design System for React

で、ようやく入れてみようとドキュメントを頼りにやってみたところ色々手こずったので、手順をまとめておきます。


はじめに

design-system-react の設定に関するドキュメントは、以下のように点在しています。

  1. Getting Started
  2. リポジトリREADME#Usage
  3. リポジトリdocs/webpack.md (Usage with Webpack)

1 が一番参考にしたドキュメント。webpack.config.js の設定例なども載っています。基本はここを見ながらやりました。
ここに書かれてる内容は private repo で管理してるらしい) 2 は 1 と被る部分もあり、ただ Icon の設定に関してはここにしか記載されてません。
また 1, 2 は design-system-react のインストール手順であり、これだけだと LDS はインストールされず、スタイルがあたりません。
LDS を webpack から使えるようにするための情報が 3 に載っています。

以下では、設定手順を大きく「1. design-system-react の設定」と「2. LDS の設定」に分けて記載します。


サンプルコード

Redux & Express でのアプリのひな形リポジトリに導入したときの PR です。

ディレクトリ構成

クライアント側のファイルは public というディレクトリに配置するような構成になっています。

- public
  - assets
    - lds --- LDS はここに展開
    - bundle.js --- ビルド後のファイル
  - components --- React & Redux の
  - containers
  - ...
  - index.js --- エントリーポイント
  - index.html
- package.json
- webpack.config.base.babel.js
- webpack.config.dev.babel.js
- webpack.config.prod.babel.js


1. design-system-react の設定

まずは design-system-react のインストールから設定までの手順。主に先ほどの 1. Getting Started を参考にします。

インストール

npm でインストールできます。

$ npm install @salesforce-ux/design-system @salesforce/design-system-react


webpack の設定

Getting Started のページに webpack.config.js の設定例があるので、それを参考に設定していきます。

 // webpack.config.babel.js (抜粋)
 export default {
   context: path.resolve(path.join(__dirname, 'public')),
   entry: [
     './index',
   ],
+  resolve: {
+    extensions: ['.js', '.jsx'],
+  },
   output: {
     filename: 'bundle.js',
     path: path.resolve(path.join(__dirname, 'public', 'assets')),
     publicPath: '/assets/',
   },
   module: {
     rules: [
       {
-        test: /\.js$/,
-        exclude: /node_modules/,
+        test: /\.jsx?$/,
+        include: [
+          path.resolve(path.join(__dirname, 'public')),
+          path.resolve(path.join(__dirname, 'node_modules/@salesforce/design-system-react')),
+        ],
         use: 'babel-loader',
       },
       {
         ...

(ファイル全体は こちら を参照)

ポイントとしては

  • design-system-react のファイルは .jsx なので、 .jsx もビルドできるように resolve.extensions および babel-loader を適用する正規表現を修正
  • 元々 node_modules 以下はすべて babe-loader の対象外としていたが、design-system-react は対象に含めるよう修正

です。

また、この記事を書いた時点ではドキュメントの方では

path.join(__dirname, 'node_modules/design-system-react')

というように @salesforce が入ってなかったんですが、入れるのが正しいです。
Issue で報告したのでそのうち直るはず。


Babel の設定

.babelrc を修正します。
これには @salesforce/babel-preset-design-system-react という preset を使えとドキュメントにはありますが、中身

https://github.com/salesforce/design-system-react/blob/master/preset/index.js

を見てみると

  • babel-preset-env
  • babel-preset-react
  • babel-plugin-transform-object-rest-spread
  • babel-plugin-transform-class-properties
  • babel-plugin-transform-export-extensions

を指定しているだけなので、既に設定されている .babelrc の内容に合わせて必要な preset/plugin を個別に追加するという対応でもいいのかもしれません。
(実際自分のリポジトリでも babel-plugin-transform-export-extensions 以外は使っていた)

今回は素直にこの preset を使うようにします。

$ npm install -D @salesforce/babel-preset-design-system-react
// .babelrc
{
  "presets": ["@salesforce/babel-preset-design-system-react"]
}


使う

このような形で import して使います。

// components/App.js
import React, { Component } from 'react';
import Button from '@salesforce/design-system-react/components/button';

export default class App extends Component {
  render() {
    return (
      <Button
        iconName="download"
        iconPosition="left"
        label="Neutral Icon"
      />
    );
  }
}


2. LDS の設定

さて、今度は LDS を読み込むための設定をします。
これは docs/webpack.md がある程度参考になります。


インストール
$ npm install @salesforce-ux/design-system style-loader css-loader file-loader

必要になる loader も一緒にインストールしときます。


webpack の設定
 // webpack.config.babel.js
 ...
 export default {
   ...
   module: {
     rules: [
       ...
+      {
+        test: /\.min\.css$/,
+        use: ['style-loader', 'css-loader'],
+      },
+      {
+        test: /\.(eot|svg|ttf|woff|woff2)$/,
+        loader: 'file-loader',
+        options: {
+          name: '[name].[ext]',
+          outputPath: 'lds/',
+        },
+      },
       ...


postinstall 時の処理

次に、npm install 後に LDS を静的リソース配信用のディレクトリ(ここでは public/assets/lds/)にコピーしておきます。
ドキュメントでは postinstall.js スクリプトを作ってシンボリックリンクを貼る処理をやっているようですが、単にコピーするだけなら package.json 内に記述しても十分だと思います。

 // package.json
 {
   "scripts": {
+    "postinstall": "rm -rf public/assets/lds && cp -r node_modules/@salesforce-ux/design-system/assets public/assets/lds",
   ...
 }


読み込み

アプリのエントリーポイントで

 // public/index.js
 import { render } from 'react-dom';
 import { AppContainer } from 'react-hot-loader';
 
+import '@salesforce-ux/design-system/assets/styles/salesforce-lightning-design-system.min.css';
+
 import configureStore from './store/configureStore';
 import App from './containers/App';
 ...

とすれば OK です。


3. Icon パスの設定

最後にもう一点だけ。Icon を使う場合、アプリのルートで <IconSettings> コンポーネントを使い、パスを正しく設定しておく必要があります。

README#icon-usageSLDS React | Icon Settings あたりに記載があります。

 // public/index.js
 import { AppContainer } from 'react-hot-loader';
 
 import '@salesforce-ux/design-system/assets/styles/salesforce-lightning-design-system.min.css';
+import IconSettings from '@salesforce/design-system-react/components/icon-settings';
 
 import configureStore from './store/configureStore';
 import App from './containers/App';
 
 import './styles/index.scss';
 
 const store = configureStore();
 
 const rootEl = document.getElementById('root');
+const LDS_ROOT = 'assets/lds';
 
 render(
   <AppContainer>
     <Provider store={store}>
-      <App />
+      <IconSettings
+        standardSprite={`${LDS_ROOT}/icons/standard-sprite/svg/symbols.svg`}
+        utilitySprite={`${LDS_ROOT}/icons/utility-sprite/svg/symbols.svg`}
+        actionSprite={`${LDS_ROOT}/icons/action-sprite/svg/symbols.svg`}
+        doctypeSprite={`${LDS_ROOT}/icons/doctype-sprite/svg/symbols.svg`}
+        customSprite={`${LDS_ROOT}/icons/custom-sprite/svg/symbols.svg`}
+      >
+        <App />
+      </IconSettings>
     </Provider>
   </AppContainer>,
   rootEl,
 );

ここに関してはよくわかってないことが 2 点あって、

1) <IconSettings> には iconPath を指定する方法と、xxxSprite というアイコンの種類ごとのパスを指定する方法とあるんですが、webpack を使ってると後者を推奨してるようです。

Individual sprites If you are using webpack it is advised to use the sprite properties {actionSprite, standardSprite...} to specify the individual sprite paths so that webpack can easily re-write the paths.

この PR で追加されたようで、そこでも webpack のためにということが書かれていますが詳しいことはよくわからず。

2) xxxSprite の指定のしかたとして、Example にあるように

import actionSprite from '@salesforce-ux/design-system/assets/icons/action-sprite/svg/symbols.svg';

のようにすればいいのかなと思ったんですが、なぜかうまくいかず。。。
結局 postinstall でコピーした方のパスを指定してうまくいったのでそうしています。


結果

f:id:dackdive:20180206041536p:plain

<Button> だけですが、無事に LDS のスタイルがあたった状態でコンポーネントが描画できていることが確認できました。アイコンも表示されています。


おわりに

書いてみるとなんてことないんですが、 @salesforce がちょいちょい抜けてたりとドキュメントの整備が追いついてないみたいで結構ハマりました。。。
とりあえず使えるところまでできてよかった。


トラブルシューティング

遭遇したエラー達。

ERROR in ./node_modules/@salesforce/design-system-react/components/button/index.jsx
Module parse failed: Unexpected token (228:3)
You may need an appropriate loader to handle this file type.
ERROR in ./public/components/App.js
Module not found: Error: Can't resolve '@salesforce/design-system-react/components/button' in '/Users/yamazaki/workspace/react/redux-express-template/public/components'

→ webpack の設定不備。 .jsx がビルド対象になっていない、 node_modules/@salesforce/design-system-react が include されていない、などなど。

/Users/yamazaki/workspace/react/redux-express-template/node_modules/webpack/lib/webpack.js:19
                throw new WebpackOptionsValidationError(webpackOptionsValidationErrors);
        ^
WebpackOptionsValidationError: Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
 - configuration.resolve.extensions[0] should not be empty.
   -> A non-empty string
    at webpack (/Users/yamazaki/workspace/react/redux-express-template/node_modules/webpack/lib/webpack.js:19:9)
    at Object.<anonymous> (/Users/yamazaki/workspace/react/redux-express-template/app.js:13:20)
    at Module._compile (module.js:643:30)
    at babelWatchLoader (/Users/yamazaki/workspace/react/redux-express-template/node_modules/babel-watch/runner.js:50:13)
    at Object.require.extensions.(anonymous function) [as .js] (/Users/yamazaki/workspace/react/redux-express-template/node_modules/babel-watch/runner.js:61:7)
    at Module.load (module.js:556:32)
    at tryModuleLoad (module.js:499:12)
    at Function.Module._load (module.js:491:3)
    at Function.Module.runMain (module.js:684:10)
    at process.on (/Users/yamazaki/workspace/react/redux-express-template/node_modules/babel-watch/runner.js:108:21)

→ webpack の resolve.exntensions に空文字 ['', '.js', '.jsx'] は webpack 2 系以降 NG になったぽい。使うなら'*'

第26回 Tokyo Atlassian ユーザーグループ に行ってきたメモ #augj

行ってきました。

途中参加かつ懇親会は都合がつかず、セッション2つ聞いて帰ってきました。

Confluenence/Jiraパフォーマンスチューニングポイント by 大中浩行

間に合わず。資料が公開されてたので貼っときます。

パフォーマンスと聞いてオンプレ版のことだろうと決めつけてたらやっぱりオンプレ版でした(弊社は Cloud 版)


Confluenceで組織を活性化させたかった話 by 南原 錦善

SES 主力の会社で Confluence Server を使って組織改善にチャレンジしたお話

  • 株式会社ヒューマンネットワーク
    • エンジニア 75 名、営業、管理部 20 名
    • SES の常駐業務が主力
  • 客先常駐なのでエンジニアはバラバラ
  • 定時後帰社、社内活動 -> 社内への働きに対して大きなパワーが必要。効率化することが重要な課題
  • 課題
    • 社内の活動の情報共有がしづらい (元desknets)
    • スキル情報を見る機会がない
    • 議事録、社内ルール、広報がワード、エクセル、PDF
    • やってる感が出ない(家で勉強してたとしても評価できないし、アピールの場がない)
  • 導入までの3つの壁
    1. 社内の反対
      • 変化に対する抵抗
      • 費用対効果の不明さによる懸念
      • 自腹で導入し、良さをアピール
    2. ユーザ管理
      • AD 連携ができるけどうまくいかない→諦め
    3. 使い方指導
  • 利用状況を Google Analytics で取得
  • DBから更新数、いいね数の取得
  • 運用のポイントというか意識したポイント
    1. 使用方法に制限をかけない
    2. 毎日みんなの投稿に目を通しリアクションする
    3. フォロワー(サクラ)を作る
  • 生きた情報は生きた組織を作る!


印象に残った話
  • 費用対効果を説明するの面倒だから 1000円/月・10人分のライセンスを自腹で購入
  • Paiza の問題のリンク集を作り、新人に問題を解かせた。また回答も Confluence に書かせた
    • Java のコードを見るとコメントしたくてたまらない人達が集まってきた
  • ポジティブな気持ちになれる偉人の名言を毎日投稿する人が出てきた

といったエピソードがありました。

弊社も Confluence に情報をまとめるのはだいぶ浸透してきたけど、開発というか業務にないことでも自由に発信するというのはできてないなー。


Making Software for the Software Makers "AtlassianはJIRAをどう使っているか" by Jason Wong

Jira Software プリシパルプロダクトマネージャーの Jason さんからの話。
Atlassian のチーム例 5 つを紹介。
Jira を徹底的に使いこなすための実践的 Tips というより、それぞれのチームで Jira をどう使っているかを通じて Atlassian のカルチャーみたいなものを感じることができて面白かったです。

  • 世界中どこを探してもまったく同じチームはない。だから Jira Software の使い方もチームによって異なる
  • アトラシアンの 5 つのチームの話
  • 世界12箇所、20+ Jira インスタンス、337 プロジェクト、468 カスタムワークフロー
1. 時間的に厳しいアジャイル
  • Identity CloudX チーム
  • Jira に登録しつつ物理カンバン

  • 見積り前提 -> NO!

    • 見積りより調査 早めにスパイクし始めよう!
    • QA 発表会
      • スプリントが終わったときにどんなソフトになっていてほしいか、スプリントの前に実施
  • 改善をし続ける社内文化を支えるために新しい習慣を作ります
    • アジャイルスラム(大勢の人の前に立って経験したことを話す)
      • 詩人会の由来から
    • ウォールボード
    • 仕事と楽しみのバランス
2. 大量の experiment を行うシステム
  • Atlassian 製品の実験的な取り組みを行うチーム?
  • 会社から大量のIdeaがくる。さばききれない
  • 自動化
    • optimizely, jira software, confluence をつなげるマイクロサービスMars
  • 情報を一つの場所にまとめるサービスやプロセスを作るのはとても大切
    • Jira + Confluence
      • Jira を仕事のステータスより、仕事の文脈や背景や結果を詳しく共有できる
3. 端から端まで、開発の見通し
  • Jira Software チーム(Jason さんが所属してるチーム)
  • デザイン・開発・マーケ・プロダクトなどさまざまなチームごとにプロジェクト
    • 使い方もさまざま
  • PM は様々な仕事をトラッキングするため Confluence のページでテーブル作った -> 情報がすぐ古くなる
  • -> クロスプロジェクトボードを作る!
  • 「ボードを歩く」Boardwalk
4.
  • SRE チーム
  • IMA というマイクロサービス作った
    • HOT チケットができると Hipchat にルームができる
    • Bluejeans も
    • StatusPage: https://ja.atlassian.com/software/statuspage
    • 各サービスへのリンクを Jira の課題に集約(自動的に記載される)
5. 開発情報のボード
  • Fusion Team (Jira Software と開発ツールの連携を作る)
  • ブランチの進行と Jira のステータスを重ね合わせると状況がよくわかる
  • development[pullrequests].all > 0
  • カードの色と組み合わせて視覚的に
印象に残った話

1 つめのチームに関しては、物理カンバンを使っていて、タスクのふせんをなぜか一本の道のようにつなげてボードにしていたチームの話。
道は途中で枝分かれしたり合流したりで、要所要所になぜかポケモンが。
またポケモンボール型のマグネットも用意されていて、タスク消化していってポケモンのところまで到達したらポケモンボール使ってポケモン GET!
→ちょっとした達成感のお祝いでみんなでコーヒー飲んだりする
みたいな話をされてました。

f:id:dackdive:20180306104701p:plain

また 2, 4 のチームにあるように、Atlassian では製品間をマイクロサービスでつなげて自動化を進めてるらしい。
StatusPage なんてサービスもやってたのか。

5 については、 JQL の development[xxx] というプロパティすら知らなかったんですが、やってみるとたしかにできました。
Bitbucket などと連携した状態で

development[pullrequests].open > 0

などとすると、「ひもづく PR でオープン状態のものがあるチケット」のような条件指定ができます。

f:id:dackdive:20180203013956p:plain

お話では、キャプチャのようにかんばんのカードの色の条件にこれを使っていて、Jira のステータスとソースコードの状況に乖離がないかを可視化してるとのことでした。

また、3 のチームの話に出てくる Boardwalk ってのがどういった目的で、どれくらいの頻度でやるのかいまいち理解できてなかったんですが
懇親会の冒頭にお話を伺うことができました。

  • 毎回のスプリント期間中に定期的に実施する。スプリントの真ん中あたりに設定してる
    • 前半はプランニング、後半はふりかえりがあるし
  • バックロググルーミングと似てるんだけど、「バックロググルーミングのような細かい話まではしないかな」とのこと
  • そのストーリーを「なぜやるか」というところを、デザイン・開発・マーケみんな集まったところで共有する
    • やる目的を共有し、全員が共感した状態で作らないとモチベーション上がらない

だいたいこんなような回答だったかと。
ググると Jason さんの記事が出てきますね。

また Jason さんからは他にも

  • かんばんはデジタル(Jira)で管理してるところもアナログ(物理)で管理してるところも、あるいは併用してるところもある。傾向として若者が多いところだと物理かんばんが多い
  • Face to Face のコミュニケーションってやっぱり大事。Jira や Confluence 上でもメンションつけてやり取りはたしかにできるけど。メンションつきで長文で重要な情報が頻繁にやり取りするようだと顔を突き合わせての対話が足りてないという兆しなんじゃないか

といった面白い話が聞けました。

総じて、対話によるコミュニケーションや、計画通りやるだけじゃなく仕事に楽しさを持たせるっていうのを大事にしてるんだなと感じました。

babel-preset-envの使い方(babel-preset-es2015からの移行)

はじめに

ES2015 の変換に babel-preset-es2015 を使っているプロジェクトで、npm install 時に

npm WARN deprecated babel-preset-es2015@6.24.1: 🙌  Thanks for using Babel: we recommend using babel-preset-env now: please read babeljs.io/env to update!

という警告が出ており、あーたしかに babel-preset-env を使った方がいいってどこかで聞いたなと思いつつ env の設定のしかたを調べられていなかったんですが、ようやく少し調べました。
そのときのメモ。

公式の

に加え、Qiita のこちらの記事も参考になりました。

注)この記事を書いた 2018/1/18 時点で Babel のバージョン 7 はベータ版だったので、6 系での設定です。
バージョン 7 での変更点は最後に書いてます。

最初にまとめ

  • babel-preset-es2015 から babel-preset-env にただ切り換えるだけであれば、babel-preset-xxx 部分を置き換えるだけで済む
  • babel-preset-env は何もオプションを指定しなければ、全部 ES5 の記法にトランスパイルする
  • が、モダンなブラウザでは Class など ES2015+ の構文に対応しているので、サポート対象ブラウザに応じて必要なところまでトランスパイルするのが望ましい
  • babel-preset-env では targets オプションで対象ブラウザを指定することが可能
// .babelrc(例)
{
  "presets": [
    ["env", {
      "targets": {
        "browsers": ["last 2 versions", "safari >= 7"]
      }
    }]
  ]
}

(2018/5/11追記)

上記の例の last 2 versions はあまりよくないらしい。という記事を読んだ。

last 2 versions - @jamiebuilds

(追記ここまで)


設定方法

babel-preset-env をインストール

babel-preset-es2015 をアンインストールして、かわりに babel-preset-env を入れます。

$ yarn remove babel-preset-es2015
$ yarn add -D babel-preset-env

.babelrc を修正

まずは単純に es2015 を env に置き換えます。

 {
-  "presets": ["react", ["es2015", { "modules": false }]],
+  "presets": ["react", ["env", { "modules": false }]],
   "plugins": [
     "transform-class-properties",
     "transform-object-rest-spread",
    "react-hot-loader/babel"
  ]
}

webpack で Tree Shaking をするための modules: false というオプションもそのままで大丈夫のようです。
https://babeljs.io/docs/plugins/preset-env/#modules

オプションで対象ブラウザを指定する

https://babeljs.io/docs/plugins/preset-env/#targets
targets というオプションで対象のブラウザを指定できます。
対象のブラウザを指定すると、そのブラウザで対応している構文についてはそのままでトランスパイルせず、未対応の構文のみトランスパイルするという挙動になるようです。

内部的には compat-table のデータを参照しているらしい。

targets の指定方法にはいくつか種類があって、

1) 対象ブラウザとバージョンを決め打ち

{
  "targets": {
    "chrome": 52
  }
}

2) targets.browsers を指定し、クエリを書く(内部的には browserslist を使っている)

"targets": {
  "browsers": ["last 2 versions", "safari 7"]
}

もしくはこれらを複数指定することができます。あとは node オプションで対象の Node のバージョンが指定できたり。
なお

Note, browsers’ results are overridden by explicit items from targets.

とあるので、 browsers の内容は個別に指定したものがあった場合上書きされます。


最終的にこうなった

というわけで、私は一旦こうしました。

// before
{
  "presets": ["react", ["es2015", { "modules": false }]],
  "plugins": [
    "transform-class-properties",
    "transform-object-rest-spread",
    "react-hot-loader/babel"
  ]
}
// after
{
  "presets": [
    "react",
    ["env", {
      "targets": {
        "browsers": ["last 2 versions"]
      },
      "modules": false
      }
    ]
  ],
  "plugins": [
    "transform-class-properties",
    "transform-object-rest-spread",
    "react-hot-loader/babel"
  ]
}

個人の適当なリポジトリで試しただけなので、対象ブラウザとかは深く考えてないです。

参考:

PR はこれ

Babel 7 での変更点

Babel 7 から babel-preset-env も Babel 本体のリポジトリに移動になったので、パッケージ名が @babel/preset-env に変わります。

参考:https://github.com/babel/babel/tree/master/packages/babel-preset-env

$ npm install @babel/preset-env --save-dev

targets の指定方法は変わってないぽいです。

IDDD本もくもく読書会メモ#5(第10章 集約)

メモが滞ってる。。。第10章「集約」のメモを。

過去メモ
教材

CodeZine の記事 も第9章から更新が止まってしまっていてつらい。

メモ

10.2 ルール:真の不変条件を、整合性の境界内にモデリングする

  • 不変条件:常に整合性を保っている必要のあるビジネスルールのこと
  • 不変条件について議論する際の整合性は、トランザクション整合性のことを指す
  • 集約はトランザクション整合性の境界

整合性の境界の論理的な意味は、「その内部にあるあらゆるものは、どんな操作をするにかかわらず、特定の不変条件のルールに従う」ということだ。

10.3 ルール:小さな集約を設計する

  • モデルの一部分をエンティティとしてモデリングしたくなったらどうするか
    • その部分自体が今後も変わり続けるものなのか、あるいは変更したくなったときに丸ごと置き換えれば済むのか考える
    • 丸ごと置き換えられるならエンティティではなく値オブジェクト
  • ユースケースを鵜呑みにするな

10.4 ルール:他の集約への参照には、その識別子を利用する

  • 集約の合成構造?
  • 集約から別の集約(へのルート)への参照を持つのはOK
  • 1つのトランザクションで参照する側とされる側の両方を更新してはならない
  • 集約そのものへのポインタではなく、一意な識別子へのポインタを保持する
    • Product ではなく ProductId (値オブジェクト)を持つ

10.5 ルール:境界の外部では結果整合性を用いる

  • ひとつの集約上でコマンドを実行するときに、他の集約のコマンドも実行するようなビジネスルールが求められるのなら、その場合は結果整合性を使う
  • 一方のインスタンスが変更されてから、もう一方のインスタンスが変更されるまでの遅延が、どの程度許容されるかをドメインエキスパートにたずねてみよう
  • 現実的な手段としては、トランザクションの最後にドメインイベントを発行する
  • 誰の役割かを考える

10.6 ルールに違反する理由

10.7 発見による知見の獲得

  • 例:バックログアイテム:タスク = 1 : n の関係にある
  • 一般的な利用シナリオを頭に浮かべながら試算する、という話が書かれている
  • バックログアイテムの状態とタスクの残作業の総計は結果整合性にすべきか?
    • -> タスクの数がどれだけあっても、バックログアイテムの状態が変わるのは、常に最後の見積もりになる
      • バックログアイテムの状態が変わらない限り version が変わらないので、結果整合性でなくロックしても問題ない
  • メモリの消費

10.8 実装

  • 集約のパーツは可能な限り、エンティティではなく値オブジェクトにする
public class Product extends ConcurrencySafeEntity {
    private Set<ProductBacklogItem> backlogItems;
    private String description;
    private String name;
    private ProductDiscussion ProductDiscussion; // VO
    private ProductId productId; // VO
    private TenantId tenantId; // VO
}

Q

  • 誰の役割かを考えてトランザクション整合性か結果整合性かを決める、というのは絶対なの?
    • -> あくまで指針の1つと捉えておくのが良い


資料