Skip to content

Commit

Permalink
feat: Choose language for exported data
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobsvante committed Oct 30, 2024
1 parent 2644175 commit 538f229
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 19 deletions.
12 changes: 12 additions & 0 deletions schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"i18n_string",
"image",
"image_summary",
"language",
"nested_attribute",
"nested_color",
"nested_price",
Expand Down Expand Up @@ -58,6 +59,9 @@
"sort_by": {
"$ref": "#/definitions/SortByJsonSchema"
},
"language": {
"$ref": "#/definitions/Language"
},
"environment": {
"$ref": "#/definitions/Environment"
},
Expand Down Expand Up @@ -1661,6 +1665,14 @@
"delivery_period:desc"
]
},
"Language": {
"type": "string",
"enum": [
"en",
"sv",
"de"
]
},
"Attribute": {
"description": "Attribute",
"type": "object",
Expand Down
1 change: 1 addition & 0 deletions src/i18n.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use strum::IntoEnumIterator;
PartialOrd,
Ord,
strum::EnumIter,
JsonSchema,
)]
#[serde(rename_all = "snake_case")]
pub enum Language {
Expand Down
1 change: 1 addition & 0 deletions src/jsonschema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ pub(crate) struct PublicJsonSchema {
export: ExportSchema,
filters: FiltersSchema,
sort_by: SortByJsonSchema,
language: crate::Language,
environment: crate::Environment,
attribute: crate::Attribute,
attribute_type: crate::AttributeType,
Expand Down
53 changes: 36 additions & 17 deletions ui/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
NestedStyleSummary,
Category,
ItemFilterChoices,
Language,
} from "./types/api";
import { useAppDispatch, useAppSelector } from "./state/hooks";
import { useEffect, useState } from "react";
Expand Down Expand Up @@ -170,6 +171,7 @@ interface ApiSurface {
token: string,
organizationId: number,
collectionSlug: string,
language: Language,
exportFormat: ExportFormat,
groupBy: GroupBy[],
fields: ExportField[],
Expand All @@ -181,6 +183,7 @@ interface ApiGetRequestOptions {
token: string;
sortOrder?: string;
filters?: object;
language?: Language; // TODO: This is only really meant for downloadExportFile...
groupBy?: GroupBy[]; // TODO: This is only really meant for downloadExportFile...
fields?: ExportField[]; // TODO: This is only really meant for downloadExportFile...
}
Expand Down Expand Up @@ -232,6 +235,9 @@ function makeApi(baseUrl: string): ApiSurface {
if (!!opts.groupBy) {
searchParams.append("group_by", JSON.stringify(opts.groupBy));
}
if (!!opts.language) {
searchParams.append("language", opts.language);
}
if (!!opts.fields) {
searchParams.append("fields", JSON.stringify(opts.fields));
}
Expand Down Expand Up @@ -387,13 +393,16 @@ function makeApi(baseUrl: string): ApiSurface {
token,
});
},
async fetchItemFilterChoices (
async fetchItemFilterChoices(
token: string,
organizationId: number,
): Promise<Result<ItemFilterChoices, ApiErrorResponse>> {
return await getJson<ItemFilterChoices>(`/${organizationId}/admin/filters/items`, {
token,
});
return await getJson<ItemFilterChoices>(
`/${organizationId}/admin/filters/items`,
{
token,
},
);
},
async fetchColors(
token: string,
Expand Down Expand Up @@ -596,18 +605,23 @@ function makeApi(baseUrl: string): ApiSurface {
token: string,
organizationId: number,
collectionSlug: string,
language: Language,
exportFormat: ExportFormat,
groupBy: GroupBy[],
fields: ExportField[],
filters?: CollectionFilters,
): Promise<Response> {
const subpath = `/${organizationId}/exports/slug:${collectionSlug}/${exportFormat}`;
return fetchRaw(subpath, { token, filters, groupBy, fields }).catch(
(err) => {
console.error(`Failed to download file, with error: ${err}`);
return err;
},
);
return fetchRaw(subpath, {
token,
filters,
groupBy,
language,
fields,
}).catch((err) => {
console.error(`Failed to download file, with error: ${err}`);
return err;
});
},
};
}
Expand Down Expand Up @@ -855,10 +869,7 @@ export function usePricelists(): PricelistsFetchResult {
useEffect(() => {
if (!!token && !!activeOrganization) {
api
.fetchPriceLists(
token as string,
activeOrganization.organization.id,
)
.fetchPriceLists(token as string, activeOrganization.organization.id)
.then((result) => {
setFetchResult(result);
});
Expand Down Expand Up @@ -918,16 +929,24 @@ export function useCollectionList(): [CollectionListFetchResult, () => void] {
return [fetchResult, refresh];
}

type ItemFilterChoicesFetchResult = Result<ItemFilterChoices | null, ApiErrorResponse>;
type ItemFilterChoicesFetchResult = Result<
ItemFilterChoices | null,
ApiErrorResponse
>;

export function useItemFilterChoices(): ItemFilterChoicesFetchResult {
const { token, activeOrganization } = useAppSelector((state) => state.user);
const [fetchResult, setFetchResult] = useState(Ok(null) as ItemFilterChoicesFetchResult);
const [fetchResult, setFetchResult] = useState(
Ok(null) as ItemFilterChoicesFetchResult,
);
useLogoutOnExpiredToken(fetchResult);
useEffect(() => {
if (!!token && !!activeOrganization) {
api
.fetchItemFilterChoices(token as string, activeOrganization.organization.id)
.fetchItemFilterChoices(
token as string,
activeOrganization.organization.id,
)
.then((result) => {
setFetchResult(result);
});
Expand Down
43 changes: 42 additions & 1 deletion ui/src/components/ExportForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ import {
GroupBy,
ExportFormat,
PriceListSummary,
Language,
} from "../types/api";
import { useLocalize } from "../i18n";
import { locales, useLocaleParam, useLocalize } from "../i18n";
import { ItemFilters, makeCollectionFilters } from "../types/filters";
import { classNames } from "../utils";
import LoadingIndicator from "./LoadingIndicator";
Expand Down Expand Up @@ -177,6 +178,8 @@ export default function ExportForm({
const { token, activeOrganization } = useAppSelector((state) => state.user);
const { i18nDbText } = useLocalize();

const locale = useLocaleParam();
const [language, setLanguage] = useState(locale as Language);
const [exportFormat, setExportFormat] = useState(ExportFormat.Xlsx);
const [groupByEntries, setGroupByEntries] = useState(() => [
...allGroupByEntries,
Expand All @@ -192,6 +195,7 @@ export default function ExportForm({
token,
activeOrganization.organization.id,
collection.slug,
language,
exportFormat,
groupByEntries.filter((g) => g.checked).map((g) => g.groupBy),
fieldEntries.filter((f) => f.checked).map((f) => f.field),
Expand Down Expand Up @@ -260,6 +264,43 @@ export default function ExportForm({
evt.preventDefault();
}}
>
<fieldset className="mt-6">
<legend className="contents text-base font-medium text-gray-900">
<Trans>Language</Trans>
</legend>
<p className="text-sm text-gray-500">
<Trans>Which language you want to export to.</Trans>
</p>
<div className="mt-2 space-y-4">
{Object.values(Language).map((value) => (
<div key={value} className="relative flex items-start">
<div className="flex h-5 items-center">
<input
id={`export-language-${value}`}
name="language"
checked={language === value}
value={value}
type="radio"
onChange={(evt) => {
return evt.target.checked
? setLanguage(value)
: "";
}}
className="h-4 w-4 border-gray-300 text-indigo-600 focus:ring-indigo-500 disabled:text-gray-400"
/>
</div>
<div className="ml-3 text-sm">
<label
htmlFor={`export-language-${value}`}
className="font-medium text-gray-700"
>
{locales[value]}
</label>
</div>
</div>
))}
</div>
</fieldset>
<fieldset className="mt-6">
<legend className="contents text-base font-medium text-gray-900">
<Trans>Format</Trans>
Expand Down
2 changes: 1 addition & 1 deletion ui/src/pages/app/Style.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ function StyleInner({ collection, item, activeColor }: StyleInnerProps) {
{attributes.map((attr) => (
<li key={attr.id}>
<>
{i18nDbText(attr.title)}{" "}
<b>{i18nDbText(attr.title)}</b>{" "}
{i18nDbText(attr.description)}
</>
</li>
Expand Down
13 changes: 13 additions & 0 deletions ui/src/types/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export interface Api {
i18n_string: I18NString;
image: Image;
image_summary: ImageSummary;
language: Language;
nested_attribute: AttributeSummary;
nested_color: NestedColor;
nested_price: NestedPrice;
Expand Down Expand Up @@ -775,6 +776,12 @@ export interface Image {
[property: string]: any;
}

export enum Language {
De = "de",
En = "en",
Sv = "sv",
}

/**
* Style nested with colors and sizes, with some metadata fields excluded
*/
Expand Down Expand Up @@ -1666,6 +1673,7 @@ const typeMap: any = {
{ json: "i18n_string", js: "i18n_string", typ: r("I18NString") },
{ json: "image", js: "image", typ: r("Image") },
{ json: "image_summary", js: "image_summary", typ: r("ImageSummary") },
{ json: "language", js: "language", typ: r("Language") },
{ json: "nested_attribute", js: "nested_attribute", typ: r("AttributeSummary") },
{ json: "nested_color", js: "nested_color", typ: r("NestedColor") },
{ json: "nested_price", js: "nested_price", typ: r("NestedPrice") },
Expand Down Expand Up @@ -2324,6 +2332,11 @@ const typeMap: any = {
"size",
"style",
],
"Language": [
"de",
"en",
"sv",
],
"NestedStyleSortOrder": [
"delivery_period:asc",
"delivery_period:desc",
Expand Down

0 comments on commit 538f229

Please sign in to comment.