@nyris/nyris-webapp 0.3.94 → 0.3.95

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@nyris/nyris-webapp",
3
- "version": "0.3.94",
3
+ "version": "0.3.95",
4
4
  "dependencies": {
5
5
  "@auth0/auth0-react": "^2.2.4",
6
6
  "@emailjs/browser": "^4.3.3",
7
7
  "@google/genai": "^1.46.0",
8
- "@nyris/nyris-api": "^0.3.94",
9
- "@nyris/nyris-react-components": "^0.3.94",
8
+ "@nyris/nyris-api": "^0.3.95",
9
+ "@nyris/nyris-react-components": "^0.3.95",
10
10
  "@radix-ui/react-accordion": "^1.2.2",
11
11
  "@radix-ui/react-dialog": "^1.1.4",
12
12
  "@radix-ui/react-popover": "^1.1.4",
@@ -4,13 +4,10 @@ import { twMerge } from 'tailwind-merge';
4
4
  import Tooltip from './Tooltip/TooltipComponent';
5
5
  import { useAuth0 } from '@auth0/auth0-react';
6
6
  import { useMemo, useState } from 'react';
7
- import { useLocation, useNavigate } from 'react-router';
7
+ import { useLocation } from 'react-router';
8
8
  import useRequestStore from 'stores/request/requestStore';
9
- import { useImageSearch } from 'hooks/useImageSearch';
10
- import { clone } from 'lodash';
11
- import { useCadSearch } from 'hooks/useCadSearch';
12
- import { isCadFile } from '@nyris/nyris-api';
13
9
  import UploadDisclaimer from './UploadDisclaimer';
10
+ import { useUploadSearch } from 'hooks/useUploadSearch';
14
11
 
15
12
  function ImageUpload({
16
13
  onCameraClick,
@@ -25,27 +22,10 @@ function ImageUpload({
25
22
  const { t } = useTranslation();
26
23
 
27
24
  const location = useLocation();
28
- const navigate = useNavigate();
25
+ const { uploadFile } = useUploadSearch();
29
26
 
30
- const preFilterList = useRequestStore(state => state.preFilterList);
31
27
  const requestImages = useRequestStore(state => state.requestImages);
32
- const setQuery = useRequestStore(state => state.setQuery);
33
- const setValueInput = useRequestStore(state => state.setValueInput);
34
28
  const setMetaFilter = useRequestStore(state => state.setMetaFilter);
35
- const specifications = useRequestStore(state => state.specifications);
36
-
37
- const setRequestImages = useRequestStore(state => state.setRequestImages);
38
- const setSpecifications = useRequestStore(state => state.setSpecifications);
39
- const setShowLoading = useRequestStore(state => state.setShowLoading);
40
- const setNameplateNotificationText = useRequestStore(
41
- state => state.setNameplateNotificationText,
42
- );
43
- const setShowNotMatchedError = useRequestStore(
44
- state => state.setShowNotMatchedError,
45
- );
46
- const setAlgoliaFilter = useRequestStore(state => state.setAlgoliaFilter);
47
- const setPreFilter = useRequestStore(state => state.setPreFilter);
48
- const setNameplateImage = useRequestStore(state => state.setNameplateImage);
49
29
 
50
30
  const [showDisclaimer, setShowDisclaimer] = useState(false);
51
31
 
@@ -80,97 +60,13 @@ function ImageUpload({
80
60
  // eslint-disable-next-line react-hooks/exhaustive-deps
81
61
  }, [showDisclaimer, requestImages, disableDisclaimer]);
82
62
 
83
- const { singleImageSearch } = useImageSearch();
84
- const { cadSearch } = useCadSearch();
85
-
86
63
  const handleUpload = (files: File[]) => {
87
- setValueInput('');
88
- setQuery('');
89
-
90
- if (isCadFile(files[0])) {
91
- cadSearch({ file: files[0], settings, newSearch: true }).then(() => {});
92
-
64
+ const file = files[0];
65
+ if (!file) {
93
66
  return;
94
67
  }
95
68
 
96
- setShowLoading(true);
97
-
98
- singleImageSearch({
99
- image: files[0],
100
- settings: window.settings,
101
- showFeedback: true,
102
- newSearch: true,
103
- clearPostFilter: true,
104
- }).then(singleImageResp => {
105
- const specificationPrefilter =
106
- singleImageResp?.image_analysis?.specification?.prefilter_value || null;
107
- const hasPrefilter = preFilterList.filter((filter: any) =>
108
- filter.values.includes(specificationPrefilter),
109
- );
110
- if (specificationPrefilter) {
111
- setRequestImages([]);
112
- setShowNotMatchedError(false);
113
- if (hasPrefilter.length) {
114
- setSpecifications(
115
- clone(singleImageResp?.image_analysis?.specification),
116
- );
117
- setNameplateImage(files[0]);
118
- setPreFilter({
119
- [singleImageResp?.image_analysis?.specification?.prefilter_value]:
120
- true,
121
- });
122
- setAlgoliaFilter(
123
- `${settings.alogoliaFilterField}:'${singleImageResp?.image_analysis?.specification?.prefilter_value}'`,
124
- );
125
-
126
- setShowLoading(false);
127
- navigate('/result');
128
-
129
- setTimeout(() => {
130
- setNameplateNotificationText(
131
- t('We have successfully defined the search criteria', {
132
- prefilter_value: specificationPrefilter,
133
- preFilterTitle:
134
- window.settings.preFilterTitle?.toLocaleLowerCase(),
135
- }),
136
- );
137
- }, 1000);
138
- setTimeout(() => {
139
- setNameplateNotificationText('');
140
- }, 10000);
141
- }
142
- if (!hasPrefilter.length && showPreFilter) {
143
- setSpecifications(
144
- clone({
145
- ...singleImageResp?.image_analysis?.specification,
146
- specificationPrefilter,
147
- }),
148
- );
149
- navigate('/result');
150
- setPreFilter({});
151
- setAlgoliaFilter('');
152
- setShowLoading(false);
153
- setShowNotMatchedError(true);
154
- setTimeout(() => {
155
- setNameplateNotificationText(
156
- t('Extracted details from the nameplate could not be matched', {
157
- preFilterTitle:
158
- window.settings.preFilterTitle?.toLocaleLowerCase(),
159
- }),
160
- );
161
- }, 1000);
162
- setTimeout(() => {
163
- setNameplateNotificationText('');
164
- }, 15000);
165
- }
166
- } else {
167
- if (!specifications?.is_nameplate) {
168
- setSpecifications({ ...specifications, is_nameplate: false });
169
- }
170
- setShowLoading(false);
171
- navigate('/result');
172
- }
173
- });
69
+ uploadFile(file, { showPreFilter });
174
70
  };
175
71
 
176
72
  return (
@@ -15,8 +15,9 @@ export const Toaster = () => {
15
15
  <ReactHotToaster
16
16
  position={isMobile ? 'bottom-center' : 'top-right'}
17
17
  containerStyle={{
18
- top: 80,
19
- bottom: isMobile ? 80 : 'auto',
18
+ top: 100,
19
+ bottom: isMobile ? 90 : 'auto',
20
+ right: isMobile ? 15 : 25,
20
21
  }}
21
22
  >
22
23
  {t => (
@@ -0,0 +1,170 @@
1
+ import { useCallback } from 'react';
2
+ import { clone } from 'lodash';
3
+ import { useNavigate } from 'react-router';
4
+ import { useTranslation } from 'react-i18next';
5
+ import { isCadFile } from '@nyris/nyris-api';
6
+
7
+ import { useImageSearch } from 'hooks/useImageSearch';
8
+ import { useCadSearch } from 'hooks/useCadSearch';
9
+ import useRequestStore from 'stores/request/requestStore';
10
+
11
+ interface UploadFileOptions {
12
+ showPreFilter?: boolean;
13
+ resetTextSearch?: boolean;
14
+ }
15
+
16
+ export const useUploadSearch = () => {
17
+ const settings = window.settings;
18
+ const navigate = useNavigate();
19
+ const { t } = useTranslation();
20
+
21
+ const { singleImageSearch } = useImageSearch();
22
+ const { cadSearch } = useCadSearch();
23
+
24
+ const preFilterList = useRequestStore(state => state.preFilterList);
25
+ const specifications = useRequestStore(state => state.specifications);
26
+
27
+ const setQuery = useRequestStore(state => state.setQuery);
28
+ const setValueInput = useRequestStore(state => state.setValueInput);
29
+
30
+ const setRequestImages = useRequestStore(state => state.setRequestImages);
31
+ const setSpecifications = useRequestStore(state => state.setSpecifications);
32
+ const setShowLoading = useRequestStore(state => state.setShowLoading);
33
+ const setNameplateNotificationText = useRequestStore(
34
+ state => state.setNameplateNotificationText,
35
+ );
36
+ const setShowNotMatchedError = useRequestStore(
37
+ state => state.setShowNotMatchedError,
38
+ );
39
+ const setAlgoliaFilter = useRequestStore(state => state.setAlgoliaFilter);
40
+ const setPreFilter = useRequestStore(state => state.setPreFilter);
41
+ const setNameplateImage = useRequestStore(state => state.setNameplateImage);
42
+
43
+ const uploadFile = useCallback(
44
+ (
45
+ file: File,
46
+ {
47
+ showPreFilter = settings.preFilterOption,
48
+ resetTextSearch = true,
49
+ }: UploadFileOptions = {},
50
+ ) => {
51
+ if (resetTextSearch) {
52
+ setValueInput('');
53
+ setQuery('');
54
+ }
55
+
56
+ if (isCadFile(file)) {
57
+ return cadSearch({ file, settings, newSearch: true }).then(() => {});
58
+ }
59
+
60
+ setShowLoading(true);
61
+
62
+ return singleImageSearch({
63
+ image: file,
64
+ settings,
65
+ showFeedback: true,
66
+ newSearch: true,
67
+ clearPostFilter: true,
68
+ }).then(singleImageResp => {
69
+ const specificationPrefilter =
70
+ singleImageResp?.image_analysis?.specification?.prefilter_value ||
71
+ null;
72
+ const hasPrefilter = preFilterList.filter((filter: any) =>
73
+ filter.values.includes(specificationPrefilter),
74
+ );
75
+
76
+ if (specificationPrefilter) {
77
+ setRequestImages([]);
78
+ setShowNotMatchedError(false);
79
+
80
+ if (hasPrefilter.length) {
81
+ setSpecifications(
82
+ clone(singleImageResp?.image_analysis?.specification),
83
+ );
84
+ setNameplateImage(file);
85
+ setPreFilter({
86
+ [singleImageResp?.image_analysis?.specification?.prefilter_value]:
87
+ true,
88
+ });
89
+ setAlgoliaFilter(
90
+ `${settings.alogoliaFilterField}:'${singleImageResp?.image_analysis?.specification?.prefilter_value}'`,
91
+ );
92
+
93
+ setShowLoading(false);
94
+ navigate('/result');
95
+
96
+ setTimeout(() => {
97
+ setNameplateNotificationText(
98
+ t('We have successfully defined the search criteria', {
99
+ prefilter_value: specificationPrefilter,
100
+ preFilterTitle:
101
+ window.settings.preFilterTitle?.toLocaleLowerCase(),
102
+ }),
103
+ );
104
+ }, 1000);
105
+
106
+ setTimeout(() => {
107
+ setNameplateNotificationText('');
108
+ }, 10000);
109
+ }
110
+
111
+ if (!hasPrefilter.length && showPreFilter) {
112
+ setSpecifications(
113
+ clone({
114
+ ...singleImageResp?.image_analysis?.specification,
115
+ specificationPrefilter,
116
+ }),
117
+ );
118
+ navigate('/result');
119
+ setPreFilter({});
120
+ setAlgoliaFilter('');
121
+ setShowLoading(false);
122
+ setShowNotMatchedError(true);
123
+
124
+ setTimeout(() => {
125
+ setNameplateNotificationText(
126
+ t('Extracted details from the nameplate could not be matched', {
127
+ preFilterTitle:
128
+ window.settings.preFilterTitle?.toLocaleLowerCase(),
129
+ }),
130
+ );
131
+ }, 1000);
132
+
133
+ setTimeout(() => {
134
+ setNameplateNotificationText('');
135
+ }, 15000);
136
+ }
137
+ } else {
138
+ if (!specifications?.is_nameplate) {
139
+ setSpecifications({ ...specifications, is_nameplate: false });
140
+ }
141
+ setShowLoading(false);
142
+ navigate('/result');
143
+ }
144
+ });
145
+ },
146
+ [
147
+ cadSearch,
148
+ navigate,
149
+ preFilterList,
150
+ setAlgoliaFilter,
151
+ setNameplateImage,
152
+ setNameplateNotificationText,
153
+ setPreFilter,
154
+ setQuery,
155
+ setRequestImages,
156
+ setShowLoading,
157
+ setShowNotMatchedError,
158
+ setSpecifications,
159
+ setValueInput,
160
+ settings,
161
+ singleImageSearch,
162
+ specifications,
163
+ t,
164
+ ],
165
+ );
166
+
167
+ return {
168
+ uploadFile,
169
+ };
170
+ };
@@ -19,6 +19,9 @@ import useResultStore from 'stores/result/resultStore';
19
19
  import useUiStore from 'stores/ui/uiStore';
20
20
  import { Toaster } from 'components/Toaster';
21
21
  import { getFilters } from 'services/filter';
22
+ import { useUploadSearch } from 'hooks/useUploadSearch';
23
+ import { ToastHelper } from 'helpers/ToastHelper';
24
+ import { useTranslation } from 'react-i18next';
22
25
 
23
26
  i18n.use(initReactI18next).init({
24
27
  resources: translations,
@@ -31,7 +34,9 @@ i18n.use(initReactI18next).init({
31
34
 
32
35
  function AppLayout(): JSX.Element {
33
36
  const { isAuthenticated } = useAuth0();
37
+ const { t } = useTranslation();
34
38
  const { auth0, alogoliaFilterField, showPoweredByNyris } = window.settings;
39
+ const { uploadFile } = useUploadSearch();
35
40
 
36
41
  const showLayout = !auth0.enabled || (auth0.enabled && isAuthenticated);
37
42
  const location = useLocation();
@@ -47,10 +52,12 @@ function AppLayout(): JSX.Element {
47
52
 
48
53
  const setAlgoliaProducts = useResultStore(state => state.setAlgoliaProducts);
49
54
  const setIsAlgoliaLoading = useUiStore(state => state.setIsAlgoliaLoading);
55
+ const isFindApiLoading = useUiStore(state => state.isFindApiLoading);
50
56
 
51
57
  const setIsCadenasLoaded = useUiStore(state => state.setIsCadenasLoaded);
52
58
  const specifications = useRequestStore(state => state.specifications);
53
59
  const requestImages = useRequestStore(state => state.requestImages);
60
+ const showLoading = useRequestStore(state => state.showLoading);
54
61
 
55
62
  const { status } = useInstantSearch();
56
63
  const { items } = useHits();
@@ -143,6 +150,69 @@ function AppLayout(): JSX.Element {
143
150
  }
144
151
  }, [getPreFilters, showPreFilter]);
145
152
 
153
+ const getImageFromClipboard = useCallback(
154
+ (event: ClipboardEvent): File | null => {
155
+ const clipboardData = event.clipboardData;
156
+ if (!clipboardData) {
157
+ return null;
158
+ }
159
+
160
+ const imageItem = Array.from(clipboardData.items || []).find(
161
+ item => item.kind === 'file' && item.type.startsWith('image/'),
162
+ );
163
+
164
+ if (imageItem) {
165
+ return imageItem.getAsFile();
166
+ }
167
+
168
+ return (
169
+ Array.from(clipboardData.files || []).find(file =>
170
+ file.type.startsWith('image/'),
171
+ ) || null
172
+ );
173
+ },
174
+ [],
175
+ );
176
+
177
+ const handleClipboardPaste = useCallback(
178
+ (event: ClipboardEvent) => {
179
+ if (isFindApiLoading || showLoading) {
180
+ return;
181
+ }
182
+
183
+ const imageFile = getImageFromClipboard(event);
184
+ if (!imageFile) {
185
+ return;
186
+ }
187
+
188
+ event.preventDefault();
189
+ ToastHelper.success(
190
+ t('Image pasted from clipboard. Starting visual search.'),
191
+ );
192
+ uploadFile(imageFile, { showPreFilter });
193
+ },
194
+ [
195
+ getImageFromClipboard,
196
+ isFindApiLoading,
197
+ showLoading,
198
+ showPreFilter,
199
+ t,
200
+ uploadFile,
201
+ ],
202
+ );
203
+
204
+ useEffect(() => {
205
+ if (!showLayout) {
206
+ return;
207
+ }
208
+
209
+ document.addEventListener('paste', handleClipboardPaste);
210
+
211
+ return () => {
212
+ document.removeEventListener('paste', handleClipboardPaste);
213
+ };
214
+ }, [handleClipboardPaste, showLayout]);
215
+
146
216
  if (!showLayout) {
147
217
  return <Outlet />;
148
218
  }
@@ -224,13 +224,13 @@ function Results() {
224
224
  <div className="block desktop:hidden desktop:mb-0 mx-2">
225
225
  {requestImages[0] && <ImagePreview />}
226
226
  {isSmartFiltersEnabled && (
227
- <div className="my-4">
228
- <SmartFilter
229
- imageAnalysis={imageAnalysis}
230
- specificationFilter={specificationFilter}
231
- />
232
- </div>
233
- )}
227
+ <div className="my-4">
228
+ <SmartFilter
229
+ imageAnalysis={imageAnalysis}
230
+ specificationFilter={specificationFilter}
231
+ />
232
+ </div>
233
+ )}
234
234
  {window.settings.showImageDetails &&
235
235
  (imageAnalysis?.imageDescription ||
236
236
  Object.keys(imageAnalysis?.specification || {}).length >
@@ -335,6 +335,7 @@ function Results() {
335
335
  'mx-0.5',
336
336
  'mobile-md:mx-2',
337
337
  'desktop:mx-4',
338
+ 'h-full',
338
339
  ])}
339
340
  >
340
341
  <div className="max-w-[840px] w-full relative flex flex-col justify-between mb-20 desktop:mb-0">
@@ -4,6 +4,8 @@ export const translations = {
4
4
  Search: 'Search',
5
5
  'Drag and drop': 'Drag and drop',
6
6
  'an image here': 'an image here',
7
+ 'Image pasted from clipboard. Starting visual search.':
8
+ 'Image pasted from clipboard. Starting visual search.',
7
9
  'Manufacturer Number': 'Manufacturer No.',
8
10
  'Mfr. No.': 'Mfr. No.',
9
11
  'Close group': 'Close group',
@@ -65,13 +67,16 @@ export const translations = {
65
67
  'Please enable location services when prompted.':
66
68
  'Please enable location services when prompted.',
67
69
  'I understand': 'I understand',
68
- 'We have successfully defined the search criteria': 'Nameplate detected and matched to {{prefilter_value}}. Items are shown for this {{preFilterTitle}}. You can now upload an image or enter a keyword to search.',
70
+ 'We have successfully defined the search criteria':
71
+ 'Nameplate detected and matched to {{prefilter_value}}. Items are shown for this {{preFilterTitle}}. You can now upload an image or enter a keyword to search.',
69
72
  'Type plates': 'Type plates',
70
- 'Parts': 'Parts',
71
- 'Labels': 'Labels',
72
- 'Barcodes': 'Barcodes',
73
- 'Nameplate not matching': 'Nameplate detected, but {{prefilter_value}} was not found in the list. You can select the correct {{preFilterTitle}} to continue.',
74
- 'Extracted details from the nameplate could not be matched': 'The extracted details could not be matched to a known {{preFilterTitle}}. Please select a different {{preFilterTitle}} and continue searching.',
73
+ Parts: 'Parts',
74
+ Labels: 'Labels',
75
+ Barcodes: 'Barcodes',
76
+ 'Nameplate not matching':
77
+ 'Nameplate detected, but {{prefilter_value}} was not found in the list. You can select the correct {{preFilterTitle}} to continue.',
78
+ 'Extracted details from the nameplate could not be matched':
79
+ 'The extracted details could not be matched to a known {{preFilterTitle}}. Please select a different {{preFilterTitle}} and continue searching.',
75
80
  'Showing results for machine': `Showing results for {{prefilter_title}} '{{prefilter_value}}'`,
76
81
  'No matches found for': `No matches found for {{prefilter_title}} '{{prefilter_value}}'. Showing all items instead.`,
77
82
  },
@@ -81,6 +86,8 @@ export const translations = {
81
86
  Search: 'Suche',
82
87
  'Drag and drop': 'Bild hierher ziehen',
83
88
  'an image here': '',
89
+ 'Image pasted from clipboard. Starting visual search.':
90
+ 'Bild aus der Zwischenablage eingefügt. Visuelle Suche gestartet.',
84
91
  'Mfr. No.': 'Herst. Teile-Nr.',
85
92
  'Manufacturer Number': 'Herstellerteilenummer',
86
93
  'Close group': 'Schließe Gruppe',
@@ -144,13 +151,16 @@ export const translations = {
144
151
  'Please enable location services when prompted.':
145
152
  'Bitte erlauben Sie den Zugriff auf Ihren Standort.',
146
153
  'I understand': 'Weiter',
147
- 'We have successfully defined the search criteria': 'Typenschild erkannt und mit {{prefilter_value}} abgeglichen. Es werden Artikel für dieses {{preFilterTitle}}. Sie können nun ein Bild hochladen oder ein Stichwort zur Suche eingeben.',
154
+ 'We have successfully defined the search criteria':
155
+ 'Typenschild erkannt und mit {{prefilter_value}} abgeglichen. Es werden Artikel für dieses {{preFilterTitle}}. Sie können nun ein Bild hochladen oder ein Stichwort zur Suche eingeben.',
148
156
  'Type plates': 'Typenschilder',
149
- 'Parts': 'Teile',
150
- 'Labels': 'Etiketten',
151
- 'Barcodes': 'Barcodes',
152
- 'Nameplate not matching': 'Typenschild erkannt, aber {{prefilter_value}} wurde nicht in der Liste gefunden. Sie können die richtigen {{preFilterTitle}}, um fortzufahren.',
153
- 'Extracted details from the nameplate could not be matched': 'Die extrahierten Details konnten keinem bekannten {{preFilterTitle}} zugeordnet werden. Bitte wählen Sie einen anderen {{preFilterTitle}} aus und setzen Sie die Suche fort.',
157
+ Parts: 'Teile',
158
+ Labels: 'Etiketten',
159
+ Barcodes: 'Barcodes',
160
+ 'Nameplate not matching':
161
+ 'Typenschild erkannt, aber {{prefilter_value}} wurde nicht in der Liste gefunden. Sie können die richtigen {{preFilterTitle}}, um fortzufahren.',
162
+ 'Extracted details from the nameplate could not be matched':
163
+ 'Die extrahierten Details konnten keinem bekannten {{preFilterTitle}} zugeordnet werden. Bitte wählen Sie einen anderen {{preFilterTitle}} aus und setzen Sie die Suche fort.',
154
164
  'Showing results for machine': `Ergebnisse für {{prefilter_title}} '{{prefilter_value}}' anzeigen`,
155
165
  'No matches found for': `Keine Übereinstimmungen gefunden für {{prefilter_title}} '{{prefilter_value}}'. Alle Artikel anzeigen stattdessen.`,
156
166
  },
@@ -160,6 +170,8 @@ export const translations = {
160
170
  Search: 'Busca',
161
171
  'Drag and drop': 'Escolha uma imagem',
162
172
  'an image here': '',
173
+ 'Image pasted from clipboard. Starting visual search.':
174
+ 'Imagem colada da área de transferência. A iniciar pesquisa visual.',
163
175
  'Manufacturer Number': 'Número do fabricante',
164
176
  'Mfr. No.': 'Nr. do Fab',
165
177
  'Close group': 'Fechar grupo',
@@ -224,13 +236,16 @@ export const translations = {
224
236
  'Please enable location services when prompted.':
225
237
  'Por favor, ative os serviços de localização quando solicitado',
226
238
  'I understand': 'Compreendo',
227
- 'We have successfully defined the search criteria': 'Placa de identificação detetada e correspondente a {{prefilter_value}}. São apresentados os itens para esta {{preFilterTitle}}. Agora pode carregar uma imagem ou introduzir uma palavra-chave para pesquisar.',
239
+ 'We have successfully defined the search criteria':
240
+ 'Placa de identificação detetada e correspondente a {{prefilter_value}}. São apresentados os itens para esta {{preFilterTitle}}. Agora pode carregar uma imagem ou introduzir uma palavra-chave para pesquisar.',
228
241
  'Type plates': 'Placa de identificação',
229
- 'Parts': 'Peças',
230
- 'Labels': 'Etiquetas',
231
- 'Barcodes': 'Códigos de barras',
232
- 'Nameplate not matching': 'Placa de identificação detetada, mas {{prefilter_value}} não foi encontrado na lista. Pode selecionar os {{preFilterTitle}} corretos para continuar.',
233
- 'Extracted details from the nameplate could not be matched': 'Os detalhes extraídos não puderam ser correspondidos a um {{preFilterTitle}} conhecido. Selecione um {{preFilterTitle}} diferente e continue a pesquisa.',
242
+ Parts: 'Peças',
243
+ Labels: 'Etiquetas',
244
+ Barcodes: 'Códigos de barras',
245
+ 'Nameplate not matching':
246
+ 'Placa de identificação detetada, mas {{prefilter_value}} não foi encontrado na lista. Pode selecionar os {{preFilterTitle}} corretos para continuar.',
247
+ 'Extracted details from the nameplate could not be matched':
248
+ 'Os detalhes extraídos não puderam ser correspondidos a um {{preFilterTitle}} conhecido. Selecione um {{preFilterTitle}} diferente e continue a pesquisa.',
234
249
  'Showing results for machine': `Mostrando resultados para {{prefilter_title}} '{{prefilter_value}}'`,
235
250
  'No matches found for': `Não foram encontrados resultados para {{prefilter_title}} '{{prefilter_value}}'. Mostrando todos os itens em vez disso.`,
236
251
  },