diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index ae61dc47f..3f8d32150 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -18,6 +18,7 @@
"clsx": "^1.1.1",
"i18next": "^19.4.5",
"i18next-browser-languagedetector": "^6.0.1",
+ "insert-text-at-cursor": "^0.3.0",
"moment": "^2.29.4",
"moment-timezone": "^0.5.35",
"notistack": "^0.9.17",
@@ -8967,6 +8968,11 @@
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
},
+ "node_modules/insert-text-at-cursor": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/insert-text-at-cursor/-/insert-text-at-cursor-0.3.0.tgz",
+ "integrity": "sha512-/nPtyeX9xPUvxZf+r0518B7uqNKlP+LqNJqSiXFEaa2T71rWIwTVXGH7hB9xO/EVdwa5/pWlFCPwShOW81XIxQ=="
+ },
"node_modules/internal-slot": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
@@ -23598,6 +23604,11 @@
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
},
+ "insert-text-at-cursor": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/insert-text-at-cursor/-/insert-text-at-cursor-0.3.0.tgz",
+ "integrity": "sha512-/nPtyeX9xPUvxZf+r0518B7uqNKlP+LqNJqSiXFEaa2T71rWIwTVXGH7hB9xO/EVdwa5/pWlFCPwShOW81XIxQ=="
+ },
"internal-slot": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 97843caa8..1dda17f32 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -13,6 +13,7 @@
"clsx": "^1.1.1",
"i18next": "^19.4.5",
"i18next-browser-languagedetector": "^6.0.1",
+ "insert-text-at-cursor": "^0.3.0",
"moment": "^2.29.4",
"moment-timezone": "^0.5.35",
"notistack": "^0.9.17",
diff --git a/frontend/src/components/jobs/JobEditor.jsx b/frontend/src/components/jobs/JobEditor.jsx
index e3d7ef5d7..14596c41e 100644
--- a/frontend/src/components/jobs/JobEditor.jsx
+++ b/frontend/src/components/jobs/JobEditor.jsx
@@ -48,6 +48,7 @@ import useUserProfile from '../../hooks/useUserProfile';
import JobTestRun from './JobTestRun';
import JobExport from './JobExport';
import useFolder from '../../hooks/useFolder';
+import VariableMenu from '../misc/VariableMenu';
const useStyles = makeStyles((theme) => ({
paper: {
@@ -346,6 +347,10 @@ export default function JobEditor({ match }) {
size='small'
defaultValue={item.value}
onBlur={({target}) => updateHeaderValue(rowNo, target.value)}
+ InputProps={{ endAdornment:
+
+
+ }}
fullWidth />
},
{
@@ -435,6 +440,10 @@ export default function JobEditor({ match }) {
onBlur={({target}) => setJobURL(target.value.trim())}
inputRef={jobURLRef}
InputLabelProps={{shrink: true}}
+ InputProps={{ endAdornment:
+
+
+ }}
fullWidth
required
/>
diff --git a/frontend/src/components/misc/VariableMenu.jsx b/frontend/src/components/misc/VariableMenu.jsx
new file mode 100644
index 000000000..3b23d0abc
--- /dev/null
+++ b/frontend/src/components/misc/VariableMenu.jsx
@@ -0,0 +1,65 @@
+import React, { useRef } from 'react';
+
+import ActionMenu from './ActionMenu';
+import { IconButton } from '@material-ui/core';
+import insertTextAtCursor from 'insert-text-at-cursor';
+import { useTranslation } from 'react-i18next';
+
+import { Config } from '../../utils/Config';
+
+import VariableIcon from '@material-ui/icons/Code';
+import HelpIcon from '@material-ui/icons/HelpOutline';
+
+function getTextField(elem) {
+ while (elem) {
+ elem = elem.parentNode;
+ if (!elem) {
+ break;
+ }
+ const textField = elem.querySelector('input[type=text]');
+ if (textField) {
+ return textField;
+ }
+ }
+ return undefined;
+}
+
+export default function VariableMenu() {
+ const { t } = useTranslation();
+ const buttonRef = useRef();
+
+ const insertVariable = text => {
+ const textField = getTextField(buttonRef.current);
+ if (textField != null) {
+ insertTextAtCursor(textField, text);
+ window.setTimeout(() => textField.focus(), 100);
+ }
+ };
+
+ return }
+ buttonRef={buttonRef}
+ items={[
+ {
+ icon: ,
+ text: '%cjo:unixtime%'
+ },
+ {
+ icon: ,
+ text: '%cjo:uuid4%'
+ },
+ {
+ divider: true
+ },
+ {
+ icon: ,
+ text: t('common.help'),
+ onClick: () => window.open(Config.variablesDocsURL)
+ }
+ ]}
+ onClickItem={item => item.onClick ? item.onClick() : insertVariable(item.text)}
+ text={}
+ />;
+}
diff --git a/frontend/src/locales/de/translation.json b/frontend/src/locales/de/translation.json
index f9d609a96..ac46b7d7f 100644
--- a/frontend/src/locales/de/translation.json
+++ b/frontend/src/locales/de/translation.json
@@ -2,6 +2,7 @@
"paddleLocale": "de",
"landingLocale": "de",
"common": {
+ "help": "Hilfe",
"menu": "Menü",
"contact": "Kontakt",
"followontwitter": "Twitter",
diff --git a/frontend/src/locales/en/translation.json b/frontend/src/locales/en/translation.json
index 35b6d51a0..ed960e00b 100644
--- a/frontend/src/locales/en/translation.json
+++ b/frontend/src/locales/en/translation.json
@@ -2,6 +2,7 @@
"paddleLocale": "en",
"landingLocale": "en",
"common": {
+ "help": "Help",
"menu": "Menu",
"contact": "Contact",
"followontwitter": "Twitter",
diff --git a/frontend/src/locales/fr/translation.json b/frontend/src/locales/fr/translation.json
index 8254f90c6..7eb1e4813 100644
--- a/frontend/src/locales/fr/translation.json
+++ b/frontend/src/locales/fr/translation.json
@@ -1,6 +1,7 @@
{
"paddleLocale": "fr",
"common": {
+ "help": "Aide",
"menu": "Menu",
"followontwitter": "Twitter",
"forkongithub": "GitHub",
diff --git a/frontend/src/locales/it/translation.json b/frontend/src/locales/it/translation.json
index 07ca98584..03622fd3b 100644
--- a/frontend/src/locales/it/translation.json
+++ b/frontend/src/locales/it/translation.json
@@ -1,6 +1,7 @@
{
"paddleLocale": "it",
"common": {
+ "help": "Aiuto",
"menu": "Menu",
"contact": "Contatti",
"followontwitter": "Twitter",
diff --git a/frontend/src/locales/pl/translation.json b/frontend/src/locales/pl/translation.json
index b73f4322e..6c08f7762 100644
--- a/frontend/src/locales/pl/translation.json
+++ b/frontend/src/locales/pl/translation.json
@@ -1,7 +1,8 @@
{
"paddleLocale": "pl",
- "landingLocale": "pl",
+ "landingLocale": "en",
"common": {
+ "help": "Pomoc",
"menu": "Menu",
"contact": "Kontakt",
"followontwitter": "Twitter",
diff --git a/frontend/src/locales/ro/translation.json b/frontend/src/locales/ro/translation.json
index 0210b02e5..03e9daef4 100644
--- a/frontend/src/locales/ro/translation.json
+++ b/frontend/src/locales/ro/translation.json
@@ -1,6 +1,7 @@
{
- "paddleLocale": "ro",
+ "paddleLocale": "en",
"common": {
+ "help": "Ajutor",
"menu": "Meniu",
"contact": "Contact",
"followontwitter": "Twitter",
diff --git a/frontend/src/locales/ru/translation.json b/frontend/src/locales/ru/translation.json
index 43c0a97d1..bc9b4ceb1 100644
--- a/frontend/src/locales/ru/translation.json
+++ b/frontend/src/locales/ru/translation.json
@@ -1,6 +1,7 @@
{
- "paddleLocale": "de",
+ "paddleLocale": "ru",
"common": {
+ "help": "Помощь",
"menu": "Меню",
"followontwitter": "Twitter",
"forkongithub": "GitHub",
diff --git a/frontend/src/locales/zh_TW/translation.json b/frontend/src/locales/zh_TW/translation.json
index 0f58f939d..90d60990a 100644
--- a/frontend/src/locales/zh_TW/translation.json
+++ b/frontend/src/locales/zh_TW/translation.json
@@ -1,5 +1,6 @@
{
"common": {
+ "help": "幫助",
"menu": "選單",
"contact": "聯繫",
"followontwitter": "Twitter",
diff --git a/frontend/src/utils/Config.default.js b/frontend/src/utils/Config.default.js
index 03ab5aa54..e6dd3ec7c 100644
--- a/frontend/src/utils/Config.default.js
+++ b/frontend/src/utils/Config.default.js
@@ -8,6 +8,7 @@ export const Config = {
'termsOfServiceURL': 'https://example.com/tos/',
'returnPolicyURL': 'https://example.com/returnpolicy/',
'apiDocsURL': 'https://example.com/docs/rest-api.html',
+ 'variablesDocsURL': 'https://example.com/creating-cron-jobs.html#cron-job-variables',
//! @note The URL of the API webserver (/api/ folder in this repo)
'apiURL': 'https://api.example.com/',