Jetpack Compose - How Do I program this composable to access the "url" in the "list" - android-jetpack-navigation

//I'm having problems trying to get the title text in the KbfPlayScreen.kt to access the "url" in the list that is in the Data.kt on button click.
**KbfPlayScreen.kt**
#Composable
fun KbfSermonsView(sermons: List<Sermon>) {
Column() {
sermons.forEach {
SermonRow(it.title, it.timestamp)
Divider(thickness = 1.dp, modifier = Modifier.padding(top = 5.dp, bottom = 5.dp))
}
}
}
**Data.kt**
val kbfList = listOf<Kbf>(
Kbf(
title = "The Purpose Of KBF", description = "", imageId = R.drawable.kbf_tony, sermons =
listOf<Sermon>(
Sermon(title= "The Purpose Of KBF", image= "kbf_tony", url=
"https://www.youtube.com/embed/O5xZCZlCqBw", timestamp= "1612674000"),
)),
Kbf(
title = "Goal Setting", description = "", imageId = R.drawable.kbf_mike, sermons =
listOf<Sermon>(
Sermon(title = "Goal Setting", image = "kbf_mike", url =
"https://www.youtube.com/embed/HRDPWpUagxY", timestamp = "1612674000")
))
)

Related

Looping over tags/aliases instead of whole resource

I'm trying to figure out a way to loop over a list of aliases for Datadog dashboards.
In 1 single dashboard I want to have multiple servers involved that will be fetched from variables.
For example:
variable "africa" {
type = map(any)
default = {
"server1" = {
alias = "server1"
hostname = "hostname1"
name = "query1"
formula_expression = "query1 * 8"
}
"server2" = {
name = "server2"
hostname = "hostname2"
name = "query2"
formula_expression = "query2 * 8"
}
"server3" = {
name = "server3
hostname = "hostname3"
name = "query3"
formula_expression = "query3 * 8"
}
}
}
resource "datadog_dashboard" "global_dashboards_africa" {
title = "Terraform - Africa"
description = "Dashboards for Global"
layout_type = "ordered"
widget {
group_definition {
title = "Quick Overview"
show_title = "true"
layout_type = "ordered"
widget {
timeseries_definition {
title = "Traffic"
title_size = "16"
title_align = "left"
show_legend = false
legend_layout = "auto"
legend_columns = ["avg", "min", "max", "value", "sum"]
request {
for server in var.africa:
formula {
alias = ${alias}
formula_expression = ${formula_expression}
}
query {
metric_query {
name = ${name}
query = "max:system.net.bytes_sent{device:bond0,host:${hostname}}"
}
}
style {
palette = "warm"
line_type = "solid"
line_width = "normal"
}
display_type = "area"
}
yaxis {
include_zero = "true"
scale = "linear"
min = "auto"
max = "auto"
}
}
widget_layout {
x = "0"
y = "5"
width = "12"
height = "5"
}
}
}
}
}
I've added for_each at the top, right after resource but it creates only 3 resources. I want to create 1 resource and in aliases - add like 50 servers with hostnames and names in specific locations.
I've tried multiple solutions but Terraform cannot help me with this.

Achieve Vertical Grid View in Jetpack Compose

