Lightning Web Component実装例2 オブジェクトにいいねボタン

前回の記事はこちら　https://qiita.com/geeorgey/items/ff2ab9503091366dfb7d

SalesforceにはChatterというチャットコミュニケーションツールがついていて、そこにはいいねつけたりできるのですが、商談や取引先や取引先責任者やリードといった基本的なオブジェクトにはそういう機能はついていません。
業務用のアプリなのであんまり遊んでも仕方ないというのもあるかもしれませんが、LWCの勉強がてらちょっと作ってみました。

![dkini-v4ej8.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/1a1d1da4-a0b0-c718-91be-cd026ba63044.gif)

## 格納用のオブジェクトを作る
ホントはケースオブジェクトについてるwhatid みたいな、どのオブジェクトにも接続できますよっていう項目が作れると良いのですが、それはできないので自力で作りましょう。
Likeオブジェクトみたいなものを作成し、参照項目として
Opportunity
Account
Contact
Lead
と接続した項目を追加します。
Likeボタンを押すと、このオブジェクトにレコードが追加される感じですね。
以下ではLID_Timeline__cというオブジェクト名になってます。

## フロントエンド
``` like.html
<template>
    <lightning-card title="Lnest Like" icon-name="utility:like">
        <div class="slds-grid slds-wrap slds-box">
            <lightning-button label={toggleLikeButtonLabel} title="Toggle content action" icon-name={toggleLikeIconName}
            variant={toggleLikeButtonVariant} 
            onclick={handleLikeToggleClick}>
            </lightning-button>
            <template if:true={goodmembers}>
                <template for:each={goodmembers} for:item="d">
                    <img src={d.LnestID_like_owner__r.smallphoto_url__c} key={d.key} style="width:35px;border-radius: 17.5px;" />
                </template>
            </template>
        </div>
    </lightning-card>
</template>
```
lightning-buttonでボタンを配置。
ボタンの右側にgoodmembersというリストを受け取って、アイコン画像を表示するシンプル設計。

``` like.js
import { LightningElement, api, track,wire } from 'lwc';
import add_good from '@salesforce/apex/Like.add_good';
import has_applied_good from '@salesforce/apex/Like.has_applied_good';
import getObj_name_front from '@salesforce/apex/Like.getObj_name_front';
import remove_good from '@salesforce/apex/Like.remove_good';

export default class Like extends NavigationMixin(LightningElement) {
    toggleLikeIconName = 'utility:like';
    toggleLikeButtonLabel = 'Add Like';
    toggleLikeButtonVariant = '';

    handleLikeToggleClick() {
        console.log('handleLikeToggleClick: ' + this.toggleLikeIconName);
        if (this.toggleLikeIconName === 'utility:like') {
            this.toggleLikeIconName = '';
            this.toggleLikeButtonLabel = 'Remove Like';
            this.toggleLikeButtonVariant = 'brand';
            const param = [
                { recordId: this.recordId,userId: this.userId }
            ];
            add_good({param: JSON.stringify(param)})
			.then(result => {
				this.goodmembers = result;
			})
			.catch(error => {
				this.error = error;
			});
        } else {
            this.toggleLikeIconName = 'utility:like';
            this.toggleLikeButtonLabel = 'Add Like';
            this.toggleLikeButtonVariant = '';
            const param = [
                { recordId: this.recordId,userId: this.userId }
            ];
            console.log('remove_good start')
            remove_good({param: JSON.stringify(param)})
			.then(result => {
                console.log(result)
				this.goodmembers = result;
			})
			.catch(error => {
				this.error = error;
			});

        }
    }
```

html側でhandleLikeToggleClickが発火したときに、ボタンの状態を切り替えてデータをaddするかremoveするかの判定をしています。
this.toggleLikeIconName 
アイコン名を変更してるのでそれで判断する形です。


