ファイルの詳細表示画面で投稿元の情報を表示する

Salesforceのファイルの詳細表示画面では、投稿元の情報が出ていません。
たまに、元のChatterを確認したいとは思っていました。
ちょうど、質問に上がっていたので簡単に作成してみました。
（設定があるかは分からなかったので、初めからコーディングだなと思いました）


#出来上がりのイメージ

コンポーネントを作って追加することで対応します。（赤矢印）
一応、複数の投稿元があってもいいようには考えます。

![サンプル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/c7e7831a-5af2-0d42-8eb6-1bfe0ef2f51d.png)


#ソースコード
今回はソースも公開します。

getFileToChatter.cmp

```
<aura:component controller="getFileToChatter" implements="flexipage:availableForAllPageTypes,force:hasRecordId" access="global">
    <!-- ************************************************** -->
    <!-- 添付ファイルからChatter情報を取得する                 -->
    <!--  K.Otsubo 2021/01/13                               -->
    <!--                                                    -->
    <!-- ************************************************** -->
    
    
    <aura:attribute name="recordId" type="String" /> <!-- ContentDocumentId -->
    <aura:attribute name="message" type="String" />
    <aura:attribute name="myFeedItemList" type="List" />
    
    <!-- 画面ロード時のイベントがあればここに書く          -->  
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    
    <div class="slds-box slds-box_xx-small slds-text-align_left slds-m-around_xx-small slds-theme_default">
        <lightning:layout multipleRows="true">    
            <lightning:layoutItem padding="around-xx-small" flexibility="grow" size="12" mediumDeviceSize="12" largeDeviceSize="12"> 
                
                <lightning:layout verticalAlign="center" multipleRows="true">
                    <div class="slds-size_12-of-12">{!v.message}</div>
                    
                    <table class="slds-table--bordered slds-table_cell-buffer" >                                                                  
                        <thead> 
                            <tr>
                            	<th>No</th>
                                <th>Title</th>
                                <th>本文</th>
                            </tr>
                        </thead>
                        <tbody> 
                            <aura:iteration items="{!v.myFeedItemList}" var="detail" indexVar="sNo">
                                <tr>
                                    <td>{!sNo+1}</td>
                                    <td>{!detail.Title}</td>
                                    <td>{!detail.Body}</td>
                                </tr>
                            </aura:iteration>
                        </tbody>
                    </table>
                
                </lightning:layout>
            </lightning:layoutItem>
        </lightning:layout>
    </div>
    
</aura:component>
```

コントローラ

```
({
	doInit : function(component, event, helper) {    
        helper.getRecordALL(component, event);    
	},
    
    
    
})

```

ヘルパー

```
({
	getRecordALL : function(component, event) {
		var myId = component.get("v.recordId");
        var action = component.get("c.getInitSearch");
        action.setParams({"myId":myId});
        action.setCallback(this, function(a){
            if (action.getState() == "SUCCESS") {   
                var myVal = action.getReturnValue();                
                component.set("v.dispMap",myVal);
                var myFeedItemList = myVal.myFeedItemList;                
                //alert(JSON.stringify(myFeedItemList[0]["Body"].replace(/<("[^"]*"|'[^']*'|[^'">])*>/g,'')));
                var len = myFeedItemList.length;
                var step;
                for (step = 0; step < len ; step++) {
                    //HTMLタグを除去して30文字だけにする
                    myFeedItemList[step]["Body"] = myFeedItemList[step]["Body"].replace(/<("[^"]*"|'[^']*'|[^'">])*>/g,'').substring(1,30);
                }
                component.set("v.myFeedItemList",myFeedItemList);
            }  else if (action.getState() == "ERROR" ) {
                var errors = a.getError();
                if (errors[0] && errors[0].message) {
                    // サーバーサイドでcatchできなかったパターン
                    component.set("v.message", errors[0].message);
                } 
            }
        });
        $A.enqueueAction(action);
		
	},
})
```

