@bigbinary/neeto-pdf-frontend 1.0.1

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.
Files changed (82) hide show
  1. package/README.md +413 -0
  2. package/app/javascript/src/translations/ar.json +5 -0
  3. package/app/javascript/src/translations/bg.json +5 -0
  4. package/app/javascript/src/translations/ca.json +5 -0
  5. package/app/javascript/src/translations/cs.json +5 -0
  6. package/app/javascript/src/translations/da.json +5 -0
  7. package/app/javascript/src/translations/de.json +5 -0
  8. package/app/javascript/src/translations/en.json +109 -0
  9. package/app/javascript/src/translations/es-MX.json +5 -0
  10. package/app/javascript/src/translations/es.json +5 -0
  11. package/app/javascript/src/translations/et.json +5 -0
  12. package/app/javascript/src/translations/fi.json +5 -0
  13. package/app/javascript/src/translations/fil.json +5 -0
  14. package/app/javascript/src/translations/fr.json +5 -0
  15. package/app/javascript/src/translations/he.json +5 -0
  16. package/app/javascript/src/translations/hi.json +5 -0
  17. package/app/javascript/src/translations/hr.json +5 -0
  18. package/app/javascript/src/translations/hu.json +5 -0
  19. package/app/javascript/src/translations/id.json +5 -0
  20. package/app/javascript/src/translations/index.js +3 -0
  21. package/app/javascript/src/translations/it.json +5 -0
  22. package/app/javascript/src/translations/ja.json +5 -0
  23. package/app/javascript/src/translations/ko.json +5 -0
  24. package/app/javascript/src/translations/nl.json +5 -0
  25. package/app/javascript/src/translations/pl.json +5 -0
  26. package/app/javascript/src/translations/pt-BR.json +5 -0
  27. package/app/javascript/src/translations/pt.json +5 -0
  28. package/app/javascript/src/translations/ro.json +5 -0
  29. package/app/javascript/src/translations/ru.json +5 -0
  30. package/app/javascript/src/translations/sk.json +5 -0
  31. package/app/javascript/src/translations/sl.json +5 -0
  32. package/app/javascript/src/translations/sv.json +5 -0
  33. package/app/javascript/src/translations/th.json +5 -0
  34. package/app/javascript/src/translations/tr.json +5 -0
  35. package/app/javascript/src/translations/uk.json +5 -0
  36. package/app/javascript/src/translations/vi.json +5 -0
  37. package/app/javascript/src/translations/zh-CN.json +5 -0
  38. package/app/javascript/src/translations/zh-TW.json +5 -0
  39. package/dist/.ready +1 -0
  40. package/dist/AttachmentCard-75GY2Thb.js +64 -0
  41. package/dist/AttachmentCard-75GY2Thb.js.map +1 -0
  42. package/dist/AttachmentCard-D_Gp0f5r.js +67 -0
  43. package/dist/AttachmentCard-D_Gp0f5r.js.map +1 -0
  44. package/dist/FilenameUtilities-Cw9Tvd6k.js +329 -0
  45. package/dist/FilenameUtilities-Cw9Tvd6k.js.map +1 -0
  46. package/dist/FilenameUtilities-De2k_NXh.js +318 -0
  47. package/dist/FilenameUtilities-De2k_NXh.js.map +1 -0
  48. package/dist/IconBlock-BTPLDDiO.js +15 -0
  49. package/dist/IconBlock-BTPLDDiO.js.map +1 -0
  50. package/dist/IconBlock-hZ_gOnb1.js +17 -0
  51. package/dist/IconBlock-hZ_gOnb1.js.map +1 -0
  52. package/dist/PdfAttachmentSelector.js +94 -0
  53. package/dist/PdfAttachmentSelector.js.map +1 -0
  54. package/dist/PdfAttachmentsPreview.js +43 -0
  55. package/dist/PdfAttachmentsPreview.js.map +1 -0
  56. package/dist/PdfDocumentsPage.js +555 -0
  57. package/dist/PdfDocumentsPage.js.map +1 -0
  58. package/dist/PdfEditorPage.js +2051 -0
  59. package/dist/PdfEditorPage.js.map +1 -0
  60. package/dist/cjs/PdfAttachmentSelector.js +96 -0
  61. package/dist/cjs/PdfAttachmentSelector.js.map +1 -0
  62. package/dist/cjs/PdfAttachmentsPreview.js +45 -0
  63. package/dist/cjs/PdfAttachmentsPreview.js.map +1 -0
  64. package/dist/cjs/PdfDocumentsPage.js +557 -0
  65. package/dist/cjs/PdfDocumentsPage.js.map +1 -0
  66. package/dist/cjs/PdfEditorPage.js +2072 -0
  67. package/dist/cjs/PdfEditorPage.js.map +1 -0
  68. package/dist/cjs/index.js +75 -0
  69. package/dist/cjs/index.js.map +1 -0
  70. package/dist/constants-CTDOz942.js +5 -0
  71. package/dist/constants-CTDOz942.js.map +1 -0
  72. package/dist/constants-DvvJYjxW.js +8 -0
  73. package/dist/constants-DvvJYjxW.js.map +1 -0
  74. package/dist/index.js +66 -0
  75. package/dist/index.js.map +1 -0
  76. package/package.json +240 -0
  77. package/types/PdfAttachmentSelector.d.ts +2 -0
  78. package/types/PdfAttachmentsPreview.d.ts +2 -0
  79. package/types/PdfDocumentsPage.d.ts +6 -0
  80. package/types/PdfEditorPage.d.ts +7 -0
  81. package/types/index.d.ts +88 -0
  82. package/types.d.ts +1 -0
