From cde1381b526f812e343a760756d993951d3eb488 Mon Sep 17 00:00:00 2001 From: Alexander Salas Bastidas Date: Tue, 18 Sep 2018 04:34:31 +0200 Subject: [PATCH 01/26] docs: add Contributor Covenant Code of Conduct --- CODE_OF_CONDUCT.md | 47 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 63d85a4b6c..7f4dc95399 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,11 +1,46 @@ -# Code of Conduct +# Contributor Covenant Code of Conduct -As contributors and maintainers of the Flyve MDM projects, we pledge to respect everyone who contributes by posting issues, updating documentation, submitting pull requests, providing feedback in comments, and any other activities. +## Our Pledge -Communication through any of our channels (GitHub, Telegram, mailing lists, Google+, Twitter, etc.) must be constructive and never resort to personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. -We promise to extend courtesy and respect to everyone involved in this project regardless of gender, gender identity, sexual orientation, disability, age, race, ethnicity, religion, or level of experience. We expect anyone contributing to the Flyve MDM projects to do the same. +## Our Standards -If any member of the community violates this code of conduct, the maintainers of the Flyve MDM projects may take action, removing issues, comments, and PRs or blocking accounts as deemed appropriate. +Examples of behavior that contributes to creating a positive environment include: -If you are subject to or witness unacceptable behavior, or have any other concerns, please email us at ml-flyvemdm@teclib.com \ No newline at end of file +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at contact@teclib.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ From 894d630f612887e5e36c16f8209b52a314217aba Mon Sep 17 00:00:00 2001 From: Gianfranco Manganiello Date: Tue, 25 Sep 2018 18:26:04 -0400 Subject: [PATCH 02/26] refactor(search-engine): split the item type selector Signed-off-by: Gianfranco Manganiello --- .../components/ItemTypeSelector.js | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 src/containers/SearchEngine/components/ItemTypeSelector.js diff --git a/src/containers/SearchEngine/components/ItemTypeSelector.js b/src/containers/SearchEngine/components/ItemTypeSelector.js new file mode 100644 index 0000000000..d6b93a0ff2 --- /dev/null +++ b/src/containers/SearchEngine/components/ItemTypeSelector.js @@ -0,0 +1,73 @@ +/* + * Copyright © 2018 Teclib. All rights reserved. + * + * This file is part of web-mdm-dashboard + * + * web-mdm-dashboard is a subproject of Flyve MDM. Flyve MDM is a mobile + * device management software. + * + * Flyve MDM is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 3 + * of the License, or (at your option) any later version. + * + * Flyve MDM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * ------------------------------------------------------------------------------ + * @author Gianfranco Manganiello (gmanganiello@teclib.com) + * @author Hector Rondon (hrondon@teclib.com) + * @copyright Copyright © 2018 Teclib. All rights reserved. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/flyve-mdm/web-mdm-dashboard + * @link http://flyve.org/web-mdm-dashboard + * @link https://flyve-mdm.com + * ------------------------------------------------------------------------------ + */ + +/** import dependencies */ +import React, { + PureComponent, +} from 'react' +import PropTypes from 'prop-types' +import I18n from 'shared/i18n' + +/** + * Component to select a item type + * @class SearchEngine + * @extends PureComponent + */ +class ItemTypeSelector extends PureComponent { + render() { + return ( + + + + + + ) + } +} + +ItemTypeSelector.propTypes = { + itemType: PropTypes.string.isRequired, + handleChangeItemType: PropTypes.func.isRequired, + handleRequestItemType: PropTypes.func.isRequired, +} + +export default ItemTypeSelector From 09f6bae39c2ba459fd4b19bc9ef0be5414b0e703 Mon Sep 17 00:00:00 2001 From: Gianfranco Manganiello Date: Tue, 25 Sep 2018 18:26:46 -0400 Subject: [PATCH 03/26] refactor(search-engine): split the results display Signed-off-by: Gianfranco Manganiello --- .../SearchEngine/components/ResultsDisplay.js | 89 +++++++++++++++++++ src/containers/SearchEngine/index.js | 77 ++++------------ 2 files changed, 104 insertions(+), 62 deletions(-) create mode 100644 src/containers/SearchEngine/components/ResultsDisplay.js diff --git a/src/containers/SearchEngine/components/ResultsDisplay.js b/src/containers/SearchEngine/components/ResultsDisplay.js new file mode 100644 index 0000000000..abc579426d --- /dev/null +++ b/src/containers/SearchEngine/components/ResultsDisplay.js @@ -0,0 +1,89 @@ +/* + * Copyright © 2018 Teclib. All rights reserved. + * + * This file is part of web-mdm-dashboard + * + * web-mdm-dashboard is a subproject of Flyve MDM. Flyve MDM is a mobile + * device management software. + * + * Flyve MDM is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 3 + * of the License, or (at your option) any later version. + * + * Flyve MDM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * ------------------------------------------------------------------------------ + * @author Gianfranco Manganiello (gmanganiello@teclib.com) + * @author Hector Rondon (hrondon@teclib.com) + * @copyright Copyright © 2018 Teclib. All rights reserved. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/flyve-mdm/web-mdm-dashboard + * @link http://flyve.org/web-mdm-dashboard + * @link https://flyve-mdm.com + * ------------------------------------------------------------------------------ + */ + +/** import dependencies */ +import React, { + PureComponent, +} from 'react' +import PropTypes from 'prop-types' +import I18n from 'shared/i18n' +import Panel from './Panel' + +/** + * Component to select a item type + * @class SearchEngine + * @extends PureComponent + */ +class ResultsDisplay extends PureComponent { + render() { + let display = null + + if (this.props.results) { + if (this.props.results.length > 0) { + const resultsWithFields = [] + + this.props.results.forEach((result) => { + const arrayResult = [] + const arrayOfArraysIdAndData = Object.entries(result) + + arrayOfArraysIdAndData.forEach((field) => { + const objectField = { + fieldName: this.props.listSearchOptions[field[0]].name, + fieldValue: field[1], + fieldId: field[0], + } + arrayResult.push(objectField) + }) + resultsWithFields.push(arrayResult) + }) + + display = + } else { + display = ( +