getFileToChatter.apex

```
public with sharing class getFileToChatter {
	// **************************************************************
    // 添付ファイルからChatter情報を取得する                
    // K.Otsubo 2021/01/13    
    //                 
    // **************************************************************
    
    
    /**
	* doInitの呼び出しをまとめる myIdはContentDocumentId
	*/    
    @AuraEnabled
    public static Map<String,Object> getInitSearch(String myId) {
        Map<String,Object>  RetMap = new Map<String,Object>();
        
        List<FeedItem> myFeedItemList = getFeedItem(myId);
        RetMap.put('myFeedItemList',myFeedItemList);
        
        return RetMap;        
    }
    
    
    public static List<FeedItem>  getFeedItem(String myId) {
        List<FeedItem> RetFeedItemList = new List<FeedItem>();
        if (String.isEmpty(myId)) return RetFeedItemList;
        if (myId == 'undefined') return RetFeedItemList;
        
        List<ContentVersion> ContentVersionIdList = [select Id from ContentVersion where ContentDocumentId =: myId];
        
        List<feedAttachment> feedAttachmentIdList = [select FeedEntityId from feedAttachment where RecordId =: ContentVersionIdList];
        
        Set<String> feedAttachmentIdSet = new Set<String>();
        for (feedAttachment f : feedAttachmentIdList){
            feedAttachmentIdSet.add(f.FeedEntityId);
        }
        
        RetFeedItemList = [select Id,Title,Body,LastEditDate from feedItem where Id=: feedAttachmentIdSet];
        
               
        return RetFeedItemList;
        
    }
     
}
```

テストクラス

```
@isTest
public class getFileToChatter_test {
    // **************************************************************
    // 添付ファイルからChatter情報を取得する Test Apex                
    // K.Otsubo 2021/01/15    
    //                 
    // **************************************************************

    
    static testMethod void test_main(){
        
 		// プロファイルを取得する
		Profile p = [select Id from Profile where Name = '標準 Platform ユーザ'];
         
        // ユーザを作成する
		User u = new User();
        u.FirstName = 'keiji';
		u.LastName = 'Otsubo';
		u.Alias = 'Otsubo';
		u.Email = 'K_otsubo@test.com';
		u.UserName = u.Email;
		u.EmailEncodingKey = 'ISO-2022-JP';
		u.TimeZoneSidKey = 'Asia/Tokyo';
		u.LocaleSidKey = 'ja_JP';
		u.LanguageLocaleKey = 'ja';
		u.profileId = p.Id;        
		insert u;
        
        feedItem fi = new feedItem();
        fi.title = 'test';
        fi.Body = 'test';
        fi.ParentId = u.Id;
        fi.Type = 'TextPost';
        insert fi;
        
        ContentVersion cv = new ContentVersion(); // ファイル本体（バージョン管理）
        cv.Title  = 'test';
        cv.PathOnClient = cv.Title + '.pdf';
        cv.versionData = EncodingUtil.base64Decode('12345678');
        cv.ContentLocation = 'S';
        cv.ContentDocumentId = null; // 既にあるファイルはありません
        insert cv;
        
        List<ContentVersion> cv2 = [SELECT Id, Title, ContentDocumentId FROM ContentVersion WHERE Id =: cv.Id];
        feedAttachment fa = new feedAttachment();
        fa.FeedEntityId = fi.Id;
        fa.RecordId = cv2[0].Id;
        fa.Type = 'Content';
        insert fa;
        
        Test.startTest();
        
        Map<String,Object> RetMap = getFileToChatter.getInitSearch(cv2[0].ContentDocumentId);
        List<FeedItem> RetFiList = (List<FeedItem>)RetMap.get('myFeedItemList');
        System.assertEquals(RetFiList.size(),1);        
            
        Test.stopTest();
    }
}
```

この程度の短いコードですが、便利になったと思います。