My Code :::
#Composable
fun VerticalImageCards(toolsList: List<HealthTool>) {
val domainName = stringResource(id = R.string.media_url)
FlowRow(mainAxisSpacing = 8.dp,
crossAxisSpacing = 16.dp,
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 16.dp),
mainAxisSize = SizeMode.Wrap) {
for (i in toolsList) {
val imgUrl = "$domainName${i.url}"
ToolsCardLayout(cardTitle = i.title, imgUrl = imgUrl)
}
}
}
#Composable
fun ToolsCardLayout(
imgUrl: String,
cardTitle: String,
) {
Box(modifier = Modifier.clickable {}) {
AsyncImage(model = imgUrl,
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxWidth())
Box(modifier = Modifier
.size(32.dp)
.align(Alignment.TopEnd)) {
Image(painter = painterResource(id = R.drawable.schedule),
contentDescription = null,
modifier = Modifier
.fillMaxSize()
.padding(top = 8.dp, end = 8.dp),
contentScale = ContentScale.Fit)
}
}
Card(modifier = Modifier
.height(44.dp)
.fillMaxWidth()) {
Text(text = cardTitle,
style = MaterialTheme.typography.h6,
modifier = Modifier
.padding(horizontal = 16.dp, vertical = 8.dp)
.clip(RoundedCornerShape(bottomStart = 8.dp, bottomEnd = 8.dp)))
}
}
Code Explanation:::
I'm getting a list of tools details which is having tool image, title, description from server.
imgURl -> url for image
cardTitle -> tool's name
Problem :::
Card is taking the whole width. Earlier, I used weight(1f) when the data was hardcoded and I don't have to retrieve it from backend. Also, I'm going to use it on the Homescreen, so the grid shouldn't be scrollable.
PLEASE VISIT THIS DRIVE LINK FOR MORE DETAILS, I have added code snippet and images + screen recording for better understanding
You can use official LazyVerticalGrid
#Composable
fun VerticalImageCards(toolsList: List<HealthTool>) {
val domainName = stringResource(id = R.string.media_url) {
LazyVerticalGrid(
columns = GridCells.Fixed(2),
modifier = modifier,
state = rememberLazyGridState()
) {
items(toolsList) {
val imgUrl = "$domainName${it.url}"
ToolsCardLayout(cardTitle = it.title, imgUrl = imageUrl)
}
}
}

Align composable to bottom of another composable in Jetpack compose?

I have 3 composable in Column and I want to align 2nd composable to bottom of 1st composable like this:
But currently i'm getting output like this:
Here is my current code:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ComposePlaygroundTheme {
Column(modifier = Modifier
.fillMaxSize()) {
topControls("Game 1",34,Modifier.weight(1f))
centerControls()
bottomControls()
}
}
}
}
}
#Composable
fun topControls(gamename: String, totalTime: Int, modifier: Modifier) {
Column(modifier = modifier
.background(Color.LightGray)
.padding(start = 24.dp, end = 24.dp, top = 24.dp)) {
Row(modifier = Modifier.padding(end = 32.dp)) {
Image(
painter = painterResource(R.drawable.ic_launcher_foreground),
contentDescription = "",
Modifier
.height(32.dp)
.width(32.dp)
)
Text(
text = gamename,
modifier = Modifier
.weight(1f)
.align(Alignment.CenterVertically),
textAlign = TextAlign.Center
)
}
Text(text = totalTime.toString(),modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center,fontSize = 53.sp)
Image(
painter = painterResource(R.drawable.ic_launcher_background),
contentDescription = "",
Modifier.fillMaxSize(),
contentScale = ContentScale.FillBounds
)
}
}
#Composable
fun centerControls() {
Box(modifier = Modifier
.fillMaxWidth()) {
Divider(color = Color.Blue, thickness = 1.dp, modifier = Modifier.align(Alignment.Center))
Row(modifier = Modifier.padding(start = 20.dp, end = 20.dp)) {
Button(onClick = { },colors = ButtonDefaults.buttonColors(backgroundColor = Color.Black,contentColor = Color.White), modifier = Modifier
.weight(1f)
.padding(end = 20.dp)
.fillMaxWidth()) {
Text(text = "End Game",modifier = Modifier
.wrapContentWidth()
.wrapContentHeight(), textAlign = TextAlign.Center,fontSize = 20.sp)
}
Image(painter = ColorPainter(Color.Gray), contentDescription = "", modifier = Modifier
.padding(horizontal = 25.dp)
.align(Alignment.CenterVertically)
.height(32.dp)
.width(32.dp))
}
}
}
#Composable
fun bottomControls() {
Spacer(modifier = Modifier.height(170.dp))
}
Is there anyway I can achieve this in jetpack compose without using Constraint layout?
As you need to place one view under an other one, you should use Box.
Using Modifier.align, you can specify position of your centerControls, in this case Alignment.BottomCenter.
Using Modifier.layout you can add offset, equal to half view size.
Column(modifier = Modifier
.fillMaxSize()
) {
Box(Modifier.weight(1f)) {
topControls("Game 1", 34, Modifier.fillMaxHeight())
centerControls(
Modifier
.align(Alignment.BottomCenter)
.layout { measurable, constraints ->
val placeable = measurable.measure(constraints)
layout(placeable.width, placeable.height) {
placeable.place(0, placeable.height / 2)
}
}
)
}
bottomControls()
}
Result:
Something like this should work
ComposePlaygroundTheme {
Column(modifier = Modifier
.fillMaxSize()) {
topControls("Game 1",34)
Box(modifier = Modifier.weight(1f)) { // FrameLayout, weight will occupy rest of the content
centerControls()
bottomControls() // will be stacked up on top of topControls()
}
}
}

Terraform reusing config blocks

