Skip to content

vc as social trust assertion proof #135

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

Merged
merged 1 commit into from
Apr 20, 2021
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
28 changes: 14 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,46 +21,46 @@
"js-sha3": "0.8.0",
"jsonschema": "1.2.6",
"leaflet": "1.7.1",
"lodash": "4.17.20",
"lodash": "4.17.21",
"moment": "2.29.1",
"node-sass": "5.0.0",
"prop-types": "15.7.2",
"query-string": "6.14.0",
"radium": "0.26.1",
"react": "17.0.1",
"react": "17.0.2",
"react-animations": "1.0.0",
"react-blockies": "1.4.1",
"react-dom": "17.0.1",
"react-dom": "17.0.2",
"react-dotdotdot": "1.3.1",
"react-dropzone": "11.0.1",
"react-esri-leaflet": "0.2.2",
"react-leaflet": "3.0.0",
"react-number-format": "4.4.4",
"react-paginate": "6.3.2",
"react-redux": "7.2.2",
"react-redux": "7.2.3",
"react-router": "5.2.0",
"react-router-dom": "5.2.0",
"react-router-redux": "4.0.8",
"react-scripts": "4.0.2",
"react-scripts": "4.0.3",
"react-visibility-sensor": "5.1.1",
"redux": "4.0.5",
"redux-devtools-extension": "2.13.8",
"redux-devtools-extension": "2.13.9",
"redux-logger": "3.0.6",
"redux-persist": "6.0.0",
"redux-saga": "1.1.3",
"reselect": "4.0.0",
"web3": "1.3.4"
"web3": "1.3.5"
},
"devDependencies": {
"@storybook/addon-actions": "^6.2.1",
"@storybook/addon-essentials": "^6.2.1",
"@storybook/addon-links": "^6.2.1",
"@storybook/node-logger": "^6.2.1",
"@storybook/preset-create-react-app": "^3.1.7",
"@storybook/react": "^6.2.1",
"@storybook/addon-actions": "6.2.8",
"@storybook/addon-essentials": "6.2.8",
"@storybook/addon-links": "6.2.8",
"@storybook/node-logger": "6.2.8",
"@storybook/preset-create-react-app": "3.1.7",
"@storybook/react": "6.2.8",
"env-cmd": "10.1.0",
"now": "21.0.1",
"storybook-addon-material-ui": "^0.9.0-alpha.24"
"storybook-addon-material-ui": "0.9.0-alpha.24"
},
"scripts": {
"start": "react-scripts start",
Expand Down
15 changes: 14 additions & 1 deletion src/components/ProofItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import IconFacebook from './icons/IconFacebook';
import IconTwitter from './icons/IconTwitter';
import IconInstagram from './icons/IconInstagram';
import IconLinkedin from './icons/IconLinkedin';
import IconTelegram from './icons/IconTelegram';
import {
selectPendingState
} from '../ducks/wizard';
Expand Down Expand Up @@ -184,6 +185,10 @@ const ProofWebsiteNameAndIcon = ({ icon }) => {
iconElem =<IconLinkedin />;
text='LinkedIn'
break;
case 'telegram':
iconElem =<IconTelegram />;
text='Telegram'
break;
default:
iconElem = <div />;
text=''
Expand Down Expand Up @@ -262,7 +267,15 @@ const ProofItem = props => {
<ProofWebsiteNameAndIcon icon={icon} />
</Grid>
<Grid item xs={12} sm={5}>
<ProofTitle title={title} canManage={canManage} proof={assertion.proof} removed={removed} verified={verified} deployed={deployed} onClick={onClick}/>
<ProofTitle
title={title}
canManage={canManage}
proof={assertion.proof}
removed={removed}
verified={verified}
deployed={deployed}
onClick={onClick}
/>
{assertion.proof && <ProofExternalLinkIcon url={assertion.proof}/>}

{/*
Expand Down
28 changes: 27 additions & 1 deletion src/components/ProofsList.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { makeStyles } from '@material-ui/core/styles';
import ProofItem from './ProofItem';
import LifDepositValue from './LifDepositValue';
import ProofsWizard from './ProofsWizard';
import VcProofsWizard from './VcProofsWizard';
import ProofsSaver from './ProofsSaver';
import RefreshButton from './buttons/Refresh';
import CancelButton from './buttons/Cancel';
Expand Down Expand Up @@ -126,6 +127,18 @@ const proofsTemplate = [
],
icon: 'twitter'
},
{
id: 't1',
type: 'social',
subtype: 'telegram',
title: 'Prove your Telegram group',
pubTitle: 'Telegram group account proof not submitted yet',
notes: [
'To prove that a Telegram group account is yours copy the content of proof generated by the ORGiD bot to the following form'
],
icon: 'telegram',
proofType: 'vc'
},
// {
// id: 's3',
// type: 'social',
Expand Down Expand Up @@ -234,6 +247,7 @@ export const ProofsList = props => {
const { canManage, title, orgid, organization, assertions, verifications, fetchOrganizationInfo } = props;
// const { proofsQty } = organization;
const [isOpen, toggleModalOpenState] = useState(false);
const [isVcOpen, toggleVcModalOpenState] = useState(false);
const [chosenProof, setProof] = useState();
const [updatedProofs, setUpdatedProofs] = useState({});
const [isSaverOpen, toggleSaverState] = useState(false);
Expand All @@ -260,8 +274,14 @@ export const ProofsList = props => {
};

const openWizard = proof => {
console.log('@@@', proof);
setProof(proof);
toggleModalOpenState(true);

if (proof.proofType && proof.proofType === 'vc') {
toggleVcModalOpenState(true);
} else {
toggleModalOpenState(true);
}
};

const onWizardClose = (updatedProof) => {
Expand All @@ -273,6 +293,7 @@ export const ProofsList = props => {
}));
}
toggleModalOpenState(false);
toggleVcModalOpenState(false);
}

const handleAssertionRemove = (assertion, proof) => {
Expand Down Expand Up @@ -312,6 +333,11 @@ export const ProofsList = props => {
proof={chosenProof}
handleClose={updatedProof => onWizardClose(updatedProof)}
/>
<VcProofsWizard
isOpen={isVcOpen}
proof={chosenProof}
handleClose={updatedProof => onWizardClose(updatedProof)}
/>
<Box className={classes.titleLine}>
<Grid container alignItems='center' spacing={2}>
<Grid item>
Expand Down
196 changes: 196 additions & 0 deletions src/components/VcProofsWizard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
import React from 'react';
import { connect } from 'react-redux';
import DialogComponent from './Dialog';
import { Formik } from 'formik';
import {
TextareaAutosize,
TextField,
Typography
} from "@material-ui/core";
import { makeStyles } from '@material-ui/core/styles';
import {
addAssertion
} from '../ducks/wizard';
import SaveButton from './buttons/Save';

const useStyles = makeStyles({
root: {

},
info: {
fontFamily: 'Inter',
fontDtyle: 'normal',
fontWeight: 'normal',
fontSize: '16px',
lineHeight: '28px',
color: '#8F999F',
marginBottom: '20px'
},
textarea: {
width: '100%',
backgroundColor: '#FAFAFA',
border: 'none',
padding: '12px',
borderRadius: '8px',
color: '#5E666A',
resize: 'none',
'&:focus': {
outline: 'none !important',
border: '1px solid #8F999F'
}
},
save: {
marginTop: '40px'
}
});

const extractDomainName = uri => new URL(uri).hostname;

const extractSocialClaim = uri => {
const url = new URL(uri);
const hostname = url.hostname.split('www.').filter(d => d)[0];
const account = url.pathname.split('/').splice(1,1)[0];
return `${hostname}/${account}`;
}

const ProofForm = props => {
const { proof, addAssertion, handleClose, classes } = props;

return (
<>
<Formik
initialValues={{
vc: ''
}}
enableReinitialize={true}
validate={values => {
const errors = {};

try {
if (!values.vc || values.vc.trim() === '') {
throw new Error('content is empty');
}
const vc = JSON.parse(values.vc);
if (!vc.proof ||
!vc.proof.verificationMethod) {
throw new Error('proof not defined');
}
if (!vc.credentialSubject ||
!vc.credentialSubject.claim) {
throw new Error('credential subject not defined');
}
} catch (error) {
errors.vc = `Incorrect VC: ${error.message}`;
}

return errors;
}}
onSubmit={(values, { setSubmitting }) => {
const vc = JSON.parse(values.vc);
const assertion = {
type: proof.type,
claim: vc.credentialSubject.claim,
proof: vc
};
addAssertion(assertion);
setSubmitting(false);
handleClose({
...proof,
assertion,
title: assertion.claim,
verified: false,
deployed: false
});
}}
>
{({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
isSubmitting
}) => (
<form onSubmit={handleSubmit}>
<div>
{proof.notes.map((n, i) => {

if (n.match(/^>/)) {
return (
<TextareaAutosize
key={i}
className={classes.textarea}
value={n.replace(/^>/, '')}
/>
);
}

return (
<Typography
key={i}
className={classes.info}
>
{n}
</Typography>
);
})}
</div>
<div>
<TextField
label='VC content'
name='vc'
multiline
rows={5}
value={values['vc']}
helperText={errors['vc'] && touched['vc'] ? errors['vc'] : undefined}
required={true}
error={errors['vc'] && touched['vc']}
onChange={handleChange}
onBlur={handleBlur}
fullWidth
/>
</div>
<div className={classes.save}>
<SaveButton
type='submit'
disabled={isSubmitting}
>
Save
</SaveButton>
</div>
</form>
)}
</Formik>
</>
);
};

const VcProofsWizard = props => {
const { isOpen, handleClose, proof } = props;
const classes = useStyles();

if (!proof) {
return false;
}

return (
<DialogComponent
className={classes.root}
maxWidth='xs'
handleClose={() => handleClose(null)}
isOpen={isOpen}
children={(
<ProofForm classes={classes} {...props} />
)}
/>
);
};

const mapStateToProps = state => ({});

const mapDispatchToProps = {
addAssertion
};

export default connect(mapStateToProps, mapDispatchToProps)(VcProofsWizard);
10 changes: 10 additions & 0 deletions src/components/icons/IconTelegram.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react';
import SvgIcon from '@material-ui/core/SvgIcon';

export default props => (
<SvgIcon
{...props}
>
<path d="M9.83648 14.5584L18.4871 7.71097L7.26049 13.3689L2.71205 12.0154C1.73182 11.7285 1.72482 11.0851 2.93388 10.6219L20.65 4.1052C21.4584 3.75635 22.2398 4.29107 21.931 5.47202L18.9144 19.0334C18.7036 19.998 18.095 20.2268 17.2477 19.7817L12.6523 16.5438C11.9188 17.2242 10.6736 19.0315 9.52273 19.0315L9.83648 14.5584ZM9.83648 14.5584H9.83448" stroke="#42424F" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</SvgIcon>
);
Loading