Skip to content

Commit

Permalink
Merge 0a47813 into c8e4440
Browse files Browse the repository at this point in the history
  • Loading branch information
duvld committed Jun 11, 2024
2 parents c8e4440 + 0a47813 commit 1582eb0
Show file tree
Hide file tree
Showing 10 changed files with 221 additions and 28 deletions.
9 changes: 8 additions & 1 deletion jsapp/js/assetUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ export function getOrganizationDisplayString(asset: AssetResponse | ProjectViewA
* Returns the index of language or null if not found.
*/
export function getLanguageIndex(asset: AssetResponse, langString: string) {
let foundIndex = null;
// Return -1 instead of null as that would allow
// `getQuestionOrChoiceDisplayName` to defualt to xml names.
let foundIndex = -1;

if (
Array.isArray(asset.summary?.languages) &&
Expand Down Expand Up @@ -224,6 +226,11 @@ export function getQuestionOrChoiceDisplayName(
}

if (questionOrChoice.label && Array.isArray(questionOrChoice.label)) {
// If the user hasn't made translations yet for a form language show
// the xml names instead of blank.
if (questionOrChoice.label[translationIndex] === null) {
return getRowName(questionOrChoice);
}
return questionOrChoice.label[translationIndex];
} else if (questionOrChoice.label && !Array.isArray(questionOrChoice.label)) {
// in rare cases the label could be a string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
padding-top: 12px;
}

.settingsWrapper {
display: flex;
justify-content: flex-end;
}

.displays {
flex: 1;
display: flex;
Expand Down
8 changes: 6 additions & 2 deletions jsapp/js/components/processing/sidebar/processingSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import singleProcessingStore, {
} from 'js/components/processing/singleProcessingStore';
import TransxDisplay from './transxDisplay';
import SidebarDisplaySettings from 'js/components/processing/sidebar/sidebarDisplaySettings';
import SidebarLabelsSettings from 'js/components/processing/sidebar/sidebarLabelsSettings.component';
import type {AssetResponse} from 'jsapp/js/dataInterface';
import SidebarSubmissionData from 'js/components/processing/sidebar/sidebarSubmissionData';
import SidebarSubmissionMedia from 'js/components/processing/sidebar/sidebarSubmissionMedia';
Expand All @@ -23,7 +24,10 @@ export default function ProcessingSidebar(props: ProcessingSidebarProps) {

return (
<div className={styles.root}>
<SidebarDisplaySettings assetContent={props.asset.content}/>
<div className={styles.settingsWrapper}>
<SidebarLabelsSettings />
<SidebarDisplaySettings assetContent={props.asset.content} />
</div>

<div className={styles.displays}>
{Array.from(translations).map((translation) => {
Expand All @@ -48,7 +52,7 @@ export default function ProcessingSidebar(props: ProcessingSidebarProps) {
)}

{displays.includes(StaticDisplays.Data) && (
<SidebarSubmissionData assetContent={props.asset.content} />
<SidebarSubmissionData asset={props.asset} />
)}

{displays.length === 0 && (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import React, {useState} from 'react';
import Button from 'js/components/common/button';
import KoboModal from 'js/components/modals/koboModal';
import KoboModalHeader from 'js/components/modals/koboModalHeader';
import KoboModalFooter from 'js/components/modals/koboModalFooter';
import KoboSelect from 'js/components/common/koboSelect';
import singleProcessingStore from 'js/components/processing/singleProcessingStore';
import styles from './sidebarLabelsSettings.module.scss';
import type {LanguageCode} from 'js/components/languages/languagesStore';

export default function SidebarLabelsSettings() {
const [store] = useState(() => singleProcessingStore);
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);

const [labelLanguage, setLabelLanguage] = useState<LanguageCode | string>(
store.getCurrentlyDisplayedLanguage()
);

const displayedLanguageList = store.getDisplayedLanguagesList();

return (
<div className={styles.root}>
<Button
size='m'
type='bare'
label={t('Change question language')}
color='storm'
startIcon='globe-alt'
onClick={() => setIsModalOpen(true)}
/>
<KoboModal
isOpen={isModalOpen}
onRequestClose={() => {
setLabelLanguage(store.getCurrentlyDisplayedLanguage());
setIsModalOpen(false);
}}
size='medium'
>
<KoboModalHeader
onRequestCloseByX={() => {
setLabelLanguage(store.getCurrentlyDisplayedLanguage());
setIsModalOpen(false);
}}
>
{t('Change label language')}
</KoboModalHeader>
<div className={styles.selectWrapper}>
<KoboSelect
label={t('Select displayed language')}
name='displayedLanguage'
type='outline'
size='s'
options={displayedLanguageList}
selectedOption={labelLanguage}
onChange={(languageCode) => {
if (languageCode) {
setLabelLanguage(languageCode);
}
}}
/>
</div>
<KoboModalFooter>
<Button
label={<strong>{t('Apply')}</strong>}
type='frame'
color='light-blue'
size='m'
onClick={() => {
store.setCurrentlyDisplayedLanguage(labelLanguage);
setIsModalOpen(false);
}}
/>
</KoboModalFooter>
</KoboModal>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
@use 'scss/sizes';

$kobo-modal-padding: sizes.$x30;

.root {
height: sizes.$x48;
display: flex;
justify-content: right;
align-items: center;
}

.selectWrapper {
padding: $kobo-modal-padding;
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React, {useState} from 'react';
import SubmissionDataList from 'js/components/submissions/submissionDataList';
import singleProcessingStore from 'js/components/processing/singleProcessingStore';
import type {AssetContent} from 'js/dataInterface';
import type {AssetContent, AssetResponse} from 'js/dataInterface';
import {META_QUESTION_TYPES, ADDITIONAL_SUBMISSION_PROPS} from 'js/constants';
import styles from './sidebarSubmissionData.module.scss';

interface SidebarSubmissionDataProps {
assetContent: AssetContent | undefined;
asset: AssetResponse;
}

export default function SidebarSubmissionData(
Expand All @@ -16,7 +16,7 @@ export default function SidebarSubmissionData(

const submissionData = store.getSubmissionData();

if (!props.assetContent) {
if (!props.asset.content) {
return null;
}

Expand All @@ -41,7 +41,7 @@ export default function SidebarSubmissionData(
<div className={styles.dataListBody}>
{submissionData && (
<SubmissionDataList
assetContent={props.assetContent}
asset={props.asset}
submissionData={submissionData}
hideQuestions={getQuestionsToHide()}
hideGroups
Expand Down
21 changes: 16 additions & 5 deletions jsapp/js/components/processing/singleProcessingHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React from 'react';
import {QUESTION_TYPES, META_QUESTION_TYPES} from 'js/constants';
import type {AssetContent} from 'js/dataInterface';
import type {AssetContent, AssetResponse} from 'js/dataInterface';
import {
findRowByQpath,
getRowTypeIcon,
getTranslatedRowLabel,
getRowName,
getLanguageIndex,
} from 'js/assetUtils';
import {ROUTES} from 'js/router/routerConstants';
import Button from 'js/components/common/button';
Expand All @@ -22,7 +23,7 @@ import classNames from 'classnames';
interface SingleProcessingHeaderProps extends WithRouterProps {
submissionEditId: string;
assetUid: string;
assetContent: AssetContent;
asset: AssetResponse;
}

interface SingleProcessingHeaderState {
Expand Down Expand Up @@ -86,9 +87,19 @@ class SingleProcessingHeader extends React.Component<
getQuestionSelectorOptions() {
const options: KoboSelectOption[] = [];
const editIds = singleProcessingStore.getSubmissionsEditIds();
const assetContent = this.props.asset.content;
const languageIndex = getLanguageIndex(
this.props.asset,
singleProcessingStore.getCurrentlyDisplayedLanguage()
);

if (!assetContent) {
return [];
}

if (editIds) {
Object.keys(editIds).forEach((qpath) => {
const questionData = findRowByQpath(this.props.assetContent, qpath);
const questionData = findRowByQpath(assetContent, qpath);
// At this point we want to find out whether the question has at least
// one editId (i.e. there is at least one transcriptable response to
// the question). Otherwise there's no point in having the question as
Expand All @@ -107,8 +118,8 @@ class SingleProcessingHeader extends React.Component<
const rowName = getRowName(questionData);
const translatedLabel = getTranslatedRowLabel(
rowName,
this.props.assetContent.survey,
0
assetContent.survey,
languageIndex
);
options.push({
value: qpath,
Expand Down
2 changes: 1 addition & 1 deletion jsapp/js/components/processing/singleProcessingRoute.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ export default class SingleProcessingRoute extends React.Component<
<SingleProcessingHeader
submissionEditId={this.props.params.submissionEditId}
assetUid={this.props.params.uid}
assetContent={this.state.asset.content}
asset={this.state.asset}
/>
</section>

Expand Down
49 changes: 48 additions & 1 deletion jsapp/js/components/processing/singleProcessingStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
getRowName,
getRowNameByQpath,
getFlatQuestionsList,
getLanguageIndex,
} from 'js/assetUtils';
import type {SurveyFlatPaths} from 'js/assetUtils';
import assetStore from 'js/assetStore';
Expand All @@ -34,6 +35,7 @@ import {
getCurrentProcessingRouteParts,
ProcessingTab,
} from 'js/components/processing/routes.utils';
import type {KoboSelectOption} from 'js/components/common/koboSelect';

export enum StaticDisplays {
Data = 'Data',
Expand Down Expand Up @@ -125,6 +127,7 @@ interface SingleProcessingStoreData {
isFetchingData: boolean;
isPollingForTranscript: boolean;
hiddenSidebarQuestions: string[];
currentlyDisplayedLanguage: LanguageCode | string;
}

class SingleProcessingStore extends Reflux.Store {
Expand Down Expand Up @@ -155,6 +158,7 @@ class SingleProcessingStore extends Reflux.Store {
isFetchingData: false,
isPollingForTranscript: false,
hiddenSidebarQuestions: [],
currentlyDisplayedLanguage: this.getInitialDisplayedLanguage(),
};

/** Clears all data - useful before making initialisation call */
Expand Down Expand Up @@ -957,6 +961,40 @@ class SingleProcessingStore extends Reflux.Store {
);
}

getDisplayedLanguagesList(): KoboSelectOption[] {
const languagesList = [];

languagesList.push({label: t('XML names'), value: 'xml_names'});
const asset = assetStore.getAsset(this.currentAssetUid);
if (asset?.summary?.languages && asset?.summary?.languages.length > 0) {
asset.summary.languages.forEach((language) => {
if (language !== null) {
languagesList.push({
label: language,
value: language,
});
}
});
} else {
languagesList.push({label: t('Default'), value: 'default'});
}

return languagesList;
}

getInitialDisplayedLanguage() {
const asset = assetStore.getAsset(this.currentAssetUid);
if (asset?.summary?.languages && asset?.summary?.languages[0]) {
return asset?.summary?.languages[0];
} else {
return '';
}
}

getCurrentlyDisplayedLanguage() {
return this.data.currentlyDisplayedLanguage;
}

getInitialDisplays(): SidebarDisplays {
return {
transcript: DefaultDisplays.get(ProcessingTab.Transcript) || [],
Expand Down Expand Up @@ -992,7 +1030,10 @@ class SingleProcessingStore extends Reflux.Store {
const asset = assetStore.getAsset(this.currentAssetUid);

if (asset?.content?.survey) {
const questionsList = getFlatQuestionsList(asset.content.survey, 0)
const questionsList = getFlatQuestionsList(
asset.content.survey,
getLanguageIndex(asset, this.data.currentlyDisplayedLanguage)
)
.filter((question) => !(question.name === this.currentQuestionName))
.map((question) => {
// We make an object to show the question label to the user but use the
Expand Down Expand Up @@ -1063,6 +1104,12 @@ class SingleProcessingStore extends Reflux.Store {

this.trigger(this.data);
}

setCurrentlyDisplayedLanguage(language: LanguageCode) {
this.data.currentlyDisplayedLanguage = language;

this.trigger(this.data);
}
}

/**
Expand Down
Loading

0 comments on commit 1582eb0

Please sign in to comment.