Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added support for human readable predicates #994

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions packages/legacy/core/App/components/misc/CredentialCard11.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { useConfiguration } from '../../contexts/configuration'
import { useTheme } from '../../contexts/theme'
import { GenericFn } from '../../types/fn'
import { credentialTextColor, getCredentialIdentifiers, toImageSource } from '../../utils/credential'
import { getCredentialConnectionLabel, isDataUrl } from '../../utils/helpers'
import { formatIfDate, getCredentialConnectionLabel, isDataUrl, pTypeToText } from '../../utils/helpers'
import { testIdWithKey } from '../../utils/testable'

import CardWatermark from './CardWatermark'
Expand Down Expand Up @@ -102,6 +102,15 @@ const CredentialCard11: React.FC<CredentialCard11Props> = ({
(field) => field.name === overlay?.brandingOverlay?.secondaryAttribute
)

const attributeTypes = overlay.bundle?.captureBase.attributes
const attributeFormats: Record<string, string | undefined> = (overlay.bundle as any)?.bundle.attributes
.map((attr: any) => {
return { name: attr.name, format: attr.format }
})
.reduce((prev: { [key: string]: string }, curr: { name: string; format?: string }) => {
return { ...prev, [curr.name]: curr.format }
}, {})

const cardData = [...(displayItems ?? []), primaryField, secondaryField]

const getSecondaryBackgroundColor = () => {
Expand Down Expand Up @@ -215,7 +224,18 @@ const CredentialCard11: React.FC<CredentialCard11Props> = ({
})

const parseAttribute = (item: (Attribute & Predicate) | undefined) => {
return { label: item?.label ?? item?.name ?? '', value: item?.value || `${item?.pType} ${item?.pValue}` }
let parsedItem = item
if (item && !item.value) {
parsedItem = pTypeToText(item, t, attributeTypes) as Attribute & Predicate
}
const parsedValue = formatIfDate(
attributeFormats?.[item?.name ?? ''],
parsedItem?.value ?? parsedItem?.pValue ?? null
)
return {
label: item?.label ?? item?.name ?? '',
value: item?.value ? parsedValue : `${parsedItem?.pType} ${parsedValue}`,
}
}

useEffect(() => {
Expand Down Expand Up @@ -345,6 +365,7 @@ const CredentialCard11: React.FC<CredentialCard11Props> = ({

const renderCardAttribute = (item: Attribute & Predicate) => {
const { label, value } = parseAttribute(item)
const parsedValue = formatIfDate(item?.format, value) ?? ''
return (
item && (
<View style={{ marginTop: 15 }}>
Expand All @@ -371,7 +392,7 @@ const CredentialCard11: React.FC<CredentialCard11Props> = ({
size={ListItems.recordAttributeText.fontSize}
/>
)}
<AttributeValue warn={flaggedAttributes?.includes(label) && !item.pValue && proof} value={value} />
<AttributeValue warn={flaggedAttributes?.includes(label) && !item.pValue && proof} value={parsedValue} />
</View>
)}
{item?.satisfied != undefined && item?.satisfied === false ? (
Expand Down
26 changes: 22 additions & 4 deletions packages/legacy/core/App/components/misc/SharedProofData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
import { useConfiguration } from '../../contexts/configuration'
import { useTheme } from '../../contexts/theme'
import { toImageSource } from '../../utils/credential'
import { formatIfDate, pTypeToText } from '../../utils/helpers'
import { buildFieldsFromSharedAnonCredsProof } from '../../utils/oca'
import { testIdWithKey } from '../../utils/testable'
import LoadingIndicator from '../animated/LoadingIndicator'
Expand Down Expand Up @@ -59,6 +60,7 @@ const SharedDataCard: React.FC<{ sharedData: GroupedSharedProofDataItem }> = ({
elevation: 5,
},
cardAttributes: {
width: '65%',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same Q as above

paddingTop: 20,
paddingBottom: 10,
},
Expand All @@ -79,6 +81,15 @@ const SharedDataCard: React.FC<{ sharedData: GroupedSharedProofDataItem }> = ({

const [overlay, setOverlay] = useState<CredentialOverlay<BrandingOverlay> | undefined>(undefined)

const attributeTypes = overlay?.bundle?.captureBase.attributes
const attributeFormats: Record<string, string | undefined> = (overlay?.bundle as any)?.bundle.attributes
.map((attr: any) => {
return { name: attr.name, format: attr.format }
})
.reduce((prev: { [key: string]: string }, curr: { name: string; format?: string }) => {
return { ...prev, [curr.name]: curr.format }
}, {})

useEffect(() => {
const attributes = buildFieldsFromSharedAnonCredsProof(sharedData.data)
const params = {
Expand All @@ -95,14 +106,21 @@ const SharedDataCard: React.FC<{ sharedData: GroupedSharedProofDataItem }> = ({
}, [sharedData])

const CardField: React.FC<{ item: Field }> = ({ item }) => {
const { t } = useTranslation()
let parsedPredicate: Predicate | undefined = undefined
if (item instanceof Predicate) {
parsedPredicate = pTypeToText(item, t, attributeTypes) as Predicate
parsedPredicate.pValue = formatIfDate(attributeFormats[item.name ?? ''], parsedPredicate.pValue)
} else {
;(item as Attribute).value = formatIfDate(attributeFormats[item.name ?? ''], (item as Attribute).value)
}

return (
<View key={item.name} style={styles.attributeContainer}>
<View key={item.name} style={[styles.attributeContainer]}>
<Text style={styles.attributeName}>{item.label || item.name}</Text>
{item instanceof Attribute && <AttributeValue style={styles.attributeValue} field={item} shown={true} />}
{item instanceof Predicate && (
<Text style={styles.attributeValue}>
{item.pType} {item.pValue}
</Text>
<Text style={styles.attributeValue}>{`${parsedPredicate?.pType} ${parsedPredicate?.pValue}`}</Text>
)}
</View>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const AttributeValue: React.FC<AttributeValueParams> = ({ field, style, s
) {
return <RecordBinaryField attributeValue={field.value as string} style={style} shown={shown} />
}
if (field.type == CaptureBaseAttributeType.DateInt) {
if (field.type == CaptureBaseAttributeType.DateInt || field.type == CaptureBaseAttributeType.DateTime) {
return <RecordDateIntField field={field} style={style} shown={shown} />
}
return (
Expand Down
6 changes: 6 additions & 0 deletions packages/legacy/core/App/localization/en/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,12 @@ const translation = {
"DeleteOfferDescription": "Don't recognize the organization? Check your Contacts list. You only receive notifications from Contacts you've initiated",
},
"ProofRequest": {
"PredicateGeDate": "is after",
"PredicateLeDate": "is before",
"PredicateGe": "is greater than or equal to",
"PredicateGr": "is greater than",
"PredicateLe": "is less than or equal to",
"PredicateLs": "is less than",
"ProofRequest": "Proof Request",
"RequestProcessing": "Just a moment...",
"OfferDelay": "Offer delay",
Expand Down
6 changes: 6 additions & 0 deletions packages/legacy/core/App/localization/fr/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,12 @@ const translation = {
"CustomOfferParagraph2": "Vous ne reconnaissez pas l'organisation? Vérifiez votre liste de Contacts. Vous ne recevez des notifications que des Contacts que vous avez initiés."
},
"ProofRequest": {
"PredicateGeDate": "is after (FR)",
"PredicateLeDate": "is before (FR)",
"PredicateGe": "is greater than or equal to (FR)",
"PredicateGr": "is greater than (FR)",
"PredicateLe": "is less than or equal to (FR)",
"PredicateLs": "is less than (FR)",
"ProofRequest": "Demande de preuve",
"RequestProcessing": "Juste un instant...",
"OfferDelay": "Retard de l'offre",
Expand Down
6 changes: 6 additions & 0 deletions packages/legacy/core/App/localization/pt-br/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,12 @@ const translation = {
"CustomOfferParagraph2": "Não reconhece a organização. Verifique sua lista de Contatos. Você só recebe notificões de Contatos que você tenha adicionado.",
},
"ProofRequest": {
"PredicateGeDate": "é posterior a",
"PredicateLeDate": "é anterior a",
"PredicateGe": "é maior ou igual a",
"PredicateGr": "é maior que",
"PredicateLe": "é menor ou igual a",
"PredicateLs": "é menor que",
"ProofRequest": "Requisição de Prova",
"RequestProcessing": "Só um momento...",
"OfferDelay": "Atrasar oferta",
Expand Down
65 changes: 45 additions & 20 deletions packages/legacy/core/App/screens/ProofRequestDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { useStore } from '../contexts/store'
import { useTheme } from '../contexts/theme'
import { useTemplate } from '../hooks/proof-request-templates'
import { Screens, ProofRequestsStackParams } from '../types/navigators'
import { formatIfDate } from '../utils/helpers'
import { formatIfDate, pTypeToText } from '../utils/helpers'
import { buildFieldsFromAnonCredsProofRequestTemplate } from '../utils/oca'
import { parseSchemaFromId } from '../utils/schema'
import { testIdWithKey } from '../utils/testable'
Expand All @@ -37,7 +37,7 @@ const AttributeItem: React.FC<{ item: Attribute; style?: StyleProp<TextStyle> }>
const [value, setValue] = useState(item.value)

useEffect(() => {
formatIfDate(item.format, value, setValue)
setValue(formatIfDate(item.format, value))
}, [])

return (
Expand All @@ -54,14 +54,6 @@ const PredicateItem: React.FC<{
onChangeValue: (name: string, value: string) => void
}> = ({ item, style, onChangeValue }) => {
const { ColorPallet } = useTheme()
const [pValue, setPValue] = useState(item.pValue)

useEffect(() => {
// can't format the date if parameterizable, must remain a number
if (!item.parameterizable) {
formatIfDate(item.format, pValue, setPValue)
}
}, [])

const defaultStyle = StyleSheet.create({
input: {
Expand All @@ -72,7 +64,7 @@ const PredicateItem: React.FC<{
})

return (
<View style={{ flexDirection: 'row' }}>
<View style={{ flexDirection: 'row', flexWrap: 'wrap' }}>
<Text style={style}>{item.label || item.name}</Text>
<Text style={style}>{item.pType}</Text>
{item.parameterizable && (
Expand All @@ -81,17 +73,17 @@ const PredicateItem: React.FC<{
style={[style, defaultStyle.input]}
onChangeText={(value) => onChangeValue(item.name || '', value)}
>
{pValue}
{item.pValue}
</TextInput>
)}
{!item.parameterizable && <Text style={style}>{pValue}</Text>}
{!item.parameterizable && <Text style={style}>{item.pValue}</Text>}
</View>
)
}

const ProofRequestAttributesCard: React.FC<ProofRequestAttributesCardParams> = ({ data, onChangeValue }) => {
const { ListItems, ColorPallet } = useTheme()
const { i18n } = useTranslation()
const { t, i18n } = useTranslation()
const { OCABundleResolver } = useConfiguration()

const style = StyleSheet.create({
Expand All @@ -113,16 +105,18 @@ const ProofRequestAttributesCard: React.FC<ProofRequestAttributesCardParams> = (
...ListItems.requestTemplateTitle,
fontWeight: 'bold',
fontSize: 18,
paddingVertical: 8,
marginRight: 8,
},
attributesList: {
paddingLeft: 14,
},
fieldContainer: { flexDirection: 'row', paddingVertical: 8 },
})

const [meta, setMeta] = useState<MetaOverlay | undefined>(undefined)
const [attributes, setAttributes] = useState<Field[] | undefined>(undefined)
const [attributeTypes, setAttributeTypes] = useState<Record<string, string> | undefined>(undefined)
const [attributeFormats, setAttributeFormats] = useState<Record<string, string | undefined> | undefined>(undefined)

useEffect(() => {
OCABundleResolver.resolve({ identifiers: { schemaId: data.schema }, language: i18n.language }).then((bundle) => {
Expand All @@ -142,9 +136,6 @@ const ProofRequestAttributesCard: React.FC<ProofRequestAttributesCardParams> = (
})
setMeta(metaOverlay)
})
}, [data.schema])

useEffect(() => {
const attributes = buildFieldsFromAnonCredsProofRequestTemplate(data)
OCABundleResolver.presentationFields({
identifiers: { schemaId: data.schema },
Expand All @@ -155,6 +146,32 @@ const ProofRequestAttributesCard: React.FC<ProofRequestAttributesCardParams> = (
})
}, [data.schema])

useEffect(() => {
const credDefId = (data.requestedAttributes ?? data.requestedPredicates)
?.flatMap((reqItem) => reqItem.restrictions?.map((restrictionItem) => restrictionItem.cred_def_id))
.find((item) => item !== undefined)
const params = {
identifiers: {
credentialDefinitionId: credDefId,
schemaId: data.schema,
},
language: i18n.language,
attributes,
}
OCABundleResolver.resolveAllBundles(params).then((bundle) => {
setAttributeTypes(bundle?.bundle?.captureBase.attributes)
setAttributeFormats(
(bundle.bundle as any)?.bundle.attributes
.map((attr: any) => {
return { name: attr.name, format: attr.format }
})
.reduce((prev: { [key: string]: string }, curr: { name: string; format?: string }) => {
return { ...prev, [curr.name]: curr.format }
}, {})
)
})
}, [])

return (
<View style={[style.credentialCard]}>
<Text style={style.schemaTitle}>{meta?.name}</Text>
Expand All @@ -163,13 +180,21 @@ const ProofRequestAttributesCard: React.FC<ProofRequestAttributesCardParams> = (
data={attributes}
keyExtractor={(record, index) => record.name || index.toString()}
renderItem={({ item }) => {
item.format = attributeFormats?.[item.name ?? '']
let parsedPredicate: Predicate | undefined = undefined
if (item instanceof Predicate) {
parsedPredicate = pTypeToText(item, t, attributeTypes) as Predicate
if (!parsedPredicate.parameterizable) {
parsedPredicate.pValue = formatIfDate(parsedPredicate.format, parsedPredicate.pValue)
}
}
return (
<View style={{ flexDirection: 'row' }}>
<View style={style.fieldContainer}>
<Text style={style.attributeTitle}>{`\u2022`}</Text>
{item instanceof Attribute && <AttributeItem style={style.attributeTitle} item={item as Attribute} />}
{item instanceof Predicate && (
<PredicateItem
item={item as Predicate}
item={parsedPredicate as Predicate}
style={style.attributeTitle}
onChangeValue={(name, value) => {
onChangeValue(data.schema, item.label || name, name, value)
Expand Down
Loading