Salesforce Lwc Action アクション

① ●●-meta.xml の定義について

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
      <target>lightning__RecordAction</target>
    </targets>
     <targetConfigs>
    <targetConfig targets="lightning__RecordAction">
      <actionType>ScreenAction</actionType>
    </targetConfig>
  </targetConfigs>
</LightningComponentBundle>

actionType : ScreenAction 画面あり。Action:画面なし(裏処理のみ)

➁ ●●.js

処理入口: invoke 固定の記載
@api invoke() {
// Do something
}


③ recordIdの取得

_recordId;
@api set recordId(value) {
    this._recordId = value;
    // do your thing right here with this.recordId / value
}

get recordId() {
    return this._recordId;
}

API Post application/json Line richMenu API

curl

* curl -v -X POST https://api.line.me/v2/bot/richmenu/bulk/link \
-H "Authorization: Bearer {channel access token}" \
-H "Content-Type: application/json" \
-d '{
"richMenuId":"{richMenuId}",
"userIds":["{userId1}","{userId2}"]
}'

apex

JSONGenerator gen = JSON.createGenerator(true);
gen.writeStartObject();
gen.writeStringField('richMenuId', 'richmenu-xxxxxxx');
gen.writeObjectField('userIds', Set<String> strSet);
gen.writeEndObject();
req.setBody(gen.getAsString());

Salesforce Pardot Demo環境構築手順

① アカウント作成

 https://developer.salesforce.com/promotions/orgs/pardot-de

以下の案内の通りでインストールする。
  https://●●●●●●●●● -dev-ed.lightning.force.com/lightning/setup/PardotSetupAssistant/home#-81

➁ Appインストール(上記にて含めて)

 https://pardot-appexchange.herokuapp.com/

 Production Environments

Salesforce site apex 公開

① apexクラス作成

