mirror of
https://github.com/inaturalist/iNaturalistReactNative.git
synced 2026-06-19 13:11:23 -04:00
47
src/api/qualityMetrics.js
Normal file
47
src/api/qualityMetrics.js
Normal file
@@ -0,0 +1,47 @@
|
||||
// @flow
|
||||
|
||||
import inatjs from "inaturalistjs";
|
||||
|
||||
import handleError from "./error";
|
||||
|
||||
const setQualityMetric = async (
|
||||
params: Object = {},
|
||||
opts: Object = {}
|
||||
): Promise<any> => {
|
||||
try {
|
||||
const response = await inatjs.observations.setQualityMetric( params, opts );
|
||||
return response.results;
|
||||
} catch ( e ) {
|
||||
return handleError( e );
|
||||
}
|
||||
};
|
||||
|
||||
const deleteQualityMetric = async (
|
||||
params: Object = {},
|
||||
opts: Object = {}
|
||||
): Promise<any> => {
|
||||
try {
|
||||
const { results } = await inatjs.observations.deleteQualityMetric( params, opts );
|
||||
return results;
|
||||
} catch ( e ) {
|
||||
return handleError( e );
|
||||
}
|
||||
};
|
||||
|
||||
const fetchQualityMetrics = async (
|
||||
params: Object = {},
|
||||
opts: Object = {}
|
||||
): Promise<any> => {
|
||||
try {
|
||||
const response = await inatjs.observations.qualityMetrics( params, opts );
|
||||
return response.results;
|
||||
} catch ( e ) {
|
||||
return handleError( e );
|
||||
}
|
||||
};
|
||||
|
||||
export {
|
||||
deleteQualityMetric,
|
||||
fetchQualityMetrics,
|
||||
setQualityMetric
|
||||
};
|
||||
120
src/components/ObsDetails/DQAVoteButtons.js
Normal file
120
src/components/ObsDetails/DQAVoteButtons.js
Normal file
@@ -0,0 +1,120 @@
|
||||
// @flow
|
||||
|
||||
import {
|
||||
Body3,
|
||||
INatIconButton
|
||||
} from "components/SharedComponents";
|
||||
import { View } from "components/styledComponents";
|
||||
import * as React from "react";
|
||||
import { ActivityIndicator, useTheme } from "react-native-paper";
|
||||
|
||||
type Props = {
|
||||
metric: string,
|
||||
qualityMetrics: Object,
|
||||
loadingAgree: boolean,
|
||||
loadingDisagree: boolean,
|
||||
loadingMetric: ?string,
|
||||
setVote: Function,
|
||||
removeVote: Function
|
||||
}
|
||||
|
||||
const getUserVote = ( metric, qualityMetrics ) => {
|
||||
if ( qualityMetrics ) {
|
||||
const match = qualityMetrics.find( element => (
|
||||
element.metric === metric && element.user_id ) );
|
||||
if ( match ) {
|
||||
return match.agree === true;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const renderVoteCount = ( status, metric, qualityMetrics ) => {
|
||||
if ( !qualityMetrics ) return null;
|
||||
|
||||
const count = qualityMetrics
|
||||
?.filter( qualityMetric => qualityMetric.agree === status && qualityMetric.metric === metric )
|
||||
?.length;
|
||||
if ( !count || count === 0 ) return null;
|
||||
|
||||
return <Body3 classname="ml-[5px]">{count}</Body3>;
|
||||
};
|
||||
|
||||
const DQAVoteButtons = ( {
|
||||
metric, qualityMetrics, loadingAgree, loadingDisagree, loadingMetric, setVote, removeVote
|
||||
}: Props ): React.Node => {
|
||||
const theme = useTheme( );
|
||||
const userAgrees = getUserVote( metric, qualityMetrics );
|
||||
const activityIndicatorOffset = "mx-[7px]";
|
||||
|
||||
const renderAgree = () => {
|
||||
if ( loadingAgree && loadingMetric === metric ) {
|
||||
return ( <ActivityIndicator size={33} className={activityIndicatorOffset} /> );
|
||||
}
|
||||
if ( userAgrees ) {
|
||||
return (
|
||||
<INatIconButton
|
||||
icon="arrow-up-bold-circle"
|
||||
size={33}
|
||||
color={theme.colors.secondary}
|
||||
onPress={() => removeVote( metric, true )}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<INatIconButton
|
||||
icon="arrow-up-bold-circle-outline"
|
||||
size={33}
|
||||
onPress={() => setVote( metric, true )}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const renderDisagree = () => {
|
||||
if ( loadingDisagree && loadingMetric === metric ) {
|
||||
return ( <ActivityIndicator size={30} className={activityIndicatorOffset} /> );
|
||||
}
|
||||
|
||||
if ( userAgrees === null ) {
|
||||
return (
|
||||
<INatIconButton
|
||||
icon="arrow-down-bold-circle-outline"
|
||||
size={33}
|
||||
onPress={() => setVote( metric, false )}
|
||||
/>
|
||||
);
|
||||
}
|
||||
if ( !userAgrees ) {
|
||||
return (
|
||||
<INatIconButton
|
||||
icon="arrow-down-bold-circle"
|
||||
size={33}
|
||||
color={theme.colors.error}
|
||||
onPress={() => removeVote( metric, false )}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<INatIconButton
|
||||
icon="arrow-down-bold-circle-outline"
|
||||
size={33}
|
||||
onPress={() => setVote( metric, false )}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<View className="flex-row items-center justify-between w-[97px] space-x-[11px]">
|
||||
<View className="flex-row items-center w-1/2">
|
||||
{renderAgree()}
|
||||
{renderVoteCount( true, metric, qualityMetrics )}
|
||||
</View>
|
||||
<View className="flex-row items-center w-1/2">
|
||||
{renderDisagree()}
|
||||
{renderVoteCount( false, metric, qualityMetrics )}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default DQAVoteButtons;
|
||||
415
src/components/ObsDetails/DataQualityAssessment.js
Normal file
415
src/components/ObsDetails/DataQualityAssessment.js
Normal file
@@ -0,0 +1,415 @@
|
||||
// @flow
|
||||
import { useRoute } from "@react-navigation/native";
|
||||
import { deleteQualityMetric, fetchQualityMetrics, setQualityMetric } from "api/qualityMetrics";
|
||||
import DQAVoteButtons from "components/ObsDetails/DQAVoteButtons";
|
||||
import PlaceholderText from "components/PlaceholderText";
|
||||
import {
|
||||
Body3,
|
||||
BottomSheet,
|
||||
Button,
|
||||
Divider,
|
||||
Heading4,
|
||||
INatIcon,
|
||||
List1,
|
||||
List2,
|
||||
ScrollViewWrapper
|
||||
} from "components/SharedComponents";
|
||||
import QualityGradeStatus from "components/SharedComponents/QualityGradeStatus/QualityGradeStatus";
|
||||
import { View } from "components/styledComponents";
|
||||
import { t } from "i18next";
|
||||
import {
|
||||
useEffect, useState
|
||||
} from "react";
|
||||
import * as React from "react";
|
||||
import { useTheme } from "react-native-paper";
|
||||
import useAuthenticatedMutation from "sharedHooks/useAuthenticatedMutation";
|
||||
|
||||
const titleOption = option => {
|
||||
switch ( option ) {
|
||||
case "research":
|
||||
return t( "Data-quality-assessment-title-research" );
|
||||
case "needs_id":
|
||||
return t( "Data-quality-assessment-title-needs-id" );
|
||||
default:
|
||||
return t( "Data-quality-assessment-title-casual" );
|
||||
}
|
||||
};
|
||||
|
||||
const titleDescription = option => {
|
||||
switch ( option ) {
|
||||
case "research":
|
||||
return t( "Data-quality-assessment-description-research" );
|
||||
case "needs_id":
|
||||
return t( "Data-quality-assessment-description-needs-id" );
|
||||
default:
|
||||
return t( "Data-quality-assessment-description-casual" );
|
||||
}
|
||||
};
|
||||
|
||||
const DataQualityAssessment = ( ): React.Node => {
|
||||
const { params } = useRoute( );
|
||||
const { observationUUID, observation, qualityGrade } = params;
|
||||
const isResearchGrade = qualityGrade === "research";
|
||||
const theme = useTheme( );
|
||||
const sectionClass = "flex-row my-[14px] space-x-[11px]";
|
||||
const voteClass = "flex-row mr-[15px] my-[7px] justify-between items-center";
|
||||
const listTextClass = "flex-row space-x-[11px]";
|
||||
const [qualityMetrics, setQualityMetrics] = useState( null );
|
||||
const [loadingAgree, setLoadingAgree] = useState( false );
|
||||
const [loadingDisagree, setLoadingDisagree] = useState( false );
|
||||
const [loadingMetric, setLoadingMetric] = useState( null );
|
||||
const [hideErrorSheet, setHideErrorSheet] = useState( true );
|
||||
|
||||
const fetchMetricsParams = {
|
||||
id: observationUUID,
|
||||
fields: "metric,agree,user_id",
|
||||
ttl: -1
|
||||
};
|
||||
|
||||
// destructured mutate to pass into useEffect to prevent infinite
|
||||
// rerender and disabling eslint useEffect dependency rule
|
||||
const { mutate } = useAuthenticatedMutation(
|
||||
( qualityMetricParams, optsWithAuth ) => fetchQualityMetrics(
|
||||
qualityMetricParams,
|
||||
optsWithAuth
|
||||
),
|
||||
{
|
||||
onSuccess: response => {
|
||||
setLoadingMetric( null );
|
||||
if ( loadingAgree ) {
|
||||
setLoadingAgree( false );
|
||||
}
|
||||
if ( loadingDisagree ) {
|
||||
setLoadingDisagree( false );
|
||||
}
|
||||
setQualityMetrics( response );
|
||||
},
|
||||
onError: () => {
|
||||
setHideErrorSheet( false );
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
useEffect( ( ) => {
|
||||
mutate( {
|
||||
id: params.observationUUID,
|
||||
fields: "metric,agree,user_id",
|
||||
ttl: -1
|
||||
} );
|
||||
}, [mutate, params] );
|
||||
|
||||
const createQualityMetricMutation = useAuthenticatedMutation(
|
||||
( qualityMetricParams, optsWithAuth ) => setQualityMetric( qualityMetricParams, optsWithAuth ),
|
||||
{
|
||||
onSuccess: () => {
|
||||
// fetch updated quality metrics with updated votes
|
||||
mutate( fetchMetricsParams );
|
||||
},
|
||||
onError: () => {
|
||||
setHideErrorSheet( false );
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const setMetricVote = ( metric, vote ) => {
|
||||
const qualityMetricParams = {
|
||||
id: observationUUID,
|
||||
metric,
|
||||
agree: vote,
|
||||
ttyl: -1
|
||||
};
|
||||
setLoadingMetric( metric );
|
||||
if ( vote ) {
|
||||
setLoadingAgree( true );
|
||||
} else {
|
||||
setLoadingDisagree( true );
|
||||
}
|
||||
createQualityMetricMutation.mutate( qualityMetricParams );
|
||||
};
|
||||
|
||||
const createRemoveQualityMetricMutation = useAuthenticatedMutation(
|
||||
( qualityMetricParams, optsWithAuth ) => deleteQualityMetric(
|
||||
qualityMetricParams,
|
||||
optsWithAuth
|
||||
),
|
||||
{
|
||||
onSuccess: () => {
|
||||
// fetch updated quality metrics with updated votes
|
||||
mutate( fetchMetricsParams );
|
||||
},
|
||||
onError: () => {
|
||||
setHideErrorSheet( false );
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const removeMetricVote = ( metric, vote ) => {
|
||||
const qualityMetricParams = {
|
||||
id: observationUUID,
|
||||
metric,
|
||||
ttyl: -1
|
||||
};
|
||||
setLoadingMetric( metric );
|
||||
if ( vote ) {
|
||||
setLoadingAgree( true );
|
||||
} else {
|
||||
setLoadingDisagree( true );
|
||||
}
|
||||
createRemoveQualityMetricMutation.mutate( qualityMetricParams );
|
||||
};
|
||||
|
||||
const ifMajorityAgree = metric => {
|
||||
if ( qualityMetrics ) {
|
||||
const agreeCount = qualityMetrics.filter(
|
||||
element => ( element.agree && element.metric === metric )
|
||||
).length;
|
||||
const disagreeCount = qualityMetrics.filter(
|
||||
element => ( !element.agree && element.metric === metric )
|
||||
).length;
|
||||
|
||||
return agreeCount >= disagreeCount;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const renderMetricIndicator = metric => {
|
||||
const ifAgree = ifMajorityAgree( metric );
|
||||
if ( ifAgree || ifAgree === null ) {
|
||||
return (
|
||||
<INatIcon name="checkmark-circle" size={19} color={theme.colors.secondary} /> );
|
||||
}
|
||||
return (
|
||||
<INatIcon name="triangle-exclamation" size={19} color={theme.colors.error} />
|
||||
);
|
||||
};
|
||||
|
||||
const checkTest = metric => {
|
||||
if ( observation ) {
|
||||
if ( metric === "date" ) {
|
||||
return observation[metric] !== null;
|
||||
}
|
||||
if ( metric === "location" ) {
|
||||
const removedNull = observation[metric]
|
||||
.filter( value => ( value !== null ) );
|
||||
return removedNull.length !== 0;
|
||||
}
|
||||
if ( metric === "evidence" ) {
|
||||
const removedEmpty = observation[metric]
|
||||
.filter( value => ( Object.keys( value ).length !== 0 ) );
|
||||
return removedEmpty.length !== 0;
|
||||
}
|
||||
if ( observation.taxon ) {
|
||||
if ( metric === "id_supported" ) {
|
||||
const taxonId = observation.taxon.id;
|
||||
const supportedIDs = observation.identifications.filter(
|
||||
identification => ( identification.taxon.id === taxonId )
|
||||
).length;
|
||||
return supportedIDs >= 2;
|
||||
}
|
||||
if ( metric === "rank" && observation.taxon.rank_level <= 10 ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const renderIndicator = metric => {
|
||||
const ifAgree = checkTest( metric );
|
||||
if ( ifAgree || ifAgree === null ) {
|
||||
return (
|
||||
<INatIcon name="checkmark-circle" size={19} color={theme.colors.secondary} /> );
|
||||
}
|
||||
return (
|
||||
<INatIcon name="triangle-exclamation" size={19} color={theme.colors.error} />
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<ScrollViewWrapper testID="DataQualityAssessment">
|
||||
<View className="mx-[26px] my-[19px] space-y-[9px]">
|
||||
<QualityGradeStatus
|
||||
qualityGrade={qualityGrade}
|
||||
color={( qualityGrade === "research" )
|
||||
? theme.colors.secondary
|
||||
: theme.colors.primary}
|
||||
/>
|
||||
<View className="flex-row space-x-[7px]">
|
||||
{isResearchGrade
|
||||
&& (
|
||||
<INatIcon
|
||||
name="checkmark-circle"
|
||||
size={19}
|
||||
color={theme.colors.secondary}
|
||||
/>
|
||||
)}
|
||||
<List1 className="text-black">
|
||||
{titleOption( qualityGrade )}
|
||||
</List1>
|
||||
</View>
|
||||
<List2 className="text-black">
|
||||
{titleDescription( qualityGrade )}
|
||||
</List2>
|
||||
</View>
|
||||
<Divider />
|
||||
<View className="mx-[15px]">
|
||||
<View className={sectionClass}>
|
||||
{renderIndicator( "date" ) }
|
||||
<Body3>{t( "Data-quality-assessment-date-specified" )}</Body3>
|
||||
</View>
|
||||
<Divider />
|
||||
|
||||
<View className={sectionClass}>
|
||||
{renderIndicator( "location" )}
|
||||
<Body3>{t( "Data-quality-assessment-location-specified" )}</Body3>
|
||||
</View>
|
||||
<Divider />
|
||||
|
||||
<View className={sectionClass}>
|
||||
{renderIndicator( "evidence" )}
|
||||
<Body3>{t( "Data-quality-assessment-has-photos-or-sounds" )}</Body3>
|
||||
</View>
|
||||
<Divider />
|
||||
|
||||
<View className={sectionClass}>
|
||||
{renderIndicator( "id_supported" )}
|
||||
<Body3>{t( "Data-quality-assessment-id-supported-by-two-or-more" )}</Body3>
|
||||
</View>
|
||||
<Divider />
|
||||
|
||||
<View className={sectionClass}>
|
||||
{renderIndicator( "rank" )}
|
||||
<Body3>{t( "Data-quality-assessment-community-taxon-species-level-or-lower" )}</Body3>
|
||||
</View>
|
||||
<Divider />
|
||||
|
||||
<View className={voteClass}>
|
||||
<View className={listTextClass}>
|
||||
{renderMetricIndicator( "date" )}
|
||||
<Body3>{t( "Data-quality-assessment-date-is-accurate" )}</Body3>
|
||||
</View>
|
||||
<DQAVoteButtons
|
||||
metric="date"
|
||||
qualityMetrics={qualityMetrics}
|
||||
setVote={setMetricVote}
|
||||
loadingAgree={loadingAgree}
|
||||
loadingDisagree={loadingDisagree}
|
||||
loadingMetric={loadingMetric}
|
||||
removeVote={removeMetricVote}
|
||||
/>
|
||||
</View>
|
||||
<Divider />
|
||||
|
||||
<View className={voteClass}>
|
||||
<View className={listTextClass}>
|
||||
{renderMetricIndicator( "location" )}
|
||||
<Body3>{t( "Data-quality-assessment-location-is-accurate" )}</Body3>
|
||||
</View>
|
||||
<DQAVoteButtons
|
||||
metric="location"
|
||||
qualityMetrics={qualityMetrics}
|
||||
setVote={setMetricVote}
|
||||
loadingAgree={loadingAgree}
|
||||
loadingDisagree={loadingDisagree}
|
||||
loadingMetric={loadingMetric}
|
||||
removeVote={removeMetricVote}
|
||||
/>
|
||||
</View>
|
||||
<Divider />
|
||||
|
||||
<View className={voteClass}>
|
||||
<View className={listTextClass}>
|
||||
{renderMetricIndicator( "wild" )}
|
||||
<Body3>{t( "Data-quality-assessment-organism-is-wild" )}</Body3>
|
||||
</View>
|
||||
<DQAVoteButtons
|
||||
metric="wild"
|
||||
qualityMetrics={qualityMetrics}
|
||||
setVote={setMetricVote}
|
||||
loadingAgree={loadingAgree}
|
||||
loadingDisagree={loadingDisagree}
|
||||
loadingMetric={loadingMetric}
|
||||
removeVote={removeMetricVote}
|
||||
/>
|
||||
</View>
|
||||
<Divider />
|
||||
|
||||
<View className={voteClass}>
|
||||
<View className={listTextClass}>
|
||||
{renderMetricIndicator( "evidence" )}
|
||||
<Body3>{t( "Data-quality-assessment-evidence-of-organism" )}</Body3>
|
||||
</View>
|
||||
<DQAVoteButtons
|
||||
metric="evidence"
|
||||
qualityMetrics={qualityMetrics}
|
||||
setVote={setMetricVote}
|
||||
loadingAgree={loadingAgree}
|
||||
loadingDisagree={loadingDisagree}
|
||||
loadingMetric={loadingMetric}
|
||||
removeVote={removeMetricVote}
|
||||
/>
|
||||
</View>
|
||||
<Divider />
|
||||
|
||||
<View className={voteClass}>
|
||||
<View className={listTextClass}>
|
||||
{renderMetricIndicator( "recent" )}
|
||||
<Body3>{t( "Data-quality-assessment-recent-evidence-of-organism" )}</Body3>
|
||||
</View>
|
||||
<DQAVoteButtons
|
||||
metric="recent"
|
||||
qualityMetrics={qualityMetrics}
|
||||
setVote={setMetricVote}
|
||||
loadingAgree={loadingAgree}
|
||||
loadingDisagree={loadingDisagree}
|
||||
loadingMetric={loadingMetric}
|
||||
removeVote={removeMetricVote}
|
||||
/>
|
||||
</View>
|
||||
<Divider />
|
||||
</View>
|
||||
|
||||
<View className="flex-row bg-lightGray px-[15px] py-[7px] mt-[20px]">
|
||||
<PlaceholderText text="TODO" />
|
||||
<Body3 className="shrink">
|
||||
{t(
|
||||
"Data-quality-assessment-can-taxon-still-be-confirmed-improved-based-on-the-evidence"
|
||||
)}
|
||||
</Body3>
|
||||
<DQAVoteButtons
|
||||
metric="needs_id"
|
||||
qualityMetrics={qualityMetrics}
|
||||
setVote={setMetricVote}
|
||||
loadingAgree={loadingAgree}
|
||||
loadingDisagree={loadingDisagree}
|
||||
loadingMetric={loadingMetric}
|
||||
removeVote={removeMetricVote}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View className="mt-[30px] mx-[15px] space-y-[11px]">
|
||||
<Heading4>{t( "ABOUT-THE-DQA" )}</Heading4>
|
||||
<List2>{t( "About-the-DQA-description" )}</List2>
|
||||
</View>
|
||||
|
||||
</ScrollViewWrapper>
|
||||
<BottomSheet
|
||||
headerText={t( "ERROR-VOTING-IN-DQA" )}
|
||||
hide={hideErrorSheet}
|
||||
hideCloseButton
|
||||
snapPoints={["25"]}
|
||||
>
|
||||
<View className="px-[26px] pt-[20px] flex-col space-y-[20px]">
|
||||
<List2 className="text-black">{t( "Error-voting-in-DQA-description" )}</List2>
|
||||
<Button
|
||||
text={t( "OK" )}
|
||||
onPress={() => setHideErrorSheet( true )}
|
||||
/>
|
||||
</View>
|
||||
</BottomSheet>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DataQualityAssessment;
|
||||
@@ -1,5 +1,6 @@
|
||||
// @flow
|
||||
|
||||
import { useNavigation } from "@react-navigation/native";
|
||||
import {
|
||||
Body4,
|
||||
Button,
|
||||
@@ -22,7 +23,8 @@ import Attribution from "./Attribution";
|
||||
import checkCamelAndSnakeCase from "./helpers/checkCamelAndSnakeCase";
|
||||
|
||||
type Props = {
|
||||
observation: Object
|
||||
observation: Object,
|
||||
uuid:string
|
||||
}
|
||||
|
||||
const qualityGradeOption = option => {
|
||||
@@ -51,9 +53,11 @@ const headingClass = "mt-[20px] mb-[11px] text-black";
|
||||
const sectionClass = "mx-[15px] mb-[20px]";
|
||||
|
||||
const DetailsTab = ( { observation }: Props ): Node => {
|
||||
const navigation = useNavigation( );
|
||||
const application = observation?.application?.name;
|
||||
const [locationKebabMenuVisible, setLocationKebabMenuVisible] = useState( false );
|
||||
const qualityGrade = observation?.quality_grade;
|
||||
const observationUUID = observation.uuid;
|
||||
|
||||
const displayQualityGradeOption = option => {
|
||||
const labelClassName = ( qualityGrade === option )
|
||||
@@ -94,12 +98,14 @@ const DetailsTab = ( { observation }: Props ): Node => {
|
||||
/>
|
||||
</KebabMenu>
|
||||
</View>
|
||||
<Map
|
||||
obsLatitude={observation.latitude}
|
||||
obsLongitude={observation.longitude}
|
||||
mapHeight={230}
|
||||
showMarker
|
||||
/>
|
||||
{ ( observation.latitude || observation.private_latitude ) && (
|
||||
<Map
|
||||
obsLatitude={observation.latitude}
|
||||
obsLongitude={observation.longitude}
|
||||
mapHeight={230}
|
||||
showMarker
|
||||
/>
|
||||
) }
|
||||
|
||||
<View className={`mt-[11px] ${sectionClass}`}>
|
||||
<ObservationLocation observation={observation} details />
|
||||
@@ -131,7 +137,23 @@ const DetailsTab = ( { observation }: Props ): Node => {
|
||||
<Body4>
|
||||
{qualityGradeDescription( qualityGrade )}
|
||||
</Body4>
|
||||
<Button text={t( "VIEW-DATA-QUALITY-ASSESSEMENT" )} />
|
||||
<Button
|
||||
text={t( "VIEW-DATA-QUALITY-ASSESSEMENT" )}
|
||||
onPress={() => navigation.navigate( "DataQualityAssessment", {
|
||||
qualityGrade,
|
||||
observationUUID,
|
||||
observation: {
|
||||
date: observation.observed_on,
|
||||
location: [observation.latitude, observation.longitude],
|
||||
evidence: [observation.observationPhotos, observation.observationSounds],
|
||||
taxon: {
|
||||
id: observation.taxon.id,
|
||||
rank_level: observation.taxon.rank_level
|
||||
},
|
||||
identifications: observation.identifications
|
||||
}
|
||||
} )}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<Divider />
|
||||
|
||||
@@ -423,7 +423,7 @@ const ObsDetails = (): Node => {
|
||||
/>
|
||||
</HideView>
|
||||
<HideView noInitialRender show={currentTabId === DETAILS_TAB_ID}>
|
||||
<DetailsTab observation={observation} />
|
||||
<DetailsTab observation={observation} uuid={uuid} />
|
||||
</HideView>
|
||||
{addingComment && (
|
||||
<View className="flex-row items-center justify-center">
|
||||
|
||||
@@ -3,6 +3,11 @@ ABOUT = ABOUT
|
||||
|
||||
About-iNaturalist = About iNaturalist
|
||||
|
||||
# About the Data Quality Assement
|
||||
ABOUT-THE-DQA = ABOUT THE DQA
|
||||
|
||||
About-the-DQA-description = The Quality Grade summarizes the accuracy, precision, completeness, relevance, and appropriateness of an iNaturalist observation as biodiversity data. Some attributes are automatically determined, while others are subject to a vote by iNat users. iNaturalist shares licensed "Research Grade" observations with a number of data partners for use in science and conservation.
|
||||
|
||||
Accept-community-identifications = Accept community identifications
|
||||
|
||||
Account = Account
|
||||
@@ -64,6 +69,18 @@ attribution-cc-by-nc-sa = some rights reserved (CC BY-NC-SA)
|
||||
|
||||
attribution-cc-by-nc-nd = some rights reserved (CC BY-NC-ND)
|
||||
|
||||
attribution-cc-by = some rights reserved (CC BY)
|
||||
|
||||
attribution-cc-by-sa = some rights reserved (CC BY-SA)
|
||||
|
||||
attribution-cc-by-nc = some rights reserved (CC BY-NC)
|
||||
|
||||
attribution-cc-by-nd = some rights reserved (CC BY-ND)
|
||||
|
||||
attribution-cc-by-nc-sa = some rights reserved (CC BY-NC-SA)
|
||||
|
||||
attribution-cc-by-nc-nd = some rights reserved (CC BY-NC-ND)
|
||||
|
||||
app-authorized-on-date = { $appName } (authorized on: { $date })
|
||||
|
||||
Applications = Applications
|
||||
@@ -111,6 +128,8 @@ Content-Display = Content & Display
|
||||
|
||||
Copy-coordinates = Copy Coordinates
|
||||
|
||||
Copy-coordinates = Copy Coordinates
|
||||
|
||||
Couldnt-create-comment = Couldn't create comment
|
||||
|
||||
Couldnt-create-identification = Couldn't create identification
|
||||
@@ -119,12 +138,66 @@ Couldnt-create-identification-error = Couldn't create identification { $error }
|
||||
|
||||
Couldnt-create-identification-unknown-error = Couldn't create identification, Unknown Error.
|
||||
|
||||
Couldnt-create-identification-error = Couldn't create identification { $error }
|
||||
|
||||
Couldnt-create-identification-unknown-error = Couldn't create identification, Unknown Error.
|
||||
|
||||
CREATE-AN-ACCOUNT = CREATE AN ACCOUNT
|
||||
|
||||
Create-an-iNaturalist-account-to-save-your-observations = Create an iNaturalist account to save your observations and contribute them to science.
|
||||
|
||||
CREATE-YOUR-FIRST-OBSERVATION = CREATE YOUR FIRST OBSERVATION
|
||||
|
||||
DATA-QUALITY = DATA QUALITY
|
||||
|
||||
DATA-QUALITY-ASSESSMENT = DATA QUALITY ASSESSMENT
|
||||
|
||||
# declares the current data quality status of the observation
|
||||
Data-quality-assessment-title-research = This observation is Research Grade!
|
||||
|
||||
Data-quality-assessment-title-needs-id = This observation Needs ID
|
||||
|
||||
Data-quality-assessment-title-casual = This observation is Casual Grade
|
||||
|
||||
# description for different quality grades in the DQA
|
||||
Data-quality-assessment-description-research = It can now be used for research and featured on other websites.
|
||||
|
||||
Data-quality-assessment-description-research-not-licensed = However, it is not licensed for re-use and will not be shared with data repositories that respect license choices.
|
||||
|
||||
Data-quality-assessment-description-needs-id = This observation has not yet met the conditions for Research Grade status:
|
||||
|
||||
Data-quality-assessment-description-casual = This observation has not met the conditions for Research Grade status.
|
||||
|
||||
# checklist test for Data Quality Assessment of Observation Details
|
||||
Data-quality-assessment-date-specified = Date specified
|
||||
|
||||
Data-quality-assessment-location-specified = Location specified
|
||||
|
||||
Data-quality-assessment-has-photos-or-sounds = Has Photos or Sounds
|
||||
|
||||
Data-quality-assessment-id-supported-by-two-or-more = Has ID supported by two or more
|
||||
|
||||
Data-quality-assessment-community-taxon-species-level-or-lower = Community taxon at species level or lower
|
||||
|
||||
Data-quality-assessment-date-is-accurate = Date is accurate
|
||||
|
||||
Data-quality-assessment-location-is-accurate = Location is accurate
|
||||
|
||||
Data-quality-assessment-organism-is-wild = Organism is wild
|
||||
|
||||
Data-quality-assessment-evidence-of-organism = Evidence of organism
|
||||
|
||||
Data-quality-assessment-recent-evidence-of-organism = Recent evidence of an organism
|
||||
|
||||
Data-quality-assessment-can-taxon-still-be-confirmed-improved-based-on-the-evidence = Based on the evidence, can the Community Taxon still be improved?
|
||||
|
||||
Data-quality-research-description = This observation has enough identifications to be considered resarch grade
|
||||
|
||||
Data-quality-needs-id-description = This observation needs more identifications to reach research grade
|
||||
|
||||
Data-quality-casual-description = This observation needs more information verified to be considered verifiable
|
||||
|
||||
|
||||
DATA-QUALITY = DATA QUALITY
|
||||
|
||||
Data-quality-research-description = This observation has enough identifications to be considered resarch grade
|
||||
@@ -137,6 +210,8 @@ Date = Date
|
||||
|
||||
DATE = DATE
|
||||
|
||||
DATE = DATE
|
||||
|
||||
Date-added-newest-to-oldest = Date added - newest to oldest
|
||||
|
||||
Date-added-oldest-to-newest = Date added - oldest to newest
|
||||
@@ -202,6 +277,10 @@ Error-Couldnt-Upload-Photo = Error: Couldn't Upload Photo
|
||||
|
||||
Error-Could-Not-Fetch-Taxon = Error: Could Not Fetch Taxon
|
||||
|
||||
ERROR-VOTING-IN-DQA = ERROR VOTING IN DQA
|
||||
|
||||
Error-voting-in-DQA-description = Your vote may not have been cast in the DQA. Check your internet connection and try again.
|
||||
|
||||
EVIDENCE = EVIDENCE
|
||||
|
||||
Explore = Explore
|
||||
@@ -307,6 +386,8 @@ Location = Location
|
||||
|
||||
LOCATION = LOCATION
|
||||
|
||||
LOCATION = LOCATION
|
||||
|
||||
Location-accuracy-is-too-imprecise = Location accuracy is too imprecise to help identifiers. Please zoom in.
|
||||
|
||||
LOCATION-TOO-IMPRECISE = LOCATION TOO IMPRECISE
|
||||
@@ -395,8 +476,9 @@ none = none
|
||||
No-photos-found = No photos found. If this is your first time opening the app and giving permissions, try restarting the app.
|
||||
|
||||
# license code
|
||||
no-rights-reserved-cc0 = no rights reserved (CC0)
|
||||
no-rights-reserved-cc0-cc0 = no rights reserved (CC0) (CC0)
|
||||
|
||||
# Header for observation description on observation detail
|
||||
# Header for observation description on observation detail
|
||||
NOTES = NOTES
|
||||
|
||||
@@ -469,6 +551,11 @@ quality-grade-research = Research
|
||||
quality-grade-needs-id = Needs Id
|
||||
quality-grade-casual = Casual
|
||||
|
||||
# Quality grade options
|
||||
quality-grade-research = Research
|
||||
quality-grade-needs-id = Needs Id
|
||||
quality-grade-casual = Casual
|
||||
|
||||
Rank = Rank
|
||||
|
||||
# The following Ranks- strings are taxonomic ranks (in taxonomic order, not alphabetical order)
|
||||
@@ -589,6 +676,8 @@ SAVE-CHANGES = SAVE CHANGES
|
||||
|
||||
Saved-Observation = Saved observation, in queue to upload
|
||||
|
||||
Saved-Observation = Saved observation, in queue to upload
|
||||
|
||||
Search-for-a-location = Search for a location
|
||||
|
||||
Search-for-a-project = Search for a project
|
||||
@@ -611,6 +700,8 @@ SHARE-DEBUG-LOGS = SHARE DEBUG LOGS
|
||||
|
||||
Share-location = Share Location
|
||||
|
||||
Share-location = Share Location
|
||||
|
||||
Sign-out = Sign out
|
||||
|
||||
Sign-Up = Sign Up
|
||||
@@ -696,6 +787,9 @@ IMPORT-X-OBSERVATIONS = IMPORT {$count ->
|
||||
# Describes whether a user made this observation from web, iOS, or Android
|
||||
Uploaded-via-application = Uploaded via: { $application }
|
||||
|
||||
# Describes whether a user made this observation from web, iOS, or Android
|
||||
Uploaded-via-application = Uploaded via: { $application }
|
||||
|
||||
# Shows the number of observations a user is currently uploading on my observations page
|
||||
Uploading-X-Observations = Uploading {$count ->
|
||||
[one] 1 Observation
|
||||
@@ -728,6 +822,10 @@ VIEW-DATA-QUALITY-ASSESSEMENT = VIEW DATA QUALITY ASSESSEMENT
|
||||
|
||||
View-in-browser = View in Browser
|
||||
|
||||
VIEW-DATA-QUALITY-ASSESSEMENT = VIEW DATA QUALITY ASSESSEMENT
|
||||
|
||||
View-in-browser = View in Browser
|
||||
|
||||
Visually-search-iNaturalist-data = Visually search iNaturalist’s wealth of data. Search by a taxon in a location
|
||||
|
||||
Welcome-to-iNaturalist = Welcome to iNaturalist!
|
||||
@@ -955,19 +1053,25 @@ Take-photo = Take photo
|
||||
# See complete list of formatting styles: https://date-fns.org/v2.29.3/docs/format
|
||||
date-format-short = M/d/yy
|
||||
|
||||
# Date formatting using date-fns
|
||||
# See complete list of formatting styles: https://date-fns.org/v2.29.3/docs/format
|
||||
|
||||
# Date formatting using date-fns
|
||||
# See complete list of formatting styles: https://date-fns.org/v2.29.3/docs/format
|
||||
datetime-format-short = M/d/yy h:mm a
|
||||
|
||||
# Date formatting using date-fns
|
||||
# See complete list of formatting styles: https://date-fns.org/v2.29.3/docs/format
|
||||
|
||||
# Date formatting using date-fns
|
||||
# See complete list of formatting styles: https://date-fns.org/v2.29.3/docs/format
|
||||
date-format-long = PP
|
||||
|
||||
# Onboarding text on MyObservations: 0-10 observations
|
||||
As-you-upload-more-observations = As you upload more observations, others in our community may be able to help you identify them!
|
||||
# Onboarding text on MyObservations: 11-50 observations
|
||||
# Onboarding text on MyObservations: Onboarding text on MyObservations: 11-50 observations
|
||||
Observations-you-upload-to-iNaturalist = Observations you upload to iNaturalist can be used by scientists and researchers worldwide.
|
||||
# Onboarding text on MyObservations: 51-100 observations
|
||||
# Onboarding text on MyObservations: Onboarding text on MyObservations: 51-100 observations
|
||||
You-can-search-observations-of-any-plant-or-animal = You can search observations of any plant or animal anywhere in the world with Explore!
|
||||
|
||||
DISCARD-MEDIA = DISCARD MEDIA?
|
||||
@@ -986,16 +1090,16 @@ Failed-to-log-in = Failed to log in
|
||||
# Generic error message
|
||||
Something-went-wrong = Something went wrong.
|
||||
|
||||
# Geoprivacy sheet descriptions
|
||||
# Geoprivacy sheet descriptions
|
||||
Anyone-using-iNaturalist-can-see = Anyone using iNaturalist can see where this species was observed, and scientists can most easily use it for research.
|
||||
The-exact-location-will-be-hidden = The exact location will be hidden publicly, and instead generalized to a larger area. (Threatened and endangered species are automatically obscured).
|
||||
The-location-will-not-be-visible = The location will not be visible to others, which means it may be difficult to identify.
|
||||
|
||||
# Wild status sheet descriptions
|
||||
# Wild status sheet descriptions
|
||||
This-is-a-wild-organism = This is a wild organism and wasn’t placed in this location by humans.
|
||||
This-organism-was-placed-by-humans = This organism was placed in this location by humans. This applies to things like garden plants, pets, and zoo animals.
|
||||
|
||||
# Latitude, longitude, and accuracy on a single line
|
||||
# Latitude, longitude, and accuracy on a single line on a single line
|
||||
Lat-Lon-Acc = Lat: { NUMBER($latitude, maximumFractionDigits: 6) }, Lon: { NUMBER($longitude, maximumFractionDigits: 6) }, Acc: { $accuracy }
|
||||
|
||||
# Missing evidence sheet
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
"val": "ABOUT"
|
||||
},
|
||||
"About-iNaturalist": "About iNaturalist",
|
||||
"ABOUT-THE-DQA": {
|
||||
"comment": "About the Data Quality Assement",
|
||||
"val": "ABOUT THE DQA"
|
||||
},
|
||||
"About-the-DQA-description": "The Quality Grade summarizes the accuracy, precision, completeness, relevance, and appropriateness of an iNaturalist observation as biodiversity data. Some attributes are automatically determined, while others are subject to a vote by iNat users. iNaturalist shares licensed \"Research Grade\" observations with a number of data partners for use in science and conservation.",
|
||||
"Accept-community-identifications": "Accept community identifications",
|
||||
"Account": "Account",
|
||||
"ADD-AN-ID": "ADD AN ID",
|
||||
@@ -81,6 +86,34 @@
|
||||
"Create-an-iNaturalist-account-to-save-your-observations": "Create an iNaturalist account to save your observations and contribute them to science.",
|
||||
"CREATE-YOUR-FIRST-OBSERVATION": "CREATE YOUR FIRST OBSERVATION",
|
||||
"DATA-QUALITY": "DATA QUALITY",
|
||||
"DATA-QUALITY-ASSESSMENT": "DATA QUALITY ASSESSMENT",
|
||||
"Data-quality-assessment-title-research": {
|
||||
"comment": "declares the current data quality status of the observation ",
|
||||
"val": "This observation is Research Grade!"
|
||||
},
|
||||
"Data-quality-assessment-title-needs-id": "This observation Needs ID",
|
||||
"Data-quality-assessment-title-casual": "This observation is Casual Grade",
|
||||
"Data-quality-assessment-description-research": {
|
||||
"comment": "description for different quality grades in the DQA",
|
||||
"val": "It can now be used for research and featured on other websites."
|
||||
},
|
||||
"Data-quality-assessment-description-research-not-licensed": "However, it is not licensed for re-use and will not be shared with data repositories that respect license choices.",
|
||||
"Data-quality-assessment-description-needs-id": "This observation has not yet met the conditions for Research Grade status:",
|
||||
"Data-quality-assessment-description-casual": "This observation has not met the conditions for Research Grade status.",
|
||||
"Data-quality-assessment-date-specified": {
|
||||
"comment": "checklist test for Data Quality Assessment of Observation Details ",
|
||||
"val": "Date specified"
|
||||
},
|
||||
"Data-quality-assessment-location-specified": "Location specified",
|
||||
"Data-quality-assessment-has-photos-or-sounds": "Has Photos or Sounds",
|
||||
"Data-quality-assessment-id-supported-by-two-or-more": "Has ID supported by two or more",
|
||||
"Data-quality-assessment-community-taxon-species-level-or-lower": "Community taxon at species level or lower",
|
||||
"Data-quality-assessment-date-is-accurate": "Date is accurate",
|
||||
"Data-quality-assessment-location-is-accurate": "Location is accurate",
|
||||
"Data-quality-assessment-organism-is-wild": "Organism is wild",
|
||||
"Data-quality-assessment-evidence-of-organism": "Evidence of organism",
|
||||
"Data-quality-assessment-recent-evidence-of-organism": "Recent evidence of an organism",
|
||||
"Data-quality-assessment-can-taxon-still-be-confirmed-improved-based-on-the-evidence": "Based on the evidence, can the Community Taxon still be improved?",
|
||||
"Data-quality-research-description": "This observation has enough identifications to be considered resarch grade",
|
||||
"Data-quality-needs-id-description": "This observation needs more identifications to reach research grade",
|
||||
"Data-quality-casual-description": "This observation needs more information verified to be considered verifiable",
|
||||
@@ -118,6 +151,8 @@
|
||||
"Error-Couldnt-Complete-Upload": "Error: Couldn't Complete Upload",
|
||||
"Error-Couldnt-Upload-Photo": "Error: Couldn't Upload Photo",
|
||||
"Error-Could-Not-Fetch-Taxon": "Error: Could Not Fetch Taxon",
|
||||
"ERROR-VOTING-IN-DQA": "ERROR VOTING IN DQA",
|
||||
"Error-voting-in-DQA-description": "Your vote may not have been cast in the DQA. Check your internet connection and try again.",
|
||||
"EVIDENCE": "EVIDENCE",
|
||||
"Explore": "Explore",
|
||||
"EXPLORE-OBSERVATIONS": "EXPLORE OBSERVATIONS",
|
||||
@@ -248,12 +283,12 @@
|
||||
"No-Location": "No Location",
|
||||
"none": "none",
|
||||
"No-photos-found": "No photos found. If this is your first time opening the app and giving permissions, try restarting the app.",
|
||||
"no-rights-reserved-cc0": {
|
||||
"no-rights-reserved-cc0-cc0": {
|
||||
"comment": "license code",
|
||||
"val": "no rights reserved (CC0)"
|
||||
"val": "no rights reserved (CC0) (CC0)"
|
||||
},
|
||||
"NOTES": {
|
||||
"comment": "Header for observation description on observation detail",
|
||||
"comment": "Header for observation description on observation detail\nHeader for observation description on observation detail",
|
||||
"val": "NOTES"
|
||||
},
|
||||
"Notifications": "Notifications",
|
||||
@@ -660,6 +695,7 @@
|
||||
"comment": "Date formatting using date-fns\nSee complete list of formatting styles: https://date-fns.org/v2.29.3/docs/format",
|
||||
"val": "M/d/yy"
|
||||
},
|
||||
"comment": "Date formatting using date-fns\nSee complete list of formatting styles: https://date-fns.org/v2.29.3/docs/format",
|
||||
"datetime-format-short": {
|
||||
"comment": "Date formatting using date-fns\nSee complete list of formatting styles: https://date-fns.org/v2.29.3/docs/format",
|
||||
"val": "M/d/yy h:mm a"
|
||||
@@ -673,11 +709,11 @@
|
||||
"val": "As you upload more observations, others in our community may be able to help you identify them!"
|
||||
},
|
||||
"Observations-you-upload-to-iNaturalist": {
|
||||
"comment": "Onboarding text on MyObservations: 11-50 observations",
|
||||
"comment": "Onboarding text on MyObservations: Onboarding text on MyObservations: 11-50 observations",
|
||||
"val": "Observations you upload to iNaturalist can be used by scientists and researchers worldwide."
|
||||
},
|
||||
"You-can-search-observations-of-any-plant-or-animal": {
|
||||
"comment": "Onboarding text on MyObservations: 51-100 observations",
|
||||
"comment": "Onboarding text on MyObservations: Onboarding text on MyObservations: 51-100 observations",
|
||||
"val": "You can search observations of any plant or animal anywhere in the world with Explore!"
|
||||
},
|
||||
"DISCARD-MEDIA": "DISCARD MEDIA?",
|
||||
@@ -697,18 +733,18 @@
|
||||
"val": "Something went wrong."
|
||||
},
|
||||
"Anyone-using-iNaturalist-can-see": {
|
||||
"comment": "Geoprivacy sheet descriptions",
|
||||
"comment": " Geoprivacy sheet descriptions",
|
||||
"val": "Anyone using iNaturalist can see where this species was observed, and scientists can most easily use it for research."
|
||||
},
|
||||
"The-exact-location-will-be-hidden": "The exact location will be hidden publicly, and instead generalized to a larger area. (Threatened and endangered species are automatically obscured).",
|
||||
"The-location-will-not-be-visible": "The location will not be visible to others, which means it may be difficult to identify.",
|
||||
"This-is-a-wild-organism": {
|
||||
"comment": "Wild status sheet descriptions",
|
||||
"comment": " Wild status sheet descriptions",
|
||||
"val": "This is a wild organism and wasn’t placed in this location by humans."
|
||||
},
|
||||
"This-organism-was-placed-by-humans": "This organism was placed in this location by humans. This applies to things like garden plants, pets, and zoo animals.",
|
||||
"Lat-Lon-Acc": {
|
||||
"comment": "Latitude, longitude, and accuracy on a single line",
|
||||
"comment": "Latitude, longitude, and accuracy on a single line on a single line",
|
||||
"val": "Lat: { NUMBER($latitude, maximumFractionDigits: \"6\") }, Lon: { NUMBER($longitude, maximumFractionDigits: \"6\") }, Acc: { $accuracy }"
|
||||
},
|
||||
"Every-observation-needs": {
|
||||
|
||||
@@ -3,6 +3,11 @@ ABOUT = ABOUT
|
||||
|
||||
About-iNaturalist = About iNaturalist
|
||||
|
||||
# About the Data Quality Assement
|
||||
ABOUT-THE-DQA = ABOUT THE DQA
|
||||
|
||||
About-the-DQA-description = The Quality Grade summarizes the accuracy, precision, completeness, relevance, and appropriateness of an iNaturalist observation as biodiversity data. Some attributes are automatically determined, while others are subject to a vote by iNat users. iNaturalist shares licensed "Research Grade" observations with a number of data partners for use in science and conservation.
|
||||
|
||||
Accept-community-identifications = Accept community identifications
|
||||
|
||||
Account = Account
|
||||
@@ -64,6 +69,18 @@ attribution-cc-by-nc-sa = some rights reserved (CC BY-NC-SA)
|
||||
|
||||
attribution-cc-by-nc-nd = some rights reserved (CC BY-NC-ND)
|
||||
|
||||
attribution-cc-by = some rights reserved (CC BY)
|
||||
|
||||
attribution-cc-by-sa = some rights reserved (CC BY-SA)
|
||||
|
||||
attribution-cc-by-nc = some rights reserved (CC BY-NC)
|
||||
|
||||
attribution-cc-by-nd = some rights reserved (CC BY-ND)
|
||||
|
||||
attribution-cc-by-nc-sa = some rights reserved (CC BY-NC-SA)
|
||||
|
||||
attribution-cc-by-nc-nd = some rights reserved (CC BY-NC-ND)
|
||||
|
||||
app-authorized-on-date = { $appName } (authorized on: { $date })
|
||||
|
||||
Applications = Applications
|
||||
@@ -111,6 +128,8 @@ Content-Display = Content & Display
|
||||
|
||||
Copy-coordinates = Copy Coordinates
|
||||
|
||||
Copy-coordinates = Copy Coordinates
|
||||
|
||||
Couldnt-create-comment = Couldn't create comment
|
||||
|
||||
Couldnt-create-identification = Couldn't create identification
|
||||
@@ -119,12 +138,66 @@ Couldnt-create-identification-error = Couldn't create identification { $error }
|
||||
|
||||
Couldnt-create-identification-unknown-error = Couldn't create identification, Unknown Error.
|
||||
|
||||
Couldnt-create-identification-error = Couldn't create identification { $error }
|
||||
|
||||
Couldnt-create-identification-unknown-error = Couldn't create identification, Unknown Error.
|
||||
|
||||
CREATE-AN-ACCOUNT = CREATE AN ACCOUNT
|
||||
|
||||
Create-an-iNaturalist-account-to-save-your-observations = Create an iNaturalist account to save your observations and contribute them to science.
|
||||
|
||||
CREATE-YOUR-FIRST-OBSERVATION = CREATE YOUR FIRST OBSERVATION
|
||||
|
||||
DATA-QUALITY = DATA QUALITY
|
||||
|
||||
DATA-QUALITY-ASSESSMENT = DATA QUALITY ASSESSMENT
|
||||
|
||||
# declares the current data quality status of the observation
|
||||
Data-quality-assessment-title-research = This observation is Research Grade!
|
||||
|
||||
Data-quality-assessment-title-needs-id = This observation Needs ID
|
||||
|
||||
Data-quality-assessment-title-casual = This observation is Casual Grade
|
||||
|
||||
# description for different quality grades in the DQA
|
||||
Data-quality-assessment-description-research = It can now be used for research and featured on other websites.
|
||||
|
||||
Data-quality-assessment-description-research-not-licensed = However, it is not licensed for re-use and will not be shared with data repositories that respect license choices.
|
||||
|
||||
Data-quality-assessment-description-needs-id = This observation has not yet met the conditions for Research Grade status:
|
||||
|
||||
Data-quality-assessment-description-casual = This observation has not met the conditions for Research Grade status.
|
||||
|
||||
# checklist test for Data Quality Assessment of Observation Details
|
||||
Data-quality-assessment-date-specified = Date specified
|
||||
|
||||
Data-quality-assessment-location-specified = Location specified
|
||||
|
||||
Data-quality-assessment-has-photos-or-sounds = Has Photos or Sounds
|
||||
|
||||
Data-quality-assessment-id-supported-by-two-or-more = Has ID supported by two or more
|
||||
|
||||
Data-quality-assessment-community-taxon-species-level-or-lower = Community taxon at species level or lower
|
||||
|
||||
Data-quality-assessment-date-is-accurate = Date is accurate
|
||||
|
||||
Data-quality-assessment-location-is-accurate = Location is accurate
|
||||
|
||||
Data-quality-assessment-organism-is-wild = Organism is wild
|
||||
|
||||
Data-quality-assessment-evidence-of-organism = Evidence of organism
|
||||
|
||||
Data-quality-assessment-recent-evidence-of-organism = Recent evidence of an organism
|
||||
|
||||
Data-quality-assessment-can-taxon-still-be-confirmed-improved-based-on-the-evidence = Based on the evidence, can the Community Taxon still be improved?
|
||||
|
||||
Data-quality-research-description = This observation has enough identifications to be considered resarch grade
|
||||
|
||||
Data-quality-needs-id-description = This observation needs more identifications to reach research grade
|
||||
|
||||
Data-quality-casual-description = This observation needs more information verified to be considered verifiable
|
||||
|
||||
|
||||
DATA-QUALITY = DATA QUALITY
|
||||
|
||||
Data-quality-research-description = This observation has enough identifications to be considered resarch grade
|
||||
@@ -137,6 +210,8 @@ Date = Date
|
||||
|
||||
DATE = DATE
|
||||
|
||||
DATE = DATE
|
||||
|
||||
Date-added-newest-to-oldest = Date added - newest to oldest
|
||||
|
||||
Date-added-oldest-to-newest = Date added - oldest to newest
|
||||
@@ -202,6 +277,10 @@ Error-Couldnt-Upload-Photo = Error: Couldn't Upload Photo
|
||||
|
||||
Error-Could-Not-Fetch-Taxon = Error: Could Not Fetch Taxon
|
||||
|
||||
ERROR-VOTING-IN-DQA = ERROR VOTING IN DQA
|
||||
|
||||
Error-voting-in-DQA-description = Your vote may not have been cast in the DQA. Check your internet connection and try again.
|
||||
|
||||
EVIDENCE = EVIDENCE
|
||||
|
||||
Explore = Explore
|
||||
@@ -307,6 +386,8 @@ Location = Location
|
||||
|
||||
LOCATION = LOCATION
|
||||
|
||||
LOCATION = LOCATION
|
||||
|
||||
Location-accuracy-is-too-imprecise = Location accuracy is too imprecise to help identifiers. Please zoom in.
|
||||
|
||||
LOCATION-TOO-IMPRECISE = LOCATION TOO IMPRECISE
|
||||
@@ -395,8 +476,9 @@ none = none
|
||||
No-photos-found = No photos found. If this is your first time opening the app and giving permissions, try restarting the app.
|
||||
|
||||
# license code
|
||||
no-rights-reserved-cc0 = no rights reserved (CC0)
|
||||
no-rights-reserved-cc0-cc0 = no rights reserved (CC0) (CC0)
|
||||
|
||||
# Header for observation description on observation detail
|
||||
# Header for observation description on observation detail
|
||||
NOTES = NOTES
|
||||
|
||||
@@ -469,6 +551,11 @@ quality-grade-research = Research
|
||||
quality-grade-needs-id = Needs Id
|
||||
quality-grade-casual = Casual
|
||||
|
||||
# Quality grade options
|
||||
quality-grade-research = Research
|
||||
quality-grade-needs-id = Needs Id
|
||||
quality-grade-casual = Casual
|
||||
|
||||
Rank = Rank
|
||||
|
||||
# The following Ranks- strings are taxonomic ranks (in taxonomic order, not alphabetical order)
|
||||
@@ -589,6 +676,8 @@ SAVE-CHANGES = SAVE CHANGES
|
||||
|
||||
Saved-Observation = Saved observation, in queue to upload
|
||||
|
||||
Saved-Observation = Saved observation, in queue to upload
|
||||
|
||||
Search-for-a-location = Search for a location
|
||||
|
||||
Search-for-a-project = Search for a project
|
||||
@@ -611,6 +700,8 @@ SHARE-DEBUG-LOGS = SHARE DEBUG LOGS
|
||||
|
||||
Share-location = Share Location
|
||||
|
||||
Share-location = Share Location
|
||||
|
||||
Sign-out = Sign out
|
||||
|
||||
Sign-Up = Sign Up
|
||||
@@ -696,6 +787,9 @@ IMPORT-X-OBSERVATIONS = IMPORT {$count ->
|
||||
# Describes whether a user made this observation from web, iOS, or Android
|
||||
Uploaded-via-application = Uploaded via: { $application }
|
||||
|
||||
# Describes whether a user made this observation from web, iOS, or Android
|
||||
Uploaded-via-application = Uploaded via: { $application }
|
||||
|
||||
# Shows the number of observations a user is currently uploading on my observations page
|
||||
Uploading-X-Observations = Uploading {$count ->
|
||||
[one] 1 Observation
|
||||
@@ -728,6 +822,10 @@ VIEW-DATA-QUALITY-ASSESSEMENT = VIEW DATA QUALITY ASSESSEMENT
|
||||
|
||||
View-in-browser = View in Browser
|
||||
|
||||
VIEW-DATA-QUALITY-ASSESSEMENT = VIEW DATA QUALITY ASSESSEMENT
|
||||
|
||||
View-in-browser = View in Browser
|
||||
|
||||
Visually-search-iNaturalist-data = Visually search iNaturalist’s wealth of data. Search by a taxon in a location
|
||||
|
||||
Welcome-to-iNaturalist = Welcome to iNaturalist!
|
||||
@@ -955,19 +1053,25 @@ Take-photo = Take photo
|
||||
# See complete list of formatting styles: https://date-fns.org/v2.29.3/docs/format
|
||||
date-format-short = M/d/yy
|
||||
|
||||
# Date formatting using date-fns
|
||||
# See complete list of formatting styles: https://date-fns.org/v2.29.3/docs/format
|
||||
|
||||
# Date formatting using date-fns
|
||||
# See complete list of formatting styles: https://date-fns.org/v2.29.3/docs/format
|
||||
datetime-format-short = M/d/yy h:mm a
|
||||
|
||||
# Date formatting using date-fns
|
||||
# See complete list of formatting styles: https://date-fns.org/v2.29.3/docs/format
|
||||
|
||||
# Date formatting using date-fns
|
||||
# See complete list of formatting styles: https://date-fns.org/v2.29.3/docs/format
|
||||
date-format-long = PP
|
||||
|
||||
# Onboarding text on MyObservations: 0-10 observations
|
||||
As-you-upload-more-observations = As you upload more observations, others in our community may be able to help you identify them!
|
||||
# Onboarding text on MyObservations: 11-50 observations
|
||||
# Onboarding text on MyObservations: Onboarding text on MyObservations: 11-50 observations
|
||||
Observations-you-upload-to-iNaturalist = Observations you upload to iNaturalist can be used by scientists and researchers worldwide.
|
||||
# Onboarding text on MyObservations: 51-100 observations
|
||||
# Onboarding text on MyObservations: Onboarding text on MyObservations: 51-100 observations
|
||||
You-can-search-observations-of-any-plant-or-animal = You can search observations of any plant or animal anywhere in the world with Explore!
|
||||
|
||||
DISCARD-MEDIA = DISCARD MEDIA?
|
||||
@@ -986,16 +1090,16 @@ Failed-to-log-in = Failed to log in
|
||||
# Generic error message
|
||||
Something-went-wrong = Something went wrong.
|
||||
|
||||
# Geoprivacy sheet descriptions
|
||||
# Geoprivacy sheet descriptions
|
||||
Anyone-using-iNaturalist-can-see = Anyone using iNaturalist can see where this species was observed, and scientists can most easily use it for research.
|
||||
The-exact-location-will-be-hidden = The exact location will be hidden publicly, and instead generalized to a larger area. (Threatened and endangered species are automatically obscured).
|
||||
The-location-will-not-be-visible = The location will not be visible to others, which means it may be difficult to identify.
|
||||
|
||||
# Wild status sheet descriptions
|
||||
# Wild status sheet descriptions
|
||||
This-is-a-wild-organism = This is a wild organism and wasn’t placed in this location by humans.
|
||||
This-organism-was-placed-by-humans = This organism was placed in this location by humans. This applies to things like garden plants, pets, and zoo animals.
|
||||
|
||||
# Latitude, longitude, and accuracy on a single line
|
||||
# Latitude, longitude, and accuracy on a single line on a single line
|
||||
Lat-Lon-Acc = Lat: { NUMBER($latitude, maximumFractionDigits: 6) }, Lon: { NUMBER($longitude, maximumFractionDigits: 6) }, Acc: { $accuracy }
|
||||
|
||||
# Missing evidence sheet
|
||||
|
||||
@@ -14,6 +14,7 @@ import MediaViewer from "components/MediaViewer/MediaViewer";
|
||||
import Messages from "components/Messages/Messages";
|
||||
import MyObservationsContainer from "components/MyObservations/MyObservationsContainer";
|
||||
import NetworkLogging from "components/NetworkLogging";
|
||||
import DataQualityAssessment from "components/ObsDetails/DataQualityAssessment";
|
||||
import ObsDetails from "components/ObsDetails/ObsDetails";
|
||||
import ObsEdit from "components/ObsEdit/ObsEdit";
|
||||
import GroupPhotosContainer from "components/PhotoImporter/GroupPhotosContainer";
|
||||
@@ -35,7 +36,8 @@ import {
|
||||
hideHeader,
|
||||
hideHeaderLeft,
|
||||
showCustomHeader,
|
||||
showHeaderLeft
|
||||
showHeaderLeft,
|
||||
showLongHeader
|
||||
} from "navigation/navigationOptions";
|
||||
import React from "react";
|
||||
import { PermissionsAndroid, Platform } from "react-native";
|
||||
@@ -351,6 +353,15 @@ const BottomTabs = ( ) => {
|
||||
...hideHeaderLeft
|
||||
}}
|
||||
/>
|
||||
<Tab.Screen
|
||||
name="DataQualityAssessment"
|
||||
component={DataQualityAssessment}
|
||||
options={{
|
||||
...showLongHeader,
|
||||
headerTitle: t( "DATA-QUALITY-ASSESSMENT" ),
|
||||
unmountOnBlur: true
|
||||
}}
|
||||
/>
|
||||
<Tab.Screen name="Login" component={MortalLogin} options={hideHeader} />
|
||||
<Tab.Screen name="SignUp" component={SignUp} options={hideHeader} />
|
||||
<Tab.Screen name="ForgotPassword" component={ForgotPassword} options={hideHeader} />
|
||||
|
||||
@@ -26,6 +26,20 @@ const showHeader: Object = {
|
||||
}
|
||||
};
|
||||
|
||||
const showLongHeader: Object = {
|
||||
...baseHeaderOptions,
|
||||
headerTintColor: colors.black,
|
||||
// Note: left header is not supported on iOS
|
||||
// so we would need to build a custom header for this:
|
||||
// https://reactnavigation.org/docs/native-stack-navigator#headertitlealign
|
||||
headerTitleStyle: {
|
||||
fontSize: 16,
|
||||
fontFamily: Platform.OS === "ios"
|
||||
? "Whitney-Medium"
|
||||
: "Whitney-Medium-Pro"
|
||||
}
|
||||
};
|
||||
|
||||
export const showHeaderLeft: Object = {
|
||||
...showHeader,
|
||||
headerLeft: ( ) => <BackButton />
|
||||
@@ -53,5 +67,6 @@ export {
|
||||
blankHeaderTitle,
|
||||
hideHeader,
|
||||
showCustomHeader,
|
||||
showHeader
|
||||
showHeader,
|
||||
showLongHeader
|
||||
};
|
||||
|
||||
@@ -33,6 +33,7 @@ class Observation extends Realm.Object {
|
||||
location: true,
|
||||
longitude: true,
|
||||
observation_photos: ObservationPhoto.OBSERVATION_PHOTOS_FIELDS,
|
||||
observed_on: true,
|
||||
place_guess: true,
|
||||
quality_grade: true,
|
||||
taxon: Taxon.TAXON_FIELDS,
|
||||
@@ -47,6 +48,9 @@ class Observation extends Realm.Object {
|
||||
captive_flag: false,
|
||||
geoprivacy: "open",
|
||||
owners_identification_from_vision: false,
|
||||
observed_on: obs
|
||||
? obs?.observed_on
|
||||
: createObservedOnStringForUpload( ),
|
||||
observed_on_string: obs
|
||||
? obs?.observed_on_string
|
||||
: createObservedOnStringForUpload( ),
|
||||
@@ -187,6 +191,7 @@ class Observation extends Realm.Object {
|
||||
species_guess: obs.species_guess,
|
||||
description: obs.description,
|
||||
observed_on_string: obs.observed_on_string,
|
||||
observed_on: obs.observed_on,
|
||||
place_guess: obs.place_guess,
|
||||
latitude: obs.latitude,
|
||||
longitude: obs.longitude,
|
||||
@@ -486,6 +491,7 @@ class Observation extends Realm.Object {
|
||||
observationSounds: "ObservationSound[]",
|
||||
// date and/or time submitted to the server when a new obs is uploaded
|
||||
observed_on_string: "string?",
|
||||
observed_on: "string?",
|
||||
owners_identification_from_vision: "bool?",
|
||||
species_guess: "string?",
|
||||
place_guess: { type: "string?", mapTo: "placeGuess" },
|
||||
|
||||
@@ -24,9 +24,18 @@ export default {
|
||||
Taxon,
|
||||
User
|
||||
],
|
||||
schemaVersion: 33,
|
||||
schemaVersion: 34,
|
||||
path: `${RNFS.DocumentDirectoryPath}/db.realm`,
|
||||
migration: ( oldRealm, newRealm ) => {
|
||||
if ( oldRealm.schemaVersion < 34 ) {
|
||||
const oldObservations = oldRealm.objects( "Observation" );
|
||||
const newObservations = newRealm.objects( "Observation" );
|
||||
oldObservations.keys( ).forEach( objectIndex => {
|
||||
const oldObservation = oldObservations[objectIndex];
|
||||
const newObservation = newObservations[objectIndex];
|
||||
newObservation.observed_on = oldObservation.time_observed_at;
|
||||
} );
|
||||
}
|
||||
if ( oldRealm.schemaVersion < 33 ) {
|
||||
const oldObservations = oldRealm.objects( "Observation" );
|
||||
const newObservations = newRealm.objects( "Observation" );
|
||||
|
||||
Reference in New Issue
Block a user