Skip to content

Commit

Permalink
#3 added energy label efficiency arrow preview to admin block
Browse files Browse the repository at this point in the history
  • Loading branch information
bennobuilder committed Sep 5, 2024
1 parent 642f035 commit 9a636e9
Show file tree
Hide file tree
Showing 17 changed files with 153 additions and 30 deletions.
13 changes: 11 additions & 2 deletions apps/sfy-eu-blocks-app/admin-block-extension/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"invalid": "Ungültige Energieklasse. Bitte wählen Sie einen Wert von A bis F."
},
"labelUrl": {
"invalidFormat": "Bitte geben Sie eine gültige URL für das Etikett ein."
"invalidFormat": "Bitte geben Sie eine gültige URL für das Etikett ein.",
"mustEndWithPdf": "Die URL muss mit .pdf enden."
}
},
"banner": {
Expand All @@ -27,6 +28,13 @@
"content2": ", sind Eigentum der Europäischen Union, lizenziert unter der ",
"link2Text": "Creative Commons Namensnennung 4.0 International (CC BY 4.0) Lizenz",
"content3": ", und werden wie besehen bereitgestellt."
},

},
"warning": {
"noDatasheetForLocale": {
"title": "Achtung",
"content": "Kein Datenblatt für die Hauptsprache {{locale}} wurde gefunden. Sie können eine neue Sprache hinzufügen, indem Sie zusätzliche Metafelder bearbeiten."
}
},
"error": {
Expand All @@ -38,7 +46,8 @@
},
"success": {
"energyLabelFound": "Energielabel für '{{productName}}' erfolgreich geladen",
"energyLabelUpdated": "Energielabel für '{{productName}}' erfolgreich aktualisiert"
"energyLabelUpdated": "Energielabel für '{{productName}}' erfolgreich aktualisiert",
"energyLabelReset": "Energielabel zurückgesetzt"
}
},
"button": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"invalid": "Invalid energy class. Please select a value from A to F."
},
"labelUrl": {
"invalidFormat": "Please enter a valid URL for the label."
"invalidFormat": "Please enter a valid URL for the label.",
"mustEndWithPdf": "The URL must end with .pdf."
}
},
"banner": {
Expand All @@ -27,6 +28,13 @@
"content2": ", are owned by the European Union, are licensed under the ",
"link2Text": "Creative Commons Attribution 4.0 International (CC BY 4.0) license",
"content3": ", and are provided as is."
},

},
"warning": {
"noDatasheetForLocale": {
"title": "Warning",
"content": "No datasheet was found for the primary locale {{locale}}. You can add a new locale by modifying additional metafields."
}
},
"error": {
Expand All @@ -38,7 +46,8 @@
},
"success": {
"energyLabelFound": "Energy Label for '{{productName}}' successfully loaded",
"energyLabelUpdated": "Energy Label for '{{productName}}' successfully updated"
"energyLabelUpdated": "Energy Label for '{{productName}}' successfully updated",
"energyLabelReset": "Energy Label reset"
}
},
"button": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import {
Banner,
BlockStack,
Image,
InlineStack,
Link,
Paragraph,
Pressable
} from '@shopify/ui-extensions-react/admin';
import React from 'react';

import { coreApiConfig, t } from '../environment';
import { TEnergyLabel } from '../lib';

export const EnergyLabelPreview: React.FC<TProps> = (props) => {
const { energyLabel, primaryLocale } = props;
const sheetUrl = React.useMemo(
() => (energyLabel.sheetUrlMap as Record<string, string>)[primaryLocale],
[energyLabel.sheetUrlMap, primaryLocale]
);

return (
<BlockStack gap>
<InlineStack gap>
<Pressable href={energyLabel.labelUrlMap.PDF} target="_blank">
<Image
alt={`Energy Label Efficiency Class ${energyLabel.energyClass}`}
source={`${coreApiConfig.baseUrl}/v1/energy-label/efficiency-class/arrow.svg?efficiencyClass=${energyLabel.energyClass}&size=26`}
/>
</Pressable>
<Link href={sheetUrl} target="_blank">
Product Datasheet
</Link>
</InlineStack>
{sheetUrl == null && (
<Banner title={t('banner.warning.noDatasheetForLocale.title')} tone="warning">
<Paragraph>
{t('banner.warning.noDatasheetForLocale.content', { locale: primaryLocale })}
</Paragraph>
</Banner>
)}
</BlockStack>
);
};

