public override async Task FollowUp()
        {
            //If Salesforce object is empty then we should clear filters as they are no longer applicable
            if (string.IsNullOrEmpty(SelectedChatter))
            {
                Storage.RemoveByLabel(QueryFilterCrateLabel);
                Storage.RemoveByLabel(SalesforceObjectFieldsCrateLabel);
                this[nameof(SelectedChatter)] = SelectedChatter;
                return;
            }
            //If the same object is selected we shouldn't do anything
            if (SelectedChatter == this[nameof(SelectedChatter)])
            {
                return;
            }
            //Prepare new query filters from selected object properties
            var selectedObjectProperties = await _salesforceManager.GetProperties(SelectedChatter.ToEnum <SalesforceObjectType>(), AuthorizationToken, false, PostedFeedCrateLabel);

            var queryFilterCrate = Crate <FieldDescriptionsCM> .FromContent(
                QueryFilterCrateLabel,
                new FieldDescriptionsCM(selectedObjectProperties));

            Storage.ReplaceByLabel(queryFilterCrate);

            var objectPropertiesCrate = Crate <FieldDescriptionsCM> .FromContent(
                SalesforceObjectFieldsCrateLabel,
                new FieldDescriptionsCM(selectedObjectProperties));

            Storage.ReplaceByLabel(objectPropertiesCrate);
            this[nameof(SelectedChatter)] = SelectedChatter;
            //Publish information for downstream activities
            CrateSignaller.MarkAvailableAtRuntime <StandardTableDataCM>(PostedFeedCrateLabel);
        }
        public override async Task Run()
        {
            var feedText = FeedText;

            if (IsPostingToQueryiedChatter)
            {
                try
                {
                    var chatters = await _salesforceManager.Query(SelectedChatter.ToEnum <SalesforceObjectType>(),
                                                                  new[] { new FieldDTO("Id") },
                                                                  FilterConditionHelper.ParseConditionToText(JsonConvert.DeserializeObject <List <FilterConditionDTO> >(ChatterFilter)),
                                                                  AuthorizationToken);

                    var tasks = new List <Task <string> >(chatters.Table.Count);
                    foreach (var chatterId in chatters.DataRows.Select(x => x.Row[0].Cell.Value))
                    {
                        Logger.Info($"Posting message to chatter id: {chatterId}");

                        tasks.Add(_salesforceManager.PostToChatter(StripHTML(feedText), chatterId, AuthorizationToken).ContinueWith(x =>
                        {
                            Logger.Info($"Posting message to chatter succeded with feedId: {x.Result}");
                            return(x.Result);
                        }));
                    }
                    await Task.WhenAll(tasks);

                    //If we did not find any chatter object we don't fail activity execution but rather returns empty list and inform caller about it
                    if (!chatters.HasDataRows)
                    {
                        Logger.Info("No salesforce objects were found to use as chatter id.");
                        Success($"No {SelectedChatter} that satisfies specified conditions were found. No message were posted");
                    }
                    else
                    {
                        var resultPayload = new StandardPayloadDataCM();
                        resultPayload.PayloadObjects.AddRange(tasks.Select(x => new PayloadObjectDTO(new KeyValueDTO(FeedIdKeyName, x.Result))));
                        Payload.Add(Crate <StandardPayloadDataCM> .FromContent(PostedFeedCrateLabel, resultPayload));
                    }
                }
                catch (Exception ex)
                {
                    RaiseError(ex.Message);
                    return;
                }
            }
            else
            {
                var incomingChatterId = IncomingChatterId;
                if (string.IsNullOrWhiteSpace(incomingChatterId))
                {
                    throw new ActivityExecutionException("Upstream crates doesn't contain value for feed parent Id");
                }

                Logger.Info($"Posting message to chatter id: {incomingChatterId}");

                var feedId = await _salesforceManager.PostToChatter(StripHTML(feedText), incomingChatterId, AuthorizationToken);

                Logger.Info($"Posting message to chatter succeded with feedId: {feedId}");

                Payload.Add(Crate.FromContent(PostedFeedCrateLabel, new StandardPayloadDataCM(new KeyValueDTO(FeedIdKeyName, feedId))));
            }
        }