Terraform noob here. I have a datadog config along the line of (shamelessly copied from terraform website):
resource "datadog_dashboard" "ordered_dashboard" {
title = "Ordered Layout Dashboard"
description = "Created using the Datadog provider in Terraform"
layout_type = "ordered"
is_read_only = true
widget { # SIMILAR GRAPH
alert_graph_definition {
alert_id = "895605"
viz_type = "timeseries"
title = "Widget Title"
live_span = "1h"
}
}
widget { # SIMILAR GRAPH
alert_graph_definition {
alert_id = "895605"
viz_type = "timeseries"
title = "Widget Title"
live_span = "2h"
}
}
widget {
alert_value_definition {
alert_id = "895605"
precision = 3
unit = "b"
text_align = "center"
title = "Widget Title"
}
}
widget { # SIMILAR GRAPH
alert_graph_definition {
alert_id = "895605"
viz_type = "timeseries"
title = "Widget Title"
live_span = "1w"
}
}
widget { # SIMILAR GRAPH
alert_graph_definition {
alert_id = "895605"
viz_type = "timeseries"
title = "Widget Title"
live_span = "2w"
}
}
}
As seen, we have 5 graphs: graph 1,2,4 and 5 are very similar, and only differ at 1 attribute, whereas graph 3 is very different. Is there a strategy in TF to reuse all the configs for graph 1,2 4 and 5?
I have attempted at using dynamic blocks, but while dynamic blocks can generate graphs 1 and 2 well, graph 3 is so different that I cannot fit it in the dynamic block.
In practice, the graphs are much more complex, and there are more of them, hence I find the config to be too hard to manage.
This is what I tried:
resource "datadog_dashboard" "ordered_dashboard" {
title = "Ordered Layout Dashboard"
description = "Created using the Datadog provider in Terraform"
layout_type = "ordered"
is_read_only = true
dynamic widget {
for_each = ["1h", "2h"]
iterator = live_span_iterator
content {
alert_graph_definition {
alert_id = "895605"
viz_type = "timeseries"
title = "Widget Title"
live_span = live_span_iterator.value
}
}
}
widget {
alert_value_definition {
alert_id = "895605"
precision = 3
unit = "b"
text_align = "center"
title = "Widget Title"
}
}
dynamic widget {
for_each = ["1w", "2w"]
iterator = live_span_iterator
content {
alert_graph_definition {
alert_id = "895605"
viz_type = "timeseries"
title = "Widget Title"
live_span = live_span_iterator.value
}
}
}
}
Are there any other strategies that might help me reduce the code duplication? I hope to retain the order of the graphs if possible.

How to use the ThumbnailCard in IDialog Context

Hi I am developing one bot using Microsoft botframework project in that I am using IDialog interface. In that I am using the ThumbnailCard for displaying the cards. Here when I am attaching some data to my cards and the data is attaching properly but within the PostAsync method it’s not providing the reply.
public virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
ThumbnailCard plCard = null;
IMessageActivity replyToConversation =await argument;
replyToConversation.Type = "message";
replyToConversation.Attachments = new List<Attachment>();
replyToConversation.Text = "welcome to book my show";
Dictionary<string, string> cardContentList = new Dictionary<string, string>();
cardContentList.Add("Jason Bourne", "URL");
cardContentList.Add("The Land", "URL");
cardContentList.Add("Yoga Hosers", "URL");
foreach (KeyValuePair<string, string> cardContent in cardContentList)
{
List<CardImage> cardImages = new List<CardImage>();
cardImages.Add(new CardImage(url: cardContent.Value));
List<CardAction> cardButtons = new List<CardAction>();
if (cardContent.Key == "Jason Bourne")
{
CardAction plButton1 = new CardAction()
{
Value = $"",
Type = "openUrl",
Title = "Book Now"
};
CardAction plButton2 = new CardAction()
{
Value = "tel:1-800-800-5705",
Type = "call",
Title = "Show timings"
};
cardButtons.Add(plButton1);
cardButtons.Add(plButton2);
plCard = new ThumbnailCard()
{
Title = $"Jason Bourne",
Subtitle = " ",
Images = cardImages,
Buttons = cardButtons,
};
Attachment plAttachment = plCard.ToAttachment();
replyToConversation.Attachments.Add(plAttachment);
}
else if (cardContent.Key == "The Land")
{
CardAction plButton1 = new CardAction()
{
Value = $"",
Type = "openUrl",
Title = "Book Now"
};
CardAction plButton2 = new CardAction()
{
Value = "tel:1-800-800-5705",
Type = "call",
Title = "Show Timings"
};
cardButtons.Add(plButton1);
cardButtons.Add(plButton2);
plCard = new ThumbnailCard()
{
Title = $"The Land",
Subtitle = "",
Images = cardImages,
Buttons = cardButtons,
};
Attachment plAttachment = plCard.ToAttachment();
replyToConversation.Attachments.Add(plAttachment);
}
else if (cardContent.Key == "Yoga Hosers")
{
CardAction plButton1 = new CardAction()
{
Value = $"",
Type = "openUrl",
Title = "Book Now"
};
CardAction plButton2 = new CardAction()
{
Value = "tel:1-800-800-5705",
Type = "call",
Title = "Show timings"
};
cardButtons.Add(plButton1);
cardButtons.Add(plButton2);
plCard = new ThumbnailCard()
{
Title = $"Yoga Hosers",
Subtitle = "",
Images = cardImages,
Buttons = cardButtons,
};
Attachment plAttachment = plCard.ToAttachment();
replyToConversation.Attachments.Add(plAttachment);
}
}
replyToConversation.AttachmentLayout = AttachmentLayoutTypes.List;
await context.PostAsync(replyToConversation);
}
When I run the bot its show the following error
Can we use cards in IDialog Context for attachments?
The issue is with the IMessageActivity, you are trying to send IMessageActicity in context.PostAsync. That's the reason it is failing.
Do the following changes to make it work
Change the method signature like below
private async Task messageReceived(IDialogContext context, IAwaitable<object> argument)
and modify the IMessageActivity replyToConversation =await argument; to like below
var message = await argument as Activity;
Activity replyToConversation = message.CreateReply("Welcome." + "(Hi)");
replyToConversation.Recipient = message.From;
Now it should work, if you still have issue please comment here.
-Kishore

Resources