```Like.cls
public with sharing class Like {

    //apexからの要求でオブジェクトタイプを返却する
    private static string getObj_name(String recordId){
        Schema.SObjectType st = Id.valueOf(recordId).getSobjectType();
        Schema.DescribeSObjectResult dsr = st.getDescribe();
        String Obj_name = dsr.getName();
        return Obj_name;
    }

    @AuraEnabled
    public static LIST<LID_Timeline__c> add_good(string param){
        system.debug('add_good start');
        List<Object> lm = (List<Object>)JSON.deserializeUntyped(param);
        String recordId;
        String userId;
        //https://note.com/koji_matae/n/n2344bde286bc
        for(Integer i=0 ; i<lm.size() ; i++) {
            Map<String, Object> m = (Map<String, Object>)lm[i];
            recordId = (String)m.get('recordId');
            userId = (String)m.get('userId');
        }

        //オブジェクト判定
        String Obj_name = getObj_name(recordId);
        LID_Timeline__c myGood = new LID_Timeline__c();
        if(Obj_name == 'Opportunity'){
            myGood.Opportunity__c = recordId;
        }else if(Obj_name == 'Account'){
            myGood.Account__c = recordId;
        }else if(Obj_name == 'Contact'){
            myGood.Contact__c = recordId;
        }else if(Obj_name == 'Lead'){
            myGood.Lead__c = recordId;
        }
        insert myGood;

        LIST<LID_Timeline__c> goodAll = new LIST<LID_Timeline__c>();
        String allparam = '[{"recordId": "' + recordId + '"}]';
        goodAll = get_good_list(allparam);
        return goodAll;
    }


    @AuraEnabled
    public static LIST<LID_Timeline__c> remove_good(string param){
        system.debug('remove_good start');
        List<Object> lm = (List<Object>)JSON.deserializeUntyped(param);
        String recordId;
        String userId;
        //https://note.com/koji_matae/n/n2344bde286bc
        for(Integer i=0 ; i<lm.size() ; i++) {
            Map<String, Object> m = (Map<String, Object>)lm[i];
            recordId = (String)m.get('recordId');
            userId = (String)m.get('userId');
        }

        //オブジェクト判定
        String Obj_name = getObj_name(recordId);
        ID myLID = myLnestID[0].id;
        String sqlString='select id FROM LID_Timeline__c WHERE User = :userId AND ';
        myGood = Database.query(addOptionQuery(sqlString,Obj_name,goodString));
        delete myGood;

        LIST<LID_Timeline__c> goodAll = new LIST<LID_Timeline__c>();
        String allparam = '[{"recordId": "' + recordId + '"}]';
        goodAll = get_good_list(allparam);
        return goodAll;
    } 


    private static string addOptionQuery(String sqlString,String Obj_name,String goodString){
        if(Obj_name == 'Opportunity'){
            sqlString += 'Opportunity__c = :recordId';
        }else if(Obj_name == 'Account'){
            sqlString += 'Account__c = :recordId';
        }else if(Obj_name == 'Contact'){
            sqlString += 'Contact__c = :recordId';
        }else if(Obj_name == 'Lead'){
            sqlString += 'Lead__c = :recordId';
        }
        return sqlString;
    }
}

```

テスト

```Like_test.cls
@istest(seealldata=true)
public with sharing class Like_test {

	@isTest
	static void testMethod_add() {
        User admin = [select id from User where id = 'xxxxxxx'];←ユーザIDは適当な物を使うか、新規に生成してください。
        System.runAs(admin){
            List<Opportunity>ops = new List<Opportunity>();
            ops = [select id from Opportunity Order By CreatedDate Desc LIMIT 1];
            String param = '[{"recordId":"'+ ops[0].id + '","userId": "00510000001tXKg"}]';
            LIST<LID_Timeline__c> res = new LIST<LID_Timeline__c> ();
            res = Like.get_good_list(param);
            Like.has_applied_good(param);
	}
}
```