ontap in the gesture detector in my code below is not work for me.
return Scaffold(
appBar: AppBar(
title: const Text('BMI CALCULATOR'),
),
body: Column(
children: [
Expanded(child: Row(
children: [
Expanded(
child: GestureDetector(
onTap: (){
setState(() {
selectedGender = Gender.male;
});
},
child: ReusableCard(
selectedGender == Gender.male? activeColor:inactiveColor,
const IconContent(FontAwesomeIcons.mars,"MALE")
),
),
),
I try to tap the maleCard then the color is not changed to active
it is not work as I expect please any one can help me
Every time onTap clicked selectedGender is getting the same value and that's why its not changing the color
setState(() {
selectedGender = Gender.male;
});
At above selected Gender value is always Gender.Male
You can do it like this
setState(() {
(selectedGender==Gender.male)?(selectedGender=Gender.female):(selectedGender=Gender.male)
});
In changed code when you click on tap then first it will check the value of selectedFender and if its value is male then it will changed into female and vice versa
Related
New to typescript and have been using it for 2 days now mainly to build a custom component for my streamlit app. I have created the below navigation bar and the custom component is a tab that can be clicked on the sidebar though it is behaving strangely. When I click on the component tab, sometimes it loads the corresponding page and at times it does not as demonstrated below:
custom navigation bar gif
I have a hunch it might be how I wrote the typescript code, perhaps the onClick function. Is there a better way to do this so as to:
return the value input labelName via Streamlit.setComponentValue()
make sure that upon clicking on the component tab, it actually loads the page behind it? I have placed the python code for how it should behave below:
Typescript component
import {
Streamlit,
StreamlitComponentBase,
withStreamlitConnection,
} from "streamlit-component-lib"
import React, { ReactNode } from "react"
interface State {
navLabel: string|number
}
class MyComponent extends StreamlitComponentBase<State> {
public state = {navLabel: ""}
public render = (): ReactNode => {
const labelName = this.props.args["name"]
const iconName = this.props.args["iconName"]
const { theme } = this.props
const styles: React.CSSProperties = {}
return (
<div className="navtab" onClick={this.onClicked}>
<div className="content">
<input type="radio" name="indicator" id="input-data"/>
<div className="list">
<label htmlFor="input-data" className="input-data">
<span><i className="material-icons">{iconName}</i></span>
<span className="text-display">{labelName}</span>
</label>
</div>
</div>
</div>
)
}
private onClicked = (): void => {
this.setState(
prevState => ({navLabel: this.props.args["name"]}),
() => Streamlit.setComponentValue(this.state.navLabel)
)
}
Python execution code
import streamlit as st
import streamlit.components.v1 as components
def my_component(name, iconName, tabIndex, key=None):
component_value = _component_func(name=name, iconName=iconName, tabIndex=tabIndex, key=key, default='Option')
# We could modify the value returned from the component if we wanted.
# There's no need to do this in our simple example - but it's an option.
return component_value
with st.sidebar:
test = my_component(name='Dashboard', iconName='dashboard', tabIndex=1, key="1")
test_2 = my_component(name='Data Analysis', iconName='insights', tabIndex=2, key="2")
test_3 = my_component(name='Testing', iconName='business', tabIndex=3, key="3")
if test == 'Dashboard':
st.title("Dashboard")
st.write('Name of option is {}'.format(test))
elif test_2 == 'Data Analysis':
st.title("Data Analysis")
st.write('Name of option is {}'.format(test_2))
elif test_3 == "Testing":
st.title("Third one")
I was able to sort this out using the li and ul element:
import {
Streamlit,
StreamlitComponentBase,
withStreamlitConnection,
} from "streamlit-component-lib"
import React, { ReactNode } from "react"
interface State {
label: string,
icon: string
}
class MyComponent extends StreamlitComponentBase<State> {
public render = (): ReactNode => {
const labelName:string[] = this.props.args["name"]
const iconName:string[] = this.props.args["iconName"]
let data:any[] = [];
iconName.forEach((v,i) =>
data= [...data, {"id":i+1, "label": labelName[i], "icon":v}]
)
this.state = {
icon:data[0].icon,
label:data[0].label
}
const res = data.map(({id, icon, label}) => (
<span>
<li className="tab"
key={id}
onClick={() => this.setState(
prevState => ({icon:icon, label:label}),
() => Streamlit.setComponentValue(label)
)}><i className="material-icons">{icon}</i><span className="labelName">{label}</span></li></span>
))
return (
<div className="navtab">
<ul className="tab-options">
{res}
</ul>
</div>
)
}
}
I enjoy the simplicity of the stripe APIs but I'm not sure if it's possible to retrieve nested objects. I'd love to be able to retrieve all products and prices to display them publically on my website.
I can list all prices and products like this:
stripe.Price.list(limit=3)
stripe.Products.list(limit=3)
On the frontend, I then have to write some logic that associates the prices with the products, makes the distinctions for monthly and yearly prices etc. I'd love to have this nested. Is this possible?
I'm also not entirely sure if it is safe to expose the returned information publically (API key is obviously hidden). I'd love some more info on this.
Whenever an id is present in an object, the expand parameter can be called to also return that item.
This can be further explored in the Stripe docs for Expanding Responses: https://stripe.com/docs/expand
A solution in nodejs would be the following:
const productPriceData = await stripe.prices.list({
expand: ['data.product'], // 🎉 Give me the product data too!
})
I actually came across the same issue and documented how I got to this solution here: https://blog.focusotter.com/fetch-both-price-and-product-data-from-stripe-in-a-single-api-call
On the frontend, I then have to write some logic that associates the prices with the products, makes the distinctions for monthly and yearly prices etc. I'd love to have this nested. Is this possible?
The approach would be to first list the Products from the API, then iterate over them and retrieve all the Prices associated with a given Product:
List all Prices: https://stripe.com/docs/api/prices/list?lang=python
While specifying the Product ID: https://stripe.com/docs/api/prices/list?lang=python#list_prices-product
The Product object doesn't contain a list of its Prices, so there is really no way around making the two separate requests: https://stripe.com/docs/api/products/object
I'm also not entirely sure if it is safe to expose the returned information publically (API key is obviously hidden). I'd love some more info on this.
This is a good question, since generally speaking only objects retrievable with a publishable key are safe to directly consume client-side from the Stripe API. In those cases the API reference marks the properties on the object as "retrievable with a publishable key", for example:
Retrieve a PaymentIntent client-side: https://stripe.com/docs/js/payment_intents/retrieve_payment_intent
Properties retrievable: https://stripe.com/docs/api/payment_intents/object
But, as long as your server-side endpoint doesn't directly return the Product/Price objects retrieved using your secret key, and instead returns a filtered version with just the required properties you should be fine!
Do it the other way around; get all the prices, then get the corresponding product.
Create your Stripe instance first, and then request the data from your function
// index.ts
import { getStripeProduct, getStripeProducts } from './products'
import * as express from 'express'
import Stripe from 'stripe'
const router = express.Router()
const stripe = (apiKey:string) => {
return new Stripe(apiKey, {
apiVersion: "2020-08-27",
typescript: true
});
}
// GET a product
router.get('/product/:id', async (req: express.Request, res: express.Response) => {
console.log(`API call to GET /public/product/${req.params.id}`)
await getStripeProduct(stripe(STRIPE_SECRET_KEY)), req.params.id )
.then((product) => {
respond(res, {data: product})
})
.catch((error) => {
respond(res, {code: error.statusCode, message: error.message})
})
})
// GET a product list
router.get('/products', async (req: express.Request, res: express.Response) => {
console.log('API call to GET /public/products')
await getStripeProducts(stripe(STRIPE_SECRET_KEY))
.then((products) => {
respond(res, {data: products})
})
.catch((error) => {
console.error(error)
respond(res, {code: error.statusCode, message: error.message})
})
})
// products.ts
import { ProductModel } from '../../models'
import { Stripe } from 'stripe'
export async function getStripeProduct(stripe: Stripe, id: string) {
return new Promise((resolve, reject) => {
stripe.prices.retrieve(id)
.then(async (price) => {
const product: ProductModel = {
id: price.id,
name: 'Unnamed Product',
price: price.unit_amount,
recurring: price.recurring || undefined,
metadata: price.metadata
}
if(typeof(price.product) == 'string') {
await stripe.products.retrieve(price.product)
.then((stripeProduct) => {
product.name = stripeProduct.name
product.caption = stripeProduct.description || undefined
product.images = stripeProduct.images || undefined
product.active = stripeProduct.active
resolve(product)
})
}
resolve(product)
})
.catch((error:any) => {
reject(error)
})
})
}
export async function getStripeProducts(stripe: Stripe) {
return new Promise((resolve, reject) => {
stripe.prices.list()
.then(async (prices) => {
const products: ProductModel[] = []
for(let price of prices.data) {
const product: ProductModel = {
id: price.id,
name: 'Unnamed Product',
price: price.unit_amount,
recurring: price.recurring || undefined,
metadata: price.metadata
}
if(typeof price.product == 'string') {
await stripe.products.retrieve(price.product)
.then((stripeProduct) => {
product.name = stripeProduct.name
product.caption = stripeProduct.description || undefined
product.images = stripeProduct.images || undefined
product.active = stripeProduct.active
products.push(product)
})
}
}
resolve(products)
})
.catch((error:any) => {
reject(error)
})
})
}
// Product Model
export interface ProductModel {
id: string;
name: string;
caption?: string;
description?: string;
active?: boolean;
images?: string[];
price?: string | number | null;
recurring?: {
interval: string,
interval_count: number
},
metadata?: object
}
export class ProductModel implements ProductModel {
constructor(productData?: ProductModel) {
if (productData) {
Object.assign(this, productData);
}
}
}
NB: I have a utility function called respond that standarizes our API responses. You can just res.send the response
Read ttmarek's answer first. However, note that the pages do not seem to provide a full example if you need all the answers. From "List all Prices":
Each entry in the array is a separate price object. If no more prices
are available, the resulting array will be empty.
As it states, and is also stated here and in the docs, to get all of them, you need to loop until the resulting array is empty....
Here is some code that will get you all the products and all the prices...
import stripe
stripe.api_key = stripe_test_private_key
def get_all_stripe_objects(stripe_listable):
objects = []
get_more = True
starting_after = None
while get_more:
#stripe.Customer implements ListableAPIResource(APIResource):
resp = stripe_listable.list(limit=100,starting_after=starting_after)
objects.extend(resp['data'])
get_more = resp['has_more']
if len(resp['data'])>0:
starting_after = resp['data'][-1]['id']
return objects
all_stripe_products = get_all_stripe_objects(stripe.Product)
all_stripe_prices = get_all_stripe_objects(stripe.Price)
I am working with Clarifai's API to write the returned responses to a CSV. For each image I submit, I want to take the top 5 images and append their metadata to a row in a data frame with the file_id as the first column. So each image would have 5 rows with the metadata attached to it in each successive columns. I seem to be generating some dictionary entries where the order of the values in the list being appended isn't preserved and I am trying to figure out why. This is a sample response I am iterating over.
[score: 0.8935652375221252
input {
id: "1002648140"
data {
image {
url: "https://images.lowes.com/product/converted/192665/192665007798.jpg"
hosted {
prefix: "https://s3.amazonaws.com/clarifai-api/img3/prod"
suffix: "3617f25f9ee5463497e7abf350091b93/c1ee1a24260772d532f0d371ac08fb06"
sizes: "orig"
sizes: "tiny"
sizes: "small"
sizes: "large"
}
}
metadata {
fields {
key: "cat_entry_id"
value {
string_value: "1002648140"
}
}
fields {
key: "catalog_name"
value {
string_value: "Roses"
}
}
fields {
key: "catalog_path"
value {
string_value: "Outdoors$Plants & Planters$Plants, Bulbs & Seeds$Roses"
}
}
fields {
key: "link_url"
value {
string_value: "https://www.lowes.com/pd/Spring-Hill-Nurseries-in-Bare-Root-Red-Flowering-Blaze-Climbing-Rose/1002648140"
}
}
fields {
key: "product_name"
value {
string_value: "Spring Hill Nurseries in Bare Root Red Flowering Blaze Climbing Rose"
}
}
}
clusters {
id: "985_203"
}
}
created_at {
seconds: 1599796898
nanos: 391916000
}
modified_at {
seconds: 1599798078
nanos: 291417000
}
status {
code: INPUT_DOWNLOAD_SUCCESS
description: "Download complete"
}
}
annotation {
id: "c588c2f17f01465f94bde2d2c2e5687f"
input_id: "1002648140"
data {
}
status {
code: ANNOTATION_SUCCESS
description: "Annotation success"
}
created_at {
seconds: 1599798076
nanos: 759651000
}
modified_at {
seconds: 1599798076
nanos: 759651000
}
model_version_id: "bb186755eda04f9cbb6fe32e816be104"
}
, score: 0.8807249665260315
input {
id: "1000383061"
data {
image {
url: "https://images.lowes.com/product/converted/743425/743425079649.jpg"
hosted {
prefix: "https://s3.amazonaws.com/clarifai-api/img3/prod"
suffix: "3617f25f9ee5463497e7abf350091b93/756b268566daea823f07248208c05e21"
sizes: "orig"
sizes: "tiny"
sizes: "small"
sizes: "large"
}
}
metadata {
fields {
key: "cat_entry_id"
value {
string_value: "1000383061"
}
}
fields {
key: "catalog_name"
value {
string_value: "Annuals"
}
}
fields {
key: "catalog_path"
value {
string_value: "Outdoors$Plants & Planters$Plants, Bulbs & Seeds$Annuals"
}
}
fields {
key: "link_url"
value {
string_value: "https://www.lowes.com/pd/3-Quart-Purple-Purple-Garden-Mum-in-Pot/1000383061"
}
}
fields {
key: "product_name"
value {
string_value: " 3-Quart Purple Purple Garden Mum in Pot"
}
}
}
clusters {
id: "54_203"
}
}
created_at {
seconds: 1599795418
nanos: 883441000
}
modified_at {
seconds: 1599795429
nanos: 301624000
}
status {
code: INPUT_DOWNLOAD_SUCCESS
description: "Download complete"
}
}
annotation {
id: "91434754e4bd425ba3c528be9cd901e0"
input_id: "1000383061"
data {
}
status {
code: ANNOTATION_SUCCESS
description: "Annotation success"
}
created_at {
seconds: 1599795427
nanos: 683212000
}
modified_at {
seconds: 1599795427
nanos: 683212000
}
model_version_id: "bb186755eda04f9cbb6fe32e816be104"
}
I am using a dictionary and adding the value of metadata as a list and not getting the same order of the lists being appended. Please see the following sample dictionary for reference.
{'test_output/fe_IMG_0574.jpg_0': ['Outdoors$Plants & Planters$Plants, Bulbs & Seeds$Roses',
'https://www.lowes.com/pd/Spring-Hill-Nurseries-in-Bare-Root-Red-Flowering-Blaze-Climbing-Rose/1002648140',
'Roses',
'Spring Hill Nurseries in Bare Root Red Flowering Blaze Climbing Rose',
'1002648140'],
'test_output/fe_IMG_0574.jpg_1': ['https://www.lowes.com/pd/3-Quart-Purple-Purple-Garden-Mum-in-Pot/1000383061',
'1000383061',
' 3-Quart Purple Purple Garden Mum in Pot',
'Outdoors$Plants & Planters$Plants, Bulbs & Seeds$Annuals',
'Annuals'],
'test_output/fe_IMG_0574.jpg_2': ['https://www.lowes.com/pd/4-Count-Dahlia-Bulbs-L3480/1000151071',
'1000151071',
' 4 Count Dahlia Bulbs (L3480)',
'Outdoors$Plants & Planters$Plants, Bulbs & Seeds$Plant Bulbs',
'Plant Bulbs']}
which then creates a data frame that has different values for columns in what seems like sporadic rows. This is the code I am using to generate this.
final_dict = {}
for i in range(5):
response_object = response.hits[i].input.data.metadata.items()
final_list = []
url = response_object[0][1]
product_name = response_object[1][1]
catalog_entry_id = response_object[2][1]
catalog_path = response_object[3][1]
catalog_name = response_object[4][1]
final_list.append(url)
final_list.append(catalog_entry_id)
final_list.append(product_name)
final_list.append(catalog_path)
final_list.append(catalog_name)
final_dict[file_id+'_'+str(i)] = final_list
print(final_dict)
final_df = pd.DataFrame.from_dict(final_dict, orient='index')
Please see the following rows as an example of what I mean
This is for posterity. The new Clarifai GRPC client has different data structuring. So as a result, I had to parse them by first listing fields. This is what my final loop looked like. It had the ListFields added line
for i in range(5):
response_object = response.ListFields()[1]
test_meta = response_object[1][i].input.data.metadata
final_list = []
url = test_meta['link_url']
product_name = test_meta['product_name']
catalog_entry_id = test_meta['cat_entry_id']
catalog_path = test_meta['catalog_path']
catalog_name = test_meta['catalog_name']
final_list.append(i+1)
final_list.append(url)
final_list.append(catalog_entry_id)
final_list.append(product_name)
final_list.append(catalog_path)
final_list.append(catalog_name)
final_dict[file_id+'_'+str(i)] = final_list
I work with project.task model. I need to add confirmation for every stage change when user did the drag and drop. Is there any possible way.. I add validation error in write method. But Its not complete my wish. please help me
Finally I found the solution...
In this case you have to change the kanban_view.js file in web_kanban module. You can replace
add_record_to_column: function (event)
this function by this code in "kanban_view.js" file.
add_record_to_column: function (event) {
var self = this;
var column = event.target;
var record = event.data.record;
var data = {};
data[this.group_by_field] = event.target.id;
// display confirm message
if (confirm("Are you sure you want to change this stage?")){
//if click yes do this
this.dataset.write(record.id, data, {}).done(function () {
if (!self.isDestroyed()) {
self.reload_record(record);
self.resequence_column(column);
alert("You have change the stage!");
}
}).fail(this.do_reload);
}else{// if no reload the page and remain the tile in same satage
location.reload();
}},
On odoo 14, here this code:
Do search "_onAddRecordToColumn" in addons/web/static/src/js/views/kanban/kanban_controller.js
then override function (with inherited module) to this:
_onAddRecordToColumn: function (ev) {
var self = this;
var record = ev.data.record;
var column = ev.target;
if (confirm("Are you sure want to change this stage?")){
this.alive(this.model.moveRecord(record.db_id, column.db_id, this.handle))
.then(function (column_db_ids) {
return self._resequenceRecords(column.db_id, ev.data.ids)
.then(function () {
_.each(column_db_ids, function (db_id) {
var data = self.model.get(db_id);
self.renderer.updateColumn(db_id, data);
});
});
}).guardedCatch(this.reload.bind(this));
}else{
this.reload();
}
},
Being very new to GraphQL, I have a graphene django implementation of a server with two models, following rather closely the graphene docs' example.
In graphiql, I can do this, and get a result back.
Following another relay tutorial, I'm intending to render the result of this query on screen.
My attempt looks like this:
class Note extends Component {
render() {
return(
<div> {this.props.store.title} </div>
)
}
}
Note = Relay.createContainer(Note, {
fragments: {
store: () => Relay.QL`
fragment on Query {
note(id: "Tm90ZU5vZGU6MQ==") {
id
title
}
}
`
}
});
class NoteRoute extends Relay.Route {
static routeName = 'NoteRoute';
static queries = {
store: Component => {
return Relay.QL`
query {
${Component.getFragment('store')}
}
`},
};
}
My browser's console shows the following error:
Uncaught Error: Relay transform error ``There are 0 fields supplied to the query named `Index`, but queries must have exactly one field.`` in file `/Users/.../src/index.js`. Try updating your GraphQL schema if an argument/field/type was recently added.
I've been trying to figure it out on my own with limited success.
Can someone point me in the right direction?
Thanks #stubailo for pointing me in the right direction. I made some adjustments, and now have a minimum example running like this:
NoteList = Relay.createContainer(NoteList, {
fragments: {
store: () => Relay.QL`
fragment N on NoteNodeConnection {
edges {
node{
id
title
note
}
}
}
`
}
});
class NoteRoute extends Relay.Route {
static routeName = 'NoteRoute';
static queries = {
store: Component => {
return Relay.QL`
query {
notes {
${Component.getFragment('store')}
}
}
`},
};
}