+ { I18n.t('search_engine.item_not_found') } +

+ ) + } + } + + return display + } +} + +ResultsDisplay.defaultProps = { + listSearchOptions: {}, + results: null, +} + +ResultsDisplay.propTypes = { + results: PropTypes.array, + listSearchOptions: PropTypes.object, +} + +export default ResultsDisplay diff --git a/src/containers/SearchEngine/index.js b/src/containers/SearchEngine/index.js index 842476f5d9..bc22f76ce7 100644 --- a/src/containers/SearchEngine/index.js +++ b/src/containers/SearchEngine/index.js @@ -35,7 +35,9 @@ import I18n from 'shared/i18n' import withGLPI from 'hoc/withGLPI' import ContentPane from 'components/ContentPane' import SearchQueryBuilder from './components/SearchQueryBuilder' -import Panel from './components/Panel' +import ItemTypeSelector from './components/ItemTypeSelector' +import ResultsDisplay from './components/ResultsDisplay' + import { setFields, getTranslation, @@ -152,37 +154,6 @@ class SearchEngine extends PureComponent { } } - /** - * Create Array of objects with the result of the search - * @function arrayResultsWithFields - * @return {array} - */ - arrayResultsWithFields = () => { - const { - itemResults, - listSearchOptions, - } = this.state - - const resultsWithFields = [] - - itemResults && itemResults.forEach((result) => { - const arrayResult = [] - const arrayOfArraysIdAndData = Object.entries(result) - - arrayOfArraysIdAndData.forEach((field) => { - const objectField = { - fieldName: listSearchOptions[field[0]].name, - fieldValue: field[1], - fieldId: field[0], - } - arrayResult.push(objectField) - }) - resultsWithFields.push(arrayResult) - }) - - return resultsWithFields - } - /** * Render component * @function render @@ -194,6 +165,7 @@ class SearchEngine extends PureComponent { isLoading, query, itemResults, + listSearchOptions, } = this.state return ( @@ -202,23 +174,14 @@ class SearchEngine extends PureComponent {

{I18n.t('search_engine.title')}

- - + { fields.length > 0 && ( @@ -229,7 +192,9 @@ class SearchEngine extends PureComponent { /> ) } +
+
{ isLoading @@ -257,21 +222,9 @@ class SearchEngine extends PureComponent {

) } - { - itemResults - ? itemResults.length > 0 - ? ( - 0 ? this.arrayResultsWithFields() : []} - /> - ) - : ( -

- {I18n.t('search_engine.item_not_found')} -

- ) - : null - } + + +
) From 68846ff296e41f29a562d56bf4696d8e09ad6c57 Mon Sep 17 00:00:00 2001 From: Gianfranco Manganiello Date: Wed, 26 Sep 2018 14:22:03 -0400 Subject: [PATCH 04/26] refactor(search-engine): pass actions to pure functions Signed-off-by: Gianfranco Manganiello --- src/containers/SearchEngine/actions.js | 39 +++++++++----------------- src/containers/SearchEngine/index.js | 11 ++++---- 2 files changed, 20 insertions(+), 30 deletions(-) diff --git a/src/containers/SearchEngine/actions.js b/src/containers/SearchEngine/actions.js index 5668432a0c..0a23923d06 100644 --- a/src/containers/SearchEngine/actions.js +++ b/src/containers/SearchEngine/actions.js @@ -26,20 +26,20 @@ * ------------------------------------------------------------------------------ */ + /** - * Set state for render field in the QueryBuilder component - * @function setFields - * @param {object} ctx + * Returns the fields to use in the QueryBuilder component + * @function getFields + * @param {object} listSearchOptions */ -const setFields = (ctx) => { +function getFields(listSearchOptions) { const fields = [] - const { listSearchOptions } = ctx.state for (const key in listSearchOptions) { if (Object.prototype.hasOwnProperty.call(listSearchOptions, key)) { - if (listSearchOptions[key].name !== undefined - && listSearchOptions[key].field !== undefined) { - const { name } = listSearchOptions[key] + const { name, field } = listSearchOptions[key] + + if (name !== undefined && field !== undefined) { fields.push({ name: key, label: name, @@ -47,22 +47,9 @@ const setFields = (ctx) => { } } } - ctx.setState({ - fields, - }) -} -/** - * Normalize keys of rule object - * @param {object} ctx - * @param {object} rule - * @return {object} - */ -const normalizeRule = (ctx, rule) => ({ - field: Number(rule.field), - searchtype: rule.operator, - value: rule.value, -}) + return fields +} /** * Create the array of rules extracted @@ -80,7 +67,9 @@ const recursiveExtractQueryRules = (query, ctx, arrayRulesExtracted, combinator) */ arrayRulesExtracted.push({ link: combinator, // 'AND' or 'OR' - ...normalizeRule(ctx, query), + field: Number(query.field), + searchtype: query.operator, + value: query.value, }) } else { /* @@ -149,7 +138,7 @@ const getTranslation = () => ({ }) module.exports = { - setFields, getTranslation, normalizeQuery, + getFields, } diff --git a/src/containers/SearchEngine/index.js b/src/containers/SearchEngine/index.js index bc22f76ce7..b7f1f35665 100644 --- a/src/containers/SearchEngine/index.js +++ b/src/containers/SearchEngine/index.js @@ -39,7 +39,7 @@ import ItemTypeSelector from './components/ItemTypeSelector' import ResultsDisplay from './components/ResultsDisplay' import { - setFields, + getFields, getTranslation, normalizeQuery, } from './actions' @@ -60,10 +60,10 @@ class SearchEngine extends PureComponent { itemResults: undefined, fields: [], isLoading: true, + listSearchOptions: null, } this.translations = getTranslation() // Friendly translations of each QueryBuilder input - this.setFields = () => setFields(this) this.normalizeQuery = () => normalizeQuery(this) } @@ -98,6 +98,7 @@ class SearchEngine extends PureComponent { fields: [], isLoading: true, }) + try { const { itemType } = this.state const { glpi } = this.props @@ -109,8 +110,7 @@ class SearchEngine extends PureComponent { this.setState({ isLoading: false, listSearchOptions, - }, () => { - this.setFields() + fields: getFields(listSearchOptions), }) } catch (error) { this.setState({ @@ -144,6 +144,7 @@ class SearchEngine extends PureComponent { itemtype: itemType, criteria: this.normalizeQuery(), }) + this.setState({ itemResults: search.data ? search.data : [], }) @@ -195,7 +196,7 @@ class SearchEngine extends PureComponent {
-
+
{ isLoading ? ( From 4f575e5c3e60645618f359dd54009808249d187e Mon Sep 17 00:00:00 2001 From: Gianfranco Manganiello Date: Wed, 26 Sep 2018 15:36:17 -0400 Subject: [PATCH 05/26] refactor(search-engine): split the search area Signed-off-by: Gianfranco Manganiello --- .../SearchEngine/components/SeachArea.js | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 src/containers/SearchEngine/components/SeachArea.js diff --git a/src/containers/SearchEngine/components/SeachArea.js b/src/containers/SearchEngine/components/SeachArea.js new file mode 100644 index 0000000000..2fa85f7be2 --- /dev/null +++ b/src/containers/SearchEngine/components/SeachArea.js @@ -0,0 +1,83 @@ +/* + * Copyright © 2018 Teclib. All rights reserved. + * + * This file is part of web-mdm-dashboard + * + * web-mdm-dashboard is a subproject of Flyve MDM. Flyve MDM is a mobile + * device management software. + * + * Flyve MDM is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 3 + * of the License, or (at your option) any later version. + * + * Flyve MDM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * ------------------------------------------------------------------------------ + * @author Gianfranco Manganiello (gmanganiello@teclib.com) + * @author Hector Rondon (hrondon@teclib.com) + * @copyright Copyright © 2018 Teclib. All rights reserved. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/flyve-mdm/web-mdm-dashboard + * @link http://flyve.org/web-mdm-dashboard + * @link https://flyve-mdm.com + * ------------------------------------------------------------------------------ + */ + +/** import dependencies */ +import React, { + PureComponent, +} from 'react' +import PropTypes from 'prop-types' +import I18n from 'shared/i18n' + +/** + * Component with the render of the search button + * @class SearchQueryBuilder + * @extends SeachArea + */ +class SeachArea extends PureComponent { + render() { + let display + + if (this.props.isLoading) { + display = ( +

+ {I18n.t('commons.loading')} + ... +

+ ) + } else if (this.props.query) { + if (this.props.query.rules.length) { + display = ( + + ) + } else { + display = ( +

+ {I18n.t('search_engine.itemType_not_found')} +

+ ) + } + } + + return display + } +} + +SeachArea.propTypes = { + isLoading: PropTypes.bool.isRequired, + query: PropTypes.object.isRequired, + handleOnSearch: PropTypes.func.isRequired, +} + + +export default SeachArea From 75f62dc3bea0b442f7f0876a0b241d2d5be5fb35 Mon Sep 17 00:00:00 2001 From: Gianfranco Manganiello Date: Wed, 26 Sep 2018 15:48:27 -0400 Subject: [PATCH 06/26] refactor(search-engine): reorganize and simplify functions Signed-off-by: Gianfranco Manganiello --- .../5_level_components/_search_engine.scss | 96 ---------- .../SearchEngine/actions/getFields.js | 51 +++++ .../actions/getListSearchOptions.js | 40 ++++ src/containers/SearchEngine/actions/index.js | 37 ++++ .../{actions.js => actions/normalizeQuery.js} | 79 +------- .../SearchEngine/actions/searchItem.js | 48 +++++ .../components/ItemTypeSelector.js | 14 +- .../components/QueryBuilder/Rule.js | 78 ++++++++ .../components/QueryBuilder/index.js | 93 +++++++++ .../SearchEngine/components/ResultsDisplay.js | 4 +- .../SearchEngine/components/SeachArea.js | 14 +- .../components/SearchQueryBuilder.js | 78 -------- src/containers/SearchEngine/index.js | 181 +++++++----------- 13 files changed, 442 insertions(+), 371 deletions(-) create mode 100644 src/containers/SearchEngine/actions/getFields.js create mode 100644 src/containers/SearchEngine/actions/getListSearchOptions.js create mode 100644 src/containers/SearchEngine/actions/index.js rename src/containers/SearchEngine/{actions.js => actions/normalizeQuery.js} (60%) create mode 100644 src/containers/SearchEngine/actions/searchItem.js create mode 100644 src/containers/SearchEngine/components/QueryBuilder/Rule.js create mode 100644 src/containers/SearchEngine/components/QueryBuilder/index.js delete mode 100644 src/containers/SearchEngine/components/SearchQueryBuilder.js diff --git a/src/assets/styles/scss/architecture/5_level_components/_search_engine.scss b/src/assets/styles/scss/architecture/5_level_components/_search_engine.scss index c168fd6039..e69de29bb2 100644 --- a/src/assets/styles/scss/architecture/5_level_components/_search_engine.scss +++ b/src/assets/styles/scss/architecture/5_level_components/_search_engine.scss @@ -1,96 +0,0 @@ -.queryBuilder { - .ruleGroup { - background: $color-2-primary; - padding: 10px; - - .ruleGroup-combinators { - margin: 0 10px 0 0; - height: 32px; - border: 0; - box-shadow: none; - -webkit-box-shadow: none; - outline: 1px solid $color-1-primary; - outline-offset: -1px; - - @include font-source(Segoe UI, 15px, #616264); - } - - .ruleGroup-addRule, .ruleGroup-addGroup { - margin: 0 10px 10px 0; - padding: 4px 8px; - height: 32px; - min-width: 80px; - border-radius: 0; - border-width: 2px; - color: #000000; - background-color: rgba(0, 0, 0, 0.2); - border-color: transparent; - border-style: solid; - background-clip: border-box; - touch-action: manipulation; - -webkit-appearance: none; - font-size: 15px; - font-weight: 400; - line-height: 1.333; - box-shadow: none; - -webkit-box-shadow: none; - - @include font-source(Segoe UI, 15px, #616264); - - &:focus, &:active { - outline:0; - } - } - - .rule { - input[type="text"] { - height: 30px; - } - .rule-fields, .rule-operators, input[type="text"] { - @extend .ruleGroup-combinators; - margin: 0px 10px 10px 0; - } - - .rule-remove { - @extend .ruleGroup-addRule; - min-width: 32px; - } - } - } -} - -.searchList { - padding: 10px 0 0 0; - border: 1px solid $color-2-primary; - width: 100%; display:table -} -.searchListHeader { - border: 1px solid $color-2-primary; - background-color: $color-1-primary; - color: white; - font-weight: bold; display:table-row -} -.cellHeader { - border-right: 1px solid white; - display: table-cell; - width:12%; - padding: 1px; - text-align: center; -} -.rowContent { - border: 1px solid $color-2-primary; - background-color: white; - display:table-row -} -.cellContent { - border-right: 1px solid white; - display: table-cell; - width:10%; - padding-right: 4px; - text-align: center; - border-bottom: none; -} - -.cellContentTwo { - background-color: rgba(0, 0, 0, 0.1); -} diff --git a/src/containers/SearchEngine/actions/getFields.js b/src/containers/SearchEngine/actions/getFields.js new file mode 100644 index 0000000000..d32e1508be --- /dev/null +++ b/src/containers/SearchEngine/actions/getFields.js @@ -0,0 +1,51 @@ +/* + * Copyright © 2018 Teclib. All rights reserved. + * + * This file is part of web-mdm-dashboard + * + * web-mdm-dashboard is a subproject of Flyve MDM. Flyve MDM is a mobile + * device management software. + * + * Flyve MDM is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 3 + * of the License, or (at your option) any later version. + * + * Flyve MDM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * ------------------------------------------------------------------------------ + * @author Gianfranco Manganiello (gmanganiello@teclib.com) + * @author Hector Rondon (hrondon@teclib.com) + * @copyright Copyright © 2018 Teclib. All rights reserved. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/flyve-mdm/web-mdm-dashboard + * @link http://flyve.org/web-mdm-dashboard + * @link https://flyve-mdm.com + * ------------------------------------------------------------------------------ + */ + +/** + * Returns the fields to use in the QueryBuilder component + * @function getFields + * @param {object} listSearchOptions + */ +export default function (listSearchOptions) { + const fields = [] + + for (const key in listSearchOptions) { + if (Object.prototype.hasOwnProperty.call(listSearchOptions, key)) { + const { name, field } = listSearchOptions[key] + + if (name !== undefined && field !== undefined) { + fields.push({ + name: key, + label: name, + }) + } + } + } + + return fields +} diff --git a/src/containers/SearchEngine/actions/getListSearchOptions.js b/src/containers/SearchEngine/actions/getListSearchOptions.js new file mode 100644 index 0000000000..c5b32d1746 --- /dev/null +++ b/src/containers/SearchEngine/actions/getListSearchOptions.js @@ -0,0 +1,40 @@ +/* + * Copyright © 2018 Teclib. All rights reserved. + * + * This file is part of web-mdm-dashboard + * + * web-mdm-dashboard is a subproject of Flyve MDM. Flyve MDM is a mobile + * device management software. + * + * Flyve MDM is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 3 + * of the License, or (at your option) any later version. + * + * Flyve MDM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * ------------------------------------------------------------------------------ + * @author Gianfranco Manganiello (gmanganiello@teclib.com) + * @author Hector Rondon (hrondon@teclib.com) + * @copyright Copyright © 2018 Teclib. All rights reserved. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/flyve-mdm/web-mdm-dashboard + * @link http://flyve.org/web-mdm-dashboard + * @link https://flyve-mdm.com + * ------------------------------------------------------------------------------ + */ + +/** + * Fetch search options list of itemType + * @function getListSearchOptions + * @async + */ +export default async (itemtype, glpi) => new Promise(async (resolve, reject) => { + try { + resolve(await glpi.listSearchOptions({ itemtype })) + } catch (error) { + reject(error) + } +}) diff --git a/src/containers/SearchEngine/actions/index.js b/src/containers/SearchEngine/actions/index.js new file mode 100644 index 0000000000..c300fefdea --- /dev/null +++ b/src/containers/SearchEngine/actions/index.js @@ -0,0 +1,37 @@ +/* + * Copyright © 2018 Teclib. All rights reserved. + * + * This file is part of web-mdm-dashboard + * + * web-mdm-dashboard is a subproject of Flyve MDM. Flyve MDM is a mobile + * device management software. + * + * Flyve MDM is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 3 + * of the License, or (at your option) any later version. + * + * Flyve MDM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * ------------------------------------------------------------------------------ + * @author Gianfranco Manganiello (gmanganiello@teclib.com) + * @author Hector Rondon (hrondon@teclib.com) + * @copyright Copyright © 2018 Teclib. All rights reserved. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/flyve-mdm/web-mdm-dashboard + * @link http://flyve.org/web-mdm-dashboard + * @link https://flyve-mdm.com + * ------------------------------------------------------------------------------ + */ + +import normalizeQuery from './normalizeQuery' +import getListSearchOptions from './getListSearchOptions' +import searchItem from './searchItem' + +export { + normalizeQuery, + getListSearchOptions, + searchItem, +} diff --git a/src/containers/SearchEngine/actions.js b/src/containers/SearchEngine/actions/normalizeQuery.js similarity index 60% rename from src/containers/SearchEngine/actions.js rename to src/containers/SearchEngine/actions/normalizeQuery.js index 0a23923d06..15aeda5348 100644 --- a/src/containers/SearchEngine/actions.js +++ b/src/containers/SearchEngine/actions/normalizeQuery.js @@ -26,41 +26,15 @@ * ------------------------------------------------------------------------------ */ - -/** - * Returns the fields to use in the QueryBuilder component - * @function getFields - * @param {object} listSearchOptions - */ -function getFields(listSearchOptions) { - const fields = [] - - for (const key in listSearchOptions) { - if (Object.prototype.hasOwnProperty.call(listSearchOptions, key)) { - const { name, field } = listSearchOptions[key] - - if (name !== undefined && field !== undefined) { - fields.push({ - name: key, - label: name, - }) - } - } - } - - return fields -} - /** * Create the array of rules extracted * @function recursiveExtractQueryRules * @param {object} query - * @param {object} ctx * @param {array} arrayRulesExtracted * @param {string} combinator * @return {array} */ -const recursiveExtractQueryRules = (query, ctx, arrayRulesExtracted, combinator) => { +const recursiveExtractQueryRules = (query, arrayRulesExtracted, combinator) => { if (typeof (query.rules) === 'undefined' || typeof (query.field) === 'string') { /* * It means that it is a rule, and it has operator, value and field @@ -76,7 +50,7 @@ const recursiveExtractQueryRules = (query, ctx, arrayRulesExtracted, combinator) * It means that it is a group and you have rules and combinator */ query.rules.forEach((rule) => { - recursiveExtractQueryRules(rule, ctx, arrayRulesExtracted, query.combinator) + recursiveExtractQueryRules(rule, arrayRulesExtracted, query.combinator) }) } @@ -87,58 +61,17 @@ const recursiveExtractQueryRules = (query, ctx, arrayRulesExtracted, combinator) * Process query create by QueryBuilde. * And normalize for correct format to GLPI REST API URI * @function normalizeQuery - * @param {object} ctx + * @param {object} query * @return {array} */ -const normalizeQuery = (ctx) => { - const query = { ...ctx.state.query } +const normalizeQuery = (query) => { const arrayRules = [] const arrayRulesExtracted = recursiveExtractQueryRules( - query, ctx, arrayRules, query.combinator, + query, arrayRules, query.combinator, ) return arrayRulesExtracted } -/** - * Friendly translation for each QueryBuilder input - * @function getTranslation - * @return {object} - */ -const getTranslation = () => ({ - fields: { - title: 'Fields', - }, - operators: { - title: 'Operators', - }, - value: { - title: 'Value', - }, - removeRule: { - label: 'x', - title: 'Remove rule', - }, - removeGroup: { - label: 'x', - title: 'Remove group', - }, - addRule: { - label: '+Rule', - title: 'Add rule', - }, - addGroup: { - label: '+Group', - title: 'Add group', - }, - combinators: { - title: 'Combinators', - }, -}) - -module.exports = { - getTranslation, - normalizeQuery, - getFields, -} +export default normalizeQuery diff --git a/src/containers/SearchEngine/actions/searchItem.js b/src/containers/SearchEngine/actions/searchItem.js new file mode 100644 index 0000000000..3e61919f63 --- /dev/null +++ b/src/containers/SearchEngine/actions/searchItem.js @@ -0,0 +1,48 @@ +/* + * Copyright © 2018 Teclib. All rights reserved. + * + * This file is part of web-mdm-dashboard + * + * web-mdm-dashboard is a subproject of Flyve MDM. Flyve MDM is a mobile + * device management software. + * + * Flyve MDM is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 3 + * of the License, or (at your option) any later version. + * + * Flyve MDM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * ------------------------------------------------------------------------------ + * @author Gianfranco Manganiello (gmanganiello@teclib.com) + * @author Hector Rondon (hrondon@teclib.com) + * @copyright Copyright © 2018 Teclib. All rights reserved. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/flyve-mdm/web-mdm-dashboard + * @link http://flyve.org/web-mdm-dashboard + * @link https://flyve-mdm.com + * ------------------------------------------------------------------------------ + */ + +import normalizeQuery from './normalizeQuery' + +/** + * Handle click event in the search button + * @function searchItem + * @async + */ + +export default (glpi, itemtype, query) => new Promise(async (resolve, reject) => { + try { + const search = await glpi.searchItems({ + itemtype, + criteria: normalizeQuery(query), + }) + + resolve(search.data || []) + } catch (error) { + reject(error) + } +}) diff --git a/src/containers/SearchEngine/components/ItemTypeSelector.js b/src/containers/SearchEngine/components/ItemTypeSelector.js index d6b93a0ff2..7f8d0a9954 100644 --- a/src/containers/SearchEngine/components/ItemTypeSelector.js +++ b/src/containers/SearchEngine/components/ItemTypeSelector.js @@ -47,14 +47,14 @@ class ItemTypeSelector extends PureComponent { style={{ marginRight: 10 }} className="win-textbox" placeholder="Itemtype" - name="itemTypeName" - value={this.props.itemType} - onChange={this.props.handleChangeItemType} + name="itemtypeName" + value={this.props.itemtype} + onChange={this.props.changeItemType} /> +
+ ) + } +} + +Rule.defaultProps = { + itemtype: null, +} + +Rule.propTypes = { + id: PropTypes.number.isRequired, + type: PropTypes.string.isRequired, + link: PropTypes.string.isRequired, + itemtype: PropTypes.string, + field: PropTypes.string.isRequired, + searchtype: PropTypes.string.isRequired, + value: PropTypes.string.isRequired, + changeRule: PropTypes.func.isRequired, +} + +export default Rule diff --git a/src/containers/SearchEngine/components/QueryBuilder/index.js b/src/containers/SearchEngine/components/QueryBuilder/index.js new file mode 100644 index 0000000000..e547e0dd96 --- /dev/null +++ b/src/containers/SearchEngine/components/QueryBuilder/index.js @@ -0,0 +1,93 @@ +import React, { + PureComponent, +} from 'react' +import PropTypes from 'prop-types' +import Rule from './Rule' + +/** + * Component to select a item type + * @class SearchEngine + * @extends PureComponent + */ +class QueryBuilder extends PureComponent { + constructor(props) { + super(props) + + this.state = { + criteria: [], + metaCriteria: [], + } + } + + addCriteria = () => { + const { criteria: currentCriteria } = this.state + + this.setState({ + criteria: [...currentCriteria, {}], + }) + } + + addMetaCriteria = () => { + const { metaCriteria: currentMetaCriteria } = this.state + + this.setState({ + metaCriteria: [...currentMetaCriteria, {}], + }) + } + + changeRule = (type, id, newValue) => { + const CurrentRules = this.state[type] + const newRules = [...CurrentRules] + + if (newValue) { + newRules[id] = newValue + + this.setState({ + [type]: newRules, + }) + } else { + this.setState({ + [type]: newRules.slice(0, id).concat(newRules.slice(id + 1)), + }) + } + } + + render() { + return ( + + + { + this.state.criteria.map((rule, index) => { + return ( + + ) + }) + } + + ) + } +} + +QueryBuilder.propTypes = { + changeQuery: PropTypes.func.isRequired, + glpi: PropTypes.object.isRequired, + itemtype: PropTypes.string.isRequired, + listSearchOptions: PropTypes.object.isRequired, +} + +export default QueryBuilder diff --git a/src/containers/SearchEngine/components/ResultsDisplay.js b/src/containers/SearchEngine/components/ResultsDisplay.js index abc579426d..7a6b73849e 100644 --- a/src/containers/SearchEngine/components/ResultsDisplay.js +++ b/src/containers/SearchEngine/components/ResultsDisplay.js @@ -43,7 +43,7 @@ class ResultsDisplay extends PureComponent { render() { let display = null - if (this.props.results) { + if (this.props.results && this.props.query) { if (this.props.results.length > 0) { const resultsWithFields = [] @@ -79,11 +79,13 @@ class ResultsDisplay extends PureComponent { ResultsDisplay.defaultProps = { listSearchOptions: {}, results: null, + query: null, } ResultsDisplay.propTypes = { results: PropTypes.array, listSearchOptions: PropTypes.object, + query: PropTypes.object, } export default ResultsDisplay diff --git a/src/containers/SearchEngine/components/SeachArea.js b/src/containers/SearchEngine/components/SeachArea.js index 2fa85f7be2..6416bcb5e9 100644 --- a/src/containers/SearchEngine/components/SeachArea.js +++ b/src/containers/SearchEngine/components/SeachArea.js @@ -40,7 +40,7 @@ import I18n from 'shared/i18n' */ class SeachArea extends PureComponent { render() { - let display + let display = null if (this.props.isLoading) { display = ( @@ -54,7 +54,7 @@ class SeachArea extends PureComponent { display = ( - ) - : null - : ( -

- {I18n.t('search_engine.itemType_not_found')} -

- ) - } - - - -
+ + + + ) } From 2b1180df7c1e367c948965ec2a79cb33bb17aab9 Mon Sep 17 00:00:00 2001 From: Gianfranco Manganiello Date: Fri, 28 Sep 2018 10:33:57 -0400 Subject: [PATCH 07/26] refactor(forms): add a new parameter to the 'Selects' Receive 'noEmpty' parameter to validate the inclusion of the '---' option Signed-off-by: Gianfranco Manganiello --- src/components/Forms/Select/index.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/components/Forms/Select/index.js b/src/components/Forms/Select/index.js index 7386286616..2c8c9e660e 100644 --- a/src/components/Forms/Select/index.js +++ b/src/components/Forms/Select/index.js @@ -180,9 +180,15 @@ class Select extends PureComponent { onChange={this.change} required={this.props.required} > - + { + !this.props.noEmpty + && ( + + ) + } + { this.state.options.map((element, index) => (