package/README.md ADDED
@@ -0,0 +1,413 @@
1
+ # neeto-pdf-nano
2
+
3
+ `neeto-pdf-nano` provides shared PDF document support for neeto products. It
4
+ publishes two packages:
5
+
6
+ - `neeto-pdf-engine`, a Rails engine for storing PDF templates and mappings,
7
+ exposing document APIs, and rendering completed PDFs.
8
+ - `@bigbinary/neeto-pdf-frontend`, a React package for managing templates,
9
+ mapping fields, previewing PDFs, and selecting email attachments.
10
+
11
+ The host product still owns its routes and permissions, the model that owns the
12
+ documents, the fields shown in the editor, preview records, email settings, and
13
+ the values used when rendering a completed PDF.
14
+
15
+ ## Requirements
16
+
17
+ The backend expects a Rails application with Active Record, Active Storage,
18
+ PostgreSQL, and `NeetoCommonsBackend::Api::BaseController`. The provided
19
+ migration uses UUIDs for document and owner IDs and uses `jsonb` columns.
20
+
21
+ The frontend expects the standard neeto application setup for React Query,
22
+ i18next, Axios, neetoUI, neetoMolecules, and Tailwind CSS. The email attachment
23
+ components must be rendered inside a Formik.
24
+
25
+ ## Backend setup
26
+
27
+ ### 1. Add the engine
28
+
29
+ Add the gem to the host application's `Gemfile`:
30
+
31
+ ```ruby
32
+ source "NEETO_GEM_SERVER_URL" do
33
+ # Existing gems
34
+ gem "neeto-pdf-engine"
35
+ end
36
+ ```
37
+
38
+ Then install it:
39
+
40
+ ```sh
41
+ bundle install
42
+ ```
43
+
44
+ ### 2. Install the database migration
45
+
46
+ Copy only `db/migrate/20260706120000_create_neeto_pdf_engine_documents.rb` from
47
+ this engine into the host application's `db/migrate` directory. Give the copied
48
+ file a timestamp that does not conflict with a host migration, then run:
49
+
50
+ ```sh
51
+ bundle exec rails db:migrate
52
+ ```
53
+
54
+ Do not run the general engine migration installer yet. This repository still
55
+ contains migrations inherited from the nano template that do not belong to the
56
+ PDF feature.
57
+
58
+ The migration stores `owner_id` as a UUID. Adjust and test the migration before
59
+ running it if the host's owner model does not use UUID primary keys.
60
+
61
+ ### 3. Configure the document owner
62
+
63
+ Create `config/initializers/neeto_pdf_engine.rb` in the host application and set
64
+ the class name of the model that owns PDF documents:
65
+
66
+ ```ruby
67
+ NeetoPdfEngine.owner_class = "Form"
68
+ ```
69
+
70
+ The value must be a class-name string. The owner must either be the current
71
+ organization or support `where(organization: @organization)`, because the engine
72
+ scopes every request through `@organization`.
73
+
74
+ Add an association to the owner model so its PDF documents are removed with the
75
+ owner:
76
+
77
+ ```ruby
78
+ class Form < ApplicationRecord
79
+ belongs_to :organization
80
+
81
+ has_many :neeto_pdf_documents,
82
+ as: :owner,
83
+ class_name: "NeetoPdfEngine::Document",
84
+ dependent: :destroy
85
+ end
86
+ ```
87
+
88
+ ### 4. Mount the engine
89
+
90
+ Mount the engine at a stable path in `config/routes.rb`:
91
+
92
+ ```ruby
93
+ mount NeetoPdfEngine::Engine, at: "/neeto_pdf"
94
+ ```
95
+
96
+ The frontend API base URL for this mount point is:
97
+
98
+ ```js
99
+ const pdfApiBaseUrl = "/neeto_pdf/api/v1";
100
+ ```
101
+
102
+ ### 5. Enforce product permissions
103
+
104
+ The engine authenticates requests and scopes documents to the current
105
+ organization and owner. It does not know the host product's permission model.
106
+ The host must enforce permissions for every applicable read and write endpoint
107
+ on the server. Add the check through the host's shared API authorization layer
108
+ or prepend a host-owned controller override with a permission `before_action` to
109
+ `NeetoPdfEngine::Api::V1::DocumentsController`.
110
+
111
+ The frontend `canManage` prop only controls parts of the interface. It is not a
112
+ server-side authorization check and must not be used as one.
113
+
114
+ ## Frontend setup
115
+
116
+ ### 1. Add the package
117
+
118
+ Install the frontend package in the host application:
119
+
120
+ ```sh
121
+ yarn add @bigbinary/neeto-pdf-frontend pdf-lib@1.17.1 pdfjs-dist@6.1.200
122
+ ```
123
+
124
+ The package uses the host's configured Axios instance and expects the normal
125
+ neeto request and response case transformations. It also expects a React Query
126
+ provider and an initialized i18next instance.
127
+
128
+ Template uploads in the provided UI use the neetoMolecules `FileUpload` direct
129
+ upload flow. Confirm that Active Storage direct uploads are configured and that
130
+ uploaded files receive a signed ID before integrating the documents page.
131
+
132
+ ### 2. Include package styles
133
+
134
+ The components use Tailwind utility classes from the installed package. Make
135
+ sure the host's Tailwind stylesheet scans `@bigbinary` packages. For Tailwind
136
+ CSS 4, add an appropriate `@source` path relative to the host stylesheet:
137
+
138
+ ```css
139
+ @import "tailwindcss" important;
140
+ @source "../../../../node_modules/@bigbinary";
141
+ ```
142
+
143
+ Keep the host application's usual neetoUI and neetoMolecules styles enabled.
144
+ There is no separate PDF package stylesheet to import.
145
+
146
+ ### 3. Load translations
147
+
148
+ Applications using the standard neeto-commons build configuration load
149
+ translations from installed `@bigbinary` packages automatically. Other hosts
150
+ must merge the package's `app/javascript/src/translations/en.json` file into
151
+ their i18next resources before rendering these components.
152
+
153
+ ### 4. Install the PDF.js worker
154
+
155
+ The editor loads the PDF.js worker from `/pdf.worker.min.js`. Add a script to
156
+ the host application's `package.json` that copies the worker from the installed
157
+ `pdfjs-dist` version:
158
+
159
+ ```json
160
+ {
161
+ "scripts": {
162
+ "sync:pdf-worker": "mkdir -p public && cp -f node_modules/pdfjs-dist/build/pdf.worker.min.mjs public/pdf.worker.min.js"
163
+ }
164
+ }
165
+ ```
166
+
167
+ Prepend `yarn sync:pdf-worker &&` to the host's existing `build` and `dev`
168
+ commands so the sync runs in development and production. The host must serve the
169
+ copied file at the root URL `/pdf.worker.min.js`.
170
+
171
+ ## Documents page
172
+
173
+ `PdfDocumentsPage` lists the owner's templates and supports uploading, renaming,
174
+ replacing, cloning, and deleting documents. The host owns the route that renders
175
+ this page and the route used to open the editor.
176
+
177
+ ```jsx
178
+ import { PdfDocumentsPage } from "@bigbinary/neeto-pdf-frontend";
179
+
180
+ const Documents = ({ formId, selectedPdfDocumentIds }) => (
181
+ <PdfDocumentsPage
182
+ apiBaseUrl="/neeto_pdf/api/v1"
183
+ canManage={canManagePdfDocuments}
184
+ emailRoutes={{
185
+ submitter: submitterEmailSettingsUrl,
186
+ receiver: receiverEmailSettingsUrl,
187
+ }}
188
+ ownerId={formId}
189
+ selectedPdfDocumentIds={selectedPdfDocumentIds}
190
+ onOpenEditor={document => navigateToPdfEditor(document.id)}
191
+ />
192
+ );
193
+ ```
194
+
195
+ `onOpenEditor` receives the full document object, not only its ID.
196
+ `selectedPdfDocumentIds` is display-only on this page; the host's email settings
197
+ remain the source of truth for selected attachments.
198
+
199
+ Use the optional `renderHeader` and `renderContent` props when the page needs to
200
+ fit an existing host layout:
201
+
202
+ ```jsx
203
+ <PdfDocumentsPage
204
+ renderHeader={({ actionBlock, title }) => (
205
+ <HostPageHeader {...{ actionBlock, title }} />
206
+ )}
207
+ renderContent={content => <HostPageContent>{content}</HostPageContent>}
208
+ {...otherProps}
209
+ />
210
+ ```
211
+
212
+ ## Editor page
213
+
214
+ The host must load and normalize its product-specific fields and preview records
215
+ before passing them to `PdfEditorPage`. The nano does not import form or
216
+ submission APIs from a host product.
217
+
218
+ ```jsx
219
+ import { PdfEditorPage } from "@bigbinary/neeto-pdf-frontend";
220
+
221
+ <PdfEditorPage
222
+ apiBaseUrl="/neeto_pdf/api/v1"
223
+ canManage={canManagePdfDocuments}
224
+ documentId={documentId}
225
+ fields={pdfFields}
226
+ homeUrl={pdfDocumentsUrl}
227
+ isPreviewLoading={isPreviewLoading}
228
+ mode={mode}
229
+ ownerId={formId}
230
+ ownerRecord={form}
231
+ previewPage={previewPage}
232
+ previewRecord={submission}
233
+ previewTotal={submissionsTotal}
234
+ onBack={navigateToPdfDocuments}
235
+ onModeChange={setMode}
236
+ onPreviewPageChange={setPreviewPage}
237
+ />;
238
+ ```
239
+
240
+ Pass a real `homeUrl` so the visible back action has a valid link. Use `onBack`
241
+ as well when the host needs custom history behavior. The `mode` and
242
+ `onModeChange` props are optional; pass them when editor mode should be stored
243
+ in the host URL or state.
244
+
245
+ ### Field shape
246
+
247
+ Each host field may include the following values:
248
+
249
+ ```js
250
+ {
251
+ id: "record-id",
252
+ key: "email",
253
+ recordId: "record-id",
254
+ slug: "email",
255
+ label: "Email",
256
+ kind: "email",
257
+ icon: EmailIcon,
258
+ typeLabel: "Email"
259
+ }
260
+ ```
261
+
262
+ Use stable IDs and slugs. Convert HTML labels to plain text, omit records that
263
+ cannot contain answers, and attach the host's icon and type label before passing
264
+ fields to the editor. The nano adds its own system fields for form name,
265
+ submission ID, and submission date.
266
+
267
+ ### Preview record shape
268
+
269
+ Preview records should have an ID, a creation time, and responses whose slugs
270
+ match the editor fields:
271
+
272
+ ```js
273
+ {
274
+ id: "submission-id",
275
+ createdAt: "2026-07-14T10:30:00Z",
276
+ responses: [
277
+ { slug: "email", value: "oliver@example.com" }
278
+ ]
279
+ }
280
+ ```
281
+
282
+ The preview will be blank for a field when its slug has no matching response.
283
+
284
+ ## Email attachment controls
285
+
286
+ `PdfAttachmentSelector` and `PdfAttachmentsPreview` read the top-level
287
+ `pdfDocumentIds` field from Formik. Pass all available PDF documents to both
288
+ components; the preview component filters the selected documents itself.
289
+
290
+ ```jsx
291
+ import {
292
+ PdfAttachmentSelector,
293
+ PdfAttachmentsPreview,
294
+ } from "@bigbinary/neeto-pdf-frontend";
295
+ import { Formik, Form } from "formik";
296
+
297
+ <Formik
298
+ initialValues={{ pdfDocumentIds: persistedPdfDocumentIds }}
299
+ onSubmit={saveEmailSettings}
300
+ >
301
+ <Form>
302
+ <PdfAttachmentSelector documents={pdfDocuments} />
303
+ <PdfAttachmentsPreview documents={pdfDocuments} />
304
+ </Form>
305
+ </Formik>;
306
+ ```
307
+
308
+ In a typical host integration, this value appears in three forms:
309
+
310
+ - Formik uses `pdfDocumentIds`.
311
+ - Frontend API objects use `customFields.pdfDocumentIds`.
312
+ - Rails persistence uses `custom_fields["pdf_document_ids"]`.
313
+
314
+ The host email API must permit an array at `custom_fields[:pdf_document_ids]`.
315
+ Remove IDs for deleted or inaccessible documents before saving email settings.
316
+
317
+ ## Rendering PDFs on the server
318
+
319
+ The renderer knows how to place text on the template, but it does not know how
320
+ the host stores or formats product data. Pass either a callable or an object
321
+ that implements `value_for(mapping)`:
322
+
323
+ ```ruby
324
+ document = form.neeto_pdf_documents.find(document_id)
325
+
326
+ attachment = NeetoPdfEngine::Documents::RendererService.new(
327
+ document,
328
+ value_resolver: ->(mapping) { value_for_submission(mapping, submission) },
329
+ filename_context: { id: submission.id }
330
+ ).process
331
+ ```
332
+
333
+ The result contains the generated filename, MIME type, and raw PDF bytes:
334
+
335
+ ```ruby
336
+ {
337
+ filename: "agreement-123.pdf",
338
+ mime_type: "application/pdf",
339
+ content: "<binary PDF>"
340
+ }
341
+ ```
342
+
343
+ When rendering selected email attachments, always scope document IDs to their
344
+ owner instead of querying IDs globally:
345
+
346
+ ```ruby
347
+ documents = NeetoPdfEngine::Document.where(
348
+ owner_type: "Form",
349
+ owner_id: form.id,
350
+ id: selected_pdf_document_ids
351
+ )
352
+ ```
353
+
354
+ The host mailer decides whether the raw `content` needs Base64 encoding or any
355
+ other transformation.
356
+
357
+ The renderer currently turns whitespace into a single line and supports ASCII
358
+ and Latin-1 text. Values outside that character range are removed, so hosts
359
+ should account for this when deciding which fields can be rendered. Browser
360
+ downloads and server-generated attachments can also differ for some styles;
361
+ underline mappings are currently rendered only by the browser.
362
+
363
+ ## API reference
364
+
365
+ With the engine mounted at `/neeto_pdf`, these endpoints are available:
366
+
367
+ ```text
368
+ GET /neeto_pdf/api/v1/documents
369
+ POST /neeto_pdf/api/v1/documents
370
+ GET /neeto_pdf/api/v1/documents/:id
371
+ PATCH /neeto_pdf/api/v1/documents/:id
372
+ PUT /neeto_pdf/api/v1/documents/:id
373
+ PATCH /neeto_pdf/api/v1/documents/:id/template_file
374
+ POST /neeto_pdf/api/v1/documents/:id/clone
375
+ DELETE /neeto_pdf/api/v1/documents/:id
376
+ ```
377
+
378
+ Every request must include `owner_id`. The engine derives the polymorphic owner
379
+ type from `NeetoPdfEngine.owner_class`; clients cannot choose `owner_type`.
380
+ Member actions are also scoped to that owner.
381
+
382
+ The package UI uploads templates through the host's Active Storage direct upload
383
+ setup and sends the signed blob ID. A custom client may instead send the PDF as
384
+ multipart `FormData` under `template_file`. Do not set multipart boundaries
385
+ manually.
386
+
387
+ When a document is renamed, update both `name` and `output_filename` if the host
388
+ does not expose a separate output filename field. The default filename follows
389
+ this pattern:
390
+
391
+ ```text
392
+ <parameterized-document-name>-{{id}}.pdf
393
+ ```
394
+
395
+ The renderer replaces `{{id}}` with `filename_context[:id]`.
396
+
397
+ ## Local development
398
+
399
+ To use a local checkout of the Rails engine from a neighboring host, point the
400
+ host Gemfile to this repository:
401
+
402
+ ```ruby
403
+ gem "neeto-pdf-engine", path: "../neeto-pdf-nano"
404
+ ```
405
+
406
+ For frontend package development, follow the
407
+ [frontend package development guide](https://neetozone.neetokb.com/p/a-d34cb4b0).
408
+
409
+ ## Publishing
410
+
411
+ Follow the
412
+ [building and releasing packages](https://neetozone.neetokb.com/articles/building-and-releasing-packages)
413
+ guide to publish the gem or frontend package.
@@ -0,0 +1,5 @@
1
+ {
2
+ "neetoWheel": {
3
+ "welcomeScreen": "مرحبًا بك في نيتو ويل نانو"
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "neetoWheel": {
3
+ "welcomeScreen": "Добре дошли в neeto wheel nano"
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "neetoWheel": {
3
+ "welcomeScreen": "Benvingut a neeto wheel nano"
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "neetoWheel": {
3
+ "welcomeScreen": "Vítejte na neeto wheel nano"
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "neetoWheel": {
3
+ "welcomeScreen": "Velkommen til neeto wheel nano"
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "neetoWheel": {
3
+ "welcomeScreen": "Willkommen beim neeto wheel nano"
4
+ }
5
+ }
@@ -0,0 +1,109 @@
1
+ {
2
+ "neetoPdf": {
3
+ "common": {
4
+ "cancel": "Cancel",
5
+ "height": "Height",
6
+ "save": "Save",
7
+ "width": "Width"
8
+ },
9
+ "pdfDocuments": {
10
+ "title": "PDF documents",
11
+ "description": "Upload your own PDF template and drop form answers onto it - one document is generated for every submission.",
12
+ "newDocument": "New document",
13
+ "attachedToEmail": "Attached to email",
14
+ "empty": "Upload a PDF template to get started.",
15
+ "uploadSuccess": "PDF document has been uploaded successfully.",
16
+ "uploadError": "Unable to upload PDF document.",
17
+ "errors": {
18
+ "invalidType": "must be a PDF file",
19
+ "fileTooLarge": "must be 10 MB or smaller"
20
+ },
21
+ "menu": {
22
+ "edit": "Edit",
23
+ "rename": "Rename",
24
+ "updatePdf": "Update PDF",
25
+ "clone": "Clone",
26
+ "delete": "Delete"
27
+ },
28
+ "rename": {
29
+ "title": "Rename document",
30
+ "label": "Name",
31
+ "placeholder": "Enter document name",
32
+ "success": "PDF document has been renamed successfully.",
33
+ "error": "Unable to rename PDF document."
34
+ },
35
+ "updatePdf": {
36
+ "success": "PDF document has been updated successfully.",
37
+ "error": "Unable to update PDF document."
38
+ },
39
+ "clone": {
40
+ "success": "PDF document has been cloned successfully.",
41
+ "error": "Unable to clone PDF document."
42
+ },
43
+ "delete": {
44
+ "title": "Delete PDF document?",
45
+ "message": "You are deleting \"{{name}}\". This can't be undone.",
46
+ "success": "PDF document has been deleted successfully.",
47
+ "error": "Unable to delete PDF document."
48
+ },
49
+ "sendPdfInEmail": {
50
+ "title": "Send PDF in email",
51
+ "description": "Attach the generated PDFs to the email sent on each submission.",
52
+ "submitter": "Send the PDF to the form submitter",
53
+ "notification": "Send the PDF in the notification email"
54
+ },
55
+ "attachments": {
56
+ "title": "Attachments",
57
+ "description": "Attach generated PDF documents to this email.",
58
+ "empty": "Upload a PDF document to attach it to this email.",
59
+ "fileType": "PDF",
60
+ "selected": "{{count}} PDF attached to email",
61
+ "selected_other": "{{count}} PDFs attached to email",
62
+ "previewTitle": "{{count}} attachment",
63
+ "previewTitle_other": "{{count}} attachments"
64
+ },
65
+ "editor": {
66
+ "back": "Back to PDF documents",
67
+ "addNewElement": "Add new element",
68
+ "addNewElementDescription": "To add elements, click or drag them onto the preview.",
69
+ "mapFields": "Map fields",
70
+ "previewWithData": "Preview with data",
71
+ "downloadPdf": "Download PDF",
72
+ "downloadTooltip": "Download this submission as a PDF",
73
+ "downloadHint": "Switch to Preview with data to download",
74
+ "downloadError": "Unable to generate the PDF.",
75
+ "formFields": "Form fields",
76
+ "formFieldsDescription": "Drag a field onto the document, or click + to place it.",
77
+ "searchFields": "Search fields",
78
+ "searchElements": "Search elements",
79
+ "answers": "Answers",
80
+ "system": "System",
81
+ "noFields": "No fields match your search.",
82
+ "addField": "Add to document",
83
+ "renderError": "Unable to render this PDF.",
84
+ "saveSuccess": "Field placements have been saved.",
85
+ "saveError": "Unable to save field placements.",
86
+ "systemFields": {
87
+ "formName": "Form name",
88
+ "submissionId": "Submission ID",
89
+ "submissionDate": "Submission date"
90
+ },
91
+ "field": {
92
+ "title": "Field",
93
+ "emptyTitle": "No field selected",
94
+ "emptyDescription": "Click a placed field on the document to edit its font, size, color and format, or drag its edges to resize.",
95
+ "font": "Font",
96
+ "size": "Size",
97
+ "format": "Format",
98
+ "fontColor": "Font color",
99
+ "alignment": "Alignment",
100
+ "remove": "Remove from document"
101
+ },
102
+ "preview": {
103
+ "counter": "Submission {{page}} of {{total}}",
104
+ "noSubmissions": "No submissions yet"
105
+ }
106
+ }
107
+ }
108
+ }
109
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "neetoWheel": {
3
+ "welcomeScreen": "Bienvenido a neeto wheel nano"
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "neetoWheel": {
3
+ "welcomeScreen": "Bienvenido a neeto wheel nano"
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "neetoWheel": {
3
+ "welcomeScreen": "Tere tulemast neeto ratta nano"
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "neetoWheel": {
3
+ "welcomeScreen": "Tervetuloa neeto wheel nano"
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "neetoWheel": {
3
+ "welcomeScreen": "Maligayang pagdating sa neeto wheel nano"
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "neetoWheel": {
3
+ "welcomeScreen": "Bienvenue dans neeto wheel nano"
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "neetoWheel": {
3
+ "welcomeScreen": "ברוכים הבאים ל-neeto wheel nano"
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "neetoWheel": {
3
+ "welcomeScreen": "नीटो व्हील नैनो में आपका स्वागत है"
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "neetoWheel": {
3
+ "welcomeScreen": "Dobrodošli u neeto wheel nano"
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "neetoWheel": {
3
+ "welcomeScreen": "Üdvözöljük a neeto wheel nano-n"
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "neetoWheel": {
3
+ "welcomeScreen": "Selamat datang di neeto wheel nano"
4
+ }
5
+ }
@@ -0,0 +1,3 @@
1
+ import en from "./en.json";
2
+
3
+ export { en };
@@ -0,0 +1,5 @@
1
+ {
2
+ "neetoWheel": {
3
+ "welcomeScreen": "Benvenuto su neeto wheel nano"
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "neetoWheel": {
3
+ "welcomeScreen": "ネートホイールナノへようこそ"
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "neetoWheel": {
3
+ "welcomeScreen": "네이토 휠 나노에 오신 것을 환영합니다"
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "neetoWheel": {
3
+ "welcomeScreen": "Welkom bij neeto wheel nano"
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "neetoWheel": {
3
+ "welcomeScreen": "Witamy w neeto wheel nano"
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "neetoWheel": {
3
+ "welcomeScreen": "Bem-vindo ao neeto wheel nano"
4
+ }
5
+ }