<commit_before>import React, { ReactElement, useContext, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Redirect, useParams } from 'react-router-dom';
import { search } from '../api/documents';
import { LoginContext } from '../App';
import { NotFound } from '../shared/NotFound';


export default function ResourceRedirect(): ReactElement {

    const { project, identifier } = useParams<{ project: string, identifier: string }>();
    const [id, setId] = useState<string>(null);
    const [error, setError] = useState<string>(null);
    const loginData = useContext(LoginContext);
    const { t } = useTranslation();

    useEffect (() => {
        
        getId(project, identifier, loginData.token)
            .then(setId)
            .catch(setError);
    }, [project, identifier, loginData]);

    return error
        ? <NotFound />
        : id
            ? <Redirect to={ `/project/${project}/${id}` } />
            : <div>{ t('resourceRedirect.waitForRedirection')}</div>;
}


const getId = async (project: string, identifier: string, token: string): Promise<string> => {

    const result = await search({ filters: getFilters(project, identifier), q: '' }, token);

    if (result.documents.length > 0) {
        return result.documents[0].resource.id;
    } else {
        throw 'Not found';
    }
};

<commit_msg>Properly handle missing resource identifiers in ResourceRedirect<commit_after>import React, { ReactElement, useContext, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Redirect, useParams } from 'react-router-dom';
import { search } from '../api/documents';
import { LoginContext } from '../App';
import { NotFound } from '../shared/NotFound';


export default function ResourceRedirect(): ReactElement {

    const { project, identifier } = useParams<{ project: string, identifier: string }>();
    const [id, setId] = useState<string>(null);
    const [error, setError] = useState<string>(null);
    const loginData = useContext(LoginContext);
    const { t } = useTranslation();

    useEffect (() => {
        
        getId(project, identifier, loginData.token)
            .then((resultId: string) => resultId ? setId(resultId) : setError('Not found'))
            .catch(setError);
    }, [project, identifier, loginData]);

    return error
        ? <NotFound />
        : id
            ? <Redirect to={ `/project/${project}/${id}` } />
            : <div>{ t('resourceRedirect.waitForRedirection')}</div>;
}


const getId = async (project: string, identifier: string, token: string): Promise<string> => {

    const result = await search({ filters: getFilters(project, identifier), q: '' }, token);

    if (result.documents.length > 0) {
        return result.documents[0].resource.id;
    } else {
        throw 'Not found';
    }
};


{'fraction_non_alphanumeric': 0.151673640167364, 'fraction_numerical': 0.002789400278940028, 'mean_word_length': 3.2129221732745963, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 26, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6945646', 'n_tokens_mistral': 806, 'n_tokens_neox': 793, 'n_words': 215}