interface TProps {
energyLabel: TEnergyLabel;
primaryLocale: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,23 @@ import {
$banner,
$energyLabel,
$updateEnergyLabelMetafieldForm,
deleteEnergyLabelFromMetafields
deleteEnergyLabelFromMetafields,
TEnergyLabel
} from '../lib';
import { EnergyLabelPreview } from './EnergyLabelPreview';
import { FormTextField } from './FormTextField';

export const UpdateEnergyLabelMetaFieldsBlock: React.FC<TProps> = (props) => {
const { productId } = props;
const { productId, energyLabel, primaryLocale } = props;
const { handleSubmit, field } = useForm($updateEnergyLabelMetafieldForm);
const isSubmitting = useGlobalState($updateEnergyLabelMetafieldForm.isSubmitting);
const [formChanged, setFormChanged] = React.useState(false);

// gid:/shopify/Product/9436272754952 -> 9436272754952
const productIdNumber = React.useMemo(() => productId.replace(/^(.*[\\\/])/, ''), [productId]);

// To disable save button
useGlobalState($updateEnergyLabelMetafieldForm.fields.energyClass);
useGlobalState($updateEnergyLabelMetafieldForm.fields.pdfLabelUrl);

React.useEffect(() => {
$updateEnergyLabelMetafieldForm.fields.energyClass.listen(() => {
$updateEnergyLabelMetafieldForm.fields.energyClass.listen((data) => {
setFormChanged(hasFormChanged($updateEnergyLabelMetafieldForm));
});
$updateEnergyLabelMetafieldForm.fields.pdfLabelUrl.listen(() => {
Expand All @@ -53,7 +51,7 @@ export const UpdateEnergyLabelMetaFieldsBlock: React.FC<TProps> = (props) => {
}
$banner.set({
tone: 'success',
content: 'todo',
content: t('banner.success.energyLabelReset'),
source: 'RESET_METAFIELD'
});
$energyLabel.set(null);
Expand Down Expand Up @@ -96,6 +94,7 @@ export const UpdateEnergyLabelMetaFieldsBlock: React.FC<TProps> = (props) => {
field={field('pdfLabelUrl')}
disabled={isSubmitting}
/>

{/* </Form> */}
</BlockStack>
</Section>
Expand Down Expand Up @@ -135,6 +134,10 @@ export const UpdateEnergyLabelMetaFieldsBlock: React.FC<TProps> = (props) => {
</Button>
</InlineStack>

<Section heading={`Preview (${primaryLocale})`}>
<EnergyLabelPreview energyLabel={energyLabel} primaryLocale={primaryLocale} />
</Section>

<Banner tone="info">
<Paragraph>
{t('banner.info.eprelNotice.content1')}
Expand All @@ -152,4 +155,6 @@ export const UpdateEnergyLabelMetaFieldsBlock: React.FC<TProps> = (props) => {

interface TProps {
productId: string;
energyLabel: TEnergyLabel;
primaryLocale: string;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './BannerBlock';
export * from './EnergyLabelPreview';
export * from './FormTextField';
export * from './LoadEnergyLabelSection';
export * from './UpdateEnergyLabelMetaFieldsSection';
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export const coreApiConfig = {
baseUrl: 'https://rica-neither-reducing-legends.trycloudflare.com' // TODO: Find way to sync url from api-core-node
baseUrl: 'https://excess-dear-samsung-blonde.trycloudflare.com' // TODO: Find way to sync url from api-core-node
};
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ type TTranslationOptions = {
'banner.error.notFound': { registrationNumber: string };
'banner.success.energyLabelFound': { productName: string };
'banner.success.energyLabelUpdated': { productName: string };
'banner.warning.noDatasheetForLocale.content': { locale: string };
};
29 changes: 25 additions & 4 deletions apps/sfy-eu-blocks-app/admin-block-extension/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import {
$banner,
$energyLabel,
applyEnergyLabelToUpdateMetafieldForm,
getEnergyLabelFormMetafields
getEnergyLabelFormMetafields,
getShopLocales
} from './lib';

const queryClient = new QueryClient();
Expand All @@ -39,6 +40,21 @@ export default reactExtension(appConfig.target, async (api) => {
return <BannerBlock content={t('banner.error.productIdMissing')} tone="critical" />;
}

const shopLocalesResult = await getShopLocales();
if (shopLocalesResult.isErr()) {
return (
<BannerBlock
content={t('banner.error.metadataReadError', {
errorMessage: shopLocalesResult.error.message
})}
tone="critical"
/>
);
}
const primaryLocale =
shopLocalesResult.value.shopLocales.find((local) => local.primary)?.locale.toUpperCase() ??
'EN';

const energyLabelResult = await getEnergyLabelFormMetafields(productId);
if (energyLabelResult.isErr()) {
return (
Expand All @@ -59,13 +75,13 @@ export default reactExtension(appConfig.target, async (api) => {

return (
<QueryClientProvider client={queryClient}>
<Extension productId={productId} />
<Extension productId={productId} primaryLocale={primaryLocale} />
</QueryClientProvider>
);
});

const Extension: React.FC<TProps> = (props) => {
const { productId } = props;
const { productId, primaryLocale } = props;
const banner = useGlobalState($banner);
const energyLabel = useGlobalState($energyLabel);

Expand All @@ -85,7 +101,11 @@ const Extension: React.FC<TProps> = (props) => {
</Banner>
)}
{energyLabel != null ? (
<UpdateEnergyLabelMetaFieldsBlock productId={productId} />
<UpdateEnergyLabelMetaFieldsBlock
productId={productId}
energyLabel={energyLabel}
primaryLocale={primaryLocale}
/>
) : (
<LoadEnergyLabelBlock productId={productId} />
)}
Expand All @@ -96,4 +116,5 @@ const Extension: React.FC<TProps> = (props) => {

interface TProps {
productId: string;
primaryLocale: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,11 @@ export const $updateEnergyLabelMetafieldForm = createForm<TFormFields>({
validator: vValidator(
v.pipe(
v.string(),
v.url(() => t('validation.labelUrl.invalidFormat'))
// TODO: needs to end with .pdf
v.url(() => t('validation.labelUrl.invalidFormat')),
v.custom(
(url) => typeof url === 'string' && url.endsWith('.pdf'),
() => t('validation.labelUrl.mustEndWithPdf')
)
)
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { gql } from 'feature-fetch';

import { q } from '../../environment';

export async function getShopLocales() {
return await q<{}, TGetShopLocalesQueryResponseData>(
gql`
query shopInfo {
shopLocales {
locale
primary
}
}
`,
{}
);
}

export interface TGetShopLocalesQueryResponseData {
shopLocales: {
locale: string;
primary: boolean;
}[];
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './delete-metafield.mutation';
export * from './get-metafield.query';
export * from './get-shop-locales.query';
export * from './update-metafield.mutation';
10 changes: 5 additions & 5 deletions apps/sfy-eu-blocks-app/app/shopify.app.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ extension_directories = [
]
name = "eu-blocks"
handle = "eu-blocks"
application_url = "https://jpg-conjunction-prefers-chip.trycloudflare.com"
application_url = "https://agreed-merchant-mason-wallet.trycloudflare.com"
embedded = true

[build]
Expand All @@ -18,13 +18,13 @@ include_config_on_deploy = true

[access_scopes]
# Learn more at https://shopify.dev/docs/apps/tools/cli/configuration#access_scopes
scopes = "read_files,read_products,write_files,write_products"
scopes = "read_files,read_locales,read_products,write_files,write_products"

[auth]
redirect_urls = [
"https://jpg-conjunction-prefers-chip.trycloudflare.com/auth/callback",
"https://jpg-conjunction-prefers-chip.trycloudflare.com/auth/shopify/callback",
"https://jpg-conjunction-prefers-chip.trycloudflare.com/api/auth/callback"
"https://agreed-merchant-mason-wallet.trycloudflare.com/auth/callback",
"https://agreed-merchant-mason-wallet.trycloudflare.com/auth/shopify/callback",
"https://agreed-merchant-mason-wallet.trycloudflare.com/api/auth/callback"
]

[webhooks]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { vValidator } from 'validation-adapters/valibot';
import { openApiRouter } from '../../router';
import { EfficiencyArrowLg, EfficiencyArrowSm } from './components';

openApiRouter.get('/efficiency-class/arrow', {
openApiRouter.get('/efficiency-class/arrow.svg', {
queryValidator: vValidator(
v.object({
efficiencyClass: v.picklist(['A', 'B', 'C', 'D', 'E', 'F', 'G']),
Expand Down
2 changes: 1 addition & 1 deletion packages/types/src/api/.openapi/core-api-v1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ export interface paths {
patch?: never;
trace?: never;
};
"/v1/energy-label/efficiency-class/arrow": {
"/v1/energy-label/efficiency-class/arrow.svg": {
parameters: {
query?: never;
header?: never;
Expand Down
2 changes: 1 addition & 1 deletion packages/types/src/api/.openapi/energy-label-api-v1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ export interface paths {
patch?: never;
trace?: never;
};
"/efficiency-class/arrow": {
"/efficiency-class/arrow.svg": {
parameters: {
query?: never;
header?: never;
Expand Down
4 changes: 2 additions & 2 deletions packages/types/src/api/resources/core-api_v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ paths:
$ref: './energy-label-api_v1.yaml#/paths/~1product~1{registrationNumber}~1sheet'
/v1/energy-label/product/{registrationNumber}/label:
$ref: './energy-label-api_v1.yaml#/paths/~1product~1{registrationNumber}~1label'
/v1/energy-label/efficiency-class/arrow:
$ref: './energy-label-api_v1.yaml#/paths/~1efficiency-class~1arrow'
/v1/energy-label/efficiency-class/arrow.svg:
$ref: './energy-label-api_v1.yaml#/paths/~1efficiency-class~1arrow.svg'

components:
schemas:
Expand Down
2 changes: 1 addition & 1 deletion packages/types/src/api/resources/energy-label-api_v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ paths:
'500':
$ref: './common.yaml#/components/responses/InternalServerError'

/efficiency-class/arrow:
/efficiency-class/arrow.svg:
get:
summary: Get energy efficiency class arrow as SVG
description: Retrieves an SVG of the energy efficiency class arrow for a given energy class.
Expand Down

0 comments on commit 9a636e9

Please sign in to comment.