Better presentation of OSM notes.

This commit is contained in:
Eric van der Vlist 2022-10-10 19:13:14 +02:00
parent bdc527ae05
commit 6c0d3bfb11
4 changed files with 292 additions and 29 deletions

157
package-lock.json generated
View File

@ -20,6 +20,8 @@
"@capacitor/haptics": "4.0.1", "@capacitor/haptics": "4.0.1",
"@capacitor/keyboard": "4.0.1", "@capacitor/keyboard": "4.0.1",
"@capacitor/status-bar": "4.0.1", "@capacitor/status-bar": "4.0.1",
"@chatscope/chat-ui-kit-react": "^1.9.7",
"@chatscope/chat-ui-kit-styles": "^1.4.0",
"@ionic/react": "^6.2.6", "@ionic/react": "^6.2.6",
"@ionic/react-router": "^6.2.6", "@ionic/react-router": "^6.2.6",
"@openpgp/asmcrypto.js": "^2.3.2", "@openpgp/asmcrypto.js": "^2.3.2",
@ -35,6 +37,7 @@
"@types/react-dom": "^18.0.6", "@types/react-dom": "^18.0.6",
"@types/react-router": "^5.1.11", "@types/react-router": "^5.1.11",
"@types/react-router-dom": "^5.1.7", "@types/react-router-dom": "^5.1.7",
"avatar-initials": "^5.0.0",
"buffer": "^6.0.3", "buffer": "^6.0.3",
"cordova-plugin-geolocation": "^4.1.0", "cordova-plugin-geolocation": "^4.1.0",
"crypto-browserify": "^3.12.0", "crypto-browserify": "^3.12.0",
@ -2137,6 +2140,30 @@
"@capacitor/core": "^4.0.0" "@capacitor/core": "^4.0.0"
} }
}, },
"node_modules/@chatscope/chat-ui-kit-react": {
"version": "1.9.7",
"resolved": "https://registry.npmjs.org/@chatscope/chat-ui-kit-react/-/chat-ui-kit-react-1.9.7.tgz",
"integrity": "sha512-1Yj9ktmP/U576M9MFhBJ4me/HHMCcosBrJDCtZePnFShquAQIUPB2kOeNy+zMNIAYqYHkzj7VEm2DZfRxaFLFw==",
"dependencies": {
"@chatscope/chat-ui-kit-styles": "^1.2.0",
"@fortawesome/fontawesome-free": "^5.12.1",
"@fortawesome/fontawesome-svg-core": "^1.2.26",
"@fortawesome/free-solid-svg-icons": "^5.12.0",
"@fortawesome/react-fontawesome": "^0.1.8",
"classnames": "^2.2.6",
"prop-types": "^15.7.2"
},
"peerDependencies": {
"prop-types": "^15.7.2",
"react": "^16.12.0 || ^17.0.0 || ^18.2.0",
"react-dom": "^16.12.0 || ^17.0.0 || ^18.2.0"
}
},
"node_modules/@chatscope/chat-ui-kit-styles": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@chatscope/chat-ui-kit-styles/-/chat-ui-kit-styles-1.4.0.tgz",
"integrity": "sha512-016mBJD3DESw7Nh+lkKcPd22xG92ghA0VpIXIbjQtmXhC7Ve6wRazTy8z1Ahut+Tbv179+JxrftuMngsj/yV8Q=="
},
"node_modules/@cspotcode/source-map-support": { "node_modules/@cspotcode/source-map-support": {
"version": "0.8.1", "version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
@ -2491,6 +2518,60 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/@fortawesome/fontawesome-common-types": {
"version": "0.2.36",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz",
"integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==",
"hasInstallScript": true,
"engines": {
"node": ">=6"
}
},
"node_modules/@fortawesome/fontawesome-free": {
"version": "5.15.4",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.4.tgz",
"integrity": "sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg==",
"hasInstallScript": true,
"engines": {
"node": ">=6"
}
},
"node_modules/@fortawesome/fontawesome-svg-core": {
"version": "1.2.36",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.36.tgz",
"integrity": "sha512-YUcsLQKYb6DmaJjIHdDWpBIGCcyE/W+p/LMGvjQem55Mm2XWVAP5kWTMKWLv9lwpCVjpLxPyOMOyUocP1GxrtA==",
"hasInstallScript": true,
"dependencies": {
"@fortawesome/fontawesome-common-types": "^0.2.36"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@fortawesome/free-solid-svg-icons": {
"version": "5.15.4",
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz",
"integrity": "sha512-JLmQfz6tdtwxoihXLg6lT78BorrFyCf59SAwBM6qV/0zXyVeDygJVb3fk+j5Qat+Yvcxp1buLTY5iDh1ZSAQ8w==",
"hasInstallScript": true,
"dependencies": {
"@fortawesome/fontawesome-common-types": "^0.2.36"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@fortawesome/react-fontawesome": {
"version": "0.1.19",
"resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.19.tgz",
"integrity": "sha512-Hyb+lB8T18cvLNX0S3llz7PcSOAJMLwiVKBuuzwM/nI5uoBw+gQjnf9il0fR1C3DKOI5Kc79pkJ4/xB0Uw9aFQ==",
"dependencies": {
"prop-types": "^15.8.1"
},
"peerDependencies": {
"@fortawesome/fontawesome-svg-core": "~1 || ~6",
"react": ">=16.x"
}
},
"node_modules/@humanwhocodes/config-array": { "node_modules/@humanwhocodes/config-array": {
"version": "0.10.4", "version": "0.10.4",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz",
@ -5553,6 +5634,14 @@
"postcss": "^8.1.0" "postcss": "^8.1.0"
} }
}, },
"node_modules/avatar-initials": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/avatar-initials/-/avatar-initials-5.0.0.tgz",
"integrity": "sha512-4fgzwu70faLzVIAXguRryGjJhfIz9XmXwTQTXUNTg1E+6Pf9dfuhr/1Hvs6mOrw7p0yEGnYKkBjniECxhXSbxw==",
"engines": {
"node": ">= 12"
}
},
"node_modules/axe-core": { "node_modules/axe-core": {
"version": "4.4.3", "version": "4.4.3",
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.3.tgz", "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.3.tgz",
@ -6393,6 +6482,11 @@
"resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz",
"integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==" "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA=="
}, },
"node_modules/classnames": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
"integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
},
"node_modules/clean-css": { "node_modules/clean-css": {
"version": "5.3.1", "version": "5.3.1",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.1.tgz", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.1.tgz",
@ -21151,6 +21245,25 @@
"integrity": "sha512-BmEyOf3m/hAf8bO4hCX0m5gpQPSgd05mGYl+9E841WUZeJjcYlmiG/EBshAUb2uGCVtyNaG36yPXB0r0Ypg+rw==", "integrity": "sha512-BmEyOf3m/hAf8bO4hCX0m5gpQPSgd05mGYl+9E841WUZeJjcYlmiG/EBshAUb2uGCVtyNaG36yPXB0r0Ypg+rw==",
"requires": {} "requires": {}
}, },
"@chatscope/chat-ui-kit-react": {
"version": "1.9.7",
"resolved": "https://registry.npmjs.org/@chatscope/chat-ui-kit-react/-/chat-ui-kit-react-1.9.7.tgz",
"integrity": "sha512-1Yj9ktmP/U576M9MFhBJ4me/HHMCcosBrJDCtZePnFShquAQIUPB2kOeNy+zMNIAYqYHkzj7VEm2DZfRxaFLFw==",
"requires": {
"@chatscope/chat-ui-kit-styles": "^1.2.0",
"@fortawesome/fontawesome-free": "^5.12.1",
"@fortawesome/fontawesome-svg-core": "^1.2.26",
"@fortawesome/free-solid-svg-icons": "^5.12.0",
"@fortawesome/react-fontawesome": "^0.1.8",
"classnames": "^2.2.6",
"prop-types": "^15.7.2"
}
},
"@chatscope/chat-ui-kit-styles": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@chatscope/chat-ui-kit-styles/-/chat-ui-kit-styles-1.4.0.tgz",
"integrity": "sha512-016mBJD3DESw7Nh+lkKcPd22xG92ghA0VpIXIbjQtmXhC7Ve6wRazTy8z1Ahut+Tbv179+JxrftuMngsj/yV8Q=="
},
"@cspotcode/source-map-support": { "@cspotcode/source-map-support": {
"version": "0.8.1", "version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
@ -21340,6 +21453,40 @@
} }
} }
}, },
"@fortawesome/fontawesome-common-types": {
"version": "0.2.36",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz",
"integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg=="
},
"@fortawesome/fontawesome-free": {
"version": "5.15.4",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.4.tgz",
"integrity": "sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg=="
},
"@fortawesome/fontawesome-svg-core": {
"version": "1.2.36",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.36.tgz",
"integrity": "sha512-YUcsLQKYb6DmaJjIHdDWpBIGCcyE/W+p/LMGvjQem55Mm2XWVAP5kWTMKWLv9lwpCVjpLxPyOMOyUocP1GxrtA==",
"requires": {
"@fortawesome/fontawesome-common-types": "^0.2.36"
}
},
"@fortawesome/free-solid-svg-icons": {
"version": "5.15.4",
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz",
"integrity": "sha512-JLmQfz6tdtwxoihXLg6lT78BorrFyCf59SAwBM6qV/0zXyVeDygJVb3fk+j5Qat+Yvcxp1buLTY5iDh1ZSAQ8w==",
"requires": {
"@fortawesome/fontawesome-common-types": "^0.2.36"
}
},
"@fortawesome/react-fontawesome": {
"version": "0.1.19",
"resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.19.tgz",
"integrity": "sha512-Hyb+lB8T18cvLNX0S3llz7PcSOAJMLwiVKBuuzwM/nI5uoBw+gQjnf9il0fR1C3DKOI5Kc79pkJ4/xB0Uw9aFQ==",
"requires": {
"prop-types": "^15.8.1"
}
},
"@humanwhocodes/config-array": { "@humanwhocodes/config-array": {
"version": "0.10.4", "version": "0.10.4",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz",
@ -23733,6 +23880,11 @@
"postcss-value-parser": "^4.2.0" "postcss-value-parser": "^4.2.0"
} }
}, },
"avatar-initials": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/avatar-initials/-/avatar-initials-5.0.0.tgz",
"integrity": "sha512-4fgzwu70faLzVIAXguRryGjJhfIz9XmXwTQTXUNTg1E+6Pf9dfuhr/1Hvs6mOrw7p0yEGnYKkBjniECxhXSbxw=="
},
"axe-core": { "axe-core": {
"version": "4.4.3", "version": "4.4.3",
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.3.tgz", "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.3.tgz",
@ -24359,6 +24511,11 @@
"resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz",
"integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==" "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA=="
}, },
"classnames": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
"integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
},
"clean-css": { "clean-css": {
"version": "5.3.1", "version": "5.3.1",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.1.tgz", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.1.tgz",

View File

@ -15,6 +15,8 @@
"@capacitor/haptics": "4.0.1", "@capacitor/haptics": "4.0.1",
"@capacitor/keyboard": "4.0.1", "@capacitor/keyboard": "4.0.1",
"@capacitor/status-bar": "4.0.1", "@capacitor/status-bar": "4.0.1",
"@chatscope/chat-ui-kit-react": "^1.9.7",
"@chatscope/chat-ui-kit-styles": "^1.4.0",
"@ionic/react": "^6.2.6", "@ionic/react": "^6.2.6",
"@ionic/react-router": "^6.2.6", "@ionic/react-router": "^6.2.6",
"@openpgp/asmcrypto.js": "^2.3.2", "@openpgp/asmcrypto.js": "^2.3.2",
@ -30,6 +32,7 @@
"@types/react-dom": "^18.0.6", "@types/react-dom": "^18.0.6",
"@types/react-router": "^5.1.11", "@types/react-router": "^5.1.11",
"@types/react-router-dom": "^5.1.7", "@types/react-router-dom": "^5.1.7",
"avatar-initials": "^5.0.0",
"buffer": "^6.0.3", "buffer": "^6.0.3",
"cordova-plugin-geolocation": "^4.1.0", "cordova-plugin-geolocation": "^4.1.0",
"crypto-browserify": "^3.12.0", "crypto-browserify": "^3.12.0",

View File

@ -14,6 +14,20 @@ import {
IonAccordion, IonAccordion,
} from '@ionic/react'; } from '@ionic/react';
import React, { Fragment, useRef, useState } from 'react'; import React, { Fragment, useRef, useState } from 'react';
import {
MainContainer,
Sidebar,
ConversationList,
Conversation,
ConversationHeader,
ChatContainer,
MessageList,
Message,
Avatar,
} from '@chatscope/chat-ui-kit-react';
import '@chatscope/chat-ui-kit-styles/dist/default/styles.min.css';
import AvatarInitial from 'avatar-initials';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import i18n from '../../i18n'; import i18n from '../../i18n';
import { geoPoint } from '../../lib/geo'; import { geoPoint } from '../../lib/geo';
@ -103,6 +117,11 @@ const LocationInfo: React.FC<{}> = () => {
return format.format(date); return format.format(date);
}; };
const [noteIndex, setNoteIndex] = useState(0);
const conversationClickHandlerFactory = (index: number) => (event: any) => {
setNoteIndex(index);
};
return ( return (
<IonModal <IonModal
trigger='information-request' trigger='information-request'
@ -160,40 +179,123 @@ const LocationInfo: React.FC<{}> = () => {
</IonLabel> </IonLabel>
</IonListHeader> </IonListHeader>
{notes !== undefined && ( {notes !== undefined && (
<IonAccordionGroup> <MainContainer>
{notes.features.map((feature: any) => ( <Sidebar position='left'>
<IonAccordion key={feature.properties.id}> <ConversationList>
<IonItem slot='header'> {notes.features!.map((feature: any, index: number) => (
<IonLabel> <Conversation
{i18n.locationInfo!.at!( onClick={conversationClickHandlerFactory(index)}
key={feature.properties.id}
name={i18n.locationInfo!.at!(
roughDistance(scope.center, { roughDistance(scope.center, {
lon: feature.geometry.coordinates[0], lon: feature.geometry.coordinates[0],
lat: feature.geometry.coordinates[1], lat: feature.geometry.coordinates[1],
}) })
)} )}
</IonLabel> info={feature.properties.status}
</IonItem> >
<div className='ion-padding' slot='content'> <Avatar
<IonList lines='full' class='ion-no-margin'> src={AvatarInitial.initialAvatar({
<IonListHeader lines='full'> size: 100,
<IonLabel> initials: Math.round(
{i18n.locationInfo!.created} roughDistance(scope.center, {
{localDate(feature.properties.date_created)} lon: feature.geometry.coordinates[0],
{', '} lat: feature.geometry.coordinates[1],
{feature.properties.status === 'open' })
? i18n.locationInfo.status?.opened ),
: i18n.locationInfo.status?.closed} initial_fg: '#888888',
{'.'} initial_bg: '#f4f6f7',
</IonLabel> initial_size: 25, // Defaults to height / 2
</IonListHeader> initial_weight: 500,
{feature.properties.comments.map((comment: any) => ( initial_font_family:
<IonItem>{comment.html}</IonItem> "'Lato', 'Lato-Regular', 'Helvetica Neue'",
})}
/>
</Conversation>
))} ))}
</IonList> </ConversationList>
</div> </Sidebar>
</IonAccordion> <ChatContainer>
))} <ConversationHeader>
</IonAccordionGroup> <ConversationHeader.Content>
<span
style={{
color: '#ec1212',
alignSelf: 'flex-center',
}}
>
{i18n.locationInfo!.at!(
roughDistance(scope.center, {
lon: notes.features[noteIndex].geometry
.coordinates[0],
lat: notes.features[noteIndex].geometry
.coordinates[1],
})
)}
</span>
</ConversationHeader.Content>
<Avatar
src={AvatarInitial.initialAvatar({
size: 100,
initials: Math.round(
roughDistance(scope.center, {
lon: notes.features[noteIndex].geometry
.coordinates[0],
lat: notes.features[noteIndex].geometry
.coordinates[1],
})
),
initial_fg: '#888888',
initial_bg: '#f4f6f7',
initial_size: 25, // Defaults to height / 2
initial_weight: 500,
initial_font_family:
"'Lato', 'Lato-Regular', 'Helvetica Neue'",
})}
name={i18n.locationInfo!.at!(
roughDistance(scope.center, {
lon: notes.features[noteIndex].geometry.coordinates[0],
lat: notes.features[noteIndex].geometry.coordinates[1],
})
)}
/>
</ConversationHeader>
<MessageList>
{notes.features[noteIndex].properties.comments.map(
(comment: any, index: number) => (
<Message
key={`${notes.features[noteIndex].properties.id}/${index}`}
model={{
direction: 'incoming',
position: 'single',
sender: comment.user,
sentTime: comment.date,
payload: comment.html,
}}
>
<Message.Header
sender={comment.user}
sentTime={comment.date}
/>
<Avatar
src={AvatarInitial.initialAvatar({
size: 100,
initials: comment.user ? comment.user : '??',
initial_fg: '#888888',
initial_bg: '#f4f6f7',
initial_size: 0, // Defaults to height / 2
initial_weight: 500,
initial_font_family:
"'Lato', 'Lato-Regular', 'Helvetica Neue'",
})}
name={comment.user ? comment.user : 'anonymous'}
/>
</Message>
)
)}
</MessageList>
</ChatContainer>
</MainContainer>
)} )}
</IonList> </IonList>
</IonContent> </IonContent>

View File

@ -0,0 +1 @@
declare module 'avatar-initials';