@RestResource(urlMapping='/abc')
global with sharing class XXXXX {

    //@HttpGet
    @HttpPost
    global static Map<String,String> testmethod(){

➁ 作成したクラスをサイトのプロファイルにて公開する

③ アクセス(呼び出し)

・ 一般URL

https://●●●-developer-edition.ap25.force.com/services/apexrest/abc

・ パッケージとネームスペース(NameSpace利用する場合)

https://●●●-developer-edition.ap25.force.com/services/apexrest/namespace/abc

Salesforce LWC メッセージ通信

messageChannel を利用して通信する。

① messageChannel 新規作成する

メーターデータ取得する。


<types>
    <members>*</members>
    <name>LightningMessageChannel</name>
</types>

ソース格納フォルダ
force-app/main/default/messageChannels

サンプル:

LineMessageChannel.messageChannel-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningMessageChannel xmlns="http://soap.sforce.com/2006/04/metadata">
    <description>Line Message LMS.</description>
    <isExposed>true</isExposed>
    <lightningMessageFields>
        <description>Select Changed</description>
        <fieldName>lineId</fieldName>
    </lightningMessageFields>
    <lightningMessageFields>
        <description>Select Changed</description>
        <fieldName>recordId</fieldName>
    </lightningMessageFields>
    <masterLabel>LineMessageChannel</masterLabel>
</LightningMessageChannel>

➁ メッセージ送信する

import FRIEND_SELECTED_CHANNEL from '@salesforce/messageChannel/LineMessageChannel__c';
import { publish, MessageContext } from 'lightning/messageService';
     @wire(MessageContext)  messageContext;
    friendSelect(event) { 
         const payload = { recordId: recordId}; //メッセージ内容       
         publish(this.messageContext, FRIEND_SELECTED_CHANNEL, payload);
}

③メッセージ受信する

import FRIEND_SELECTED_CHANNEL from '@salesforce/messageChannel/LineMessageChannel__c';
  import { publish, MessageContext, unsubscribe,subscribe, APPLICATION_SCOPE } from 'lightning/messageService';

  //メッセージ自動更新
  connectedCallback() {
    this.subscribeToMessageChannel();    
  }

  disconnectedCallback() {
    unsubscribe(this.subscription);
    this.subscription = null;
  }

  subscribeToMessageChannel() {
    if (!this.subscription) {
        this.subscription = subscribe(
            this.messageContext,
            FRIEND_SELECTED_CHANNEL,
            (message) => this.handleMessage(message),
            { scope: APPLICATION_SCOPE }
        );
    }
  }

  handleMessage(message) {
    this.recordId = message.recordId;
  }

Linux Jenkins Install

環境: お名前 VPS サーバー

手順:

参考URL:https://weblabo.oscasierra.net/jenkins-install-centos7/

yum install vim
yum install wget
yum install git
yum install mlocate

curl -o /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
yum install jenkins
yum install java-1.8.0-openjdk

systemctl enable jenkins
systemctl start jenkins
sudo firewall-cmd --zone=public --add-port=8080/tcp --permanent
firewall-cmd --reload

###vim /etc/sysconfig/jenkins
JENKINS_ARGS="--prefix=/jenkins"

###vim /etc/httpd/conf/httpd.conf

ProxyPass           /jenkins http://xxxx.com:8080/jenkins nocanon
ProxyPassReverse    /jenkins http://xxxx.com:8080/jenkins
ProxyRequests       Off
AllowEncodedSlashes NoDecode

<Proxy http://xxxx.com:8080/jenkins*>
  Order deny,allow
  Allow from all
</Proxy>


★★ お名前の管理画面からも 8080 port 開けること。

Salesforce apex から youtubeアップロード

■環境準備:

以下、

①googleアカウント作成する

https://console.cloud.google.com/home/dashboard?project=uploadfromsalesforcedemo&authuser=0&hl=ja&supportedpurview=project

② プロジェクト作成する

③ 管理画面の「APIとサービス」 」に移動する。

   ・「ライブラリ」に移動し、「YouTube Data API v3」を追加する

   ・「認証情報」に移動し、「OAuth 2.0 クライアント ID」を作成する。

④ refresh_token 取得する用の code を取得する。

  ① 以下をブラウザにて開く

  「https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=[client_id]&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube&access_type=offline」

    ⇒「Google にログイン」⇒表示したコードメモする。

➁上記取得したコードを以下でrefresh_tokenとtokenを取得する

     curl –data “code=[code]” –data “client_id=[client_id]” –data “client_secret=[ client_secret ]” –data “redirect_uri=urn:ietf:wg:oauth:2.0:oob” –data “grant_type=authorization_code” –data “access_type=offline” https://www.googleapis.com/oauth2/v4/token

※Linux環境にて確認済み

いかのような値取得できます。

{
“access_token”: “xxxxxxxxxxxxxxx”,
“expires_in”: 3599,
“refresh_token”: “xxxxxxxxxxxxxxxxxxx”,
“scope”: “https://www.googleapis.com/auth/youtube”,
“token_type”: “Bearer”
}

➄ youtube チャンネル作成する。(デフォルト)

■apxコード

※ 上記取得した refresh_token 利用し、実行時に access_tokenを取得し、アップする。

    public static String getGoogleApiToken(){
        String access_token ='';
        HttpRequest req = new HttpRequest();
        String client_id = 'xxx';
        String client_secret = 'xx';
        String refresh_token ='xx';

        String endPoint = 'https://accounts.google.com/o/oauth2/token';
        req.setHeader('Content-Type', 'application/x-www-form-urlencoded');
        req.setEndpoint(endPoint);
        req.setMethod('POST');
          String body = 'client_id='+EncodingUtil.urlEncode(client_id,'UTF-8') 
          +'&client_secret='+EncodingUtil.urlEncode(client_secret,'UTF-8')
          +'&refresh_token='+EncodingUtil.urlEncode(refresh_token,'UTF-8')
          +'&grant_type='+EncodingUtil.urlEncode('refresh_token','UTF-8');
        req.setBody(body);

        Http http = new Http();
        HTTPResponse res = http.send(req);
        System.debug('*Resp:' + String.ValueOF(res.getBody()));

        if(res.getStatusCode() == 200){
            Map<String, Object> requestBody = (Map<String, Object>)JSON.deserializeUntyped(res.getBody());
            access_token = String.valueOf(requestBody.get('access_token'));
            system.debug('access_token=' + access_token);
        }
        return access_token;
     }
  public static String uploadFileToYoutube(String pId){
        String access_token = getGoogleApiToken();

        List<ContentVersion> cvList = getContentVersionList(pId);
        String endPoint = 'https://www.googleapis.com/upload/youtube/v3/videos';
        //以下設定方法また不明

    /**
            + '&part='+EncodingUtil.urlEncode('snippet','UTF-8') 
            + '&snippet.title='+EncodingUtil.urlEncode('test of a title','UTF-8')
            + '&snippet.title='+EncodingUtil.urlEncode('test of a title','UTF-8')
            + '&status.license='+EncodingUtil.urlEncode('creativeCommon','UTF-8')
            + '&snippet.description='+EncodingUtil.urlEncode('test of video description','UTF-8');

        ***/
        HttpRequest req = new HttpRequest();
        req.setHeader('Content-Type', 'application/octet-stream');
        // req.setHeader('Content-type', 'video/mp4');
        req.setHeader('Authorization', 'Bearer '+ access_token);
        req.setEndpoint(endPoint);
        req.setMethod('POST');
        req.setBodyAsBlob(cvList[0].VersionData);

          Http http = new Http();
          HTTPResponse res = http.send(req);
  
          System.debug('*Resp:' + String.ValueOF(res.getBody()));

          if(res.getStatusCode() == 200){
              return endPoint;
          }
          return '';
     }

現状、動画アップできましたが、「利用規約とポリシー」で自動的に非公開にしてしまいました。。。

参考:

https://pretagteam.com/question/upload-video-on-youtube-using-curl-and-api-v3

https://qiita.com/shin1ogawa/items/49a076f62e5f17f18fe5

Salesforce ゲストユーザ Insertデータ トリガーでデータ検索

ゲストユーザをデータを検索するため、あるオブジェクトにINSERTして、トリガー動かして検索処理を行う。
  ⇒ トリガーのHandlerクラスが with sharing の場合、検索できませんでした。

  Inherited Sharing に変更すれば検索できるようになりました。

参考: https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_keywords_sharing.htm

with sharing
without sharing
inherited sharing

LWC 項目API名利用する方法


import AAAAA from ‘@salesforce/schema/object__c.columnapi__c’;

参照: AAAAA.fieldApiName

ついでに
① 項目の値の値を取得

getLightningInputFieldValue(fieldNameStr){
        const inputFields = this.template.querySelectorAll('lightning-input-field');
        let retValue;
        if (inputFields) {
            inputFields.forEach(field => {
                if(field.fieldName == fieldNameStr) {
                    retValue = field.value;
                }
            });
        }

        return retValue;
}


②標準項目のリセット

    resetLightningInputField(fieldNameStr){
        const inputFields = this.template.querySelectorAll('lightning-input-field');
        if (inputFields) {
            inputFields.forEach(field => {
                if(field.fieldName == fieldNameStr) {
                    field.reset();
                }
            });
        }
    }

    //項目リセット
    resetAllField() {
        const inputFields = this.template.querySelectorAll('lightning-input-field');
        if (inputFields) {
            inputFields.forEach(field => {
                field.reset();
            });
        }
    }