diff --git a/dist/i18n/en/functions.json b/dist/i18n/en/functions.json index 6e031c322..7cee48c99 100644 --- a/dist/i18n/en/functions.json +++ b/dist/i18n/en/functions.json @@ -53,6 +53,7 @@ "CREATE_NEW_HEADER": "Create a new header", "CREATE_NEW_HOST": "Create a new host", "CREATE_NEW_LABEL": "Create a new label", + "CREATE_NEW_NODE_SELECTOR": "Create a new node selector", "CREATE_NEW_RUNTIME_ATTRIBUTE": "Create a new runtime attribute", "CREATE_NEW_SUBSCRIPTION": "Create a new subscription", "CREATE_NEW_TRIGGER": "Create a new trigger", @@ -175,6 +176,7 @@ "NO_FUNCTIONS_AVAILABLE": "No functions available", "NO_INTERNET_ACCESS": "No internet access", "NO_LOGS_HAVE_BEEN_FOUND": "No logs have been found...", + "NODE_SELECTORS": "Node selectors", "NORMAL": "Normal", "NOT_START_WITH_FORBIDDEN_WORDS": "Must not start with 'kubernetes.io', 'k8s.io' or 'nuclio.io'", "NOT_YET_DEPLOYED": "Not yet deployed", diff --git a/dist/js/iguazio.dashboard-controls.js b/dist/js/iguazio.dashboard-controls.js index 6c04b54d3..ba1500ab0 100644 --- a/dist/js/iguazio.dashboard-controls.js +++ b/dist/js/iguazio.dashboard-controls.js @@ -4266,129 +4266,24 @@ angular.module('angular-i18next', []).provider('i18next', [function () { (function () { 'use strict'; - /** - * @name igzAutoComplete - * @component - * - * @description - * An input field that wraps around `igzValidatingInputField` component and enriches it with auto-complete feature. - * The user enters input to the input field, and a suggestion drop-down menu is open according to the input value. - * An optional filter drop-down field is available to make it possible to populate the suggestion list according - * to different criteria, for example different properties of objects like first name or last name of person. - * The user can click on a suggestion from the menu to select it. - * - * @param {string} bordersMode - Forwarded to `bordersMode` attribute of `igzValidatingInputField` component. Please - * see that component's docs for more details (which also indicates its default value). - * @param {string} [browserAutoComplete='off'] - Forwarded to `autoComplete` attribute of `igzValidatingInputField`. - * Please see that component's docs for more details. Defaults to `'off'` because usually it is desired to - * cancel the built-in auto-completion feature of the web browser when using this component. - * @param {string} currentValue - The initial value to populate the input field on initialization. - * @param {Array} filterBy - A list of filter criteria. Each item will be rendered as an option in the filters - * drop-down menu. - * @param {string} filterBy[].label - The label of the drop-down menu option. - * @param {string} filterBy[].attribute - The value of the drop-down menu option that will be sent when invoking - * `onSuggestionSelected` for the parent component to use when compiling the list of suggestions. - * @param {string} [emptyMessage] - Optionally display a message when suggestion list is empty. - * @param {Object} formObject - The `
` element or `` directive containing this component. It will be - * forwarded to the `formObject` attribute of the `igzValidatingInputField` component. - * @param {string} inputName - The name of the filed, will be forwarded to the `inputName` attribute of the - * `igzValidatingInputField` component. - * @param {boolean} [isDisabled=false] - Set to `true` to make this field disabled. Forwarded to `isDisabled` - * attribute of the `igzValidatingInputField` component. - * @param {boolean} [isFocused=false] - Set to `true` to give focus to this field once it finished initializing. - * Forwarded to `isFocused` attribute of the `igzValidatingInputField` component. - * @param {boolean} [isRequired=false] - Set to `true` to make this field mandatory. The field will be invalid if it - * is empty. Forwarded to `validationIsRequired` attribute of the `igzValidatingInputField` component. - * @param {string} [noMatchPolicy='allow'] - Determines the behavior when the selected suggestion value or the value - * on blur does not match any suggestion on the current suggestion list. Could be one of: - * - `'allow'` (default): Allows the input value. The input field will be valid. - * - `'invalid'`: The input field will be invalid. The input will remain unchanged. - * - `'revert'`: Reverts the input field value bacl to the last valid value. The input field will be valid. - * @param {function} [onBlur] - A callback function for `blur` event. Invoked with `inputValue` and `inputName` when - * the field loses focus (if the focus moves from the input field to the suggestion menu - this function will - * _not_ be invoked). - * @param {function} [onEmptyData] - A callback function for the case when input is empty and `suggestionsOnEmpty` - * is false. Invoked without any argument. - * @param {function} [onTextChanged] - A callback function for changed text on losing focus. If it returns a - * rejected promise - it would tell this component the value is invalid. - * @param {function} [onSuggestionSelected] - A callback function for selecting suggestion from suggestion menu. - * If it returns a rejected promise - it would tell this component the value is invalid. - * @param {function} [onRequestSuggestions] - A callback function for retrieving suggestion list when input field - * value changes. It is invoked with: - * - `input`: The current input field's value - * - `filter`: The `attribute` property of the item in `filterBy` array that is corresponding to the selected - * option of the filter drop-down menu. - * - `inputName`: The name of the input field. - * @param {boolean} [suggestionsOnEmpty=true] - Set to `false` in order to prevent invoking `onRequestSuggestions` - * when input value changed and is now empty, and invoke `onEmptyData` instead. Default is `true` which will - * invoke `onRequestSuggestions` when input value is empty. - * @param {string} [placeholder] - Placeholder text to display when input is empty. Forwarded to `placeholderText` - * attribute of the `igzValidatingInputField` component. - * @param {Object} [tooltip] - Allows a tooltip hint to open when hovering the input field. This is useful for not - * setting a tooltip on the entire `` component, which includes the suggestion list too, and it - * is not desired to show the tooltip when hovering on the suggestion list, but only when hovering the input - * field itself. - */ - - IgzAutoCompleteController.$inject = ['$document', '$element', '$i18next', '$q', 'i18next', 'lodash', 'EventHelperService']; - angular.module('iguazio.dashboard-controls').component('igzAutoComplete', { + IgzCopyToClipboard.$inject = ['$i18next', 'i18next', 'lodash', 'DialogsService']; + angular.module('iguazio.dashboard-controls').component('igzCopyToClipboard', { bindings: { - bordersMode: '@?', - browserAutoComplete: '@?', - currentValue: ') - ignore the blur - // otherwise ... - if (shouldHandleBlur(focusedElement)) { - // if the input value matches one of the auto-complete suggestions, or is equal to the last valid - // value, or the no-match policy is set to `allow` - ctrl.currentValue = value; - var inputMatchSomeSuggestion = lodash.some(ctrl.suggestions, ['value', value]); - if (value === lastValidValue || inputMatchSomeSuggestion || selectedNoMatchPolicy === NO_MATCH_POLICIES.ALLOW) { - // notify parent component as-if this suggestion was selected and set input field valid - ctrl.formObject[ctrl.inputName].$setValidity('noMatch', true); - if (value !== lastValidValue) { - attemptToUpdateValue(value, ctrl.onTextChanged); - } - } else if (selectedNoMatchPolicy === NO_MATCH_POLICIES.INVALID) { - // if there is no match and no-match policy is set to `invalid` - set input field as invalid - // but keep entered input - ctrl.formObject[ctrl.inputName].$setValidity('noMatch', false); - } else if (selectedNoMatchPolicy === NO_MATCH_POLICIES.REVERT) { - // if there is no match and no-match policy is set to `revert` - revert view value back to last - // value provided to `ctrl.currentValue` by parent component - ctrl.formObject[ctrl.inputName].$setValidity('noMatch', true); - ctrl.currentValue = lastValidValue; - } else { - // should never reach here - throw Error('Invalid value for `no-match-policy` in `igzAutoComplete`'); - } - - // close the auto-complete suggestion drop-down menu and invoke parent's `onBlur` handler - ctrl.isSuggestionsShown = false; - ctrl.suggestions = []; - ctrl.onBlur({ inputValue: value, inputName: name }); - } - }); - } - - /** - * Handles the model change of the input field. - * @param {string} value - The new value of the input field. - */ - function handleInputChange(value) { - ctrl.currentValue = value; - if (!ctrl.suggestionsOnEmpty && lodash.isEmpty(value)) { - ctrl.onEmptyData(); - return; - } - - // request parent component for the suggestion list according to input value - // ("promisify" the result, so the parent component could return either a promise or not) - ctrl.loading = true; - ctrl.isSuggestionsShown = true; - var result = $q.when(ctrl.onRequestSuggestions({ - input: value, - filter: ctrl.selectedFilter.id, - inputName: ctrl.inputName - })); - result.then(function (response) { - ctrl.suggestions = response.suggestions; - ctrl.isMoreLabelShown = response.more; - }).finally(function () { - ctrl.loading = false; - if (lodash.isEmpty(ctrl.suggestions) && lodash.isEmpty(ctrl.emptyMessage)) { - ctrl.isSuggestionsShown = false; - } - }); - } - - /** - * Handles click on a suggestion from the auto-complete suggestion drop-down menu. - * @param {Object} value - The value of the selected suggestion. - */ - function handleSuggestionClick(value) { - attemptToUpdateValue(value, ctrl.onSuggestionSelected); - - ctrl.isSuggestionsShown = false; - ctrl.suggestions = []; - } - - /** - * Handles pressing down a key on the an auto-complete suggestion. - * @param {KeyboardEvent} event - The event. - * @param {Object} item - The current item. - */ - function handleSuggestionKeydown(event, item) { - var dropdownField = $element.find('.input-row').first(); - - switch (event.keyCode) { - case EventHelperService.UP: - if (!lodash.isNull(event.target.previousElementSibling)) { - event.target.previousElementSibling.focus(); - event.stopPropagation(); - } - break; - case EventHelperService.DOWN: - if (!lodash.isNull(event.target.nextElementSibling)) { - event.target.nextElementSibling.focus(); - event.stopPropagation(); - } - break; - case EventHelperService.SPACE: - case EventHelperService.ENTER: - dropdownField.focus(); - ctrl.handleSuggestionClick(item.value); - break; - default: - // ignore any other keystroke - break; - } - - event.preventDefault(); - event.stopPropagation(); - } - - // - // Private methods - // - - /** - * Attempts to update the field's value to `value` by notifying parent via invoking `method`. - * If it returns a resolved promise the field will be rendered invalid. - * Otherwise, if a rejected promise is returned, the field will be rendered invalid in case the `invalid` - * no-match policy is used, or reverted to the last valid value in case the `revert` no-match policy is used. - * @param {*} value - The value to update to. - * @param {function} method - The method to invoke to notify parent with `value`. - */ - function attemptToUpdateValue(value, method) { - var result = $q.when(method({ value: value, inputName: ctrl.inputName })); - result.then(function () { - ctrl.formObject[ctrl.inputName].$setValidity('noMatch', true); - lastValidValue = value; - - // dear future me (or any other developer) - // in case no-match policy is 'invalid' and the component is required and the next flow is executed: - // 1. box is empty - // 2. the user enters 'foo' and selects 'foobar' option from suggestion list - // 3. the user empties the box, which makes the field invalid (because required but empty+dirty) - // 4. the user enters 'fo' and selects 'foobar' option from suggestion list (again) - // without the next line, the box will have 'fo' instead of 'foobar' - ctrl.currentValue = value; - }).catch(function () { - if (selectedNoMatchPolicy === NO_MATCH_POLICIES.INVALID) { - // if there is no match and no-match policy is set to `invalid` - set input field as invalid - // but keep entered input - ctrl.formObject[ctrl.inputName].$setValidity('noMatch', false); - } else if (selectedNoMatchPolicy === NO_MATCH_POLICIES.REVERT) { - // if there is no match and no-match policy is set to `revert` - revert view value back to last - // valid value - ctrl.formObject[ctrl.inputName].$setValidity('noMatch', true); - ctrl.currentValue = lastValidValue; - } else { - // should never reach here - throw Error('Invalid value for `no-match-policy` in `igzAutoComplete`'); - } - }); - } - - /** - * Initializes auto-complete filters object. - */ - function initFiltersDropdown() { - ctrl.filters = lodash.map(ctrl.filterBy, function (filter) { - return { - id: filter.attribute, - name: filter.label - }; - }); - - ctrl.selectedFilter = lodash.head(ctrl.filters); - } - - /** - * Handles mouse click on document. - * @param {MouseEvent} event - The event. - */ - function onDocumentClick(event) { - // if the auto-complete suggestion drop-down menu is open and the user clicks outside of this auto-complete - // element - close the menu - if (ctrl.isSuggestionsShown) { - if ($element.find(event.target).length === 0) { - ctrl.isSuggestionsShown = false; - } - } - } - - /** - * Determines whether the input field should handle blur event according to the focused element. - * @param {HTMLElement} focusedElement - The element receiving focus. - * @returns {boolean} `true` in case the input field should handle blur event, or `false` otherwise. - */ - function shouldHandleBlur(focusedElement) { - return angular.element(focusedElement).is('.list-item.readonly') || $element.find(focusedElement).length === 0 && $document.find(focusedElement).length > 0; - } - } -})(); -'use strict'; - -(function () { - 'use strict'; - - IgzCopyToClipboard.$inject = ['$i18next', 'i18next', 'lodash', 'DialogsService']; - angular.module('iguazio.dashboard-controls').component('igzCopyToClipboard', { - bindings: { - tooltipPlacement: '@?', - tooltipText: '@?', - value: '<' - }, - templateUrl: 'igz_controls/components/copy-to-clipboard/copy-to-clipboard.tpl.html', - controller: IgzCopyToClipboard - }); - - function IgzCopyToClipboard($i18next, i18next, lodash, DialogsService) { - var ctrl = this; - var lng = i18next.language; - - ctrl.$onInit = onInit; - - ctrl.copyToClipboard = copyToClipboard; - - // - // Hook methods - // - - /** - * Initialization method - */ - function onInit() { - lodash.defaults(ctrl, { - tooltipPlacement: 'top' - }); - } - - // - // Public method - // - - /** - * Copies a string to the clipboard. - */ - function copyToClipboard() { - if (document.queryCommandSupported && document.queryCommandSupported('copy')) { - var textarea = document.createElement('textarea'); - textarea.textContent = ctrl.value; - textarea.style.position = 'fixed'; - document.body.appendChild(textarea); - textarea.select(); - - try { - return document.execCommand('copy'); // Security exception may be thrown by some browsers. - } catch (ex) { - DialogsService.alert($i18next.t('common:COPY_TO_CLIPBOARD_FAILED', { lng: lng }), ex); - } finally { - document.body.removeChild(textarea); - } - } - } - } -})(); -'use strict'; + } +})(); +'use strict'; /* eslint max-statements: ["error", 100] */ /* eslint complexity: ["error", 12] */ @@ -5451,37 +5007,129 @@ angular.module('angular-i18next', []).provider('i18next', [function () { (function () { 'use strict'; - IgzElementLoadingStatusController.$inject = ['$element', '$scope', '$state', '$timeout', '$i18next', 'i18next', 'lodash']; - angular.module('iguazio.dashboard-controls').component('igzElementLoadingStatus', { - bindings: { - errorMessage: '@?', - loadingStatusSize: '@?', - name: '@', - refresh: '` element or `` directive containing this component. It will be + * forwarded to the `formObject` attribute of the `igzValidatingInputField` component. + * @param {string} inputName - The name of the filed, will be forwarded to the `inputName` attribute of the + * `igzValidatingInputField` component. + * @param {boolean} [isDisabled=false] - Set to `true` to make this field disabled. Forwarded to `isDisabled` + * attribute of the `igzValidatingInputField` component. + * @param {boolean} [isFocused=false] - Set to `true` to give focus to this field once it finished initializing. + * Forwarded to `isFocused` attribute of the `igzValidatingInputField` component. + * @param {boolean} [isRequired=false] - Set to `true` to make this field mandatory. The field will be invalid if it + * is empty. Forwarded to `validationIsRequired` attribute of the `igzValidatingInputField` component. + * @param {string} [noMatchPolicy='allow'] - Determines the behavior when the selected suggestion value or the value + * on blur does not match any suggestion on the current suggestion list. Could be one of: + * - `'allow'` (default): Allows the input value. The input field will be valid. + * - `'invalid'`: The input field will be invalid. The input will remain unchanged. + * - `'revert'`: Reverts the input field value bacl to the last valid value. The input field will be valid. + * @param {function} [onBlur] - A callback function for `blur` event. Invoked with `inputValue` and `inputName` when + * the field loses focus (if the focus moves from the input field to the suggestion menu - this function will + * _not_ be invoked). + * @param {function} [onEmptyData] - A callback function for the case when input is empty and `suggestionsOnEmpty` + * is false. Invoked without any argument. + * @param {function} [onTextChanged] - A callback function for changed text on losing focus. If it returns a + * rejected promise - it would tell this component the value is invalid. + * @param {function} [onSuggestionSelected] - A callback function for selecting suggestion from suggestion menu. + * If it returns a rejected promise - it would tell this component the value is invalid. + * @param {function} [onRequestSuggestions] - A callback function for retrieving suggestion list when input field + * value changes. It is invoked with: + * - `input`: The current input field's value + * - `filter`: The `attribute` property of the item in `filterBy` array that is corresponding to the selected + * option of the filter drop-down menu. + * - `inputName`: The name of the input field. + * @param {boolean} [suggestionsOnEmpty=true] - Set to `false` in order to prevent invoking `onRequestSuggestions` + * when input value changed and is now empty, and invoke `onEmptyData` instead. Default is `true` which will + * invoke `onRequestSuggestions` when input value is empty. + * @param {string} [placeholder] - Placeholder text to display when input is empty. Forwarded to `placeholderText` + * attribute of the `igzValidatingInputField` component. + * @param {Object} [tooltip] - Allows a tooltip hint to open when hovering the input field. This is useful for not + * setting a tooltip on the entire `` component, which includes the suggestion list too, and it + * is not desired to show the tooltip when hovering on the suggestion list, but only when hovering the input + * field itself. + */ + + IgzAutoCompleteController.$inject = ['$document', '$element', '$i18next', '$q', 'i18next', 'lodash', 'EventHelperService']; + angular.module('iguazio.dashboard-controls').component('igzAutoComplete', { + bindings: { + bordersMode: '@?', + browserAutoComplete: '@?', + currentValue: ' 0 ? $element.height() : defaultHeight; - var elementParentHeight = $element.parent().height() > 0 ? $element.parent().height() : defaultHeight; - - if (ctrl.isShowSpinner) { - $element.find('.loader-wrapper').height(elementParentHeight || elementHeight); - $element.find('.loader-wrapper').addClass('appeared'); - } + function handleInputBlur(event, value, name) { + EventHelperService.getFocusedElement(event).then(function (focusedElement) { + // if the element receiving focus is still within this component () - ignore the blur + // otherwise ... + if (shouldHandleBlur(focusedElement)) { + // if the input value matches one of the auto-complete suggestions, or is equal to the last valid + // value, or the no-match policy is set to `allow` + ctrl.currentValue = value; + var inputMatchSomeSuggestion = lodash.some(ctrl.suggestions, ['value', value]); + if (value === lastValidValue || inputMatchSomeSuggestion || selectedNoMatchPolicy === NO_MATCH_POLICIES.ALLOW) { + // notify parent component as-if this suggestion was selected and set input field valid + ctrl.formObject[ctrl.inputName].$setValidity('noMatch', true); + if (value !== lastValidValue) { + attemptToUpdateValue(value, ctrl.onTextChanged); + } + } else if (selectedNoMatchPolicy === NO_MATCH_POLICIES.INVALID) { + // if there is no match and no-match policy is set to `invalid` - set input field as invalid + // but keep entered input + ctrl.formObject[ctrl.inputName].$setValidity('noMatch', false); + } else if (selectedNoMatchPolicy === NO_MATCH_POLICIES.REVERT) { + // if there is no match and no-match policy is set to `revert` - revert view value back to last + // value provided to `ctrl.currentValue` by parent component + ctrl.formObject[ctrl.inputName].$setValidity('noMatch', true); + ctrl.currentValue = lastValidValue; + } else { + // should never reach here + throw Error('Invalid value for `no-match-policy` in `igzAutoComplete`'); + } - if (ctrl.isShowError) { - $element.find('.loading-error').height(elementHeight || elementParentHeight); - $element.find('.loading-error').addClass('appeared'); + // close the auto-complete suggestion drop-down menu and invoke parent's `onBlur` handler + ctrl.isSuggestionsShown = false; + ctrl.suggestions = []; + ctrl.onBlur({ inputValue: value, inputName: name }); + } + }); + } + + /** + * Handles the model change of the input field. + * @param {string} value - The new value of the input field. + */ + function handleInputChange(value) { + ctrl.currentValue = value; + if (!ctrl.suggestionsOnEmpty && lodash.isEmpty(value)) { + ctrl.onEmptyData(); + return; + } + + // request parent component for the suggestion list according to input value + // ("promisify" the result, so the parent component could return either a promise or not) + ctrl.loading = true; + ctrl.isSuggestionsShown = true; + var result = $q.when(ctrl.onRequestSuggestions({ + input: value, + filter: ctrl.selectedFilter.id, + inputName: ctrl.inputName + })); + result.then(function (response) { + ctrl.suggestions = response.suggestions; + ctrl.isMoreLabelShown = response.more; + }).finally(function () { + ctrl.loading = false; + if (lodash.isEmpty(ctrl.suggestions) && lodash.isEmpty(ctrl.emptyMessage)) { + ctrl.isSuggestionsShown = false; } }); } + /** + * Handles click on a suggestion from the auto-complete suggestion drop-down menu. + * @param {Object} value - The value of the selected suggestion. + */ + function handleSuggestionClick(value) { + attemptToUpdateValue(value, ctrl.onSuggestionSelected); + + ctrl.isSuggestionsShown = false; + ctrl.suggestions = []; + } + + /** + * Handles pressing down a key on the an auto-complete suggestion. + * @param {KeyboardEvent} event - The event. + * @param {Object} item - The current item. + */ + function handleSuggestionKeydown(event, item) { + var dropdownField = $element.find('.input-row').first(); + + switch (event.keyCode) { + case EventHelperService.UP: + if (!lodash.isNull(event.target.previousElementSibling)) { + event.target.previousElementSibling.focus(); + event.stopPropagation(); + } + break; + case EventHelperService.DOWN: + if (!lodash.isNull(event.target.nextElementSibling)) { + event.target.nextElementSibling.focus(); + event.stopPropagation(); + } + break; + case EventHelperService.SPACE: + case EventHelperService.ENTER: + dropdownField.focus(); + ctrl.handleSuggestionClick(item.value); + break; + default: + // ignore any other keystroke + break; + } + + event.preventDefault(); + event.stopPropagation(); + } + // // Private methods // /** - * Show given loading spinner - * @param {Object} ev - angular event object - * @param {Object} args - arguments passed from $broadcast + * Attempts to update the field's value to `value` by notifying parent via invoking `method`. + * If it returns a resolved promise the field will be rendered invalid. + * Otherwise, if a rejected promise is returned, the field will be rendered invalid in case the `invalid` + * no-match policy is used, or reverted to the last valid value in case the `revert` no-match policy is used. + * @param {*} value - The value to update to. + * @param {function} method - The method to invoke to notify parent with `value`. */ - function showSpinner(ev, args) { - if (args.name === ctrl.name) { - ctrl.isShowError = false; - ctrl.isShowContent = false; - ctrl.isShowSpinner = true; - ctrl.setWrapperHeight(); - } + function attemptToUpdateValue(value, method) { + var result = $q.when(method({ value: value, inputName: ctrl.inputName })); + result.then(function () { + ctrl.formObject[ctrl.inputName].$setValidity('noMatch', true); + lastValidValue = value; + + // dear future me (or any other developer) + // in case no-match policy is 'invalid' and the component is required and the next flow is executed: + // 1. box is empty + // 2. the user enters 'foo' and selects 'foobar' option from suggestion list + // 3. the user empties the box, which makes the field invalid (because required but empty+dirty) + // 4. the user enters 'fo' and selects 'foobar' option from suggestion list (again) + // without the next line, the box will have 'fo' instead of 'foobar' + ctrl.currentValue = value; + }).catch(function () { + if (selectedNoMatchPolicy === NO_MATCH_POLICIES.INVALID) { + // if there is no match and no-match policy is set to `invalid` - set input field as invalid + // but keep entered input + ctrl.formObject[ctrl.inputName].$setValidity('noMatch', false); + } else if (selectedNoMatchPolicy === NO_MATCH_POLICIES.REVERT) { + // if there is no match and no-match policy is set to `revert` - revert view value back to last + // valid value + ctrl.formObject[ctrl.inputName].$setValidity('noMatch', true); + ctrl.currentValue = lastValidValue; + } else { + // should never reach here + throw Error('Invalid value for `no-match-policy` in `igzAutoComplete`'); + } + }); } /** - * Hide given loading spinner - * @param {Object} ev - angular event object - * @param {Object} args - arguments passed from $broadcast + * Initializes auto-complete filters object. */ - function hideSpinner(ev, args) { - if (args.name === ctrl.name) { - ctrl.isShowSpinner = false; - $timeout(function () { - ctrl.isShowContent = true; - }, 2); - } + function initFiltersDropdown() { + ctrl.filters = lodash.map(ctrl.filterBy, function (filter) { + return { + id: filter.attribute, + name: filter.label + }; + }); + + ctrl.selectedFilter = lodash.head(ctrl.filters); } /** - * Show given loading error - * @param {Object} ev - angular event object - * @param {Object} args - arguments passed from $broadcast + * Handles mouse click on document. + * @param {MouseEvent} event - The event. */ - function showError(ev, args) { - if (args.name === ctrl.name) { - ctrl.isShowError = true; - ctrl.isShowSpinner = false; - ctrl.setWrapperHeight(); + function onDocumentClick(event) { + // if the auto-complete suggestion drop-down menu is open and the user clicks outside of this auto-complete + // element - close the menu + if (ctrl.isSuggestionsShown) { + if ($element.find(event.target).length === 0) { + ctrl.isSuggestionsShown = false; + } } } /** - * Hide given loading error - * @param {Object} ev - angular event object - * @param {Object} args - arguments passed from $broadcast + * Determines whether the input field should handle blur event according to the focused element. + * @param {HTMLElement} focusedElement - The element receiving focus. + * @returns {boolean} `true` in case the input field should handle blur event, or `false` otherwise. */ - function hideError(ev, args) { - if (args.name === ctrl.name) { - ctrl.isShowError = false; - } + function shouldHandleBlur(focusedElement) { + return angular.element(focusedElement).is('.list-item.readonly') || $element.find(focusedElement).length === 0 && $document.find(focusedElement).length > 0; } } })(); @@ -5633,42 +5451,37 @@ angular.module('angular-i18next', []).provider('i18next', [function () { (function () { 'use strict'; - IgzImportProjectDialogController.$inject = ['$scope', '$i18next', 'i18next', 'lodash']; - angular.module('iguazio.dashboard-controls').component('igzImportProjectDialog', { + IgzElementLoadingStatusController.$inject = ['$element', '$scope', '$state', '$timeout', '$i18next', 'i18next', 'lodash']; + angular.module('iguazio.dashboard-controls').component('igzElementLoadingStatus', { bindings: { - closeDialog: '&', - dialogTitle: '<', - displayAllOptions: '<' + errorMessage: '@?', + loadingStatusSize: '@?', + name: '@', + refresh: ' 0 ? $element.height() : defaultHeight; + var elementParentHeight = $element.parent().height() > 0 ? $element.parent().height() : defaultHeight; + + if (ctrl.isShowSpinner) { + $element.find('.loader-wrapper').height(elementParentHeight || elementHeight); + $element.find('.loader-wrapper').addClass('appeared'); + } + + if (ctrl.isShowError) { + $element.find('.loading-error').height(elementHeight || elementParentHeight); + $element.find('.loading-error').addClass('appeared'); + } + }); + } + + // + // Private methods + // + + /** + * Show given loading spinner + * @param {Object} ev - angular event object + * @param {Object} args - arguments passed from $broadcast + */ + function showSpinner(ev, args) { + if (args.name === ctrl.name) { + ctrl.isShowError = false; + ctrl.isShowContent = false; + ctrl.isShowSpinner = true; + ctrl.setWrapperHeight(); + } + } + + /** + * Hide given loading spinner + * @param {Object} ev - angular event object + * @param {Object} args - arguments passed from $broadcast + */ + function hideSpinner(ev, args) { + if (args.name === ctrl.name) { + ctrl.isShowSpinner = false; + $timeout(function () { + ctrl.isShowContent = true; + }, 2); + } + } + + /** + * Show given loading error + * @param {Object} ev - angular event object + * @param {Object} args - arguments passed from $broadcast + */ + function showError(ev, args) { + if (args.name === ctrl.name) { + ctrl.isShowError = true; + ctrl.isShowSpinner = false; + ctrl.setWrapperHeight(); + } + } + + /** + * Hide given loading error + * @param {Object} ev - angular event object + * @param {Object} args - arguments passed from $broadcast + */ + function hideError(ev, args) { + if (args.name === ctrl.name) { + ctrl.isShowError = false; + } + } + } +})(); +'use strict'; + +(function () { + 'use strict'; + + IgzImportProjectDialogController.$inject = ['$scope', '$i18next', 'i18next', 'lodash']; + angular.module('iguazio.dashboard-controls').component('igzImportProjectDialog', { + bindings: { + closeDialog: '&', + dialogTitle: '<', + displayAllOptions: '<' + }, + templateUrl: 'igz_controls/components/import-project-dialog/import-project-dialog.tpl.html', + controller: IgzImportProjectDialogController + }); + + function IgzImportProjectDialogController($scope, $i18next, i18next, lodash) { + var ctrl = this; + var lng = i18next.language; + + var checkedItem = 'singleFunction'; + + ctrl.option = []; + ctrl.optionList = [{ + label: $i18next.t('common:APPLY_TO_ALL_FUNCTIONS_IN_THIS_PROJECT', { lng: lng }), + id: 'singleProject', + value: 'singleProject', + disabled: false, + visibility: true + }, { + label: $i18next.t('common:APPLY_TO_ALL_FUNCTIONS_IN_ALL_PROJECT', { lng: lng }), + id: 'allProjects', + value: 'allProjects', + disabled: false, + visibility: true + }]; + + ctrl.$onInit = onInit; + + ctrl.onClose = onClose; + ctrl.onCheckboxChange = onCheckboxChange; + + // + // Hook methods + // + + /** + * Initialization method + */ + function onInit() { + lodash.set(ctrl.optionList, '[1].visibility', ctrl.displayAllOptions); + } + // // Public methods // @@ -7059,256 +7059,153 @@ angular.module('angular-i18next', []).provider('i18next', [function () { (function () { 'use strict'; - SearchHelperService.$inject = ['lodash']; - angular.module('iguazio.dashboard-controls').factory('SearchHelperService', SearchHelperService); + IgzPaginationController.$inject = ['$scope', '$timeout', 'lodash', 'EventHelperService', 'LocalStorageService', 'PaginationService']; + angular.module('iguazio.dashboard-controls').component('igzPagination', { + bindings: { + allowJumpToPage: '} data - array of data - * @param {Array.} pathsForSearchArray - array of keys in which search will be made - * @param {boolean} isHierarchical - flag which indicates if passed data has hierarchical structure - * @param {string} ruleType - string representing the type of rule resource - * @param {Object} searchStates - * @param {string} [multiSearchName] - unique name of the search input - */ - function makeSearch(searchQuery, data, pathsForSearchArray, isHierarchical, ruleType, searchStates, multiSearchName) { - searchStates.searchNotFound = false; - searchStates.searchInProgress = false; + ctrl.$onInit = onInit; - if (isHierarchical) { - data = data.ui.children; - } else { - ruleType = ''; - } - if (searchQuery === '') { - showAllChildren(data, multiSearchName); - } else if (angular.isString(searchQuery)) { - searchStates.searchNotFound = true; - searchStates.searchInProgress = true; - findBySearchQuery(searchQuery, data, pathsForSearchArray, isHierarchical, ruleType, searchStates, multiSearchName); - } - } + ctrl.inputValueCallback = inputValueCallback; + ctrl.jumpToPage = jumpToPage; + ctrl.onPerPageChanged = onPerPageChanged; + ctrl.goToNextPage = goToNextPage; + ctrl.goToPage = goToPage; + ctrl.goToPrevPage = goToPrevPage; // - // Private methods + // Hook methods // /** - * Loop through all given data to show/hide them depending on query match criteria (recursively) - * @param {string} searchQuery - text query entered to a search input - * @param {Array.} children - array of child data - * @param {Array.} pathsForSearch - array of strings, representing data's properties keys to search from - * @param {boolean} isHierarchical - flag which indicates if passed data has hierarchical structure - * @param {string} ruleType - string representing the type of rule resource - * @param {Object} searchStates - * @param {string} [multiSearchName] - unique name of the search input + * Constructor */ - function findBySearchQuery(searchQuery, children, pathsForSearch, isHierarchical, ruleType, searchStates, multiSearchName) { - angular.forEach(children, function (child) { - // Search by text in data without children data only - if (angular.isString(child.type) && child.type !== ruleType && isHierarchical) { - // Hide all parent data while search among children and proceed recursively - child.ui.isFitQuery = false; - findBySearchQuery(searchQuery, child.ui.children, pathsForSearch, isHierarchical, ruleType, searchStates, multiSearchName); - } else { - showRelevantItem(searchQuery, child, pathsForSearch, searchStates, multiSearchName); - } + function onInit() { + lodash.defaults(ctrl, { + allowJumpToPage: true }); - } - /** - * Get all current item's properties string values and push to stringValuesArray (recursively) - * @param {string} itemPropertyValue - item's attribute value - * @param {Array} stringValuesArray - array to collect current item's all properties string values - */ - function getStringValuesFromItem(itemPropertyValue, stringValuesArray) { - if (angular.isObject(itemPropertyValue)) { - angular.forEach(itemPropertyValue, function (value) { - getStringValuesFromItem(value, stringValuesArray); - }); - } else if (angular.isString(itemPropertyValue) && itemPropertyValue.length > 0 || angular.isNumber(itemPropertyValue)) { - stringValuesArray.push(itemPropertyValue.toString()); + if (angular.isUndefined(ctrl.perPageValues)) { + ctrl.perPageValues = PaginationService.perPageDefaults(); } - return stringValuesArray; + ctrl.perPage = lodash.some(ctrl.perPageValues, 'id', ctrl.pageData.size) ? ctrl.pageData.size : ctrl.perPageValues[0].id; + + $scope.$watch('$ctrl.pageData.total', initValues); + $scope.$watch('$ctrl.pageData.number', updatePage); } + // + // Public methods + // + /** - * Sets isFitQuery value for data item - * @param {Object} dataItem - current item - * @param {string} [multiSearchName] - unique name of the search input - * @param {boolean} isFitQuery - `true` if item is matched with search query + * Update data callback + * @param {string} newData + * @param {string} field */ - function setFitQueryValue(dataItem, multiSearchName, isFitQuery) { - var filterPath = lodash.isEmpty(multiSearchName) ? 'isFitQuery' : ['filters', multiSearchName, 'isFitQuery']; - - lodash.set(dataItem.ui, filterPath, isFitQuery); + function inputValueCallback(newData, field) { + ctrl.jumpPage = newData; } /** - * Show all data item's children chain (recursively) - * @param {Array.} data - child items - * @param {string} [multiSearchName] - unique name of the search input + * Method to jump to page */ - function showAllChildren(data, multiSearchName) { - angular.forEach(data, function (value) { - var children = value.ui.children; - - setFitQueryValue(value, multiSearchName, true); + function jumpToPage() { + $timeout(function () { + ctrl.jumpPage = parseInt(ctrl.jumpPage, 10); + if (ctrl.jumpPage > 0 && ctrl.jumpPage <= ctrl.pageData.total) { - if (!lodash.isEmpty(children)) { - showAllChildren(children); + // ctrl.jumpToPage numbering begins from 1, not from 0 + ctrl.goToPage(ctrl.jumpPage - 1); + } else { + ctrl.jumpPage = String(ctrl.page + 1); } }); } /** - * Show item's all direct ancestors chain (recursively) - * @param {Object} dataItem - current item + * Method selecting active page as first on changing rows per page + * @param {Object} item - new item + * @param {boolean} isItemChanged - was value changed or not */ - function showAllParents(dataItem) { - var parent = dataItem.ui.parent; - if (angular.isDefined(parent)) { - parent.ui.isFitQuery = true; - showAllParents(parent); + function onPerPageChanged(item, isItemChanged) { + if (isItemChanged) { + lodash.set(ctrl, 'perPage', item.id); } - } - - /** - * Loop through all given data's properties and show/hide current data depending on query match criteria - * @param {string} searchQuery - query entered to a search input - * @param {Object} dataItem - current item - * @param {Array} pathsForSearch - array of strings, representing paths to item's properties to search from - * @param {Object} searchStates - * @param {string} [multiSearchName] - unique name of the search input - */ - function showRelevantItem(searchQuery, dataItem, pathsForSearch, searchStates, multiSearchName) { - var isFitQuery; - var stringValuesArray = []; - - angular.forEach(pathsForSearch, function (pathForSearch) { - getStringValuesFromItem(lodash.get(dataItem, pathForSearch), stringValuesArray); - }); - - // If at least one value in item's properties string values matched - show current item and all its direct ancestors chain - isFitQuery = stringValuesArray.some(function (value) { - return lodash.includes(value.toLowerCase(), searchQuery.toLowerCase()); - }); - - setFitQueryValue(dataItem, multiSearchName, isFitQuery); - if (dataItem.ui.isFitQuery) { - searchStates.searchNotFound = false; - showAllParents(dataItem); + if (angular.isDefined(ctrl.entityName)) { + LocalStorageService.setItem('itemsPerPage', ctrl.entityName, ctrl.perPage); } - } - } -})(); -'use strict'; - -(function () { - 'use strict'; - - IgzSearchInputController.$inject = ['$scope', '$timeout', 'lodash', 'SearchHelperService']; - angular.module('iguazio.dashboard-controls').component('igzSearchInput', { - bindings: { - dataSet: '<', - initSearchQuery: '@?', - isSearchHierarchically: '@?', - liveSearch: ' ctrl.maxPagesToDisplay) { - // default search functionality - SearchHelperService.makeSearch(ctrl.searchQuery, ctrl.dataSet, ctrl.searchKeys, ctrl.isSearchHierarchically, ctrl.ruleType, ctrl.searchStates, ctrl.multiSearchName); - } - } - - /** - * Tracks input changing and initializes search - */ - function onChangeSearchQuery(newValue, oldValue) { - if (angular.isDefined(newValue) && newValue !== oldValue) { - makeSearch(); - } - } - - /** - * Initializes search when all html has been rendered - */ - function onDataChanged() { - $timeout(makeSearch); - } - - /** - * Resets search query and initializes search - */ - function resetSearch() { - ctrl.searchQuery = ''; - $timeout(makeSearch); - } - } -})(); -'use strict'; - -(function () { - 'use strict'; - - igzShowHideSearchItem.$inject = ['lodash']; - angular.module('iguazio.dashboard-controls').directive('igzShowHideSearchItem', igzShowHideSearchItem); - - function igzShowHideSearchItem(lodash) { - return { - restrict: 'A', - scope: { - dataItem: '=igzShowHideSearchItem' - }, - link: link - }; - - function link(scope, element) { - activate(); - - // - // Private methods - // - - /** - * Constructor method - */ - function activate() { - scope.$watch('dataItem.ui.isFitQuery', changeVisibility); - scope.$watch('dataItem.ui.filters', changeVisibility, true); - } - - /** - * Method sets display property of element to false if it doesn't fit the query in search otherwise removes these property - * @param {boolean} newValue - value displays if current element fit search query - */ - function changeVisibility(newValue) { - var displayValue = ''; - - if (lodash.isObject(newValue)) { - displayValue = lodash.some(newValue, { isFitQuery: false }) ? 'none' : ''; - } else { - displayValue = newValue === false ? 'none' : ''; - } - - element.css('display', displayValue); - } - } - } -})(); -'use strict'; - -(function () { - 'use strict'; - - IgzPaginationController.$inject = ['$scope', '$timeout', 'lodash', 'EventHelperService', 'LocalStorageService', 'PaginationService']; - angular.module('iguazio.dashboard-controls').component('igzPagination', { - bindings: { - allowJumpToPage: ' 0 && ctrl.jumpPage <= ctrl.pageData.total) { - - // ctrl.jumpToPage numbering begins from 1, not from 0 - ctrl.goToPage(ctrl.jumpPage - 1); - } else { - ctrl.jumpPage = String(ctrl.page + 1); - } - }); - } - - /** - * Method selecting active page as first on changing rows per page - * @param {Object} item - new item - * @param {boolean} isItemChanged - was value changed or not - */ - function onPerPageChanged(item, isItemChanged) { - if (isItemChanged) { - lodash.set(ctrl, 'perPage', item.id); - } - - if (angular.isDefined(ctrl.entityName)) { - LocalStorageService.setItem('itemsPerPage', ctrl.entityName, ctrl.perPage); - } - - ctrl.goToPage(0); - } - - /** - * Go to next page by clicking Next button - * Or to first page if the last page is current - * @param {Object} event - */ - function goToNextPage(event) { - if (angular.isUndefined(event) || event.keyCode === EventHelperService.ENTER) { - ctrl.goToPage((ctrl.page + 1) % ctrl.pageData.total); - } - } - - /** - * Method to switch page - * @param {string|number} pageNumber - * @param {Object} [event] - * @returns {boolean} - */ - function goToPage(pageNumber, event) { - if (angular.isUndefined(event) || event.keyCode === EventHelperService.ENTER) { - if (pageNumber === '...') { - return false; - } - ctrl.page = pageNumber; - generatePagesArray(); - - if (angular.isFunction(ctrl.paginationCallback)) { - ctrl.paginationCallback({ - page: ctrl.page, - size: ctrl.perPage, - additionalParams: { - sort: ctrl.sort - } - }); - } - } - } - - /** - * Go to previous page by clicking Previous button - * @param {Object} event - */ - function goToPrevPage(event) { - if (angular.isUndefined(event) || event.keyCode === EventHelperService.ENTER) { - ctrl.goToPage(ctrl.page === 0 ? ctrl.pageData.total - 1 : ctrl.page - 1); - } - } - - // - // Private methods - // - - /** - * Generates pages array - */ - function generatePagesArray() { - - // The first page is always displayed - ctrl.pages = [0]; - - // if there are more pages than allowed, we need to exclude some pages: - // 1 2 3 4 5 6 7 ... 15 - if (ctrl.pageData.total > ctrl.maxPagesToDisplay) { - - // 4 is count of elements that should be present: '1 page', '...', '...', 'Last page' - var middleGroup = ctrl.maxPagesToDisplay - 4; + // 4 is count of elements that should be present: '1 page', '...', '...', 'Last page' + var middleGroup = ctrl.maxPagesToDisplay - 4; // if current page is in the beginning // 1 2 3 4 5 6 7 ... 15 @@ -8253,187 +7900,540 @@ angular.module('angular-i18next', []).provider('i18next', [function () { } }; - $scope.$on('size_hide-tooltip', hideChartTooltip); + $scope.$on('size_hide-tooltip', hideChartTooltip); + } + + if (ctrl.type === 'storage-pools_containers' && angular.isDefined(ctrl.entity.attr.quota) && ctrl.entity.attr.quota !== 0 && isMaxQuotaValueAppropriate()) { + + ctrl.entity.ui.lineChartOptions[ctrl.type].options.yAxis.plotLines = [{ + color: PaletteService.sizeChartLineChartOptionsYAxisPlotLinesColor, + width: 1, + value: ctrl.entity.attr.quota, + zIndex: 5 + }]; + + ctrl.entity.ui.lineChartOptions[ctrl.type].options.yAxis.max = ctrl.entity.attr.quota; + } + + if (isCpu()) { + ctrl.entity.ui.lineChartOptions[ctrl.type].options.yAxis.max = 100; + } + + $scope.$on('size_update-charts', updateChart); + $scope.$on('info-page-pane_toggled', updateChart); + $scope.$on('resize-size-cells', updateChart); + + timeout = $timeout(updateChart); + } + + /** + * Destructor method + */ + function onDestroy() { + if (!lodash.isNil(timeout)) { + $timeout.cancel(timeout); + } + } + + // + // Public methods + // + + /** + * Gets display value + * @returns {string} + */ + function getDisplayValue() { + var defaultValue = isCpu() ? '0%' : isSize() ? '0 bytes' : '0'; + var metricName = isCpu() ? 'cpu.idle' : isCpuCores() ? 'cpu.cores' : isSize() ? 'size' : 'count'; + var value = ctrl.entity.ui.metrics[metricName]; + var sizePercentage = ctrl.entity.ui.metrics.sizePercentage; + sizePercentage = lodash.isUndefined(sizePercentage) ? '' : ' (' + sizePercentage + '%)'; + + return lodash.isNil(value) ? defaultValue : isCpu() ? $filter('number')(value > 0 ? 100 - value : 0, 0) + '%' : isCpuCores() ? $filter('scale')(value, 0, 'nanos') : isSize() ? $filter('bytes')(value, 2) + sizePercentage : $filter('scale')(value); + } + + // + // Private methods + // + + /** + * Hides chart tooltip + */ + function hideChartTooltip() { + if (!ctrl.entity.ui[ctrl.chartObjName].tooltip.isHidden) { + ctrl.entity.ui[ctrl.chartObjName].tooltip.hide(); + } + } + + /** + * Determines whether this chart is for Count + * @returns {boolean} `true` if this chart is for Count or `false` otherwise + */ + function isCount() { + return lodash.includes(COUNT_TYPES, ctrl.type); + } + + /** + * Determines whether this chart is for CPU + * @returns {boolean} `true` if this chart is for CPU or `false` otherwise + */ + function isCpu() { + return lodash.includes(CPU_TYPES, ctrl.type); + } + + /** + * Determines whether this chart is for CPU cores + * @returns {boolean} `true` if this chart is for CPU cores or `false` otherwise + */ + function isCpuCores() { + return lodash.includes(CPU_CORES_TYPES, ctrl.type); + } + + /** + * Defines if max quota value and max point in chart data has difference less than 20% + * @returns {boolean} + */ + function isMaxQuotaValueAppropriate() { + var maxGraphicPoint = lodash.maxBy(lodash.values(ctrl.entity.ui.metrics.sizeLineChartData), function (point) { + return point[1]; + }); + + return (ctrl.entity.attr.quota - maxGraphicPoint[1]) / ctrl.entity.attr.quota * 100 <= 20; + } + + /** + * Determines whether this chart is for Size + * @returns {boolean} `true` if this chart is for Size or `false` otherwise + */ + function isSize() { + return lodash.includes(SIZE_TYPES, ctrl.type); + } + + /** + * Checks if chart should have a tooltip + * @returns {boolean} + */ + function isTooltipEnabled() { + return lodash.includes(['containers', 'storage-pools', 'tenants', 'services_memory', 'services_cpu', 'functions_memory', 'functions_cpu', 'functions_events'], ctrl.type); + } + + /** + * Initializes data according to passed page type + * @param {string} type - page type + */ + function prepareData(type) { + var dataTypes = { + 'clusters': prepareCpuData, + 'containers': prepareSizeData, + 'nodes': prepareCpuData, + 'functions_cpu': prepareCpuCoresData, + 'functions_memory': prepareSizeData, + 'functions_events': prepareCountData, + 'services_cpu': prepareCpuData, + 'services_memory': prepareSizeData, + 'storage-pools': prepareStoragePoolsData, + 'storage-pools_containers': prepareStoragePoolsContainersData, + 'tenants': prepareSizeData + }; + + dataTypes[type](); + + function prepareCpuData() { + lodash.defaults(ctrl.entity.ui.metrics, { 'cpu.idle': 0 }); + } + + function prepareCpuCoresData() { + lodash.defaults(ctrl.entity.ui.metrics, { 'cpu.cores': 0 }); + } + + function prepareSizeData() { + lodash.defaults(ctrl.entity.ui.metrics, { size: 0 }); + } + + function prepareCountData() { + lodash.defaults(ctrl.entity.ui.metrics, { count: 0 }); + } + + function prepareStoragePoolsData() { + lodash.defaults(ctrl.entity.ui.metrics, { size: 0 }); + updateOutOf(); + } + + function prepareStoragePoolsContainersData() { + lodash.defaults(ctrl.entity.ui.metrics, { size: 0 }); + + ctrl.reserved = angular.isDefined(ctrl.entity.attr.reserved) ? $filter('bytes')(ctrl.entity.attr.reserved, 2) : 0; + ctrl.quota = angular.isDefined(ctrl.entity.attr.quota) ? $filter('bytes')(ctrl.entity.attr.quota, 2) : -1; + } + } + + /** + * Updates chart on broadcasted event + */ + function updateChart() { + var reflow = lodash.get(ctrl.entity.ui, ctrl.chartObjName + '.reflow'); + if (angular.isFunction(reflow)) { + ctrl.entity.ui[ctrl.chartObjName].reflow(); + } + } + + function updateOutOf() { + var usableCapacity = ctrl.entity.attr.usable_capacity; + ctrl.outOf = lodash.isNil(usableCapacity) ? '-' : $filter('bytes')(usableCapacity, 2); + } + } +})(); +'use strict'; + +(function () { + 'use strict'; + + SearchHelperService.$inject = ['lodash']; + angular.module('iguazio.dashboard-controls').factory('SearchHelperService', SearchHelperService); + + function SearchHelperService(lodash) { + return { + makeSearch: makeSearch + }; + + // + // Public methods + // + + /** + * Perform search of data based on text query + * @param {string} searchQuery - text query entered to a search input + * @param {Array.} data - array of data + * @param {Array.} pathsForSearchArray - array of keys in which search will be made + * @param {boolean} isHierarchical - flag which indicates if passed data has hierarchical structure + * @param {string} ruleType - string representing the type of rule resource + * @param {Object} searchStates + * @param {string} [multiSearchName] - unique name of the search input + */ + function makeSearch(searchQuery, data, pathsForSearchArray, isHierarchical, ruleType, searchStates, multiSearchName) { + searchStates.searchNotFound = false; + searchStates.searchInProgress = false; + + if (isHierarchical) { + data = data.ui.children; + } else { + ruleType = ''; + } + if (searchQuery === '') { + showAllChildren(data, multiSearchName); + } else if (angular.isString(searchQuery)) { + searchStates.searchNotFound = true; + searchStates.searchInProgress = true; + findBySearchQuery(searchQuery, data, pathsForSearchArray, isHierarchical, ruleType, searchStates, multiSearchName); + } + } + + // + // Private methods + // + + /** + * Loop through all given data to show/hide them depending on query match criteria (recursively) + * @param {string} searchQuery - text query entered to a search input + * @param {Array.} children - array of child data + * @param {Array.} pathsForSearch - array of strings, representing data's properties keys to search from + * @param {boolean} isHierarchical - flag which indicates if passed data has hierarchical structure + * @param {string} ruleType - string representing the type of rule resource + * @param {Object} searchStates + * @param {string} [multiSearchName] - unique name of the search input + */ + function findBySearchQuery(searchQuery, children, pathsForSearch, isHierarchical, ruleType, searchStates, multiSearchName) { + angular.forEach(children, function (child) { + // Search by text in data without children data only + if (angular.isString(child.type) && child.type !== ruleType && isHierarchical) { + // Hide all parent data while search among children and proceed recursively + child.ui.isFitQuery = false; + findBySearchQuery(searchQuery, child.ui.children, pathsForSearch, isHierarchical, ruleType, searchStates, multiSearchName); + } else { + showRelevantItem(searchQuery, child, pathsForSearch, searchStates, multiSearchName); + } + }); + } + + /** + * Get all current item's properties string values and push to stringValuesArray (recursively) + * @param {string} itemPropertyValue - item's attribute value + * @param {Array} stringValuesArray - array to collect current item's all properties string values + */ + function getStringValuesFromItem(itemPropertyValue, stringValuesArray) { + if (angular.isObject(itemPropertyValue)) { + angular.forEach(itemPropertyValue, function (value) { + getStringValuesFromItem(value, stringValuesArray); + }); + } else if (angular.isString(itemPropertyValue) && itemPropertyValue.length > 0 || angular.isNumber(itemPropertyValue)) { + stringValuesArray.push(itemPropertyValue.toString()); + } + + return stringValuesArray; + } + + /** + * Sets isFitQuery value for data item + * @param {Object} dataItem - current item + * @param {string} [multiSearchName] - unique name of the search input + * @param {boolean} isFitQuery - `true` if item is matched with search query + */ + function setFitQueryValue(dataItem, multiSearchName, isFitQuery) { + var filterPath = lodash.isEmpty(multiSearchName) ? 'isFitQuery' : ['filters', multiSearchName, 'isFitQuery']; + + lodash.set(dataItem.ui, filterPath, isFitQuery); + } + + /** + * Show all data item's children chain (recursively) + * @param {Array.} data - child items + * @param {string} [multiSearchName] - unique name of the search input + */ + function showAllChildren(data, multiSearchName) { + angular.forEach(data, function (value) { + var children = value.ui.children; + + setFitQueryValue(value, multiSearchName, true); + + if (!lodash.isEmpty(children)) { + showAllChildren(children); + } + }); + } + + /** + * Show item's all direct ancestors chain (recursively) + * @param {Object} dataItem - current item + */ + function showAllParents(dataItem) { + var parent = dataItem.ui.parent; + if (angular.isDefined(parent)) { + parent.ui.isFitQuery = true; + showAllParents(parent); + } + } + + /** + * Loop through all given data's properties and show/hide current data depending on query match criteria + * @param {string} searchQuery - query entered to a search input + * @param {Object} dataItem - current item + * @param {Array} pathsForSearch - array of strings, representing paths to item's properties to search from + * @param {Object} searchStates + * @param {string} [multiSearchName] - unique name of the search input + */ + function showRelevantItem(searchQuery, dataItem, pathsForSearch, searchStates, multiSearchName) { + var isFitQuery; + var stringValuesArray = []; + + angular.forEach(pathsForSearch, function (pathForSearch) { + getStringValuesFromItem(lodash.get(dataItem, pathForSearch), stringValuesArray); + }); + + // If at least one value in item's properties string values matched - show current item and all its direct ancestors chain + isFitQuery = stringValuesArray.some(function (value) { + return lodash.includes(value.toLowerCase(), searchQuery.toLowerCase()); + }); + + setFitQueryValue(dataItem, multiSearchName, isFitQuery); + + if (dataItem.ui.isFitQuery) { + searchStates.searchNotFound = false; + showAllParents(dataItem); } + } + } +})(); +'use strict'; - if (ctrl.type === 'storage-pools_containers' && angular.isDefined(ctrl.entity.attr.quota) && ctrl.entity.attr.quota !== 0 && isMaxQuotaValueAppropriate()) { +(function () { + 'use strict'; - ctrl.entity.ui.lineChartOptions[ctrl.type].options.yAxis.plotLines = [{ - color: PaletteService.sizeChartLineChartOptionsYAxisPlotLinesColor, - width: 1, - value: ctrl.entity.attr.quota, - zIndex: 5 - }]; + IgzSearchInputController.$inject = ['$scope', '$timeout', 'lodash', 'SearchHelperService']; + angular.module('iguazio.dashboard-controls').component('igzSearchInput', { + bindings: { + dataSet: '<', + initSearchQuery: '@?', + isSearchHierarchically: '@?', + liveSearch: ' 0 ? 100 - value : 0, 0) + '%' : isCpuCores() ? $filter('scale')(value, 0, 'nanos') : isSize() ? $filter('bytes')(value, 2) + sizePercentage : $filter('scale')(value); + $scope.$on('search-input_refresh-search', onDataChanged); + $scope.$on('search-input_reset', resetSearch); } // - // Private methods + // Public methods // /** - * Hides chart tooltip + * Initializes search and apply filters on press enter + * @param {Event} e */ - function hideChartTooltip() { - if (!ctrl.entity.ui[ctrl.chartObjName].tooltip.isHidden) { - ctrl.entity.ui[ctrl.chartObjName].tooltip.hide(); + function onPressEnter(e) { + if (e.keyCode === 13) { + makeSearch(); + + if (angular.isFunction(ctrl.onSearchSubmit) && ctrl.isInputFocused) { + ctrl.onSearchSubmit(); + } } } /** - * Determines whether this chart is for Count - * @returns {boolean} `true` if this chart is for Count or `false` otherwise + * Clear search input field */ - function isCount() { - return lodash.includes(COUNT_TYPES, ctrl.type); + function clearInputField() { + ctrl.searchQuery = ''; } /** - * Determines whether this chart is for CPU - * @returns {boolean} `true` if this chart is for CPU or `false` otherwise + * Toggles input focus */ - function isCpu() { - return lodash.includes(CPU_TYPES, ctrl.type); + function toggleInputFocus() { + ctrl.isInputFocused = !ctrl.isInputFocused; } - /** - * Determines whether this chart is for CPU cores - * @returns {boolean} `true` if this chart is for CPU cores or `false` otherwise - */ - function isCpuCores() { - return lodash.includes(CPU_CORES_TYPES, ctrl.type); - } + // + // Private methods + // /** - * Defines if max quota value and max point in chart data has difference less than 20% - * @returns {boolean} + * Calls service method for search */ - function isMaxQuotaValueAppropriate() { - var maxGraphicPoint = lodash.maxBy(lodash.values(ctrl.entity.ui.metrics.sizeLineChartData), function (point) { - return point[1]; - }); + function makeSearch() { + if (angular.isFunction(ctrl.searchCallback)) { - return (ctrl.entity.attr.quota - maxGraphicPoint[1]) / ctrl.entity.attr.quota * 100 <= 20; + // call custom search method + ctrl.searchCallback(lodash.pick(ctrl, ['searchQuery', 'dataSet', 'searchKeys', 'isSearchHierarchically', 'ruleType', 'searchStates', 'multiSearchName'])); + } + + if (angular.isUndefined(ctrl.type)) { + + // default search functionality + SearchHelperService.makeSearch(ctrl.searchQuery, ctrl.dataSet, ctrl.searchKeys, ctrl.isSearchHierarchically, ctrl.ruleType, ctrl.searchStates, ctrl.multiSearchName); + } } /** - * Determines whether this chart is for Size - * @returns {boolean} `true` if this chart is for Size or `false` otherwise + * Tracks input changing and initializes search */ - function isSize() { - return lodash.includes(SIZE_TYPES, ctrl.type); + function onChangeSearchQuery(newValue, oldValue) { + if (angular.isDefined(newValue) && newValue !== oldValue) { + makeSearch(); + } } /** - * Checks if chart should have a tooltip - * @returns {boolean} + * Initializes search when all html has been rendered */ - function isTooltipEnabled() { - return lodash.includes(['containers', 'storage-pools', 'tenants', 'services_memory', 'services_cpu', 'functions_memory', 'functions_cpu', 'functions_events'], ctrl.type); + function onDataChanged() { + $timeout(makeSearch); } /** - * Initializes data according to passed page type - * @param {string} type - page type + * Resets search query and initializes search */ - function prepareData(type) { - var dataTypes = { - 'clusters': prepareCpuData, - 'containers': prepareSizeData, - 'nodes': prepareCpuData, - 'functions_cpu': prepareCpuCoresData, - 'functions_memory': prepareSizeData, - 'functions_events': prepareCountData, - 'services_cpu': prepareCpuData, - 'services_memory': prepareSizeData, - 'storage-pools': prepareStoragePoolsData, - 'storage-pools_containers': prepareStoragePoolsContainersData, - 'tenants': prepareSizeData - }; + function resetSearch() { + ctrl.searchQuery = ''; + $timeout(makeSearch); + } + } +})(); +'use strict'; - dataTypes[type](); +(function () { + 'use strict'; - function prepareCpuData() { - lodash.defaults(ctrl.entity.ui.metrics, { 'cpu.idle': 0 }); - } + igzShowHideSearchItem.$inject = ['lodash']; + angular.module('iguazio.dashboard-controls').directive('igzShowHideSearchItem', igzShowHideSearchItem); - function prepareCpuCoresData() { - lodash.defaults(ctrl.entity.ui.metrics, { 'cpu.cores': 0 }); - } + function igzShowHideSearchItem(lodash) { + return { + restrict: 'A', + scope: { + dataItem: '=igzShowHideSearchItem' + }, + link: link + }; - function prepareSizeData() { - lodash.defaults(ctrl.entity.ui.metrics, { size: 0 }); - } + function link(scope, element) { + activate(); - function prepareCountData() { - lodash.defaults(ctrl.entity.ui.metrics, { count: 0 }); - } + // + // Private methods + // - function prepareStoragePoolsData() { - lodash.defaults(ctrl.entity.ui.metrics, { size: 0 }); - updateOutOf(); + /** + * Constructor method + */ + function activate() { + scope.$watch('dataItem.ui.isFitQuery', changeVisibility); + scope.$watch('dataItem.ui.filters', changeVisibility, true); } - function prepareStoragePoolsContainersData() { - lodash.defaults(ctrl.entity.ui.metrics, { size: 0 }); - - ctrl.reserved = angular.isDefined(ctrl.entity.attr.reserved) ? $filter('bytes')(ctrl.entity.attr.reserved, 2) : 0; - ctrl.quota = angular.isDefined(ctrl.entity.attr.quota) ? $filter('bytes')(ctrl.entity.attr.quota, 2) : -1; - } - } + /** + * Method sets display property of element to false if it doesn't fit the query in search otherwise removes these property + * @param {boolean} newValue - value displays if current element fit search query + */ + function changeVisibility(newValue) { + var displayValue = ''; - /** - * Updates chart on broadcasted event - */ - function updateChart() { - var reflow = lodash.get(ctrl.entity.ui, ctrl.chartObjName + '.reflow'); - if (angular.isFunction(reflow)) { - ctrl.entity.ui[ctrl.chartObjName].reflow(); - } - } + if (lodash.isObject(newValue)) { + displayValue = lodash.some(newValue, { isFitQuery: false }) ? 'none' : ''; + } else { + displayValue = newValue === false ? 'none' : ''; + } - function updateOutOf() { - var usableCapacity = ctrl.entity.attr.usable_capacity; - ctrl.outOf = lodash.isNil(usableCapacity) ? '-' : $filter('bytes')(usableCapacity, 2); + element.css('display', displayValue); + } } } })(); @@ -9644,24 +9644,31 @@ angular.module('angular-i18next', []).provider('i18next', [function () { (function () { 'use strict'; - IgzInfoPageActionsBarController.$inject = ['$scope']; - angular.module('iguazio.dashboard-controls').component('igzInfoPageActionsBar', { + IgzInfoPageContentController.$inject = ['$scope', '$timeout', '$window', '$element']; + angular.module('iguazio.dashboard-controls').component('igzInfoPageContent', { bindings: { + scrolled: '<', watchId: '@?' }, - templateUrl: 'igz_controls/components/info-page/info-page-actions-bar/info-page-actions-bar.tpl.html', + templateUrl: 'igz_controls/components/info-page/info-page-content/info-page-content.tpl.html', transclude: true, - controller: IgzInfoPageActionsBarController + controller: IgzInfoPageContentController }); - function IgzInfoPageActionsBarController($scope) { + function IgzInfoPageContentController($scope, $timeout, $window, $element) { var ctrl = this; - ctrl.isUpperPaneShowed = false; ctrl.isFiltersShowed = false; ctrl.isInfoPaneShowed = false; + // Config for horizontal scrollbar on containers view + ctrl.scrollConfigHorizontal = { + axis: 'x', + scrollInertia: 0 + }; + ctrl.$onInit = onInit; + ctrl.$postLink = postLink; // // Hook methods @@ -9676,12 +9683,46 @@ angular.module('angular-i18next', []).provider('i18next', [function () { $scope.$on('info-page-upper-pane_toggle-start' + watchId, onUpperPaneToggleStart); $scope.$on('info-page-filters_toggle-start' + watchId, onFiltersPaneToggleStart); $scope.$on('info-page-pane_toggle-start' + watchId, onInfoPaneToggleStart); + $scope.$on('info-page-pane_toggled', dispatchResize); + } + + /** + * Post linking method + */ + function postLink() { + $timeout(function () { + manageHorizontalScroll(); + + $scope.$on('info-page-filters_toggled', manageHorizontalScroll); + + $scope.$on('info-page-pane_toggled', manageHorizontalScroll); + + $scope.$on('igzWatchWindowResize::resize', manageHorizontalScroll); + }); } // // Private methods // + /** + * Manages x-scrollbar behavior + * Needed to get rid of accidental wrong content width calculations made by 'ng-scrollbars' library + * We just control x-scrollbar with lib's native enable/disable methods + */ + function manageHorizontalScroll() { + var $scrollXContainer = $element.find('.igz-scrollable-container.horizontal').first(); + var contentWrapperWidth = $element.find('.igz-info-page-content-wrapper').first().width(); + var contentMinWidth = parseInt($element.find('.igz-info-page-content').css('min-width')); + + if ($scrollXContainer.length && contentWrapperWidth < (contentMinWidth || 946)) { + $scrollXContainer.mCustomScrollbar('update'); + } else if ($scrollXContainer.length) { + $scrollXContainer.mCustomScrollbar('disable', true); + $element.find('.mCSB_container').first().width('100%'); + } + } + /** * Upper pane toggle start $broadcast listener * @param {Object} e - broadcast event @@ -9708,6 +9749,15 @@ angular.module('angular-i18next', []).provider('i18next', [function () { function onInfoPaneToggleStart(e, isShown) { ctrl.isInfoPaneShowed = isShown; } + + /** + * Updates Ui-Layout library's containers size + */ + function dispatchResize() { + $timeout(function () { + $window.dispatchEvent(new Event('resize')); + }, 0); + } } })(); 'use strict'; @@ -9715,31 +9765,24 @@ angular.module('angular-i18next', []).provider('i18next', [function () { (function () { 'use strict'; - IgzInfoPageContentController.$inject = ['$scope', '$timeout', '$window', '$element']; - angular.module('iguazio.dashboard-controls').component('igzInfoPageContent', { + IgzInfoPageActionsBarController.$inject = ['$scope']; + angular.module('iguazio.dashboard-controls').component('igzInfoPageActionsBar', { bindings: { - scrolled: '<', watchId: '@?' }, - templateUrl: 'igz_controls/components/info-page/info-page-content/info-page-content.tpl.html', + templateUrl: 'igz_controls/components/info-page/info-page-actions-bar/info-page-actions-bar.tpl.html', transclude: true, - controller: IgzInfoPageContentController + controller: IgzInfoPageActionsBarController }); - function IgzInfoPageContentController($scope, $timeout, $window, $element) { + function IgzInfoPageActionsBarController($scope) { var ctrl = this; + ctrl.isUpperPaneShowed = false; ctrl.isFiltersShowed = false; ctrl.isInfoPaneShowed = false; - // Config for horizontal scrollbar on containers view - ctrl.scrollConfigHorizontal = { - axis: 'x', - scrollInertia: 0 - }; - ctrl.$onInit = onInit; - ctrl.$postLink = postLink; // // Hook methods @@ -9754,46 +9797,12 @@ angular.module('angular-i18next', []).provider('i18next', [function () { $scope.$on('info-page-upper-pane_toggle-start' + watchId, onUpperPaneToggleStart); $scope.$on('info-page-filters_toggle-start' + watchId, onFiltersPaneToggleStart); $scope.$on('info-page-pane_toggle-start' + watchId, onInfoPaneToggleStart); - $scope.$on('info-page-pane_toggled', dispatchResize); - } - - /** - * Post linking method - */ - function postLink() { - $timeout(function () { - manageHorizontalScroll(); - - $scope.$on('info-page-filters_toggled', manageHorizontalScroll); - - $scope.$on('info-page-pane_toggled', manageHorizontalScroll); - - $scope.$on('igzWatchWindowResize::resize', manageHorizontalScroll); - }); } // // Private methods // - /** - * Manages x-scrollbar behavior - * Needed to get rid of accidental wrong content width calculations made by 'ng-scrollbars' library - * We just control x-scrollbar with lib's native enable/disable methods - */ - function manageHorizontalScroll() { - var $scrollXContainer = $element.find('.igz-scrollable-container.horizontal').first(); - var contentWrapperWidth = $element.find('.igz-info-page-content-wrapper').first().width(); - var contentMinWidth = parseInt($element.find('.igz-info-page-content').css('min-width')); - - if ($scrollXContainer.length && contentWrapperWidth < (contentMinWidth || 946)) { - $scrollXContainer.mCustomScrollbar('update'); - } else if ($scrollXContainer.length) { - $scrollXContainer.mCustomScrollbar('disable', true); - $element.find('.mCSB_container').first().width('100%'); - } - } - /** * Upper pane toggle start $broadcast listener * @param {Object} e - broadcast event @@ -9820,15 +9829,6 @@ angular.module('angular-i18next', []).provider('i18next', [function () { function onInfoPaneToggleStart(e, isShown) { ctrl.isInfoPaneShowed = isShown; } - - /** - * Updates Ui-Layout library's containers size - */ - function dispatchResize() { - $timeout(function () { - $window.dispatchEvent(new Event('resize')); - }, 0); - } } })(); 'use strict'; @@ -10248,156 +10248,154 @@ angular.module('angular-i18next', []).provider('i18next', [function () { (function () { 'use strict'; - NclVersionConfigurationBasicSettingsController.$inject = ['$rootScope', '$timeout', '$i18next', 'i18next', 'lodash', 'ConfigService', 'DialogsService', 'FunctionsService', 'ValidationService']; - angular.module('iguazio.dashboard-controls').component('nclVersionConfigurationBasicSettings', { + NclTestEventsLogsController.$inject = ['lodash']; + angular.module('iguazio.dashboard-controls').component('nclTestEventsLogs', { bindings: { - version: '<', - onChangeCallback: '<' + logs: '<' }, - templateUrl: 'nuclio/functions/version/version-configuration/tabs/version-configuration-basic-settings/version-configuration-basic-settings.tpl.html', - controller: NclVersionConfigurationBasicSettingsController + templateUrl: 'nuclio/functions/version/version-code/function-event-pane/test-events-logs/test-events-logs.tpl.html', + controller: NclTestEventsLogsController }); - function NclVersionConfigurationBasicSettingsController($rootScope, $timeout, $i18next, i18next, lodash, ConfigService, DialogsService, FunctionsService, ValidationService) { + function NclTestEventsLogsController(lodash) { var ctrl = this; - var lng = i18next.language; - - ctrl.enableFunction = false; - ctrl.enableTimeout = false; - ctrl.timeout = { - min: 0, - sec: 0 - }; - ctrl.logLevelValues = [{ - id: 'error', - name: $i18next.t('common:ERROR', { lng: lng }) - }, { - id: 'warn', - name: $i18next.t('common:WARNING', { lng: lng }) - }, { - id: 'info', - name: $i18next.t('common:INFO', { lng: lng }) - }, { - id: 'debug', - name: $i18next.t('common:DEBUG', { lng: lng }) - }]; + var REQUIRED_PARAMETERS = ['level', 'name', 'time', 'err', 'message', 'ui']; ctrl.$onInit = onInit; - ctrl.$onChanges = onChanges; - - ctrl.isDemoMode = ConfigService.isDemoMode; - ctrl.lodash = lodash; - ctrl.validationRules = { - integer: ValidationService.getValidationRules('integer') - }; - ctrl.inputValueCallback = inputValueCallback; - ctrl.setPriority = setPriority; - ctrl.updateEnableStatus = updateEnableStatus; + ctrl.collapseRow = collapseRow; + ctrl.expandAllRows = expandAllRows; + ctrl.getLevelIconClass = getLevelIconClass; + ctrl.getParameters = getParameters; + ctrl.hasAdditionalParameters = hasAdditionalParameters; // - // Hook methods + // Hook method // /** * Initialization method */ function onInit() { - ctrl.platformIsKube = FunctionsService.isKubePlatform(); + lodash.forEach(ctrl.logs, function (log) { + lodash.set(log, 'ui.collapsed', true); + }); } + // + // Public methods + // + /** - * On changes hook method. - * @param {Object} changes + * Collapse/expand row depending on `collapse` value + * @param {Object} log + * @param {boolean} collapse */ - function onChanges(changes) { - if (angular.isDefined(changes.version)) { - if (ctrl.isDemoMode()) { - var timeoutSeconds = lodash.get(ctrl.version, 'spec.timeoutSeconds'); + function collapseRow(log, collapse) { + lodash.set(log, 'ui.collapsed', collapse); + } - if (lodash.isNumber(timeoutSeconds)) { - ctrl.timeout.min = Math.floor(timeoutSeconds / 60); - ctrl.timeout.sec = Math.floor(timeoutSeconds % 60); - } - } + /** + * Collapse/expand all rows depending on `expand` value + * @param {boolean} expand + */ + function expandAllRows(expand) { + lodash.forEach(ctrl.logs, function (log) { + lodash.set(log, 'ui.collapsed', !expand); + }); + } + + /** + * Gets css class depending on log.level + * @param {Object} log + * @returns {string} + */ + function getLevelIconClass(log) { + return log.level === 'debug' ? 'ncl-icon-debug' : log.level === 'info' ? 'igz-icon-info-round' : log.level === 'warn' ? 'igz-icon-warning' : log.level === 'error' ? 'igz-icon-cancel-path' : ''; + } + + /** + * Gets additional parameters + * @param {Object} log + * @returns {Object} + */ + function getParameters(log) { + return lodash.omit(log, REQUIRED_PARAMETERS); + } + + /** + * Checks if log has additional parameters + * @param {Object} log + * @returns {boolean} + */ + function hasAdditionalParameters(log) { + return !lodash.isEmpty(getParameters(log)); + } + } +})(); +'use strict'; + +(function () { + 'use strict'; + + NclTestEventsNavigationTabsController.$inject = ['$i18next', 'i18next']; + angular.module('iguazio.dashboard-controls').component('nclTestEventsNavigationTabs', { + bindings: { + activeTab: '<', + tabItems: '<', + selectedLogLevel: ' 'G' - };ctrl.selectedRequestUnit = lodash.isNil(requestsMemory) ? defaultUnit : lodash.find(ctrl.dropdownOptions, ['unit', extractUnit(requestsMemory)]); + // get size unit from memory values into int or set default, example: '15G' -> 'G' + ctrl.selectedRequestUnit = lodash.isNil(requestsMemory) ? defaultUnit : lodash.find(ctrl.dropdownOptions, ['unit', extractUnit(requestsMemory)]); ctrl.selectedLimitUnit = lodash.isNil(limitsMemory) ? defaultUnit : lodash.find(ctrl.dropdownOptions, ['unit', extractUnit(limitsMemory)]); ctrl.selectedCpuRequestItem = lodash.isNil(requestsCpu) ? ctrl.cpuDropdownOptions[0] : lodash.find(ctrl.cpuDropdownOptions, ['unit', extractUnit(requestsCpu)]); @@ -11793,6 +12013,30 @@ angular.module('angular-i18next', []).provider('i18next', [function () { }); } + /** + * Initializes data for Node selectors section + */ + function initNodeSelectors() { + ctrl.nodeSelectors = lodash.chain(ctrl.version).get('spec.nodeSelector', {}).map(function (value, key) { + return { + name: key, + value: value, + ui: { + editModeActive: false, + isFormValid: key.length > 0 && value.length > 0, + name: 'nodeSelector' + } + }; + }).value(); + + $timeout(function () { + if (ctrl.nodeSelectorsForm.$invalid) { + ctrl.nodeSelectorsForm.$setSubmitted(); + $rootScope.$broadcast('change-state-deploy-button', { component: 'nodeSelector', isDisabled: true }); + } + }); + } + /** * Initializes data for "Scale to zero" section */ @@ -11835,6 +12079,33 @@ angular.module('angular-i18next', []).provider('i18next', [function () { } } + /** + * Updates Node selectors + */ + function updateNodeSelectors() { + var isFormValid = true; + var newNodeSelectors = {}; + + lodash.forEach(ctrl.nodeSelectors, function (nodeSelector) { + if (!nodeSelector.ui.isFormValid) { + isFormValid = false; + } + + newNodeSelectors[nodeSelector.name] = nodeSelector.value; + }); + + // since uniqueness validation rule of some fields is dependent on the entire label list, then whenever + // the list is modified - the rest of the labels need to be re-validated + FormValidationService.validateAllFields(ctrl.nodeSelectorsForm); + + $rootScope.$broadcast('change-state-deploy-button', { + component: 'nodeSelector', + isDisabled: !isFormValid || ctrl.nodeSelectorsForm.$invalid + }); + + lodash.set(ctrl.version, 'spec.nodeSelector', newNodeSelectors); + } + /** * Updates parameters for "Scale to zero" section */ @@ -11878,6 +12149,15 @@ angular.module('angular-i18next', []).provider('i18next', [function () { } }; } + + /** + * Determines `uniqueness` validation for Node selector `Key` field + * @param {string} value - value to validate + * @returns {boolean} + */ + function validateNodeSelectorUniqueness(value) { + return lodash.filter(ctrl.nodeSelectors, ['name', value]).length === 1; + } } })(); 'use strict'; @@ -12226,256 +12506,100 @@ angular.module('angular-i18next', []).provider('i18next', [function () { } }); - ctrl.onChangeCallback(); - } - - // - // Private methods - // - - /** - * Checks validation of volumes - */ - function checkValidation() { - if (lodash.some(ctrl.volumes, ['ui.isFormValid', false])) { - FormValidationService.validateAllFields(ctrl.volumesForm); - } - } - - /** - * Deletes selected item - * @param {number} index - index of variable in array - */ - function deleteHandler(index) { - ctrl.volumes.splice(index, 1); - - // since uniqueness validation rule of some fields is dependent on the entire volume list, whenever a volume - // is removed, the rest of the volumes needs to be re-validated - checkValidation(); - - var workingCopy = lodash.map(ctrl.volumes, function (volume) { - return lodash.omit(volume, 'ui'); - }); - - lodash.set(ctrl.version, 'spec.volumes', workingCopy); - } - - /** - * Toggles item to edit mode - * @param {Object} selectedItem - an object of selected volume - */ - function editHandler(selectedItem) { - selectedItem.ui.editModeActive = true; - } - - /** - * Checks if volume is in edit mode - * @returns {boolean} - */ - function isVolumeInEditMode() { - return lodash.some(ctrl.volumes, ['ui.editModeActive', true]); - } - - /** - * Updates data in selected item - * @param {Object} selectedItem - an object of selected volume - */ - function updateHandler(selectedItem) { - var workingCopy = angular.copy(ctrl.volumes); - var currentVolume = lodash.find(ctrl.volumes, ['volume.name', selectedItem.volume.name]); - var indexOfEditableElement = lodash.findIndex(ctrl.volumes, ['volume.name', selectedItem.volume.name]); - - if (angular.isDefined(currentVolume)) { - workingCopy[indexOfEditableElement] = { - volumeMount: selectedItem.volumeMount, - volume: selectedItem.volume - }; - - // since uniqueness validation rule of some fields is dependent on the entire volume list, whenever a - // volume is updated, the rest of the volumes needs to be re-validated - checkValidation(); - - lodash.forEach(workingCopy, function (volume) { - delete volume.ui; - }); - - lodash.set(ctrl.version, 'spec.volumes', workingCopy); - } - } - - /** - * Checks volumes and updates `ctrl.version.ui.isVolumesChanged` if there is some changed and unsaved trigger. - */ - function updateVolumesChangesState() { - var isSomeVolumeChanged = lodash.some(ctrl.volumes, ['ui.changed', true]); - var isSomeVolumeInEditMode = lodash.some(ctrl.volumes, ['ui.editModeActive', true]); - - lodash.set(ctrl.version, 'ui.isVolumesChanged', isSomeVolumeChanged && isSomeVolumeInEditMode); - } - - /** - * Determines `uniqueness` validation for `Name` and `Mount Path` fields - * @param {string} path - * @param {string} value - */ - function validateUniqueness(path, value) { - return lodash.filter(ctrl.volumes, [path, value]).length === 1; - } - } -})(); -'use strict'; - -(function () { - 'use strict'; - - NclTestEventsNavigationTabsController.$inject = ['$i18next', 'i18next']; - angular.module('iguazio.dashboard-controls').component('nclTestEventsNavigationTabs', { - bindings: { - activeTab: '<', - tabItems: '<', - selectedLogLevel: ' 'file.name.ext' + * + * extractFileName('\\path/to\\file/file.name.ext', false); + * // => 'file.name' + * + * extractFileName('file.name.ext', false); + * // => 'file.name' + * + * extractFileName('/path/to/////file\\\\\\\\file.name.ext', true); + * // => 'file.name.ext' + * + * extractFileName('/path/to/file\file.name.ext', true, true); + * // => 'ext' + * + * extractFileName('/path/to/file/file.name.ext', false, true); + * // => '.' + * + * extractFileName(''); + * // => '' + * + * extractFileName(undefined); + * // => '' + * + * extractFileName(null); + * // => '' + * ``` */ - function closeEventDialog() { + function extractFileName(path, includeExtension, onlyExtension) { + var start = path.lastIndexOf(lodash.defaultTo(onlyExtension, false) ? '.' : '/') + 1; + var end = lodash.defaultTo(includeExtension, true) ? path.length : path.lastIndexOf('.'); - // close dialog only if event is not deploying. Means event was deployed / failed / not changed - if (!ctrl.isLoadingState) { - ctrl.closeDialog({ - result: { - isEventDeployed: false, - selectedEvent: ctrl.selectedEvent - } - }); - } + return lodash.defaultTo(path, '').replace('\\', '/').substring(start, end); } /** - * Sets new data from "Name" field to event object - * @param {string} newData - data to be set - * @param {string} field - field which was changed + * Gets all runtimes + * @returns {Array} */ - function inputValueCallback(newData, field) { - lodash.set(ctrl.workingCopy.spec, field === 'path' ? 'attributes.path' : field, newData); + function getRuntimes() { - isFormChanged(); + // language identifiers for monaco editor are taken from: + // https://code.visualstudio.com/docs/languages/identifiers#_known-language-identifiers + return [{ + id: 'golang', + ext: 'go', + name: 'Go', + language: 'go', + sourceCode: 'cGFja2FnZSBtYWluDQoNCmltcG9ydCAoDQogICAgImdpdGh1Yi5jb20vbnVjbGlvL251Y2xpby1zZGstZ28iDQo' + 'pDQoNCmZ1bmMgSGFuZGxlcihjb250ZXh0ICpudWNsaW8uQ29udGV4dCwgZXZlbnQgbnVjbGlvLkV2ZW50KSAoaW50ZXJmYWNle3' + '0sIGVycm9yKSB7DQogICAgcmV0dXJuIG5pbCwgbmlsDQp9', // source code in base64 + visible: true + }, { + id: 'python:2.7', + ext: 'py', + name: 'Python 2.7', + language: 'python', + sourceCode: 'ZGVmIGhhbmRsZXIoY29udGV4dCwgZXZlbnQpOg0KICAgIHJldHVybiAiIg==', // source code in base64 + visible: true + }, { + id: 'python:3.6', + ext: 'py', + name: 'Python 3.6', + language: 'python', + sourceCode: 'ZGVmIGhhbmRsZXIoY29udGV4dCwgZXZlbnQpOg0KICAgIHJldHVybiAiIg==', // source code in base64 + visible: true + }, { + id: 'dotnetcore', + ext: 'cs', + name: '.NET Core', + language: 'csharp', + sourceCode: 'dXNpbmcgU3lzdGVtOw0KdXNpbmcgTnVjbGlvLlNkazsNCg0KcHVibGljIGNsYXNzIG1haW4NCnsNCiAgICBwdWJ' + 'saWMgb2JqZWN0IGhhbmRsZXIoQ29udGV4dCBjb250ZXh0LCBFdmVudCBldmVudEJhc2UpDQogICAgew0KICAgICAgICByZXR1cm' + '4gbmV3IFJlc3BvbnNlKCkNCiAgICAgICAgew0KICAgICAgICAgICAgU3RhdHVzQ29kZSA9IDIwMCwNCiAgICAgICAgICAgIENvb' + 'nRlbnRUeXBlID0gImFwcGxpY2F0aW9uL3RleHQiLA0KICAgICAgICAgICAgQm9keSA9ICIiDQogICAgICAgIH07DQogICAgfQ0K' + 'fQ==', // source code in base64 + visible: true + }, { + id: 'java', + ext: 'java', + name: 'Java', + language: 'java', + sourceCode: 'aW1wb3J0IGlvLm51Y2xpby5Db250ZXh0Ow0KaW1wb3J0IGlvLm51Y2xpby5FdmVudDsNCmltcG9ydCBpby5udWN' + 'saW8uRXZlbnRIYW5kbGVyOw0KaW1wb3J0IGlvLm51Y2xpby5SZXNwb25zZTsNCg0KcHVibGljIGNsYXNzIEhhbmRsZXIgaW1wbG' + 'VtZW50cyBFdmVudEhhbmRsZXIgew0KDQogICAgQE92ZXJyaWRlDQogICAgcHVibGljIFJlc3BvbnNlIGhhbmRsZUV2ZW50KENvb' + 'nRleHQgY29udGV4dCwgRXZlbnQgZXZlbnQpIHsNCiAgICAgICByZXR1cm4gbmV3IFJlc3BvbnNlKCkuc2V0Qm9keSgiIik7DQog' + 'ICAgfQ0KfQ==', + visible: true + }, { + id: 'nodejs', + ext: 'js', + language: 'javascript', + sourceCode: 'ZXhwb3J0cy5oYW5kbGVyID0gZnVuY3Rpb24oY29udGV4dCwgZXZlbnQpIHsNCiAgICBjb250ZXh0LmNhbGxiYWN' + 'rKCcnKTsNCn07', // source code in base64 + name: 'NodeJS', + visible: true + }, { + id: 'shell', + ext: 'sh', + name: 'Shell', + language: 'shellscript', + sourceCode: '', + visible: true + }, { + id: 'ruby', + ext: 'rb', + name: 'Ruby', + language: 'ruby', + sourceCode: 'ZGVmIGhhbmRsZXIoY29udGV4dCwgZXZlbnQpDQplbmQ=', // source code in base64 + visible: true + }]; } /** - * Callback from method drop-down - * Sets new selected method - * @param {Object} item - new selected item + * Tests whether a file is valid for dropping in code editor according to its MIME type and its extension + * @param {string} type - the MIME type of the file (e.g. 'text/plain', 'application/javascript') + * @param {string} extension - the extension of the file (e.g. 'txt', 'py', 'html') + * @returns {boolean} `true` if the file is valid for dropping in code editor, or `false` otherwise */ - function onSelectMethod(item) { - lodash.set(ctrl.workingCopy, 'spec.attributes.method', item.id); - - isFormChanged(); - } + function isFileDropValid(type, extension) { - /** - * Callback from Content Type drop-down - * Sets new selected header - * @param {Object} item - new selected item - */ - function onSelectHeader(item) { - lodash.set(ctrl.workingCopy, 'spec.attributes.headers.Content-Type', item.id); - ctrl.contentType = item.id; + // Drag'n'Drop textual files into the code editor + var validFileExtensions = ['cs', 'py', 'go', 'sh', 'txt', 'js', 'java']; - isFormChanged(); + return lodash(type).startsWith('text/') || validFileExtensions.includes(extension); } /** - * Callback from body field. + * Sets informational background over monaco editor before dropping a file */ - function onChangeBody() { - isFormChanged(); - } + function onDragNDropFile() { + var codeEditor = $element.find('.monaco-code-editor'); + var nclMonaco = $element.find('.ncl-monaco'); + var codeEditorDropZone = $element.find('.code-editor-drop-zone'); - function onChangeSourceCode(sourceCode) { - lodash.set(ctrl.workingCopy, 'spec.body', sourceCode); + // Register event handlers for drag'n'drop of files to code editor + codeEditor.on('dragover', null, false).on('dragenter', null, function (event) { + codeEditorDropZone.addClass('dragover'); - isFormChanged(); - } + codeEditor.css('opacity', '0.4'); + event.preventDefault(); + }).on('dragleave', null, function (event) { + var monacoCoords = nclMonaco[0].getBoundingClientRect(); - // - // Private methods - // + if (event.originalEvent.pageX <= monacoCoords.left || event.originalEvent.pageX >= monacoCoords.right || event.originalEvent.pageY >= monacoCoords.bottom || event.originalEvent.pageY <= monacoCoords.top) { + codeEditorDropZone.removeClass('dragover'); + codeEditor.css('opacity', ''); + } - /** - * Compares original object and working object to get know if fields was changed - * Also check if form valid and set result to corresponding variable - */ - function isFormChanged() { - $timeout(function () { - ctrl.isFormChanged = !lodash.isEqual(ctrl.workingCopy, ctrl.selectedEvent) && lodash.isEmpty(ctrl.functionEventForm.$error); - }); - } - } -})(); -'use strict'; + event.preventDefault(); + }).on('drop', null, function (event) { + var itemType = lodash.get(event, 'originalEvent.dataTransfer.items[0].type'); + var file = lodash.get(event, 'originalEvent.dataTransfer.files[0]'); + var extension = extractFileName(file.name, true, true); -(function () { - 'use strict'; + if (isFileDropValid(itemType, extension)) { + var reader = new FileReader(); - NclVersionConfigurationController.$inject = ['lodash', 'ConfigService', 'VersionHelperService']; - angular.module('iguazio.dashboard-controls').component('nclVersionConfiguration', { - bindings: { - version: '<' - }, - templateUrl: 'nuclio/functions/version/version-configuration/version-configuration.tpl.html', - controller: NclVersionConfigurationController - }); + reader.onload = function (onloadEvent) { + var functionSource = { + language: lodash.chain(ctrl.runtimeArray).find(['ext', extension]).defaultTo({ + language: 'plaintext' + }).value().language, + code: onloadEvent.target.result + }; + ctrl.sourceCode = functionSource.code; + ctrl.editorLanguage = functionSource.language; + $scope.$apply(); - function NclVersionConfigurationController(lodash, ConfigService, VersionHelperService) { - var ctrl = this; + codeEditorDropZone.removeClass('dragover'); + codeEditor.css('opacity', ''); + }; + reader.onerror = function () { + DialogsService.alert($i18next.t('functions.ERROR_MSG:COULD_NOT_READ_FILE', { lng: lng })); + }; + reader.readAsText(file); + } else { + codeEditorDropZone.removeClass('dragover'); + codeEditor.css('opacity', ''); - ctrl.scrollConfig = { - axis: 'y', - advanced: { - autoScrollOnFocus: false, - updateOnContentResize: true - } - }; + DialogsService.alert($i18next.t('common:INVALID_FILE_TYPE_EXTENSION', { lng: lng })); + } + event.preventDefault(); + }); + } - ctrl.isDemoMode = ConfigService.isDemoMode; + /** + * Resize scrollbar container. + * Layout directive (splitter) makes changes to width of scrollbar container. But scrollbar doesn't handle + * those changes in correct way. So we have to set width manually + * @param {Event} e - native broadcast event object + * @param {number} [timeout=200] - function invocation delay in milliseconds + */ + function resizeScrollBar(e, timeout) { + $timeout(function () { + var CODE_CONTAINER_MIN_WIDTH = 700; - ctrl.isRuntimeBlockVisible = isRuntimeBlockVisible; - ctrl.onConfigurationChangeCallback = onConfigurationChangeCallback; + // if scrollbar container is wider than minimal code container width (scrollbar is not needed) + if (angular.element($element.find('.code-scrollable-container')).width() >= CODE_CONTAINER_MIN_WIDTH) { + // make sure that scrollbar container takes all available width + angular.element($element.find('.mCSB_container')[0]).css('width', '100%'); - // - // Public methods - // + // hide scrollbar (make it disabled) + angular.element($element.find('.igz-scrollable-container')[0]).mCustomScrollbar('disable', true); + } else { + // set code's container minimal width to scrollbar container + angular.element($element.find('.mCSB_container')[0]).css('width', CODE_CONTAINER_MIN_WIDTH + 'px'); + } - /** - * Checks if `Runtime Attributes` block is visible - * @returns {boolean} - */ - function isRuntimeBlockVisible() { - return lodash.includes(['shell', 'java'], lodash.get(ctrl.version, 'spec.runtime')); + $timeout(function () { + // Enable scrolling again or show scrollbar + angular.element($element.find('.igz-scrollable-container')[0]).mCustomScrollbar('update'); + }, 100); + }, timeout || 200); } /** - * Checks if version's configuration was changed + * Broadcast's callback to toggle test pane + * @param {Event} event - native broadcast event object + * @param {Object} data - contains data of test pane state (closed/opened) */ - function onConfigurationChangeCallback() { - VersionHelperService.updateIsVersionChanged(ctrl.version); + function toggleTestPane(event, data) { + if (data.closeTestPane) { + ctrl.layout.collapsed = true; + angular.element(angular.element('.ui-splitbar')[0]).css('display', 'none'); + } else { + ctrl.layout.collapsed = false; + angular.element(angular.element('.ui-splitbar')[0]).css('display', 'block'); + } + + resizeScrollBar(null, 300); } } })(); @@ -20310,206 +20689,131 @@ angular.module('angular-i18next', []).provider('i18next', [function () { (function () { 'use strict'; - NclVersionCodeController.$inject = ['$element', '$rootScope', '$scope', '$timeout', '$window', '$i18next', 'i18next', 'lodash', 'Base64', 'ConfigService', 'DialogsService', 'VersionHelperService']; - angular.module('iguazio.dashboard-controls').component('nclVersionCode', { + NclFunctionEventDialogController.$inject = ['$timeout', '$i18next', 'i18next', 'lodash', 'EventHelperService']; + angular.module('iguazio.dashboard-controls').component('nclFunctionEventDialog', { bindings: { - version: '<' + closeDialog: '&', + createEvent: '<', + selectedEvent: '<', + version: '<', + createFunctionEvent: '&' }, - templateUrl: 'nuclio/functions/version/version-code/version-code.tpl.html', - controller: NclVersionCodeController + templateUrl: 'nuclio/functions/version/function-event-dialog/function-event-dialog.tpl.html', + controller: NclFunctionEventDialogController }); - function NclVersionCodeController($element, $rootScope, $scope, $timeout, $window, $i18next, i18next, lodash, Base64, ConfigService, DialogsService, VersionHelperService) { + function NclFunctionEventDialogController($timeout, $i18next, i18next, lodash, EventHelperService) { var ctrl = this; - var scrollContainer = null; - var previousEntryType = null; var lng = i18next.language; - ctrl.githubToken = ''; - ctrl.layout = { - collapsed: false - }; - ctrl.scrollConfig = { - axis: 'xy', - advanced: { - autoScrollOnFocus: false - } - }; - ctrl.scrollConfigHorizontal = { - axis: 'x', - advanced: { - autoScrollOnFocus: false - }, - callbacks: { - onCreate: function onCreate() { - scrollContainer = this.querySelector('.mCSB_container'); - scrollContainer.style.height = '100%'; - } + ctrl.inputModelOptions = { + debounce: { + 'default': 0 } }; - ctrl.codeEntryTypeArray = [{ - id: 'sourceCode', + ctrl.buttonText = $i18next.t('common:CREATE', { lng: lng }); + ctrl.errorText = $i18next.t('functions:ERROR_MSG.CREATE_FUNCTION_EVENT', { lng: lng }); + ctrl.titleText = $i18next.t('functions:CREATE_FUNCTION_EVENT', { lng: lng }); + ctrl.contentType = 'application/json'; + ctrl.bodyTheme = 'vs-light'; + ctrl.isLoadingState = false; + ctrl.isDeployFailed = false; + ctrl.isFormChanged = false; + ctrl.methods = [{ + id: 'POST', visible: true, - name: 'Source code (edit online)', - tooltip: 'Provide the function source code in the dashboard', - tooltipPlacement: 'right' + name: 'POST' }, { - id: 'image', + id: 'GET', visible: true, - name: 'Image', - defaultValues: { - spec: { - image: '' - } - }, - tooltip: 'Deploy the function from an existing image', - tooltipPlacement: 'right' + name: 'GET' }, { - id: 'archive', + id: 'PUT', visible: true, - name: 'Archive', - defaultValues: { - spec: { - build: { - path: '', - codeEntryAttributes: { - headers: { - 'X-V3io-Session-Key': '' - }, - workDir: '' - } - } - } - }, - tooltip: 'Download a function-code archive file from an Iguazio Data Science Platform (with authentication) or from any other URL (without authentication)', - tooltipPlacement: 'right' + name: 'PUT' }, { - id: 'github', + id: 'PATCH', visible: true, - name: 'GitHub', - defaultValues: { - spec: { - build: { - path: '', - codeEntryAttributes: { - branch: '', - headers: { - 'Authorization': '' - }, - workDir: '' - } - } - } - }, - tooltip: 'Download the function code from a GitHub repository', - tooltipPlacement: 'right' - }, { - id: 'jar', - visible: lodash.get(ctrl.version, 'spec.runtime') === 'java', - name: 'Jar', - defaultValues: { - spec: { - build: { - path: '' - } - } - } + name: 'PATCH' }, { - id: 's3', + id: 'DELETE', visible: true, - name: 'S3', - defaultValues: { - spec: { - build: { - codeEntryAttributes: { - s3Bucket: '', - s3ItemKey: '', - s3AccessKeyId: '', - s3SecretAccessKey: '', - s3Region: '', - s3SessionToken: '', - workDir: '' - } - } - } - }, - tooltip: 'Download the function code from an AWS S3 bucket', - tooltipPlacement: 'right' + name: 'DELETE' }]; - ctrl.themesArray = [{ - id: 'vs', - name: 'Light', - visible: true + ctrl.headers = [{ + id: 'application/json', + visible: true, + name: 'JSON' }, { - id: 'vs-dark', - name: 'Dark', - visible: true + id: 'text/plain', + visible: true, + name: 'Plain text' }]; - ctrl.selectedTheme = lodash.get(ctrl.version, 'ui.editorTheme', ctrl.themesArray[0]); + ctrl.selectedMethod = null; + ctrl.selectedHeader = null; + ctrl.workingCopy = null; ctrl.$onInit = onInit; - ctrl.$postLink = postLink; - ctrl.$onChanges = onChanges; - ctrl.isDemoMode = ConfigService.isDemoMode; + ctrl.applyChanges = applyChanges; + ctrl.closeEventDialog = closeEventDialog; ctrl.inputValueCallback = inputValueCallback; - ctrl.onChangeGithubToken = onChangeGithubToken; + ctrl.onChangeBody = onChangeBody; ctrl.onChangeSourceCode = onChangeSourceCode; - ctrl.selectEntryTypeValue = selectEntryTypeValue; - ctrl.selectRuntimeValue = selectRuntimeValue; - ctrl.selectThemeValue = selectThemeValue; + ctrl.onSelectHeader = onSelectHeader; + ctrl.onSelectMethod = onSelectMethod; + + // + // Hooks method + // /** - * Initialization method + * Init method */ function onInit() { - $scope.$on('navigation-tabs_toggle-test-pane', toggleTestPane); - $scope.$on('ui.layout.resize', resizeScrollBar); - $scope.$on('ui.layout.loaded', resizeScrollBar); - - angular.element($window).bind('resize', resizeScrollBar); - } - /** - * Post linking method - */ - function postLink() { - $timeout(onDragNDropFile); - } + // check if dialog was opened to create event, or edit existing event. + // if ctrl.createEvent is 'true', that mean dialog was open to create new event. + // otherwise, for edit existing event, so need to change all corresponding labels. + if (!ctrl.createEvent) { + ctrl.titleText = $i18next.t('functions:EDIT_FUNCTION_EVENT', { lng: lng }); + ctrl.buttonText = $i18next.t('common:APPLY', { lng: lng }); + ctrl.errorText = $i18next.t('functions:ERROR_MSG.UPDATE_FUNCTION_EVENT', { lng: lng }); + } - /** - * On changes hook method. - * @param {Object} changes - */ - function onChanges(changes) { - if (angular.isDefined(changes.version)) { - ctrl.runtimeArray = getRuntimes(); - ctrl.selectedRuntime = lodash.find(ctrl.runtimeArray, ['id', ctrl.version.spec.runtime]); - ctrl.editorLanguage = ctrl.selectedRuntime.language; + // if ctrl.selectedEvent hasn't specific fields, that means event was not deployed before, so fill it with default data + lodash.defaultsDeep(ctrl.selectedEvent, { + metadata: { + namespace: lodash.get(ctrl.version, 'metadata.namespace'), + labels: { + 'nuclio.io/function-name': lodash.get(ctrl.version, 'metadata.name') + } + }, + spec: { + displayName: '', + triggerKind: 'http', + attributes: { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + path: '' + }, + body: '' + } + }); - var sourceCode = lodash.get(ctrl.version, 'spec.build.functionSourceCode', ''); - if (lodash.isEmpty(sourceCode)) { - ctrl.sourceCode = lodash.get(ctrl.version, 'ui.versionCode', sourceCode); - } else { - ctrl.sourceCode = Base64.decode(sourceCode); + // copy event to prevent modifying the original object + ctrl.workingCopy = angular.copy(ctrl.selectedEvent); - lodash.set(ctrl.version, 'ui.versionCode', sourceCode); - } + // get method from event. + ctrl.selectedMethod = lodash.find(ctrl.methods, ['id', lodash.get(ctrl.selectedEvent, 'spec.attributes.method')]); - if (lodash.has(ctrl.version, 'spec.build.codeEntryType')) { - ctrl.selectedEntryType = lodash.find(ctrl.codeEntryTypeArray, ['id', ctrl.version.spec.build.codeEntryType]); - if (ctrl.selectedEntryType.id === 'github') { - ctrl.githubToken = lodash.chain(ctrl.version.spec.build).get('codeEntryAttributes.headers', {}).find(function (value, key) { - return key.toLowerCase() === 'authorization'; - }).defaultTo('token ').value().split(/\s+/g)[1]; - } - } else { - ctrl.selectedEntryType = ctrl.codeEntryTypeArray[0]; - lodash.set(ctrl.version, 'spec.build.codeEntryType', ctrl.selectedEntryType.id); - } + // get content type from event. + ctrl.contentType = lodash.get(ctrl.selectedEvent, 'spec.attributes.headers.Content-Type'); - previousEntryType = ctrl.selectedEntryType; - } + // get header from event. + ctrl.selectedHeader = lodash.find(ctrl.headers, ['id', ctrl.contentType]); } // @@ -20517,346 +20821,166 @@ angular.module('angular-i18next', []).provider('i18next', [function () { // /** - * Sets new value to entity type and prepares the relevant fields for this type. - * @param {Object} item - the selected option of "Code Entry Type" drop-down field. + * Saves newly created event on beck-end. + * If error occurs while saving event, then dialog remains open. + * @param {Event} event - JS event object */ - function selectEntryTypeValue(item) { - ctrl.selectedEntryType = item; - - lodash.set(ctrl.version, 'spec.build.codeEntryType', ctrl.selectedEntryType.id); - var functionSourceCode = lodash.get(ctrl.version, 'spec.build.functionSourceCode', ''); - - // delete the following paths ... - lodash.forEach(['spec.image', 'spec.build.codeEntryAttributes', 'spec.build.path', 'spec.build.functionSourceCode'], lodash.unset.bind(lodash, ctrl.version)); + function applyChanges(event) { + ctrl.functionEventForm.$setSubmitted(); - // ... then fill only the relevant ones with default value according to the selected option - lodash.merge(ctrl.version, item.defaultValues); + if ((angular.isUndefined(event) || event.keyCode === EventHelperService.ENTER) && ctrl.functionEventForm.$valid && ctrl.isFormChanged) { - if (item.id === 'sourceCode') { + // show 'Loading...' button + ctrl.isLoadingState = true; - // restore source code that was preserved in memory - if such exists - var savedSourceCode = lodash.get(ctrl.version, 'ui.versionCode', ''); - lodash.set(ctrl.version, 'spec.build.functionSourceCode', savedSourceCode); - ctrl.sourceCode = Base64.decode(savedSourceCode); + // save created event on beck-end + ctrl.createFunctionEvent({ eventData: ctrl.workingCopy, isNewEvent: ctrl.createEvent }).then(function () { + ctrl.isDeployFailed = false; - if (!lodash.isNil(scrollContainer)) { - $timeout(function () { - scrollContainer.style.height = '100%'; + // close dialog with newly created or updated event data, and state of event. + ctrl.closeDialog({ + result: { + isEventDeployed: true, // If isEventDeployed is 'true' that mean - dialog was closed after creating event, not by pressing 'X' button. + selectedEvent: ctrl.workingCopy + } }); - } - - $rootScope.$broadcast('change-state-deploy-button', { component: 'code', isDisabled: false }); - } else { + }).catch(function () { - // preserve source code (for later using it if the user selects "Edit Online" option) - if (previousEntryType.id === 'sourceCode') { - lodash.set(ctrl.version, 'ui.versionCode', functionSourceCode); - } + // dialog remains open. + // show error text + ctrl.isDeployFailed = true; - // disable "Deploy" button if required fields of the selected option are empty - if (item.id === 'image' && lodash.isEmpty(ctrl.version.spec.image) || item.id !== 'image' && lodash.isEmpty(ctrl.version.spec.build.path)) { - $rootScope.$broadcast('change-state-deploy-button', { component: 'code', isDisabled: true }); - } + // hide 'Loading...' button + ctrl.isLoadingState = false; + }); } - - previousEntryType = ctrl.selectedEntryType; - } - - /** - * Sets new selected theme for editor - * @param {Object} item - */ - function selectThemeValue(item) { - ctrl.version.ui.editorTheme = item; - ctrl.selectedTheme = item; - } - - /** - * Sets new value to runtime - * @param {Object} item - */ - function selectRuntimeValue(item) { - ctrl.selectedRuntime = item; - ctrl.editorLanguage = ctrl.selectedRuntime.language; - - lodash.set(ctrl.version, 'spec.runtime', item.id); - lodash.set(ctrl.version, 'spec.build.functionSourceCode', item.sourceCode); - lodash.set(ctrl.version, 'ui.versionCode', item.sourceCode); - - VersionHelperService.updateIsVersionChanged(ctrl.version); - } - - function onChangeGithubToken(newData) { - ctrl.githubToken = newData; - lodash.unset(ctrl.version, 'spec.build.codeEntryAttributes.headers.authorization'); - lodash.set(ctrl.version, 'spec.build.codeEntryAttributes.headers.Authorization', 'token ' + newData); } /** - * Changes function`s source code - * @param {string} sourceCode + * Closes dialog */ - function onChangeSourceCode(sourceCode) { - lodash.set(ctrl.version, 'spec.build.functionSourceCode', Base64.encode(sourceCode)); - lodash.set(ctrl.version, 'ui.versionCode', Base64.encode(sourceCode)); - - ctrl.sourceCode = sourceCode; + function closeEventDialog() { - VersionHelperService.updateIsVersionChanged(ctrl.version); + // close dialog only if event is not deploying. Means event was deployed / failed / not changed + if (!ctrl.isLoadingState) { + ctrl.closeDialog({ + result: { + isEventDeployed: false, + selectedEvent: ctrl.selectedEvent + } + }); + } } /** - * Update data callback - * @param {string} newData - * @param {string} field + * Sets new data from "Name" field to event object + * @param {string} newData - data to be set + * @param {string} field - field which was changed */ function inputValueCallback(newData, field) { - lodash.set(ctrl.version, field, newData); - VersionHelperService.updateIsVersionChanged(ctrl.version); + lodash.set(ctrl.workingCopy.spec, field === 'path' ? 'attributes.path' : field, newData); - $timeout(function () { - $rootScope.$broadcast('change-state-deploy-button', { - component: 'code', - isDisabled: ctrl.versionCodeForm.$invalid - }); - }); + isFormChanged(); } - // - // Private methods - // - /** - * Extracts a file name from a provided path - * @param {string} path - the path including a file name (delimiters: '/' or '\' or both, can be consecutive) - * @param {boolean} [includeExtension=true] - set to `true` to include extension, or `false` to exclude it - * @param {boolean} [onlyExtension=false] - set to `true` to include extension only, or `false` to include file - * name - * @returns {string} the file name at the end of the given path with or without its extension (depending on the - * value of `extension` parameter) - * - * @example - * ```js - * extractFileName('/path/to/file/file.name.ext'); - * // => 'file.name.ext' - * - * extractFileName('\\path/to\\file/file.name.ext', false); - * // => 'file.name' - * - * extractFileName('file.name.ext', false); - * // => 'file.name' - * - * extractFileName('/path/to/////file\\\\\\\\file.name.ext', true); - * // => 'file.name.ext' - * - * extractFileName('/path/to/file\file.name.ext', true, true); - * // => 'ext' - * - * extractFileName('/path/to/file/file.name.ext', false, true); - * // => '.' - * - * extractFileName(''); - * // => '' - * - * extractFileName(undefined); - * // => '' - * - * extractFileName(null); - * // => '' - * ``` + * Callback from method drop-down + * Sets new selected method + * @param {Object} item - new selected item */ - function extractFileName(path, includeExtension, onlyExtension) { - var start = path.lastIndexOf(lodash.defaultTo(onlyExtension, false) ? '.' : '/') + 1; - var end = lodash.defaultTo(includeExtension, true) ? path.length : path.lastIndexOf('.'); + function onSelectMethod(item) { + lodash.set(ctrl.workingCopy, 'spec.attributes.method', item.id); - return lodash.defaultTo(path, '').replace('\\', '/').substring(start, end); + isFormChanged(); } /** - * Gets all runtimes - * @returns {Array} + * Callback from Content Type drop-down + * Sets new selected header + * @param {Object} item - new selected item */ - function getRuntimes() { + function onSelectHeader(item) { + lodash.set(ctrl.workingCopy, 'spec.attributes.headers.Content-Type', item.id); + ctrl.contentType = item.id; - // language identifiers for monaco editor are taken from: - // https://code.visualstudio.com/docs/languages/identifiers#_known-language-identifiers - return [{ - id: 'golang', - ext: 'go', - name: 'Go', - language: 'go', - sourceCode: 'cGFja2FnZSBtYWluDQoNCmltcG9ydCAoDQogICAgImdpdGh1Yi5jb20vbnVjbGlvL251Y2xpby1zZGstZ28iDQo' + 'pDQoNCmZ1bmMgSGFuZGxlcihjb250ZXh0ICpudWNsaW8uQ29udGV4dCwgZXZlbnQgbnVjbGlvLkV2ZW50KSAoaW50ZXJmYWNle3' + '0sIGVycm9yKSB7DQogICAgcmV0dXJuIG5pbCwgbmlsDQp9', // source code in base64 - visible: true - }, { - id: 'python:2.7', - ext: 'py', - name: 'Python 2.7', - language: 'python', - sourceCode: 'ZGVmIGhhbmRsZXIoY29udGV4dCwgZXZlbnQpOg0KICAgIHJldHVybiAiIg==', // source code in base64 - visible: true - }, { - id: 'python:3.6', - ext: 'py', - name: 'Python 3.6', - language: 'python', - sourceCode: 'ZGVmIGhhbmRsZXIoY29udGV4dCwgZXZlbnQpOg0KICAgIHJldHVybiAiIg==', // source code in base64 - visible: true - }, { - id: 'dotnetcore', - ext: 'cs', - name: '.NET Core', - language: 'csharp', - sourceCode: 'dXNpbmcgU3lzdGVtOw0KdXNpbmcgTnVjbGlvLlNkazsNCg0KcHVibGljIGNsYXNzIG1haW4NCnsNCiAgICBwdWJ' + 'saWMgb2JqZWN0IGhhbmRsZXIoQ29udGV4dCBjb250ZXh0LCBFdmVudCBldmVudEJhc2UpDQogICAgew0KICAgICAgICByZXR1cm' + '4gbmV3IFJlc3BvbnNlKCkNCiAgICAgICAgew0KICAgICAgICAgICAgU3RhdHVzQ29kZSA9IDIwMCwNCiAgICAgICAgICAgIENvb' + 'nRlbnRUeXBlID0gImFwcGxpY2F0aW9uL3RleHQiLA0KICAgICAgICAgICAgQm9keSA9ICIiDQogICAgICAgIH07DQogICAgfQ0K' + 'fQ==', // source code in base64 - visible: true - }, { - id: 'java', - ext: 'java', - name: 'Java', - language: 'java', - sourceCode: 'aW1wb3J0IGlvLm51Y2xpby5Db250ZXh0Ow0KaW1wb3J0IGlvLm51Y2xpby5FdmVudDsNCmltcG9ydCBpby5udWN' + 'saW8uRXZlbnRIYW5kbGVyOw0KaW1wb3J0IGlvLm51Y2xpby5SZXNwb25zZTsNCg0KcHVibGljIGNsYXNzIEhhbmRsZXIgaW1wbG' + 'VtZW50cyBFdmVudEhhbmRsZXIgew0KDQogICAgQE92ZXJyaWRlDQogICAgcHVibGljIFJlc3BvbnNlIGhhbmRsZUV2ZW50KENvb' + 'nRleHQgY29udGV4dCwgRXZlbnQgZXZlbnQpIHsNCiAgICAgICByZXR1cm4gbmV3IFJlc3BvbnNlKCkuc2V0Qm9keSgiIik7DQog' + 'ICAgfQ0KfQ==', - visible: true - }, { - id: 'nodejs', - ext: 'js', - language: 'javascript', - sourceCode: 'ZXhwb3J0cy5oYW5kbGVyID0gZnVuY3Rpb24oY29udGV4dCwgZXZlbnQpIHsNCiAgICBjb250ZXh0LmNhbGxiYWN' + 'rKCcnKTsNCn07', // source code in base64 - name: 'NodeJS', - visible: true - }, { - id: 'shell', - ext: 'sh', - name: 'Shell', - language: 'shellscript', - sourceCode: '', - visible: true - }, { - id: 'ruby', - ext: 'rb', - name: 'Ruby', - language: 'ruby', - sourceCode: 'ZGVmIGhhbmRsZXIoY29udGV4dCwgZXZlbnQpDQplbmQ=', // source code in base64 - visible: true - }]; + isFormChanged(); } /** - * Tests whether a file is valid for dropping in code editor according to its MIME type and its extension - * @param {string} type - the MIME type of the file (e.g. 'text/plain', 'application/javascript') - * @param {string} extension - the extension of the file (e.g. 'txt', 'py', 'html') - * @returns {boolean} `true` if the file is valid for dropping in code editor, or `false` otherwise + * Callback from body field. */ - function isFileDropValid(type, extension) { + function onChangeBody() { + isFormChanged(); + } - // Drag'n'Drop textual files into the code editor - var validFileExtensions = ['cs', 'py', 'go', 'sh', 'txt', 'js', 'java']; + function onChangeSourceCode(sourceCode) { + lodash.set(ctrl.workingCopy, 'spec.body', sourceCode); - return lodash(type).startsWith('text/') || validFileExtensions.includes(extension); + isFormChanged(); } + // + // Private methods + // + /** - * Sets informational background over monaco editor before dropping a file + * Compares original object and working object to get know if fields was changed + * Also check if form valid and set result to corresponding variable */ - function onDragNDropFile() { - var codeEditor = $element.find('.monaco-code-editor'); - var nclMonaco = $element.find('.ncl-monaco'); - var codeEditorDropZone = $element.find('.code-editor-drop-zone'); - - // Register event handlers for drag'n'drop of files to code editor - codeEditor.on('dragover', null, false).on('dragenter', null, function (event) { - codeEditorDropZone.addClass('dragover'); + function isFormChanged() { + $timeout(function () { + ctrl.isFormChanged = !lodash.isEqual(ctrl.workingCopy, ctrl.selectedEvent) && lodash.isEmpty(ctrl.functionEventForm.$error); + }); + } + } +})(); +'use strict'; - codeEditor.css('opacity', '0.4'); - event.preventDefault(); - }).on('dragleave', null, function (event) { - var monacoCoords = nclMonaco[0].getBoundingClientRect(); +(function () { + 'use strict'; - if (event.originalEvent.pageX <= monacoCoords.left || event.originalEvent.pageX >= monacoCoords.right || event.originalEvent.pageY >= monacoCoords.bottom || event.originalEvent.pageY <= monacoCoords.top) { - codeEditorDropZone.removeClass('dragover'); - codeEditor.css('opacity', ''); - } + NclVersionConfigurationController.$inject = ['lodash', 'ConfigService', 'VersionHelperService']; + angular.module('iguazio.dashboard-controls').component('nclVersionConfiguration', { + bindings: { + version: '<' + }, + templateUrl: 'nuclio/functions/version/version-configuration/version-configuration.tpl.html', + controller: NclVersionConfigurationController + }); - event.preventDefault(); - }).on('drop', null, function (event) { - var itemType = lodash.get(event, 'originalEvent.dataTransfer.items[0].type'); - var file = lodash.get(event, 'originalEvent.dataTransfer.files[0]'); - var extension = extractFileName(file.name, true, true); + function NclVersionConfigurationController(lodash, ConfigService, VersionHelperService) { + var ctrl = this; - if (isFileDropValid(itemType, extension)) { - var reader = new FileReader(); + ctrl.scrollConfig = { + axis: 'y', + advanced: { + autoScrollOnFocus: false, + updateOnContentResize: true + } + }; - reader.onload = function (onloadEvent) { - var functionSource = { - language: lodash.chain(ctrl.runtimeArray).find(['ext', extension]).defaultTo({ - language: 'plaintext' - }).value().language, - code: onloadEvent.target.result - }; - ctrl.sourceCode = functionSource.code; - ctrl.editorLanguage = functionSource.language; - $scope.$apply(); + ctrl.isDemoMode = ConfigService.isDemoMode; - codeEditorDropZone.removeClass('dragover'); - codeEditor.css('opacity', ''); - }; - reader.onerror = function () { - DialogsService.alert($i18next.t('functions.ERROR_MSG:COULD_NOT_READ_FILE', { lng: lng })); - }; - reader.readAsText(file); - } else { - codeEditorDropZone.removeClass('dragover'); - codeEditor.css('opacity', ''); + ctrl.isRuntimeBlockVisible = isRuntimeBlockVisible; + ctrl.onConfigurationChangeCallback = onConfigurationChangeCallback; - DialogsService.alert($i18next.t('common:INVALID_FILE_TYPE_EXTENSION', { lng: lng })); - } - event.preventDefault(); - }); - } + // + // Public methods + // /** - * Resize scrollbar container. - * Layout directive (splitter) makes changes to width of scrollbar container. But scrollbar doesn't handle - * those changes in correct way. So we have to set width manually - * @param {Event} e - native broadcast event object - * @param {number} [timeout=200] - function invocation delay in milliseconds + * Checks if `Runtime Attributes` block is visible + * @returns {boolean} */ - function resizeScrollBar(e, timeout) { - $timeout(function () { - var CODE_CONTAINER_MIN_WIDTH = 700; - - // if scrollbar container is wider than minimal code container width (scrollbar is not needed) - if (angular.element($element.find('.code-scrollable-container')).width() >= CODE_CONTAINER_MIN_WIDTH) { - // make sure that scrollbar container takes all available width - angular.element($element.find('.mCSB_container')[0]).css('width', '100%'); - - // hide scrollbar (make it disabled) - angular.element($element.find('.igz-scrollable-container')[0]).mCustomScrollbar('disable', true); - } else { - // set code's container minimal width to scrollbar container - angular.element($element.find('.mCSB_container')[0]).css('width', CODE_CONTAINER_MIN_WIDTH + 'px'); - } - - $timeout(function () { - // Enable scrolling again or show scrollbar - angular.element($element.find('.igz-scrollable-container')[0]).mCustomScrollbar('update'); - }, 100); - }, timeout || 200); + function isRuntimeBlockVisible() { + return lodash.includes(['shell', 'java'], lodash.get(ctrl.version, 'spec.runtime')); } /** - * Broadcast's callback to toggle test pane - * @param {Event} event - native broadcast event object - * @param {Object} data - contains data of test pane state (closed/opened) + * Checks if version's configuration was changed */ - function toggleTestPane(event, data) { - if (data.closeTestPane) { - ctrl.layout.collapsed = true; - angular.element(angular.element('.ui-splitbar')[0]).css('display', 'none'); - } else { - ctrl.layout.collapsed = false; - angular.element(angular.element('.ui-splitbar')[0]).css('display', 'block'); - } - - resizeScrollBar(null, 300); + function onConfigurationChangeCallback() { + VersionHelperService.updateIsVersionChanged(ctrl.version); } } })(); @@ -23505,8 +23629,8 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('igz_controls/components/auto-complete/auto-complete.tpl.html', - '
  • {{ item.label }} {{ item.additionalInfo }}
  • {{ \'common:LOADING_CAPITALIZE_ELLIPSIS\' | i18next }}
  • {{$ctrl.emptyMessage}}

  • {{ \'common:MORE_ELLIPSIS\' | i18next }}
'); + $templateCache.put('igz_controls/components/copy-to-clipboard/copy-to-clipboard.tpl.html', + '
'); }]); })(); @@ -23517,8 +23641,13 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('igz_controls/components/copy-to-clipboard/copy-to-clipboard.tpl.html', - '
'); + $templateCache.put('igz_controls/components/default-dropdown/default-dropdown.tpl.html', + '
  • {{item.badge.value}}
    {{$ctrl.getName(item)}} {{$ctrl.getDescription(item)}}
'); }]); })(); @@ -23529,13 +23658,8 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('igz_controls/components/default-dropdown/default-dropdown.tpl.html', - '
  • {{item.badge.value}}
    {{$ctrl.getName(item)}} {{$ctrl.getDescription(item)}}
'); + $templateCache.put('igz_controls/components/auto-complete/auto-complete.tpl.html', + '
  • {{ item.label }} {{ item.additionalInfo }}
  • {{ \'common:LOADING_CAPITALIZE_ELLIPSIS\' | i18next }}
  • {{$ctrl.emptyMessage}}

  • {{ \'common:MORE_ELLIPSIS\' | i18next }}
'); }]); })(); @@ -23638,8 +23762,8 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('igz_controls/components/search-input/search-input.tpl.html', - '
'); + $templateCache.put('igz_controls/components/pagination/pagination.component.tpl.html', + '
{{ \'common:ROWS_PER_PAGE\' | i18next }}:
{{$ctrl.page + 1}}
 {{ \'common:OF_PAGES\' | i18next:{pagesTotal: $ctrl.pageData.total} }}
'); }]); })(); @@ -23650,8 +23774,8 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('igz_controls/components/pagination/pagination.component.tpl.html', - '
{{ \'common:ROWS_PER_PAGE\' | i18next }}:
{{$ctrl.page + 1}}
 {{ \'common:OF_PAGES\' | i18next:{pagesTotal: $ctrl.pageData.total} }}
'); + $templateCache.put('igz_controls/components/size/size.tpl.html', + '
{{$ctrl.getDisplayValue()}}
{{$ctrl.getDisplayValue()}}
{{$ctrl.getDisplayValue()}}
{{ \'common:OF\' | i18next }} {{$ctrl.outOf}}
{{$ctrl.getDisplayValue()}}
{{$ctrl.reserved}} {{$ctrl.quota}}
'); }]); })(); @@ -23662,8 +23786,8 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('igz_controls/components/size/size.tpl.html', - '
{{$ctrl.getDisplayValue()}}
{{$ctrl.getDisplayValue()}}
{{$ctrl.getDisplayValue()}}
{{ \'common:OF\' | i18next }} {{$ctrl.outOf}}
{{$ctrl.getDisplayValue()}}
{{$ctrl.reserved}} {{$ctrl.quota}}
'); + $templateCache.put('igz_controls/components/search-input/search-input.tpl.html', + '
'); }]); })(); @@ -23892,8 +24016,8 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('igz_controls/components/info-page/info-page-actions-bar/info-page-actions-bar.tpl.html', - '
'); + $templateCache.put('igz_controls/components/info-page/info-page-content/info-page-content.tpl.html', + '
'); }]); })(); @@ -23904,8 +24028,8 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('igz_controls/components/info-page/info-page-content/info-page-content.tpl.html', - '
'); + $templateCache.put('igz_controls/components/info-page/info-page-actions-bar/info-page-actions-bar.tpl.html', + '
'); }]); })(); @@ -23990,11 +24114,8 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('nuclio/common/components/key-value-input/key-value-input.tpl.html', - '
'); + $templateCache.put('nuclio/common/components/function-config-dialog/function-config-dialog.tpl.html', + '
{{ $ctrl.title }}
'); }]); })(); @@ -24005,8 +24126,11 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('nuclio/common/components/function-config-dialog/function-config-dialog.tpl.html', - '
{{ $ctrl.title }}
'); + $templateCache.put('nuclio/common/components/key-value-input/key-value-input.tpl.html', + '
'); }]); })(); @@ -24030,8 +24154,8 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('nuclio/common/components/navigation-tabs/navigation-tabs.tpl.html', - '
'); + $templateCache.put('nuclio/common/components/nuclio-search-input/search-input.tpl.html', + '
'); }]); })(); @@ -24042,8 +24166,8 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('nuclio/common/components/nuclio-search-input/search-input.tpl.html', - '
'); + $templateCache.put('nuclio/common/components/navigation-tabs/navigation-tabs.tpl.html', + '
'); }]); })(); @@ -24080,9 +24204,8 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('nuclio/functions/version/function-event-dialog/function-event-dialog.tpl.html', - '
{{$ctrl.titleText}}
{{ \'common:NAME\' | i18next }}
{{ \'functions:METHOD\' | i18next }}
{{ \'common:PATH\' | i18next }}
{{ \'functions:CONTENT_TYPE\' | i18next }}
{{ \'functions:BODY\' | i18next }}
{{$ctrl.errorText}}
{{ \'common:LOADING_CAPITALIZE_ELLIPSIS\' | i18next }}
'); + $templateCache.put('nuclio/functions/version/version-code/version-code.tpl.html', + '
{{ \'functions:CODE_ENTRY_TYPE\' | i18next }}
{{ \'functions:RUNTIME\' | i18next }}
{{ \'functions:HANDLER\' | i18next }}
{{ \'functions:THEME\' | i18next }}
{{ \'functions:SOURCE_CODE\' | i18next }}
{{ \'functions:CODE_ENTRY_TYPE\' | i18next }}
{{ \'functions:RUNTIME\' | i18next }}
{{ \'functions:HANDLER\' | i18next }}
{{ \'functions:IMAGE_NAME\' | i18next }}
{{ \'common:URL\' | i18next }}
{{ \'functions:ACCESS_KEY_V3IO_ONLY\' | i18next }}
{{ \'functions:WORK_DIRECTORY\' | i18next }}
{{ \'common:URL\' | i18next }}
{{ \'functions:BRANCH\' | i18next }}
{{ \'functions:TOKEN\' | i18next }}
{{ \'functions:WORK_DIRECTORY\' | i18next }}
{{ \'functions:BUCKET\' | i18next }}
{{ \'functions:ITEM_KEY\' | i18next }}
{{ \'functions:ACCESS_KEY_ID\' | i18next }}
{{ \'functions:SECRET_ACCESS_KEY\' | i18next }}
{{ \'functions:SESSION_TOKEN\' | i18next }}
{{ \'functions:REGION\' | i18next }}
{{ \'functions:WORK_DIRECTORY\' | i18next }}
'); }]); })(); @@ -24093,8 +24216,9 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('nuclio/functions/version/version-configuration/version-configuration.tpl.html', - '
'); + $templateCache.put('nuclio/functions/version/function-event-dialog/function-event-dialog.tpl.html', + '
{{$ctrl.titleText}}
{{ \'common:NAME\' | i18next }}
{{ \'functions:METHOD\' | i18next }}
{{ \'common:PATH\' | i18next }}
{{ \'functions:CONTENT_TYPE\' | i18next }}
{{ \'functions:BODY\' | i18next }}
{{$ctrl.errorText}}
{{ \'common:LOADING_CAPITALIZE_ELLIPSIS\' | i18next }}
'); }]); })(); @@ -24105,8 +24229,8 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('nuclio/functions/version/version-code/version-code.tpl.html', - '
{{ \'functions:CODE_ENTRY_TYPE\' | i18next }}
{{ \'functions:RUNTIME\' | i18next }}
{{ \'functions:HANDLER\' | i18next }}
{{ \'functions:THEME\' | i18next }}
{{ \'functions:SOURCE_CODE\' | i18next }}
{{ \'functions:CODE_ENTRY_TYPE\' | i18next }}
{{ \'functions:RUNTIME\' | i18next }}
{{ \'functions:HANDLER\' | i18next }}
{{ \'functions:IMAGE_NAME\' | i18next }}
{{ \'common:URL\' | i18next }}
{{ \'functions:ACCESS_KEY_V3IO_ONLY\' | i18next }}
{{ \'functions:WORK_DIRECTORY\' | i18next }}
{{ \'common:URL\' | i18next }}
{{ \'functions:BRANCH\' | i18next }}
{{ \'functions:TOKEN\' | i18next }}
{{ \'functions:WORK_DIRECTORY\' | i18next }}
{{ \'functions:BUCKET\' | i18next }}
{{ \'functions:ITEM_KEY\' | i18next }}
{{ \'functions:ACCESS_KEY_ID\' | i18next }}
{{ \'functions:SECRET_ACCESS_KEY\' | i18next }}
{{ \'functions:SESSION_TOKEN\' | i18next }}
{{ \'functions:REGION\' | i18next }}
{{ \'functions:WORK_DIRECTORY\' | i18next }}
'); + $templateCache.put('nuclio/functions/version/version-configuration/version-configuration.tpl.html', + '
'); }]); })(); @@ -24228,8 +24352,8 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('nuclio/functions/version/version-configuration/tabs/version-configuration-basic-settings/version-configuration-basic-settings.tpl.html', - '
{{ \'common:BASIC_SETTINGS\' | i18next }}
{{ \'functions:MIN\' | i18next }}
{{ \'functions:SEC\' | i18next }}
{{ \'common:DESCRIPTION\' | i18next }}
{{ \'common:RUN_AS_USER\' | i18next }}
{{ \'common:RUN_AS_GROUP\' | i18next }}
{{ \'common:FS_GROUP\' | i18next }}
{{ \'functions:LOGGER_LEVEL\' | i18next }}
{{ \'functions:LOGGER_DESTINATION\' | i18next }}
'); + $templateCache.put('nuclio/functions/version/version-code/function-event-pane/test-events-logs/test-events-logs.tpl.html', + '
{{log.time | date: "EEE, MMM d, yyyy, HH:mm:ss\'GMT\'" : "+0000"}}
{{log.message}}
{{log.time | date: "EEE, MMM d, yyyy, HH:mm:ss\'GMT\'" : "+0000"}}
{{log.message}}
{{log.err}}
{{ \'common:PARAMETERS\' | i18next }}
{{key}}:
{{value}}
{{ \'functions:NO_LOGS_HAVE_BEEN_FOUND\' | i18next }}
'); }]); })(); @@ -24240,8 +24364,8 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('nuclio/functions/version/version-configuration/tabs/version-configuration-annotations/version-configuration-annotations.tpl.html', - '
{{ \'functions:ANNOTATIONS\' | i18next }}
{{ \'common:KEY\' | i18next }}
{{ \'common:VALUE\' | i18next }}
{{ \'functions:CREATE_NEW_ANNOTATION\' | i18next }}
'); + $templateCache.put('nuclio/functions/version/version-code/function-event-pane/test-events-navigation-tabs/test-events-navigation-tabs.tpl.html', + '
{{item.tabName | uppercase}} {{item.badge}}
'); }]); })(); @@ -24252,8 +24376,8 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('nuclio/functions/version/version-configuration/tabs/version-configuration-build/version-configuration-build.tpl.html', - '
{{ \'functions:BUILD\' | i18next }}
{{ \'functions:DISABLED_FOR_IMAGE_CODE_ENTRY_TYPE\' | i18next }}
{{ \'functions:IMAGE_NAME\' | i18next }}
{{ $ctrl.version.ui.imageNamePrefix }}
{{ \'functions:BASE_IMAGE\' | i18next }}
{{ \'functions:ONBUILD_IMAGE\' | i18next }}
{{ \'functions:BUILD_COMMANDS\' | i18next }}
{{ \'functions:READINESS_TIMEOUT_SECONDS\' | i18next }}
{{ \'functions:REPOSITORIES\' | i18next }}
{{ \'functions:DEPENDENCIES\' | i18next }}
{{$ctrl.getFileConfig().name}}
{{$ctrl.script.name}} (/usr/bin/mybinary)
{{$ctrl.file.name}} (/usr/bin/mybinary)
'); + $templateCache.put('nuclio/functions/version/version-configuration/tabs/version-configuration-annotations/version-configuration-annotations.tpl.html', + '
{{ \'functions:ANNOTATIONS\' | i18next }}
{{ \'common:KEY\' | i18next }}
{{ \'common:VALUE\' | i18next }}
{{ \'functions:CREATE_NEW_ANNOTATION\' | i18next }}
'); }]); })(); @@ -24264,8 +24388,8 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('nuclio/functions/version/version-configuration/tabs/version-configuration-environment-variables/version-configuration-environment-variables.tpl.html', - '
{{ \'functions:ENVIRONMENT_VARIABLES\' | i18next }}
{{ \'functions:CREATE_NEW_ENVIRONMENT_VARIABLE\' | i18next }}
'); + $templateCache.put('nuclio/functions/version/version-configuration/tabs/version-configuration-build/version-configuration-build.tpl.html', + '
{{ \'functions:BUILD\' | i18next }}
{{ \'functions:DISABLED_FOR_IMAGE_CODE_ENTRY_TYPE\' | i18next }}
{{ \'functions:IMAGE_NAME\' | i18next }}
{{ $ctrl.version.ui.imageNamePrefix }}
{{ \'functions:BASE_IMAGE\' | i18next }}
{{ \'functions:ONBUILD_IMAGE\' | i18next }}
{{ \'functions:BUILD_COMMANDS\' | i18next }}
{{ \'functions:READINESS_TIMEOUT_SECONDS\' | i18next }}
{{ \'functions:REPOSITORIES\' | i18next }}
{{ \'functions:DEPENDENCIES\' | i18next }}
{{$ctrl.getFileConfig().name}}
{{$ctrl.script.name}} (/usr/bin/mybinary)
{{$ctrl.file.name}} (/usr/bin/mybinary)
'); }]); })(); @@ -24276,8 +24400,8 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('nuclio/functions/version/version-configuration/tabs/version-configuration-labels/version-configuration-labels.tpl.html', - '
{{ \'functions:LABELS\' | i18next }}
{{ \'common:KEY\' | i18next }}
{{ \'common:VALUE\' | i18next }}
{{ \'functions:CREATE_NEW_LABEL\' | i18next }}
'); + $templateCache.put('nuclio/functions/version/version-configuration/tabs/version-configuration-basic-settings/version-configuration-basic-settings.tpl.html', + '
{{ \'common:BASIC_SETTINGS\' | i18next }}
{{ \'functions:MIN\' | i18next }}
{{ \'functions:SEC\' | i18next }}
{{ \'common:DESCRIPTION\' | i18next }}
{{ \'common:RUN_AS_USER\' | i18next }}
{{ \'common:RUN_AS_GROUP\' | i18next }}
{{ \'common:FS_GROUP\' | i18next }}
{{ \'functions:LOGGER_LEVEL\' | i18next }}
{{ \'functions:LOGGER_DESTINATION\' | i18next }}
'); }]); })(); @@ -24288,8 +24412,8 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('nuclio/functions/version/version-configuration/tabs/version-configuration-logging/version-configuration-logging.tpl.html', - '
{{ \'functions:LOGGING\' | i18next }}
'); + $templateCache.put('nuclio/functions/version/version-configuration/tabs/version-configuration-environment-variables/version-configuration-environment-variables.tpl.html', + '
{{ \'functions:ENVIRONMENT_VARIABLES\' | i18next }}
{{ \'functions:CREATE_NEW_ENVIRONMENT_VARIABLE\' | i18next }}
'); }]); })(); @@ -24300,8 +24424,8 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('nuclio/functions/version/version-configuration/tabs/version-configuration-resources/version-configuration-resources.tpl.html', - '
{{ \'common:RESOURCES\' | i18next }}
{{ \'common:MEMORY\' | i18next }}
{{ \'common:REQUEST\' | i18next }}
{{ \'common:LIMIT\' | i18next }}
{{ \'common:CPU\' | i18next }}
{{ \'common:REQUEST\' | i18next }}
{{ \'common:LIMIT\' | i18next }}
{{ \'common:GPU\' | i18next }}
{{ \'common:LIMIT\' | i18next }}
{{ \'common:REPLICAS\' | i18next }}
{{ \'functions:MIN\' | i18next }}
{{ \'functions:MAX\' | i18next }}
{{ \'common:INACTIVITY_WINDOW\' | i18next }}
{{ \'common:TARGET_CPU\' | i18next }}
'); + $templateCache.put('nuclio/functions/version/version-configuration/tabs/version-configuration-labels/version-configuration-labels.tpl.html', + '
{{ \'functions:LABELS\' | i18next }}
{{ \'common:KEY\' | i18next }}
{{ \'common:VALUE\' | i18next }}
{{ \'functions:CREATE_NEW_LABEL\' | i18next }}
'); }]); })(); @@ -24312,8 +24436,8 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('nuclio/functions/version/version-configuration/tabs/version-configuration-runtime-attributes/version-configuration-runtime-attributes.tpl.html', - '
{{ \'functions:RUNTIME_ATTRIBUTES\' | i18next }}
{{ \'functions:RUNTIME\' | i18next }}
{{$ctrl.version.spec.runtime}}
{{ \'common:ARGUMENTS\' | i18next }}
{{ \'functions:JVM_OPTIONS\' | i18next }}
{{ \'functions:RESPONSE_HEADERS\' | i18next }}
{{ \'common:KEY\' | i18next }}
{{ \'common:VALUE\' | i18next }}
{{ \'functions:CREATE_NEW_RUNTIME_ATTRIBUTE\' | i18next }}
'); + $templateCache.put('nuclio/functions/version/version-configuration/tabs/version-configuration-logging/version-configuration-logging.tpl.html', + '
{{ \'functions:LOGGING\' | i18next }}
'); }]); })(); @@ -24324,8 +24448,8 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('nuclio/functions/version/version-configuration/tabs/version-configuration-volumes/version-configuration-volumes.tpl.html', - '
{{ \'functions:VOLUMES\' | i18next }}
{{ \'common:NAME\' | i18next }}
{{ \'common:TYPE\' | i18next }}
{{ \'functions:MOUNT_PATH_PARAMS\' | i18next }}
{{ \'functions:CREATE_NEW_VOLUME\' | i18next }}
'); + $templateCache.put('nuclio/functions/version/version-configuration/tabs/version-configuration-resources/version-configuration-resources.tpl.html', + '
{{ \'functions:NODE_SELECTORS\' | i18next }}
{{ \'functions:CREATE_NEW_NODE_SELECTOR\' | i18next }}
{{ \'common:RESOURCES\' | i18next }}
{{ \'common:MEMORY\' | i18next }}
{{ \'common:REQUEST\' | i18next }}
{{ \'common:LIMIT\' | i18next }}
{{ \'common:CPU\' | i18next }}
{{ \'common:REQUEST\' | i18next }}
{{ \'common:LIMIT\' | i18next }}
{{ \'common:GPU\' | i18next }}
{{ \'common:LIMIT\' | i18next }}
{{ \'common:REPLICAS\' | i18next }}
{{ \'functions:MIN\' | i18next }}
{{ \'functions:MAX\' | i18next }}
{{ \'common:INACTIVITY_WINDOW\' | i18next }}
{{ \'common:TARGET_CPU\' | i18next }}
'); }]); })(); @@ -24336,8 +24460,8 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('nuclio/functions/version/version-code/function-event-pane/test-events-navigation-tabs/test-events-navigation-tabs.tpl.html', - '
{{item.tabName | uppercase}} {{item.badge}}
'); + $templateCache.put('nuclio/functions/version/version-configuration/tabs/version-configuration-runtime-attributes/version-configuration-runtime-attributes.tpl.html', + '
{{ \'functions:RUNTIME_ATTRIBUTES\' | i18next }}
{{ \'functions:RUNTIME\' | i18next }}
{{$ctrl.version.spec.runtime}}
{{ \'common:ARGUMENTS\' | i18next }}
{{ \'functions:JVM_OPTIONS\' | i18next }}
{{ \'functions:RESPONSE_HEADERS\' | i18next }}
{{ \'common:KEY\' | i18next }}
{{ \'common:VALUE\' | i18next }}
{{ \'functions:CREATE_NEW_RUNTIME_ATTRIBUTE\' | i18next }}
'); }]); })(); @@ -24348,8 +24472,8 @@ try { module = angular.module('iguazio.dashboard-controls.templates', []); } module.run(['$templateCache', function($templateCache) { - $templateCache.put('nuclio/functions/version/version-code/function-event-pane/test-events-logs/test-events-logs.tpl.html', - '
{{log.time | date: "EEE, MMM d, yyyy, HH:mm:ss\'GMT\'" : "+0000"}}
{{log.message}}
{{log.time | date: "EEE, MMM d, yyyy, HH:mm:ss\'GMT\'" : "+0000"}}
{{log.message}}
{{log.err}}
{{ \'common:PARAMETERS\' | i18next }}
{{key}}:
{{value}}
{{ \'functions:NO_LOGS_HAVE_BEEN_FOUND\' | i18next }}
'); + $templateCache.put('nuclio/functions/version/version-configuration/tabs/version-configuration-volumes/version-configuration-volumes.tpl.html', + '
{{ \'functions:VOLUMES\' | i18next }}
{{ \'common:NAME\' | i18next }}
{{ \'common:TYPE\' | i18next }}
{{ \'functions:MOUNT_PATH_PARAMS\' | i18next }}
{{ \'functions:CREATE_NEW_VOLUME\' | i18next }}
'); }]); })(); diff --git a/dist/less/iguazio.dashboard-controls.less b/dist/less/iguazio.dashboard-controls.less index d0dc4059c..9c7b3905b 100644 --- a/dist/less/iguazio.dashboard-controls.less +++ b/dist/less/iguazio.dashboard-controls.less @@ -1,3 +1,9 @@ +.common-table-cell { + &.status { + min-width: 95px; + } +} + // // Common styles for buttons // @@ -3576,12 +3582,6 @@ html input[disabled], html textarea[disabled] { // Media Query @retina-display: ~"only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx)"; -.common-table-cell { - &.status { - min-width: 95px; - } -} - ncl-functions { igz-info-page-actions-bar { .igz-info-page-actions-bar { @@ -5883,105 +5883,6 @@ yx-axis } } -.auto-complete-wrapper { - .auto-complete-color-set(); - - position: relative; - - .input-row { - display: flex; - width: 100%; - - .auto-complete-input { - flex-grow: 3; - } - - .auto-complete-filters { - width: 20%; - } - } - - .suggestions-row { - .auto-complete-suggestions-container { - position: absolute; - background-color: @auto-complete-suggestions-container-bg-color; - border-radius: 2px; - box-shadow: @auto-complete-suggestions-container-box-shadow; - color: @auto-complete-suggestions-container-color; - max-height: 220px; - overflow: auto; - z-index: 1000; - width: 100%; - margin-top: 2px; - - .list { - padding: 0; - margin: 0; - - .list-item { - color: @auto-complete-list-item-color; - font-family: @font-family-sans-serif; - font-size: 14px; - list-style-type: none; - margin: 0; - outline: none; - width: 100%; - min-height: 32px; - - &:first-child { - margin-top: 7px; - } - - &:last-child { - margin-bottom: 4px; - } - - .list-item-block { - display: flex; - flex-flow: row nowrap; - align-items: center; - padding: 6px 16px; - width: 100%; - - .list-item-name { - flex: auto; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } - - .list-item-additional-info { - flex: none; - margin-left: 6px; - color: @auto-complete-list-item-additional-info-color; - } - } - - &:not(.readonly) { - cursor: pointer; - - &:hover, &:focus { - background-color: @auto-complete-list-item-hover-focus-bg-color; - } - } - - &.selected-item { - color: @auto-complete-list-item-selected-color; - } - } - - hr { - margin: 0; - } - } - } - - .auto-complete-suggestions-with-filters { - width: 80%; - } - } -} - .default-dropdown { .default-dropdown-color-set(); .severity-icons-color-set(); @@ -6422,6 +6323,105 @@ yx-axis } } +.auto-complete-wrapper { + .auto-complete-color-set(); + + position: relative; + + .input-row { + display: flex; + width: 100%; + + .auto-complete-input { + flex-grow: 3; + } + + .auto-complete-filters { + width: 20%; + } + } + + .suggestions-row { + .auto-complete-suggestions-container { + position: absolute; + background-color: @auto-complete-suggestions-container-bg-color; + border-radius: 2px; + box-shadow: @auto-complete-suggestions-container-box-shadow; + color: @auto-complete-suggestions-container-color; + max-height: 220px; + overflow: auto; + z-index: 1000; + width: 100%; + margin-top: 2px; + + .list { + padding: 0; + margin: 0; + + .list-item { + color: @auto-complete-list-item-color; + font-family: @font-family-sans-serif; + font-size: 14px; + list-style-type: none; + margin: 0; + outline: none; + width: 100%; + min-height: 32px; + + &:first-child { + margin-top: 7px; + } + + &:last-child { + margin-bottom: 4px; + } + + .list-item-block { + display: flex; + flex-flow: row nowrap; + align-items: center; + padding: 6px 16px; + width: 100%; + + .list-item-name { + flex: auto; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .list-item-additional-info { + flex: none; + margin-left: 6px; + color: @auto-complete-list-item-additional-info-color; + } + } + + &:not(.readonly) { + cursor: pointer; + + &:hover, &:focus { + background-color: @auto-complete-list-item-hover-focus-bg-color; + } + } + + &.selected-item { + color: @auto-complete-list-item-selected-color; + } + } + + hr { + margin: 0; + } + } + } + + .auto-complete-suggestions-with-filters { + width: 80%; + } + } +} + .element-loading-status { .element-loading-status-color-set(); @@ -7053,216 +7053,29 @@ yx-axis } } -.search-input { - .search-input-color-set(); +.igz-pagination { + .pagination-color-set(); - position: relative; - color: @search-input-color; + float: right; + padding: 24px 36px 5px 30px; - .container-search-input { - background-color: @search-input-bg-color; - border: 0; - font-family: @font-family-sans-serif; - font-size: 15px; - font-weight: 400; - height: 52px; - line-height: 52px; - margin: 0; - outline: 0; - padding-right: 20px; - width: 100%; + > div { + vertical-align: top; + } - &::-webkit-input-placeholder { - color: @search-input-placeholder-color; - } + .rows-title, .per-page, .jump-to-page, .to-page-prev, .to-page-next { + display: inline-block; + vertical-align: baseline; + } - &:-moz-placeholder { /* Firefox 18- */ - color: @search-input-placeholder-color; - } + .rows-title { + font-size: 13px; + color: @rows-title-color; + font-family: @font-family-sans-serif; + } - &::-moz-placeholder { /* Firefox 19+ */ - color: @search-input-placeholder-color; - } - - &:-ms-input-placeholder { - color: @search-input-placeholder-color; - } - - &:focus { - &, & + .igz-icon-search:before { - color: @search-input-focus-icon-search-before-color; - } - - &::-webkit-input-placeholder { - color: @search-input-focus-placeholder-color; - } - - &:-moz-placeholder { /* Firefox 18- */ - color: @search-input-focus-placeholder-color; - } - - &::-moz-placeholder { /* Firefox 19+ */ - color: @search-input-focus-placeholder-color; - } - - &:-ms-input-placeholder { - color: @search-input-focus-placeholder-color; - } - - &::placeholder { - /* modern browser versions */ - color: @search-input-focus-placeholder-color !important; - } - } - } - - .igz-icon-search { - font-size: 16px; - height: 16px; - position: absolute; - right: 0; - top: 17px; - width: 16px; - z-index: 1; - } - - .clear-button { - font-size: 10px; - position: absolute; - right: 4px; - top: 17px; - cursor: pointer; - color: @clear-button-color; - padding: 4px 5px 2px; - opacity: 0.64; - background-color: @clear-button-bg-color; - border-radius: 50%; - line-height: initial; - - &:hover { - opacity: 1; - } - } - - input::-ms-clear { - display: none; - } -} - -.search-input-actions-bar { - .search-input-color-set(); - - position: relative; - .container-search-input { - border: 0; - margin: 0; - font-family: @font-family-sans-serif; - font-size: 14px; - height: 52px; - line-height: 52px; - padding: 0 25px 0 45px; - outline: 0; - width: 100%; - } - - .igz-icon-search { - color: @search-input-actions-bar-icon-search-color; - font-size: 16px; - height: 16px; - position: absolute; - left: 18px; - top: 17px; - width: 16px; - z-index: 1; - } - - input::-ms-clear { - display: none; - } -} - -.search-input-not-found { - .search-input-color-set(); - - color: @search-input-not-found-color; - font-family: @font-family-sans-serif; - font-size: 14px; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - margin-top: 9px; - - .search-message { - min-height: 49px; - line-height: 49px; - width: 100%; - text-align: center; - letter-spacing: 0.1px; - border: @search-input-not-found-message-border; - } - - .create-item-button { - display: flex; - align-items: center; - padding: 0 19px 0 7px; - margin-top: 8px; - border-radius: 12px; - height: 24px; - color: @create-item-btn-color; - font-size: 12px; - font-weight: bold; - cursor: pointer; - background-color: @create-item-btn-bg-color; - border: @create-item-btn-border; - text-transform: uppercase; - - &:hover { - background-color: @create-item-btn-hover-bg-color; - box-shadow: @create-item-btn-hover-box-shadow; - border: @create-item-btn-hover-border; - } - - &:focus { - outline: none; - } - - &:active { - background-color: @create-item-btn-active-bg-color; - box-shadow: @create-item-btn-active-box-shadow; - border: none; - } - - .igz-icon-add { - font-size: 10px; - line-height: 15px; - padding-right: 8px; - } - } -} -.igz-pagination { - .pagination-color-set(); - - float: right; - padding: 24px 36px 5px 30px; - - > div { - vertical-align: top; - } - - .rows-title, .per-page, .jump-to-page, .to-page-prev, .to-page-next { - display: inline-block; - vertical-align: baseline; - } - - .rows-title { - font-size: 13px; - color: @rows-title-color; - font-family: @font-family-sans-serif; - } - - .per-page { - width: 66px; + .per-page { + width: 66px; .default-dropdown-field { background: none; @@ -7478,67 +7291,254 @@ yx-axis } } -.igz-slider-input-block { - .igz-slider-input-block-color-set(); +.search-input { + .search-input-color-set(); position: relative; + color: @search-input-color; - .igz-slider-input-title { - float: left; - display: table; - min-height: 30px; - line-height: 1; - color: @slider-input-title-color; - font-size: 14px; + .container-search-input { + background-color: @search-input-bg-color; + border: 0; + font-family: @font-family-sans-serif; + font-size: 15px; font-weight: 400; - text-align: left; - cursor: default; + height: 52px; + line-height: 52px; + margin: 0; + outline: 0; + padding-right: 20px; + width: 100%; - .igz-slider-input-title-text { - display: table-cell; - vertical-align: middle; + &::-webkit-input-placeholder { + color: @search-input-placeholder-color; } - } - // Custom styles for third-party library slider - .igz-slider-input-rz-slider { - float: left; - min-height: 16px; - line-height: 16px; + &:-moz-placeholder { /* Firefox 18- */ + color: @search-input-placeholder-color; + } - .rzslider { - margin: 0; - height: 8px; + &::-moz-placeholder { /* Firefox 19+ */ + color: @search-input-placeholder-color; + } - .rz-bar-wrapper { - height: auto; - margin: 0; - padding: 0; + &:-ms-input-placeholder { + color: @search-input-placeholder-color; + } - .rz-bar { - background-color: @rz-bar-bg-color; - height: 3px; - } + &:focus { + &, & + .igz-icon-search:before { + color: @search-input-focus-icon-search-before-color; } - .rz-bubble { - display: none; + &::-webkit-input-placeholder { + color: @search-input-focus-placeholder-color; } - .rz-pointer { - height: 14px; - width: 14px; - top: -6px; - box-shadow: @rz-pointer-box-shadow; - outline: 0; + &:-moz-placeholder { /* Firefox 18- */ + color: @search-input-focus-placeholder-color; + } - &:after { - display: none; - } + &::-moz-placeholder { /* Firefox 19+ */ + color: @search-input-focus-placeholder-color; } - &:not([disabled]) { - .rz-bar.rz-selection { + &:-ms-input-placeholder { + color: @search-input-focus-placeholder-color; + } + + &::placeholder { + /* modern browser versions */ + color: @search-input-focus-placeholder-color !important; + } + } + } + + .igz-icon-search { + font-size: 16px; + height: 16px; + position: absolute; + right: 0; + top: 17px; + width: 16px; + z-index: 1; + } + + .clear-button { + font-size: 10px; + position: absolute; + right: 4px; + top: 17px; + cursor: pointer; + color: @clear-button-color; + padding: 4px 5px 2px; + opacity: 0.64; + background-color: @clear-button-bg-color; + border-radius: 50%; + line-height: initial; + + &:hover { + opacity: 1; + } + } + + input::-ms-clear { + display: none; + } +} + +.search-input-actions-bar { + .search-input-color-set(); + + position: relative; + .container-search-input { + border: 0; + margin: 0; + font-family: @font-family-sans-serif; + font-size: 14px; + height: 52px; + line-height: 52px; + padding: 0 25px 0 45px; + outline: 0; + width: 100%; + } + + .igz-icon-search { + color: @search-input-actions-bar-icon-search-color; + font-size: 16px; + height: 16px; + position: absolute; + left: 18px; + top: 17px; + width: 16px; + z-index: 1; + } + + input::-ms-clear { + display: none; + } +} + +.search-input-not-found { + .search-input-color-set(); + + color: @search-input-not-found-color; + font-family: @font-family-sans-serif; + font-size: 14px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + margin-top: 9px; + + .search-message { + min-height: 49px; + line-height: 49px; + width: 100%; + text-align: center; + letter-spacing: 0.1px; + border: @search-input-not-found-message-border; + } + + .create-item-button { + display: flex; + align-items: center; + padding: 0 19px 0 7px; + margin-top: 8px; + border-radius: 12px; + height: 24px; + color: @create-item-btn-color; + font-size: 12px; + font-weight: bold; + cursor: pointer; + background-color: @create-item-btn-bg-color; + border: @create-item-btn-border; + text-transform: uppercase; + + &:hover { + background-color: @create-item-btn-hover-bg-color; + box-shadow: @create-item-btn-hover-box-shadow; + border: @create-item-btn-hover-border; + } + + &:focus { + outline: none; + } + + &:active { + background-color: @create-item-btn-active-bg-color; + box-shadow: @create-item-btn-active-box-shadow; + border: none; + } + + .igz-icon-add { + font-size: 10px; + line-height: 15px; + padding-right: 8px; + } + } +} +.igz-slider-input-block { + .igz-slider-input-block-color-set(); + + position: relative; + + .igz-slider-input-title { + float: left; + display: table; + min-height: 30px; + line-height: 1; + color: @slider-input-title-color; + font-size: 14px; + font-weight: 400; + text-align: left; + cursor: default; + + .igz-slider-input-title-text { + display: table-cell; + vertical-align: middle; + } + } + + // Custom styles for third-party library slider + .igz-slider-input-rz-slider { + float: left; + min-height: 16px; + line-height: 16px; + + .rzslider { + margin: 0; + height: 8px; + + .rz-bar-wrapper { + height: auto; + margin: 0; + padding: 0; + + .rz-bar { + background-color: @rz-bar-bg-color; + height: 3px; + } + } + + .rz-bubble { + display: none; + } + + .rz-pointer { + height: 14px; + width: 14px; + top: -6px; + box-shadow: @rz-pointer-box-shadow; + outline: 0; + + &:after { + display: none; + } + } + + &:not([disabled]) { + .rz-bar.rz-selection { background-color: @rz-selection-bg-color; } @@ -9211,117 +9211,45 @@ body { } } -// Style rules for actions bar -.border-top > .igz-info-page-actions-bar { - .info-page-actions-bar-color-set(); - - border-top: @info-page-actions-bar-border-top; -} - -.igz-info-page-actions-bar { - .info-page-actions-bar-color-set(); +.igz-info-page-content-wrapper { + .info-page-content-color-set(); - background-color: @info-page-actions-bar-bg-color; position: absolute; - top: 0; + top: 56px; right: 0; + bottom: 0; left: 0; - height: 56px; - padding: 8px 20px 8px 16px; - border-bottom: @info-page-actions-bar-border-bottom; + padding-top: 0; transition: @igz-basic-transition; + background-color: @page-content-bg-color; &.upper-pane-opened { - top: 150px; + top: 216px; } &.filters-opened { - right: 376px; - padding-right: 8px; + right: 377px; } &.info-pane-opened { right: 379px; - padding-right: 8px; - } - - .actions-bar-left { - float: left; - height: 100%; - } - - .actions-bar-right { - float: right; - height: 100%; - text-align: right; } - &:before, &:after { - content: " "; - display: table; - } - &:after { - clear: both; + .igz-info-page-content { + min-width: 946px; + max-width: 100%; + padding: 40px 25px; } +} - .actions-panes-block { - padding-left: 16px; - border-left: @actions-panes-block-border-left; +igz-info-page-actions-bar { + .igz-info-page-actions-bar .actions-content-block { + margin-left: 14px; } +} - .actions-content-block { - margin: 0 8px 0 32px; - } - - .actions-buttons-block { - margin-left: 16px; - margin-top: 1px; - - [class^="igz-button"]:not(:first-child), [class*="igz-button"]:not(:first-child) { - margin-left: 8px; - } - } -} - -.igz-info-page-content-wrapper { - .info-page-content-color-set(); - - position: absolute; - top: 56px; - right: 0; - bottom: 0; - left: 0; - padding-top: 0; - transition: @igz-basic-transition; - background-color: @page-content-bg-color; - - &.upper-pane-opened { - top: 216px; - } - - &.filters-opened { - right: 377px; - } - - &.info-pane-opened { - right: 379px; - } - - .igz-info-page-content { - min-width: 946px; - max-width: 100%; - padding: 40px 25px; - } -} - -igz-info-page-actions-bar { - .igz-info-page-actions-bar .actions-content-block { - margin-left: 14px; - } -} - -igz-info-page-content { - .info-page-content-color-set(); +igz-info-page-content { + .info-page-content-color-set(); .container-data-access-policy-table, .data-lifecycle-table { &.common-table { @@ -9405,6 +9333,78 @@ igz-info-page-content { } +// Style rules for actions bar +.border-top > .igz-info-page-actions-bar { + .info-page-actions-bar-color-set(); + + border-top: @info-page-actions-bar-border-top; +} + +.igz-info-page-actions-bar { + .info-page-actions-bar-color-set(); + + background-color: @info-page-actions-bar-bg-color; + position: absolute; + top: 0; + right: 0; + left: 0; + height: 56px; + padding: 8px 20px 8px 16px; + border-bottom: @info-page-actions-bar-border-bottom; + transition: @igz-basic-transition; + + &.upper-pane-opened { + top: 150px; + } + + &.filters-opened { + right: 376px; + padding-right: 8px; + } + + &.info-pane-opened { + right: 379px; + padding-right: 8px; + } + + .actions-bar-left { + float: left; + height: 100%; + } + + .actions-bar-right { + float: right; + height: 100%; + text-align: right; + } + + &:before, &:after { + content: " "; + display: table; + } + &:after { + clear: both; + } + + .actions-panes-block { + padding-left: 16px; + border-left: @actions-panes-block-border-left; + } + + .actions-content-block { + margin: 0 8px 0 32px; + } + + .actions-buttons-block { + margin-left: 16px; + margin-top: 1px; + + [class^="igz-button"]:not(:first-child), [class*="igz-button"]:not(:first-child) { + margin-left: 8px; + } + } +} + .info-page-filters-bookmark { .info-page-filters-color-set(); @@ -10168,6 +10168,24 @@ ncl-breadcrumbs { } } +.view-yaml-dialog-wrapper { + .ngdialog-content { + .view-yaml-dialog-header { + .title { + margin-bottom: 10px; + } + + .copy-to-clipboard { + width: 20px; + } + } + + .monaco-editor { + min-width: 700px; + min-height: 450px; + } + } +} .ncl-key-value-input { .input-wrapper { width: 100%; @@ -10206,7 +10224,7 @@ ncl-breadcrumbs { } .inputs-container { - width: calc(100% - 30px); + width: calc(100% - 45px); display: flex; &.use-checkbox { @@ -10371,24 +10389,6 @@ ncl-breadcrumbs { } } -.view-yaml-dialog-wrapper { - .ngdialog-content { - .view-yaml-dialog-header { - .title { - margin-bottom: 10px; - } - - .copy-to-clipboard { - width: 20px; - } - } - - .monaco-editor { - min-width: 700px; - min-height: 450px; - } - } -} .ncl-monaco { .ncl-monaco-wrapper { padding-top: 20px; @@ -10415,6 +10415,76 @@ ncl-breadcrumbs { } +.ncl-search-input { + position: relative; + color: @silver; + + .container-search-input { + background-color: transparent; + border-bottom: 1px solid @silver; + font-size: 13px; + font-weight: 400; + height: 36px; + line-height: 36px; + margin: 0; + outline: 0; + padding: 0 0 3px 31px; + width: 100%; + + &::-webkit-input-placeholder { + color: @silver; + } + + &:-moz-placeholder { /* Firefox 18- */ + color: @silver; + } + + &::-moz-placeholder { /* Firefox 19+ */ + color: @silver; + } + + &:-ms-input-placeholder { + color: @silver; + } + + &:focus { + border-bottom: 1px solid @light-blue; + + &, & + .igz-icon-search:before { + color: @dusk-three; + } + + &::-webkit-input-placeholder { + color: transparent; + } + + &:-moz-placeholder { /* Firefox 18- */ + color: transparent; + } + + &::-moz-placeholder { /* Firefox 19+ */ + color: transparent; + } + + &:-ms-input-placeholder { + color: transparent; + } + } + } + + .igz-icon-search { + font-size: 18px; + position: absolute; + left: 8px; + top: 5px; + z-index: 1; + color: @silver; + } + + input::-ms-clear { + display: none; + } +} ncl-navigation-tabs { .ncl-navigation-tabs-color-set(); @@ -10576,92 +10646,22 @@ ncl-navigation-tabs { } } -.ncl-search-input { +.new-function-wrapper { + .ncl-new-function-color-set(); + position: relative; - color: @silver; - .container-search-input { - background-color: transparent; - border-bottom: 1px solid @silver; - font-size: 13px; - font-weight: 400; - height: 36px; - line-height: 36px; - margin: 0; - outline: 0; - padding: 0 0 3px 31px; + .new-function-header { width: 100%; + height: 318px; + padding: 24px 55px 40px 55px; + background: url('/assets/images/nuclio.png') no-repeat center; + background-size: cover; - &::-webkit-input-placeholder { - color: @silver; - } - - &:-moz-placeholder { /* Firefox 18- */ - color: @silver; - } - - &::-moz-placeholder { /* Firefox 19+ */ - color: @silver; - } - - &:-ms-input-placeholder { - color: @silver; - } - - &:focus { - border-bottom: 1px solid @light-blue; - - &, & + .igz-icon-search:before { - color: @dusk-three; - } - - &::-webkit-input-placeholder { - color: transparent; - } - - &:-moz-placeholder { /* Firefox 18- */ - color: transparent; - } - - &::-moz-placeholder { /* Firefox 19+ */ - color: transparent; - } - - &:-ms-input-placeholder { - color: transparent; - } - } - } - - .igz-icon-search { - font-size: 18px; - position: absolute; - left: 8px; - top: 5px; - z-index: 1; - color: @silver; - } - - input::-ms-clear { - display: none; - } -} -.new-function-wrapper { - .ncl-new-function-color-set(); - - position: relative; - - .new-function-header { - width: 100%; - height: 318px; - padding: 24px 55px 40px 55px; - background: url('/assets/images/nuclio.png') no-repeat center; - background-size: cover; - - .title-wrapper { - color: white; - display: flex; - justify-content: space-between; + .title-wrapper { + color: white; + display: flex; + justify-content: space-between; .title { font-size: 18px; @@ -10869,151 +10869,6 @@ ncl-navigation-tabs { } } -.function-event-wrapper { - width: 600px; - margin-bottom: -23px; - - .header { - display: flex; - justify-content: space-between; - border-bottom: 1px solid @pale-grey; - - .title { - font-size: 18px; - } - } - - .content { - border-bottom: 1px solid @pale-grey; - padding: 16px 0 16px 16px; - - .event-form { - width: 88%; - - .field-wrapper { - display: flex; - align-items: center; - margin: 15px 0 0 0; - - .field-label { - font-size: 16px; - margin-right: 10px; - width: 195px; - } - - .field-content { - width: 100%; - - .ncl-monaco { - height: 200px; - } - - .event-body { - font-size: 13px; - outline: none; - border: 1px solid @pale-grey; - resize: none; - width: 100%; - height: 100px; - padding: 5px 5px 5px 16px; - } - } - } - } - - .event-error { - display: flex; - font-size: 13px; - align-items: center; - justify-content: center; - color: @darkish-pink; - } - } - - .bottom-bar { - height: 64px; - display: flex; - align-items: center; - justify-content: flex-end; - - .igz-button-primary { - &.disabled { - color: rgba(71, 64, 86, 0.24); - border-radius: 2px; - border: solid 1px #f3f3f6; - background-color: #f3f3f6; - cursor: default; - display: inline-block; - - &:hover { - box-shadow: none; - border: none; - } - } - } - } -} - -.ncl-version-configuration { - > .igz-scrollable-container { - padding: 24px 25px 22px 41px; - } - - .ncl-version-configuration-wrapper { - > .row { - display: flex; - justify-content: space-between; - flex-wrap: wrap; - - .configuration-block { - padding: 16px 23px 16px; - background-color: @white; - border: solid 1px @pale-grey; - flex-grow: 1; - flex-basis: 500px; - margin-right: 16px; - margin-bottom: 16px; - - &.invisible { - visibility: hidden; - } - - .title { - font-size: 16px; - font-weight: bold; - font-style: normal; - font-stretch: normal; - letter-spacing: normal; - text-align: left; - color: @dusk-three; - margin-bottom: 12px; - } - - .row { - .label { - display: block; - font-family: Roboto, sans-serif; - font-size: 14px; - font-weight: 500; - font-style: normal; - font-stretch: normal; - letter-spacing: normal; - text-align: left; - color: @dusk-three; - padding: 0; - } - } - - .ncl-version-configuration-labels, .ncl-version-configuration-annotations { - .more-info-wrapper { - height: 20px; - } - } - } - } - } -} - .ncl-edit-version-code { height: 100%; display: flex; @@ -11226,35 +11081,180 @@ ncl-navigation-tabs { } } -.ncl-version-monitoring { - > .igz-scrollable-container { - padding: 24px 25px 22px 41px; - } +.function-event-wrapper { + width: 600px; + margin-bottom: -23px; - .invocation-url-common { - margin-left: 5px; - font-family: Roboto; + .header { + display: flex; + justify-content: space-between; + border-bottom: 1px solid @pale-grey; + + .title { + font-size: 18px; + } } - .ncl-version-monitoring-wrapper { - > .row { - display: flex; - justify-content: space-between; - flex-wrap: wrap; + .content { + border-bottom: 1px solid @pale-grey; + padding: 16px 0 16px 16px; - .monitoring-block { - padding: 16px 23px 16px; - background-color: @white; - border: solid 1px @pale-grey; - overflow: hidden; - flex-grow: 1; - flex-basis: 500px; - margin-right: 16px; - margin-bottom: 16px; + .event-form { + width: 88%; - &.invocation-block { - overflow: visible; - } + .field-wrapper { + display: flex; + align-items: center; + margin: 15px 0 0 0; + + .field-label { + font-size: 16px; + margin-right: 10px; + width: 195px; + } + + .field-content { + width: 100%; + + .ncl-monaco { + height: 200px; + } + + .event-body { + font-size: 13px; + outline: none; + border: 1px solid @pale-grey; + resize: none; + width: 100%; + height: 100px; + padding: 5px 5px 5px 16px; + } + } + } + } + + .event-error { + display: flex; + font-size: 13px; + align-items: center; + justify-content: center; + color: @darkish-pink; + } + } + + .bottom-bar { + height: 64px; + display: flex; + align-items: center; + justify-content: flex-end; + + .igz-button-primary { + &.disabled { + color: rgba(71, 64, 86, 0.24); + border-radius: 2px; + border: solid 1px #f3f3f6; + background-color: #f3f3f6; + cursor: default; + display: inline-block; + + &:hover { + box-shadow: none; + border: none; + } + } + } + } +} + +.ncl-version-configuration { + > .igz-scrollable-container { + padding: 24px 25px 22px 41px; + } + + .ncl-version-configuration-wrapper { + > .row { + display: flex; + justify-content: space-between; + flex-wrap: wrap; + + .configuration-block { + padding: 16px 23px 16px; + background-color: @white; + border: solid 1px @pale-grey; + flex-grow: 1; + flex-basis: 500px; + margin-right: 16px; + margin-bottom: 16px; + + &.invisible { + visibility: hidden; + } + + .title { + font-size: 16px; + font-weight: bold; + font-style: normal; + font-stretch: normal; + letter-spacing: normal; + text-align: left; + color: @dusk-three; + margin-bottom: 12px; + } + + .row { + .label { + display: block; + font-family: Roboto, sans-serif; + font-size: 14px; + font-weight: 500; + font-style: normal; + font-stretch: normal; + letter-spacing: normal; + text-align: left; + color: @dusk-three; + padding: 0; + } + } + + .ncl-version-configuration-labels, .ncl-version-configuration-annotations { + .more-info-wrapper { + height: 20px; + } + } + } + } + } +} + +.ncl-version-monitoring { + > .igz-scrollable-container { + padding: 24px 25px 22px 41px; + } + + .invocation-url-common { + margin-left: 5px; + font-family: Roboto; + } + + .ncl-version-monitoring-wrapper { + > .row { + display: flex; + justify-content: space-between; + flex-wrap: wrap; + + .monitoring-block { + padding: 16px 23px 16px; + background-color: @white; + border: solid 1px @pale-grey; + overflow: hidden; + flex-grow: 1; + flex-basis: 500px; + margin-right: 16px; + margin-bottom: 16px; + + &.invocation-block { + overflow: visible; + } &.without-collapse { padding: 0; @@ -12581,100 +12581,298 @@ ncl-navigation-tabs { } } -@desktop: 1350px; -@desktop-low: 1202px; -@desktop-middle: 1550px; +.ncl-test-events-logs { + padding: 6px 17px 25px; + background-color: @white; -.ncl-version-configuration-basic-settings { - .row { + .functional-buttons { + .duskThree(0.64); display: flex; - justify-content: space-between; + justify-content: flex-end; + color: @color; + font-size: 16px; - &:not(:last-child) { - margin-bottom: 23px; - } + > div { + margin-right: 24px; - &:last-child { - margin-bottom: 4px; + &:hover { + color: @dusk-three; + } } + } - &.enable-checkbox { - justify-content: flex-start; - margin-bottom: 18px; - } + .collapsed-row { + .black(0.2); + display: flex; + align-items: center; + position: relative; + height: 36px; + background-color: @white; + color: @dusk-three; + box-shadow: 1.7px 1.1px 4px 0 @color; + border: solid 1px @pale-grey; + margin-bottom: 10px; - > div { - flex: 1; + .igz-icon-right { + .duskThree(0.64); + font-size: 12px; + color: @color; + margin: 0 8px 0 12px; - &:not(:last-child) { - margin-right: 46px; + &::before { + vertical-align: text-bottom; } + } - .label { - padding: 0; - margin-bottom: 5px; + .level-icon { + display: inline-block; + margin-right: 8px; + width: 20px; + text-align: center; + + &::before { + font-size: 16px; + vertical-align: text-bottom; } - &.timeout-block { - .label { - margin-bottom: 3px; + &.ncl-icon-debug { + color: @orangish; + + &::before { + font-size: 18px; } + } - .timeout-values { - margin-left: 27px; + &.igz-icon-info-round { + color: @orangish; + } - .inputs { - display: flex; - align-items: center; + &.igz-icon-warning { + color: @orangish; + } - .values-label { - .duskThree(0.9); - margin: 0 17px 0 8px; - font-size: 14px; - font-weight: normal; - font-style: normal; - letter-spacing: normal; - text-align: left; - color: @color; - } - } - } + &.igz-icon-cancel-path { + color: @orangish; } } - .logger-block { - display: flex; - margin-top: 3px; - - .logger-dropdown { - .default-dropdown { - position: relative; - height: 36px; - - .dropdown-overlap { - z-index: 100; - } + .date { + display: inline-block; + width: 230px; + font-size: 14px; + font-weight: bold; + margin-right: 15px; + } + + .message { + display: inline-block; + width: 200px; + margin-right: 30px; + } + + .ncl-icon-parameters { + .duskThree(0.64); + color: @color; + font-size: 14px; + position: absolute; + top: 9px; + right: 9px; + } + } + + .expanded-row { + background-color: @white; + color: @dusk-three; + border: solid 1px @pale-grey; + margin-bottom: 10px; + + .header { + position: relative; + display: flex; + align-items: center; + height: 34px; + + .igz-icon-down { + .duskThree(0.64); + font-size: 12px; + color: @color; + margin: 0 8px 0 12px; + + &::before { + vertical-align: text-bottom; } } - > div { - flex: 1; + .level-icon { + display: inline-block; + margin-right: 8px; + width: 20px; + text-align: center; - &:not(:last-child) { - margin-right: 16px; + &::before { + font-size: 16px; + vertical-align: text-bottom; } - .label { - padding: 0; - margin-bottom: 5px; + &.ncl-icon-debug { + color: @orangish; + + &::before { + font-size: 18px; + } } - &.logger-input { - flex-grow: 1.95; + &.igz-icon-info-round { + color: @orangish; + } + + &.igz-icon-warning { + color: @orangish; + } + + &.igz-icon-cancel-path { + color: @orangish; + } + } + + .date { + display: inline-block; + width: 230px; + font-size: 14px; + font-weight: bold; + margin-right: 15px; + } + + .ncl-icon-parameters { + .duskThree(0.64); + position: absolute; + top: 9px; + right: 9px; + color: @color; + font-size: 14px; + } + } + + .expanded-body { + font-size: 14px; + color: @dusk-three; + + .error { + width: 71%; + border-radius: 3px; + background-color: #fbe5e8; + border: solid 1px @darkish-pink; + color: @darkish-pink; + word-wrap: break-word; + margin-left: 62px; + padding: 12px; + margin-bottom: 16px; + } + + .message { + display: inline-block; + width: 70%; + word-wrap: break-word; + margin: 0 0 16px 62px; + } + + .parameters { + padding: 0 62px 16px; + + .parameters-header { + font-weight: bold; + } + + > div { + display: flex; + line-height: 2; + + .labels { + color: @greyish-purple; + font-size: 14px; + width: 30%; + } + + .values { + color: @dusk-three; + font-size: 14px; + width: 70%; + } } } } } + + .no-logs { + margin: 10px auto 0; + font-size: 14px; + color: @pale-grey; + text-align: center; + } +} +.ncl-test-events-navigation-tabs { + display: flex; + background: #f8f8fb; + height: 40px; + border-top: 1px solid @pale-grey; + border-bottom: 1px solid @pale-grey; + + .test-events-navigation-tab { + .duskThree(0.64); + position: relative; + float: left; + height: 27px; + padding: 10px 40px 0; + font-family: @font-family-sans-serif; + color: @color; + font-size: 13px; + text-align: center; + cursor: pointer; + border-bottom: none; + box-sizing: content-box; + + &.active, &.active:hover { + background: none; + color: @dusk-three; + border-bottom: 2px solid @dusk-three; + font-weight: bold; + + .badge { + color: @white; + background-color: @light-grey-blue; + } + } + + .badge { + display: inline-block; + min-width: 22px; + padding: 3px 7px; + font-size: 12px; + font-weight: 500; + color: @greyish-purple; + line-height: 1; + vertical-align: middle; + white-space: nowrap; + text-align: center; + background-color: @pale-grey; + border-radius: 7.5px; + margin-left: 7px; + margin-top: -4px; + } + } + + .default-dropdown { + float: left; + width: 105px; + + .default-dropdown-field:not(:hover) { + border-color: transparent; + } + + .default-dropdown-container { + z-index: 3; + } + } } .ncl-version-configuration-build { @@ -12916,38 +13114,134 @@ ncl-navigation-tabs { } } -.ncl-version-configuration-logging { +@desktop: 1350px; +@desktop-low: 1202px; +@desktop-middle: 1550px; + +.ncl-version-configuration-basic-settings { .row { display: flex; - position: relative; + justify-content: space-between; - .logging-wrapper { - width: 100%; + &:not(:last-child) { + margin-bottom: 23px; } - } -} - -@desktop-middle: 1550px; -.ncl-version-configuration-resources { - .row { - .range-inputs-row { - display: flex; - align-items: flex-end; + &:last-child { + margin-bottom: 4px; + } - .row-title { - margin-bottom: 8px; - } + &.enable-checkbox { + justify-content: flex-start; + margin-bottom: 18px; } - .form-row { - padding: 12px 0; + > div { + flex: 1; - .row-title, .input-title { - font-size: 14px; + &:not(:last-child) { + margin-right: 46px; } - .row-title { + .label { + padding: 0; + margin-bottom: 5px; + } + + &.timeout-block { + .label { + margin-bottom: 3px; + } + + .timeout-values { + margin-left: 27px; + + .inputs { + display: flex; + align-items: center; + + .values-label { + .duskThree(0.9); + margin: 0 17px 0 8px; + font-size: 14px; + font-weight: normal; + font-style: normal; + letter-spacing: normal; + text-align: left; + color: @color; + } + } + } + } + } + + .logger-block { + display: flex; + margin-top: 3px; + + .logger-dropdown { + .default-dropdown { + position: relative; + height: 36px; + + .dropdown-overlap { + z-index: 100; + } + } + } + + > div { + flex: 1; + + &:not(:last-child) { + margin-right: 16px; + } + + .label { + padding: 0; + margin-bottom: 5px; + } + + &.logger-input { + flex-grow: 1.95; + } + } + } + } +} + +.ncl-version-configuration-logging { + .row { + display: flex; + position: relative; + + .logging-wrapper { + width: 100%; + } + } +} + +@desktop-middle: 1550px; + +.ncl-version-configuration-resources { + .row { + .range-inputs-row { + display: flex; + align-items: flex-end; + + .row-title { + margin-bottom: 8px; + } + } + + .form-row { + padding: 12px 0; + + .row-title, .input-title { + font-size: 14px; + } + + .row-title { font-weight: 500; } @@ -13096,300 +13390,6 @@ ncl-navigation-tabs { } } -.ncl-test-events-navigation-tabs { - display: flex; - background: #f8f8fb; - height: 40px; - border-top: 1px solid @pale-grey; - border-bottom: 1px solid @pale-grey; - - .test-events-navigation-tab { - .duskThree(0.64); - position: relative; - float: left; - height: 27px; - padding: 10px 40px 0; - font-family: @font-family-sans-serif; - color: @color; - font-size: 13px; - text-align: center; - cursor: pointer; - border-bottom: none; - box-sizing: content-box; - - &.active, &.active:hover { - background: none; - color: @dusk-three; - border-bottom: 2px solid @dusk-three; - font-weight: bold; - - .badge { - color: @white; - background-color: @light-grey-blue; - } - } - - .badge { - display: inline-block; - min-width: 22px; - padding: 3px 7px; - font-size: 12px; - font-weight: 500; - color: @greyish-purple; - line-height: 1; - vertical-align: middle; - white-space: nowrap; - text-align: center; - background-color: @pale-grey; - border-radius: 7.5px; - margin-left: 7px; - margin-top: -4px; - } - } - - .default-dropdown { - float: left; - width: 105px; - - .default-dropdown-field:not(:hover) { - border-color: transparent; - } - - .default-dropdown-container { - z-index: 3; - } - } -} - -.ncl-test-events-logs { - padding: 6px 17px 25px; - background-color: @white; - - .functional-buttons { - .duskThree(0.64); - display: flex; - justify-content: flex-end; - color: @color; - font-size: 16px; - - > div { - margin-right: 24px; - - &:hover { - color: @dusk-three; - } - } - } - - .collapsed-row { - .black(0.2); - display: flex; - align-items: center; - position: relative; - height: 36px; - background-color: @white; - color: @dusk-three; - box-shadow: 1.7px 1.1px 4px 0 @color; - border: solid 1px @pale-grey; - margin-bottom: 10px; - - .igz-icon-right { - .duskThree(0.64); - font-size: 12px; - color: @color; - margin: 0 8px 0 12px; - - &::before { - vertical-align: text-bottom; - } - } - - .level-icon { - display: inline-block; - margin-right: 8px; - width: 20px; - text-align: center; - - &::before { - font-size: 16px; - vertical-align: text-bottom; - } - - &.ncl-icon-debug { - color: @orangish; - - &::before { - font-size: 18px; - } - } - - &.igz-icon-info-round { - color: @orangish; - } - - &.igz-icon-warning { - color: @orangish; - } - - &.igz-icon-cancel-path { - color: @orangish; - } - } - - .date { - display: inline-block; - width: 230px; - font-size: 14px; - font-weight: bold; - margin-right: 15px; - } - - .message { - display: inline-block; - width: 200px; - margin-right: 30px; - } - - .ncl-icon-parameters { - .duskThree(0.64); - color: @color; - font-size: 14px; - position: absolute; - top: 9px; - right: 9px; - } - } - - .expanded-row { - background-color: @white; - color: @dusk-three; - border: solid 1px @pale-grey; - margin-bottom: 10px; - - .header { - position: relative; - display: flex; - align-items: center; - height: 34px; - - .igz-icon-down { - .duskThree(0.64); - font-size: 12px; - color: @color; - margin: 0 8px 0 12px; - - &::before { - vertical-align: text-bottom; - } - } - - .level-icon { - display: inline-block; - margin-right: 8px; - width: 20px; - text-align: center; - - &::before { - font-size: 16px; - vertical-align: text-bottom; - } - - &.ncl-icon-debug { - color: @orangish; - - &::before { - font-size: 18px; - } - } - - &.igz-icon-info-round { - color: @orangish; - } - - &.igz-icon-warning { - color: @orangish; - } - - &.igz-icon-cancel-path { - color: @orangish; - } - } - - .date { - display: inline-block; - width: 230px; - font-size: 14px; - font-weight: bold; - margin-right: 15px; - } - - .ncl-icon-parameters { - .duskThree(0.64); - position: absolute; - top: 9px; - right: 9px; - color: @color; - font-size: 14px; - } - } - - .expanded-body { - font-size: 14px; - color: @dusk-three; - - .error { - width: 71%; - border-radius: 3px; - background-color: #fbe5e8; - border: solid 1px @darkish-pink; - color: @darkish-pink; - word-wrap: break-word; - margin-left: 62px; - padding: 12px; - margin-bottom: 16px; - } - - .message { - display: inline-block; - width: 70%; - word-wrap: break-word; - margin: 0 0 16px 62px; - } - - .parameters { - padding: 0 62px 16px; - - .parameters-header { - font-weight: bold; - } - - > div { - display: flex; - line-height: 2; - - .labels { - color: @greyish-purple; - font-size: 14px; - width: 30%; - } - - .values { - color: @dusk-three; - font-size: 14px; - width: 70%; - } - } - } - } - } - - .no-logs { - margin: 10px auto 0; - font-size: 14px; - color: @pale-grey; - text-align: center; - } -} .version-configuration-build-dialog-wrapper { font-family: Roboto; diff --git a/package.json b/package.json index d47fdffc7..76ab4da63 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iguazio.dashboard-controls", - "version": "0.31.1", + "version": "0.31.2", "main": "dist/js/iguazio.dashboard-controls.js", "description": "Collection of resources (such as CSS styles, fonts and images) and AngularJs 1.x components and services to share among different Iguazio repos.", "repository": {