From b0c7a1aed52e1cb98ae7c7c3b74707ea275df71c Mon Sep 17 00:00:00 2001 From: Matthias Mair Date: Thu, 22 Aug 2024 03:01:09 +0200 Subject: [PATCH 1/6] [PUI] Add Link/Unlink Barcode action (#7939) * Add Link/Unlink Barcode action Fixes #7920 * remove unneeded imports * remove duplication * simplify * add testing * refactor type * wait for reload to add coverage * Add warning if custom barcode is used --- .../src/components/items/ActionDropdown.tsx | 106 +++++++++++------- src/frontend/src/components/items/QRCode.tsx | 81 +++++++++++-- src/frontend/src/enums/ApiEndpoints.tsx | 2 + src/frontend/src/pages/build/BuildDetail.tsx | 23 +--- .../src/pages/company/SupplierPartDetail.tsx | 28 +---- src/frontend/src/pages/part/PartDetail.tsx | 24 +--- .../pages/purchasing/PurchaseOrderDetail.tsx | 23 +--- .../src/pages/sales/ReturnOrderDetail.tsx | 23 +--- .../src/pages/sales/SalesOrderDetail.tsx | 23 +--- .../src/pages/stock/LocationDetail.tsx | 17 +-- src/frontend/src/pages/stock/StockDetail.tsx | 26 +---- src/frontend/tests/pages/pui_orders.spec.ts | 27 +++++ 12 files changed, 199 insertions(+), 204 deletions(-) diff --git a/src/frontend/src/components/items/ActionDropdown.tsx b/src/frontend/src/components/items/ActionDropdown.tsx index 2e8a2df425..48603c880c 100644 --- a/src/frontend/src/components/items/ActionDropdown.tsx +++ b/src/frontend/src/components/items/ActionDropdown.tsx @@ -20,7 +20,7 @@ import { ReactNode, useMemo } from 'react'; import { ModelType } from '../../enums/ModelType'; import { identifierString } from '../../functions/conversion'; import { InvenTreeIcon } from '../../functions/icons'; -import { InvenTreeQRCode } from './QRCode'; +import { InvenTreeQRCode, QRCodeLink, QRCodeUnlink } from './QRCode'; export type ActionDropdownItem = { icon?: ReactNode; @@ -112,69 +112,91 @@ export function ActionDropdown({ // Dropdown menu for barcode actions export function BarcodeActionDropdown({ - actions -}: { - actions: ActionDropdownItem[]; -}) { + model, + pk, + hash = null, + actions = [], + perm: permission = true +}: Readonly<{ + model: ModelType; + pk: number; + hash?: boolean | null; + actions?: ActionDropdownItem[]; + perm?: boolean; +}>) { + const hidden = hash === null; + const prop = { model, pk, hash }; return ( } - actions={actions} + actions={[ + GeneralBarcodeAction({ + mdl_prop: prop, + title: t`View`, + icon: , + tooltip: t`View barcode`, + ChildItem: InvenTreeQRCode + }), + GeneralBarcodeAction({ + hidden: hidden || hash || !permission, + mdl_prop: prop, + title: t`Link Barcode`, + icon: , + tooltip: t`Link a custom barcode to this item`, + ChildItem: QRCodeLink + }), + GeneralBarcodeAction({ + hidden: hidden || !hash || !permission, + mdl_prop: prop, + title: t`Unlink Barcode`, + icon: , + tooltip: t`Unlink custom barcode`, + ChildItem: QRCodeUnlink + }), + ...actions + ]} /> ); } -// Common action button for viewing a barcode -export function ViewBarcodeAction({ - hidden = false, - model, - pk -}: { - hidden?: boolean; +export type QrCodeType = { model: ModelType; pk: number; + hash?: boolean | null; +}; + +function GeneralBarcodeAction({ + hidden = false, + mdl_prop, + title, + icon, + tooltip, + ChildItem +}: { + hidden?: boolean; + mdl_prop: QrCodeType; + title: string; + icon: ReactNode; + tooltip: string; + ChildItem: any; }): ActionDropdownItem { const onClick = () => { modals.open({ - title: t`View Barcode`, - children: + title: title, + children: }); }; return { - icon: , - name: t`View`, - tooltip: t`View barcode`, + icon: icon, + name: title, + tooltip: tooltip, onClick: onClick, hidden: hidden }; } -// Common action button for linking a custom barcode -export function LinkBarcodeAction( - props: ActionDropdownItem -): ActionDropdownItem { - return { - ...props, - icon: , - name: t`Link Barcode`, - tooltip: t`Link custom barcode` - }; -} - -// Common action button for un-linking a custom barcode -export function UnlinkBarcodeAction( - props: ActionDropdownItem -): ActionDropdownItem { - return { - ...props, - icon: , - name: t`Unlink Barcode`, - tooltip: t`Unlink custom barcode` - }; -} - // Common action button for editing an item export function EditItemAction(props: ActionDropdownItem): ActionDropdownItem { return { diff --git a/src/frontend/src/components/items/QRCode.tsx b/src/frontend/src/components/items/QRCode.tsx index 1077692314..8038ff8c23 100644 --- a/src/frontend/src/components/items/QRCode.tsx +++ b/src/frontend/src/components/items/QRCode.tsx @@ -1,24 +1,28 @@ import { Trans, t } from '@lingui/macro'; import { + Alert, Box, + Button, Code, Group, Image, Select, Skeleton, Stack, - Text + Text, + TextInput } from '@mantine/core'; +import { modals } from '@mantine/modals'; import { useQuery } from '@tanstack/react-query'; import QR from 'qrcode'; import { useEffect, useMemo, useState } from 'react'; import { api } from '../../App'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; -import { ModelType } from '../../enums/ModelType'; import { apiUrl } from '../../states/ApiState'; import { useGlobalSettingsState } from '../../states/SettingsState'; import { CopyButton } from '../buttons/CopyButton'; +import { QrCodeType } from './ActionDropdown'; type QRCodeProps = { ecl?: 'L' | 'M' | 'Q' | 'H'; @@ -51,15 +55,13 @@ export const QRCode = ({ data, ecl = 'Q', margin = 1 }: QRCodeProps) => { }; type InvenTreeQRCodeProps = { - model: ModelType; - pk: number; + mdl_prop: QrCodeType; showEclSelector?: boolean; } & Omit; export const InvenTreeQRCode = ({ + mdl_prop, showEclSelector = true, - model, - pk, ecl: eclProp = 'Q', ...props }: InvenTreeQRCodeProps) => { @@ -71,11 +73,11 @@ export const InvenTreeQRCode = ({ }, [eclProp]); const { data } = useQuery({ - queryKey: ['qr-code', model, pk], + queryKey: ['qr-code', mdl_prop.model, mdl_prop.pk], queryFn: async () => { const res = await api.post(apiUrl(ApiEndpoints.generate_barcode), { - model, - pk + model: mdl_prop.model, + pk: mdl_prop.pk }); return res.data?.barcode as string; @@ -94,6 +96,15 @@ export const InvenTreeQRCode = ({ return ( + {mdl_prop.hash ? ( + + + A custom barcode is registered for this item. The shown code is not + that custom barcode. + + + ) : null} + {data && settings.getSetting('BARCODE_SHOW_TEXT', 'false') && ( @@ -128,3 +139,55 @@ export const InvenTreeQRCode = ({ ); }; + +export const QRCodeLink = ({ mdl_prop }: { mdl_prop: QrCodeType }) => { + const [barcode, setBarcode] = useState(''); + + function linkBarcode() { + api + .post(apiUrl(ApiEndpoints.barcode_link), { + [mdl_prop.model]: mdl_prop.pk, + barcode: barcode + }) + .then((response) => { + modals.closeAll(); + location.reload(); + }); + } + return ( + + setBarcode(event.currentTarget.value)} + placeholder={t`Scan barcode data here using barcode scanner`} + /> + + + ); +}; + +export const QRCodeUnlink = ({ mdl_prop }: { mdl_prop: QrCodeType }) => { + function unlinkBarcode() { + api + .post(apiUrl(ApiEndpoints.barcode_unlink), { + [mdl_prop.model]: mdl_prop.pk + }) + .then((response) => { + modals.closeAll(); + location.reload(); + }); + } + return ( + + + This will remove the link to the associated barcode + + + + ); +}; diff --git a/src/frontend/src/enums/ApiEndpoints.tsx b/src/frontend/src/enums/ApiEndpoints.tsx index 740b73336e..1908a59577 100644 --- a/src/frontend/src/enums/ApiEndpoints.tsx +++ b/src/frontend/src/enums/ApiEndpoints.tsx @@ -39,6 +39,8 @@ export enum ApiEndpoints { settings_global_list = 'settings/global/', settings_user_list = 'settings/user/', barcode = 'barcode/', + barcode_link = 'barcode/link/', + barcode_unlink = 'barcode/unlink/', generate_barcode = 'barcode/generate/', news = 'news/', global_status = 'generic/status/', diff --git a/src/frontend/src/pages/build/BuildDetail.tsx b/src/frontend/src/pages/build/BuildDetail.tsx index 1348ff1e00..bc9a02981f 100644 --- a/src/frontend/src/pages/build/BuildDetail.tsx +++ b/src/frontend/src/pages/build/BuildDetail.tsx @@ -30,10 +30,7 @@ import { CancelItemAction, DuplicateItemAction, EditItemAction, - HoldItemAction, - LinkBarcodeAction, - UnlinkBarcodeAction, - ViewBarcodeAction + HoldItemAction } from '../../components/items/ActionDropdown'; import InstanceDetail from '../../components/nav/InstanceDetail'; import { PageDetail } from '../../components/nav/PageDetail'; @@ -43,7 +40,6 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ModelType } from '../../enums/ModelType'; import { UserRoles } from '../../enums/Roles'; import { useBuildOrderFields } from '../../forms/BuildForms'; -import { notYetImplemented } from '../../functions/notifications'; import { useCreateApiFormModal, useEditApiFormModal @@ -472,20 +468,9 @@ export default function BuildDetail() { />, , , , , , , , , , , , , , , , , location.pk ? ( , diff --git a/src/frontend/src/pages/stock/StockDetail.tsx b/src/frontend/src/pages/stock/StockDetail.tsx index 5a3f0d00e4..e787d210a4 100644 --- a/src/frontend/src/pages/stock/StockDetail.tsx +++ b/src/frontend/src/pages/stock/StockDetail.tsx @@ -27,10 +27,7 @@ import { BarcodeActionDropdown, DeleteItemAction, DuplicateItemAction, - EditItemAction, - LinkBarcodeAction, - UnlinkBarcodeAction, - ViewBarcodeAction + EditItemAction } from '../../components/items/ActionDropdown'; import { StylishText } from '../../components/items/StylishText'; import InstanceDetail from '../../components/nav/InstanceDetail'; @@ -50,7 +47,6 @@ import { useTransferStockItem } from '../../forms/StockForms'; import { InvenTreeIcon } from '../../functions/icons'; -import { notYetImplemented } from '../../functions/notifications'; import { getDetailUrl } from '../../functions/urls'; import { useCreateApiFormModal, @@ -477,22 +473,10 @@ export default function StockDetail() { () => [ , , { await page.getByRole('cell', { name: 'PO0013' }).click(); await page.getByRole('button', { name: 'Issue Order' }).waitFor(); +}); + +test('PUI - Purchase Orders - Barcodes', async ({ page }) => { + await doQuickLogin(page); + + await page.goto(`${baseUrl}/purchasing/purchase-order/13/detail`); + await page.getByRole('button', { name: 'Issue Order' }).waitFor(); // Display QR code await page.getByLabel('action-menu-barcode-actions').click(); await page.getByLabel('action-menu-barcode-actions-view').click(); await page.getByRole('img', { name: 'QR Code' }).waitFor(); + await page.getByRole('banner').getByRole('button').click(); + + // Link to barcode + await page.getByLabel('action-menu-barcode-actions').click(); + await page.getByLabel('action-menu-barcode-actions-link-barcode').click(); + await page.getByRole('heading', { name: 'Link Barcode' }).waitFor(); + await page + .getByPlaceholder('Scan barcode data here using') + .fill('1234567890'); + await page.getByRole('button', { name: 'Link' }).click(); + await page.getByRole('button', { name: 'Issue Order' }).waitFor(); + + // Unlink barcode + await page.getByLabel('action-menu-barcode-actions').click(); + await page.getByLabel('action-menu-barcode-actions-unlink-barcode').click(); + await page.getByRole('heading', { name: 'Unlink Barcode' }).waitFor(); + await page.getByText('This will remove the link to').waitFor(); + await page.getByRole('button', { name: 'Unlink Barcode' }).click(); + await page.waitForTimeout(500); + await page.getByRole('button', { name: 'Issue Order' }).waitFor(); }); From ca87df3c3dc37a69c9ab37de44a278d7e0861154 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 22 Aug 2024 13:50:04 +1000 Subject: [PATCH 2/6] [PUI] Test result fixes (#7956) * Prevent template adjustment * Prevent template from being edited * Fix 'attachment' field for StockItemTestResultSerializer - Allow 'null' value * Bump API version --- src/backend/InvenTree/InvenTree/api_version.py | 5 ++++- src/backend/InvenTree/stock/serializers.py | 5 ++++- src/frontend/src/forms/StockForms.tsx | 17 +++++++++++++++-- .../src/tables/build/BuildOrderTestTable.tsx | 3 ++- .../tables/stock/StockItemTestResultTable.tsx | 11 ++++++----- 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/backend/InvenTree/InvenTree/api_version.py b/src/backend/InvenTree/InvenTree/api_version.py index 40bff36d69..181abf41c9 100644 --- a/src/backend/InvenTree/InvenTree/api_version.py +++ b/src/backend/InvenTree/InvenTree/api_version.py @@ -1,12 +1,15 @@ """InvenTree API version information.""" # InvenTree API version -INVENTREE_API_VERSION = 246 +INVENTREE_API_VERSION = 247 """Increment this API version number whenever there is a significant change to the API that any clients need to know about.""" INVENTREE_API_TEXT = """ +v247 - 2024-08-22 : https://github.com/inventree/InvenTree/pull/7956 + - Adjust "attachment" field on StockItemTestResult serializer + - Allow null values for attachment v246 - 2024-08-21 : https://github.com/inventree/InvenTree/pull/7862 - Adds custom status fields to various serializers diff --git a/src/backend/InvenTree/stock/serializers.py b/src/backend/InvenTree/stock/serializers.py index 58ed3a2471..7c80285f6f 100644 --- a/src/backend/InvenTree/stock/serializers.py +++ b/src/backend/InvenTree/stock/serializers.py @@ -239,7 +239,10 @@ class StockItemTestResultSerializer( ) attachment = InvenTree.serializers.InvenTreeAttachmentSerializerField( - required=False + required=False, + allow_null=True, + label=_('Attachment'), + help_text=_('Test result attachment'), ) def validate(self, data): diff --git a/src/frontend/src/forms/StockForms.tsx b/src/frontend/src/forms/StockForms.tsx index 0577233192..7ac947826b 100644 --- a/src/frontend/src/forms/StockForms.tsx +++ b/src/frontend/src/forms/StockForms.tsx @@ -922,10 +922,14 @@ export function stockLocationFields(): ApiFormFieldSet { // Construct a set of fields for export function useTestResultFields({ partId, - itemId + itemId, + templateId, + editTemplate = false }: { partId: number; itemId: number; + templateId: number | undefined; + editTemplate?: boolean; }): ApiFormFieldSet { // Valid field choices const [choices, setChoices] = useState([]); @@ -947,6 +951,7 @@ export function useTestResultFields({ hidden: true }, template: { + disabled: !editTemplate && !!templateId, filters: { include_inherited: true, part: partId @@ -990,5 +995,13 @@ export function useTestResultFields({ hidden: !includeTestStation } }; - }, [choices, fieldType, partId, itemId, includeTestStation]); + }, [ + choices, + editTemplate, + fieldType, + partId, + itemId, + templateId, + includeTestStation + ]); } diff --git a/src/frontend/src/tables/build/BuildOrderTestTable.tsx b/src/frontend/src/tables/build/BuildOrderTestTable.tsx index dc4145ae5c..4905945e9d 100644 --- a/src/frontend/src/tables/build/BuildOrderTestTable.tsx +++ b/src/frontend/src/tables/build/BuildOrderTestTable.tsx @@ -67,7 +67,8 @@ export default function BuildOrderTestTable({ const testResultFields: ApiFormFieldSet = useTestResultFields({ partId: partId, - itemId: selectedOutput + itemId: selectedOutput, + templateId: selectedTemplate }); const createTestResult = useCreateApiFormModal({ diff --git a/src/frontend/src/tables/stock/StockItemTestResultTable.tsx b/src/frontend/src/tables/stock/StockItemTestResultTable.tsx index fe41d0ac12..4eca85588f 100644 --- a/src/frontend/src/tables/stock/StockItemTestResultTable.tsx +++ b/src/frontend/src/tables/stock/StockItemTestResultTable.tsx @@ -238,15 +238,16 @@ export default function StockItemTestResultTable({ ]; }, [itemId]); - const resultFields: ApiFormFieldSet = useTestResultFields({ - partId: partId, - itemId: itemId - }); - const [selectedTemplate, setSelectedTemplate] = useState( undefined ); + const resultFields: ApiFormFieldSet = useTestResultFields({ + partId: partId, + itemId: itemId, + templateId: selectedTemplate + }); + const newTestModal = useCreateApiFormModal({ url: ApiEndpoints.stock_test_result_list, fields: useMemo(() => ({ ...resultFields }), [resultFields]), From 1dff94db75cfeb71c7f6576535c94aacb498d093 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 22 Aug 2024 16:08:41 +1000 Subject: [PATCH 3/6] Table borders (#7957) * Add 'editable' attribute to table column type * Add "editable" attribute for useTable hook * Add column borders to tables --- src/frontend/src/hooks/UseTable.tsx | 8 +++++++- src/frontend/src/tables/Column.tsx | 4 ++++ src/frontend/src/tables/InvenTreeTable.tsx | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/frontend/src/hooks/UseTable.tsx b/src/frontend/src/hooks/UseTable.tsx index b1bf2ce735..4ce0800f28 100644 --- a/src/frontend/src/hooks/UseTable.tsx +++ b/src/frontend/src/hooks/UseTable.tsx @@ -39,6 +39,8 @@ export type TableState = { records: any[]; setRecords: (records: any[]) => void; updateRecord: (record: any) => void; + editable: boolean; + setEditable: (value: boolean) => void; }; /** @@ -131,6 +133,8 @@ export function useTable(tableName: string): TableState { const [isLoading, setIsLoading] = useState(false); + const [editable, setEditable] = useState(false); + return { tableKey, refreshTable, @@ -156,6 +160,8 @@ export function useTable(tableName: string): TableState { setPage, records, setRecords, - updateRecord + updateRecord, + editable, + setEditable }; } diff --git a/src/frontend/src/tables/Column.tsx b/src/frontend/src/tables/Column.tsx index b2ea9fcccd..03366ca1fb 100644 --- a/src/frontend/src/tables/Column.tsx +++ b/src/frontend/src/tables/Column.tsx @@ -1,3 +1,5 @@ +import { ApiFormFieldType } from '../components/forms/fields/ApiFormField'; + export type TableColumnProps = { accessor?: string; // The key in the record to access title?: string; // The title of the column - Note: this may be supplied by the API, and is not required, but it can be overridden if required @@ -5,6 +7,8 @@ export type TableColumnProps = { sortable?: boolean; // Whether the column is sortable switchable?: boolean; // Whether the column is switchable hidden?: boolean; // Whether the column is hidden + editable?: boolean; // Whether the value of this column can be edited + definition?: ApiFormFieldType; // Optional field definition for the column render?: (record: T, index?: number) => any; // A custom render function filter?: any; // A custom filter function filtering?: boolean; // Whether the column is filterable diff --git a/src/frontend/src/tables/InvenTreeTable.tsx b/src/frontend/src/tables/InvenTreeTable.tsx index 8da06a22e1..7585a7670e 100644 --- a/src/frontend/src/tables/InvenTreeTable.tsx +++ b/src/frontend/src/tables/InvenTreeTable.tsx @@ -697,6 +697,7 @@ export function InvenTreeTable({ Date: Thu, 22 Aug 2024 09:01:25 +0200 Subject: [PATCH 4/6] Add pagination (#7958) --- src/frontend/src/hooks/UseTable.tsx | 5 +++++ src/frontend/src/tables/InvenTreeTable.tsx | 17 ++++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/frontend/src/hooks/UseTable.tsx b/src/frontend/src/hooks/UseTable.tsx index 4ce0800f28..c44cc11d9e 100644 --- a/src/frontend/src/hooks/UseTable.tsx +++ b/src/frontend/src/hooks/UseTable.tsx @@ -36,6 +36,8 @@ export type TableState = { setRecordCount: (count: number) => void; page: number; setPage: (page: number) => void; + pageSize: number; + setPageSize: (pageSize: number) => void; records: any[]; setRecords: (records: any[]) => void; updateRecord: (record: any) => void; @@ -99,6 +101,7 @@ export function useTable(tableName: string): TableState { // Pagination data const [page, setPage] = useState(1); + const [pageSize, setPageSize] = useState(25); // A list of hidden columns, saved to local storage const [hiddenColumns, setHiddenColumns] = useLocalStorage({ @@ -158,6 +161,8 @@ export function useTable(tableName: string): TableState { setRecordCount, page, setPage, + pageSize, + setPageSize, records, setRecords, updateRecord, diff --git a/src/frontend/src/tables/InvenTreeTable.tsx b/src/frontend/src/tables/InvenTreeTable.tsx index 7585a7670e..fa74a5f468 100644 --- a/src/frontend/src/tables/InvenTreeTable.tsx +++ b/src/frontend/src/tables/InvenTreeTable.tsx @@ -55,6 +55,7 @@ import { RowAction, RowActions } from './RowActions'; import { TableSearchInput } from './Search'; const defaultPageSize: number = 25; +const PAGE_SIZES = [10, 15, 20, 25, 50, 100, 500]; /** * Set of optional properties which can be passed to an InvenTreeTable component @@ -74,7 +75,6 @@ const defaultPageSize: number = 25; * @param enableRefresh : boolean - Enable refresh actions * @param enableColumnSwitching : boolean - Enable column switching * @param enableColumnCaching : boolean - Enable caching of column names via API - * @param pageSize : number - Number of records per page * @param barcodeActions : any[] - List of barcode actions * @param tableFilters : TableFilter[] - List of custom filters * @param tableActions : any[] - List of custom action groups @@ -100,7 +100,6 @@ export type InvenTreeTableProps = { enableLabels?: boolean; enableReports?: boolean; afterBulkDelete?: () => void; - pageSize?: number; barcodeActions?: React.ReactNode[]; tableFilters?: TableFilter[]; tableActions?: React.ReactNode[]; @@ -129,7 +128,6 @@ const defaultInvenTreeTableProps: InvenTreeTableProps = { enableRefresh: true, enableSearch: true, enableSelection: false, - pageSize: defaultPageSize, defaultSortColumn: '', barcodeActions: [], tableFilters: [], @@ -360,7 +358,8 @@ export function InvenTreeTable({ // Pagination if (tableProps.enablePagination && paginate) { - let pageSize = tableProps.pageSize ?? defaultPageSize; + let pageSize = tableState.pageSize ?? defaultPageSize; + if (pageSize != tableState.pageSize) tableState.setPageSize(pageSize); queryParams.limit = pageSize; queryParams.offset = (tableState.page - 1) * pageSize; } @@ -588,6 +587,12 @@ export function InvenTreeTable({ [props.onRowClick, props.onCellClick] ); + // pagination refresth table if pageSize changes + function updatePageSize(newData: number) { + tableState.setPageSize(newData); + tableState.refreshTable(); + } + return ( <> {deleteRecords.modal} @@ -705,7 +710,7 @@ export function InvenTreeTable({ idAccessor={tableProps.idAccessor} minHeight={300} totalRecords={tableState.recordCount} - recordsPerPage={tableProps.pageSize ?? defaultPageSize} + recordsPerPage={tableState.pageSize} page={tableState.page} onPageChange={tableState.setPage} sortStatus={sortStatus} @@ -733,6 +738,8 @@ export function InvenTreeTable({ overflow: 'hidden' }) }} + recordsPerPageOptions={PAGE_SIZES} + onRecordsPerPageChange={updatePageSize} /> From cf9dcf0556bef79ef6af298e0c4075adf6ea581c Mon Sep 17 00:00:00 2001 From: Matthias Mair Date: Fri, 23 Aug 2024 01:49:57 +0200 Subject: [PATCH 5/6] [CI] Switch to using Crowdin GitHub Action (#7929) Fixes #7910 --- .github/workflows/translations.yaml | 30 ++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/.github/workflows/translations.yaml b/.github/workflows/translations.yaml index 0bdcd80517..308e171a98 100644 --- a/.github/workflows/translations.yaml +++ b/.github/workflows/translations.yaml @@ -13,10 +13,11 @@ permissions: contents: read jobs: - build: + synchronize-with-crowdin: runs-on: ubuntu-latest permissions: contents: write + pull-requests: write env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -39,16 +40,19 @@ jobs: apt-dependency: gettext - name: Make Translations run: invoke translate - - name: Commit files - run: | - git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" - git config --local user.name "github-actions[bot]" - git checkout -b l10_local - git add "*.po" - git commit -m "updated translation base" - - name: Push changes - uses: ad-m/github-push-action@d91a481090679876dfc4178fef17f286781251df # pin@v0.8.0 + - name: crowdin action + uses: crowdin/github-action@6ed209d411599a981ccb978df3be9dc9b8a81699 # pin@v2 with: - github_token: ${{ secrets.GITHUB_TOKEN }} - branch: l10 - force: true + upload_sources: true + upload_translations: false + download_translations: true + localization_branch_name: l10_crowdin + create_pull_request: true + pull_request_title: 'New Crowdin updates' + pull_request_body: 'New Crowdin translations by [Crowdin GH Action](https://github.com/crowdin/github-action)' + pull_request_base_branch_name: 'l10' + pull_request_labels: 'translations' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} + CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} From b9b44126de0bae2c8aacc5614e8de49bf8227494 Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 23 Aug 2024 11:00:20 +1000 Subject: [PATCH 6/6] Revert status fields for stock items (#7965) * Revert status fields for stock items * Fix PUI fields too * Bump API version --- src/backend/InvenTree/InvenTree/api_version.py | 5 ++++- .../common/migrations/0029_inventreecustomuserstatemodel.py | 2 +- src/backend/InvenTree/common/models.py | 2 +- src/backend/InvenTree/templates/js/translated/stock.js | 2 +- src/frontend/src/forms/StockForms.tsx | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/backend/InvenTree/InvenTree/api_version.py b/src/backend/InvenTree/InvenTree/api_version.py index 181abf41c9..f1df853784 100644 --- a/src/backend/InvenTree/InvenTree/api_version.py +++ b/src/backend/InvenTree/InvenTree/api_version.py @@ -1,12 +1,15 @@ """InvenTree API version information.""" # InvenTree API version -INVENTREE_API_VERSION = 247 +INVENTREE_API_VERSION = 248 """Increment this API version number whenever there is a significant change to the API that any clients need to know about.""" INVENTREE_API_TEXT = """ +v248 - 2024-08-23 : https://github.com/inventree/InvenTree/pull/7965 + - Small adjustments to labels for new custom status fields + v247 - 2024-08-22 : https://github.com/inventree/InvenTree/pull/7956 - Adjust "attachment" field on StockItemTestResult serializer - Allow null values for attachment diff --git a/src/backend/InvenTree/common/migrations/0029_inventreecustomuserstatemodel.py b/src/backend/InvenTree/common/migrations/0029_inventreecustomuserstatemodel.py index 7090b98279..408edf6102 100644 --- a/src/backend/InvenTree/common/migrations/0029_inventreecustomuserstatemodel.py +++ b/src/backend/InvenTree/common/migrations/0029_inventreecustomuserstatemodel.py @@ -46,7 +46,7 @@ class Migration(migrations.Migration): models.CharField( help_text="Label that will be displayed in the frontend", max_length=250, - verbose_name="label", + verbose_name="Label", ), ), ( diff --git a/src/backend/InvenTree/common/models.py b/src/backend/InvenTree/common/models.py index ca3b45c9dc..93dd5d11ce 100644 --- a/src/backend/InvenTree/common/models.py +++ b/src/backend/InvenTree/common/models.py @@ -3355,7 +3355,7 @@ class InvenTreeCustomUserStateModel(models.Model): ) label = models.CharField( max_length=250, - verbose_name=_('label'), + verbose_name=_('Label'), help_text=_('Label that will be displayed in the frontend'), ) color = models.CharField( diff --git a/src/backend/InvenTree/templates/js/translated/stock.js b/src/backend/InvenTree/templates/js/translated/stock.js index 6c21536343..2e65072853 100644 --- a/src/backend/InvenTree/templates/js/translated/stock.js +++ b/src/backend/InvenTree/templates/js/translated/stock.js @@ -380,7 +380,7 @@ function stockItemFields(options={}) { batch: { icon: 'fa-layer-group', }, - status_custom_key: {}, + status: {}, expiry_date: { icon: 'fa-calendar-alt', }, diff --git a/src/frontend/src/forms/StockForms.tsx b/src/frontend/src/forms/StockForms.tsx index 7ac947826b..3ed19c8938 100644 --- a/src/frontend/src/forms/StockForms.tsx +++ b/src/frontend/src/forms/StockForms.tsx @@ -138,7 +138,7 @@ export function useStockFields({ value: batchCode, onValueChange: (value) => setBatchCode(value) }, - status_custom_key: {}, + status: {}, expiry_date: { // TODO: icon },