Commit 5630ef89 authored by Ana Rute Mendes's avatar Ana Rute Mendes 🌈
Browse files

snipe-it: add choices.js to items list in purchase request

To make the assets field searchable, add choices.js lib to the field,
adapt its style to look like a native phabricator field and dynamically
display the items details.
parent d6594388
......@@ -513,7 +513,9 @@ return array(
'rsrc/js/core/darkconsole/DarkMessage.js' => '26cd4b73',
'rsrc/js/core/darkconsole/behavior-dark-console.js' => 'f39d968b',
'rsrc/js/core/phtize.js' => '2f1db1ed',
'rsrc/js/extensions/snipe-fields-validation.js' => '73e6e0ce',
'rsrc/js/extensions/choices/choices.css' => 'f3390b3b',
'rsrc/js/extensions/choices/choices.js' => 'e6c9320a',
'rsrc/js/extensions/snipe-fields-validation.js' => '3e0cfa32',
'rsrc/js/phui/behavior-phui-dropdown-menu.js' => '5cf0501a',
'rsrc/js/phui/behavior-phui-file-upload.js' => 'e150bd50',
'rsrc/js/phui/behavior-phui-selectable-list.js' => 'b26a41e4',
......@@ -544,6 +546,8 @@ return array(
'application-search-view-css' => '0f7c06d8',
'auth-css' => 'c2f23d74',
'bulk-job-css' => '73af99f5',
'choices-css' => 'f3390b3b',
'choices-js' => 'e6c9320a',
'conduit-api-css' => 'ce2cfc41',
'config-options-css' => '16c920ae',
'conpherence-color-css' => 'b17746b0',
......@@ -900,7 +904,7 @@ return array(
'releeph-request-differential-create-dialog' => '0ac1ea31',
'releeph-request-typeahead-css' => 'bce37359',
'setup-issue-css' => '5eed85b2',
'snipe-fields-validation-js' => '73e6e0ce',
'snipe-fields-validation-js' => '3e0cfa32',
'sprite-login-css' => '18b368a6',
'sprite-tokens-css' => 'f1896dc5',
'syntax-default-css' => '055fc231',
......
/**
* @provides choices-css
*/
.choices{position:relative;margin-bottom:24px;font-size:16px}.choices:focus{outline:0}.choices:last-child{margin-bottom:0}.choices.is-disabled .choices__inner,.choices.is-disabled input[type="text"].choices__input{background-color:#eaeaea;cursor:not-allowed;-webkit-user-select:none;-ms-user-select:none;user-select:none}.choices.is-disabled .choices__item{cursor:not-allowed}.choices [hidden]{display:none!important}.choices[data-type*=select-one]{cursor:pointer}.choices[data-type*=select-one] .choices__inner{padding-bottom:7.5px}.choices[data-type*=select-one] input[type="text"].choices__input{display:block;width:100%;padding:10px;border-bottom:1px solid #ddd;background-color:#fff;margin:0}.choices[data-type*=select-one] .choices__button{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjMDAwIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==);padding:0;background-size:8px;position:absolute;top:50%;right:0;margin-top:-10px;margin-right:25px;height:20px;width:20px;border-radius:10em;opacity:.5}.choices[data-type*=select-one] .choices__button:focus,.choices[data-type*=select-one] .choices__button:hover{opacity:1}.choices[data-type*=select-one] .choices__button:focus{box-shadow:0 0 0 2px #00bcd4}.choices[data-type*=select-one] .choices__item[data-value=''] .choices__button{display:none}.choices[data-type*=select-one]:after{content:'';height:0;width:0;border-style:solid;border-color:#333 transparent transparent;border-width:5px;position:absolute;right:11.5px;top:50%;margin-top:-2.5px;pointer-events:none}.choices[data-type*=select-one].is-open:after{border-color:transparent transparent #333;margin-top:-7.5px}.choices[data-type*=select-one][dir=rtl]:after{left:11.5px;right:auto}.choices[data-type*=select-one][dir=rtl] .choices__button{right:auto;left:0;margin-left:25px;margin-right:0}.choices[data-type*=select-multiple] .choices__inner,.choices[data-type*=text] .choices__inner{cursor:text}.choices[data-type*=select-multiple] .choices__button,.choices[data-type*=text] .choices__button{position:relative;display:inline-block;margin:0 -4px 0 8px;padding-left:16px;border-left:1px solid #008fa1;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjRkZGIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==);background-size:8px;width:8px;line-height:1;opacity:.75;border-radius:0}.choices[data-type*=select-multiple] .choices__button:focus,.choices[data-type*=select-multiple] .choices__button:hover,.choices[data-type*=text] .choices__button:focus,.choices[data-type*=text] .choices__button:hover{opacity:1}.choices__inner{display:inline-block;vertical-align:top;width:100%;background-color:#f9f9f9;padding:7.5px 7.5px 3.75px;border:1px solid #ddd;border-radius:2.5px;font-size:14px;min-height:44px;overflow:hidden}.is-focused .choices__inner,.is-open .choices__inner{border-color:#b7b7b7}.is-open .choices__inner{border-radius:2.5px 2.5px 0 0}.is-flipped.is-open .choices__inner{border-radius:0 0 2.5px 2.5px}.choices__list{margin:0;padding-left:0;list-style:none}.choices__list--single{display:inline-block;padding:4px 16px 4px 4px;width:100%}[dir=rtl] .choices__list--single{padding-right:4px;padding-left:16px}.choices__list--single .choices__item{width:100%}.choices__list--multiple{display:inline}.choices__list--multiple .choices__item{display:inline-block;vertical-align:middle;border-radius:20px;padding:4px 10px;font-size:12px;font-weight:500;margin-right:3.75px;margin-bottom:3.75px;background-color:#00bcd4;border:1px solid #00a5bb;color:#fff;word-break:break-all;box-sizing:border-box}.choices__list--multiple .choices__item[data-deletable]{padding-right:5px}[dir=rtl] .choices__list--multiple .choices__item{margin-right:0;margin-left:3.75px}.choices__list--multiple .choices__item.is-highlighted{background-color:#00a5bb;border:1px solid #008fa1}.is-disabled .choices__list--multiple .choices__item{background-color:#aaa;border:1px solid #919191}.choices__list--dropdown{visibility:hidden;z-index:1;position:absolute;width:100%;background-color:#fff;border:1px solid #ddd;top:100%;margin-top:-1px;border-bottom-left-radius:2.5px;border-bottom-right-radius:2.5px;overflow:hidden;word-break:break-all;will-change:visibility}.choices__list--dropdown.is-active{visibility:visible}.is-open .choices__list--dropdown{border-color:#b7b7b7}.is-flipped .choices__list--dropdown{top:auto;bottom:100%;margin-top:0;margin-bottom:-1px;border-radius:.25rem .25rem 0 0}.choices__list--dropdown .choices__list{position:relative;max-height:300px;overflow:auto;-webkit-overflow-scrolling:touch;will-change:scroll-position}.choices__list--dropdown .choices__item{position:relative;padding:10px;font-size:14px}[dir=rtl] .choices__list--dropdown .choices__item{text-align:right}@media (min-width:640px){.choices__list--dropdown .choices__item--selectable{padding-right:100px}.choices__list--dropdown .choices__item--selectable:after{content:attr(data-select-text);font-size:12px;opacity:0;position:absolute;right:10px;top:50%;transform:translateY(-50%)}[dir=rtl] .choices__list--dropdown .choices__item--selectable{text-align:right;padding-left:100px;padding-right:10px}[dir=rtl] .choices__list--dropdown .choices__item--selectable:after{right:auto;left:10px}}.choices__list--dropdown .choices__item--selectable.is-highlighted{background-color:#f2f2f2}.choices__list--dropdown .choices__item--selectable.is-highlighted:after{opacity:.5}.choices__item{cursor:default}.choices__item--selectable{cursor:pointer}.choices__item--disabled{cursor:not-allowed;-webkit-user-select:none;-ms-user-select:none;user-select:none;opacity:.5}.choices__heading{font-weight:600;font-size:12px;padding:10px;border-bottom:1px solid #f7f7f7;color:gray}.choices__button{text-indent:-9999px;-webkit-appearance:none;-moz-appearance:none;appearance:none;border:0;background-color:transparent;background-repeat:no-repeat;background-position:center;cursor:pointer}.choices__button:focus,input[type="text"].choices__input:focus{outline:0}input[type="text"].choices__input{display:inline-block;vertical-align:baseline;background-color:#f9f9f9;font-size:14px;margin-bottom:5px;border:0;border-radius:0;max-width:100%;padding:4px 0 4px 2px}[dir=rtl] input[type="text"].choices__input{padding-right:2px;padding-left:0}.choices__placeholder{opacity:.5}
This diff is collapsed.
......@@ -2,10 +2,15 @@
* @provides snipe-fields-validation-js
*/
function triggerEvent(elem, event) {
var clickEvent = new Event(event); // Create the event.
elem.dispatchEvent(clickEvent); // Dispatch the event.
}
function shipping_validations() {
let styles = `
.snipe_assets_select {
display: block;
display: none;
}
.item_card {
border-bottom: 1px dashed #ccc;
......@@ -13,6 +18,44 @@ function shipping_validations() {
margin-bottom: 1em;
clear:both;
}
.aphront-form-caption {
clear: both;
}
.choices__list--multiple .choices__item {
background: #ddefdd;
color: #326d34;
padding: 1px 6px;
border: 1px solid #c6e6c7;
margin: 3px 2px 0 4px;
border-radius: 3px;
}
.choices[data-type*=select-multiple] .choices__button {
border: none;
background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAMCAYAAAC0qUeeAAAABHNCSVQICAgIfAhkiAAAABl0RVh0U29mdHdhcmUAZ25vbWUtc2NyZWVuc2hvdO8Dvz4AAADQSURBVCiRY7z7/u5/BiIBE7EKyVX8juH2y6cMv5Flfj9luP7uExbFvz8xXL8zl2HyzQcM3xgYGBh+32FYd2ouw/bX71AMYIR78PcDhj1nFjGc47FikP5wjOGddDJDhpI0AytWN7MqMLjo2jOwPN/KcI7FmSEKTSGq4p+XGZaeP8jAqRLL4Mu8l2Hu5esMn7Aq/nmZYemp9Qzf5dMZUpSMGByM0xmsf65mmHz5OsQPKG7++47h9kcGBlUhIYTM33cMDz6zMCgI8GHxIBGApEgBAOKcUNYQOyC6AAAAAElFTkSuQmCC);
background-color: transparent;
background-size: 11px 12px;
padding-left: 0;
}
input[type="text"].choices__input {
padding-left: 10px;
background-color: #fff;
}
input[type="text"].choices__input:focus {
border: none;
box-shadow: none;
}
.choices.is-focused {
border-color: rgba(82, 168, 236, 0.8);
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);
box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);
}
.choices__inner {
min-height: auto;
padding: 0;
background: none;
border-color: #A1A6B0;
}
`;
var styleSheet = document.createElement("style");
......@@ -20,34 +63,61 @@ function shipping_validations() {
styleSheet.innerText = styles;
document.head.appendChild(styleSheet);
// Hide the assets tag field, as the user shouldn't be able to edit
// it manually.
asset_id = document.getElementsByName("std:maniphest:shipping:asset-id")[0];
asset_id.parentNode.parentNode.style.display = "none";
items_container = document.createElement("div");
items_container.setAttribute("id", "items_container");
tags_container = document.createElement("div");
items_container.appendChild(tags_container);
assets = document.getElementById("snipe_assets");
// Set selected values on init
const assets_element = document.getElementById("snipe_assets");
let asset_ids_array = asset_id.value.split(",");
for (var i = 0; i < assets.options.length; i++) {
assets.options[i].selected =
asset_ids_array.indexOf(assets.options[i].value) >= 0;
for (var i = 0; i < assets_element.options.length; i++) {
assets_element.options[i].selected =
asset_ids_array.indexOf(assets_element.options[i].value) >= 0;
}
let ship_to_customer = document.getElementsByName(
"std:maniphest:shipping:ship-to-customer"
)[0];
ship_to_customer.onchange = function() {
if (ship_to_customer.checked) {
ship_to_customer.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.nextSibling.style.display =
"none";
} else {
ship_to_customer.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.nextSibling.style.display =
"block";
}
};
// store assets details in an object
asset_details = {};
for (let index = 0; index < assets_element.options.length; index++) {
const option = assets_element.options[index];
asset_details[option.value] = {
href: option.attributes["data-src"]
? option.attributes["data-src"].value
: "",
country_of_origin: option.attributes["data-country-of-origin"]
? option.attributes["data-country-of-origin"].value
: "",
currency: option.attributes["data-currency"]
? option.attributes["data-currency"].value
: "",
purchase_cost: option.attributes["data-purchase-cost"]
? option.attributes["data-purchase-cost"].value
: "",
};
}
const choices = new Choices(assets_element, {
removeItemButton: true,
placeholder: true,
placeholderValue: "Select the assets to ship",
searchPlaceholderValue: "Select the assets to ship",
noResultsText: "No assets found",
searchResultLimit: 30,
sortFields: ["label"],
fuseOptions: {
findAllMatches: true,
threshold: 0.3,
distance: 100,
location: 30,
useExtendedSearch: true,
},
});
items_container = document.createElement("div");
items_container.setAttribute("id", "items_container");
// Get elements that will be modified by the select field
let import_asset = document.getElementsByName(
"std:maniphest:shipping:import-asset"
)[0];
......@@ -64,109 +134,114 @@ function shipping_validations() {
"std:maniphest:shipping:item-description"
)[0];
if (!import_asset.checked) {
assets.parentNode.parentNode.style.display = "none";
}
assets_element.addEventListener(
"change",
function (event) {
document.querySelectorAll(".item_card").forEach((e) => e.remove());
el_description.value = "";
import_asset.onchange = function() {
if (import_asset.checked) {
items_container.style.display = "block";
assets.parentNode.parentNode.style.display = "block";
} else {
items_container.style.display = "none";
assets.parentNode.parentNode.style.display = "none";
items_container.innerText = "";
assets.value = "";
asset_id.value = "";
}
};
assets.onchange = function() {
document
.querySelectorAll(".asset_tag, .item_card")
.forEach(e => e.remove());
el_description.value = "";
let values = Array.from(assets.selectedOptions).map(v => v.value);
let items = Array.from(assets.selectedOptions).map(option => {
el = document.createElement("a");
el.textContent = option.text;
el.classList.add(
"asset_tag",
"jx-tokenizer-token",
"jx-tokenizer-token-object",
"green"
let values = Array.from(assets_element.selectedOptions).map(
(v) => v.value
);
el.setAttribute("target", "blank");
el.setAttribute("href", option.attributes["data-src"].value);
close_btn = document.createElement("a");
close_btn.className = "jx-tokenizer-x";
close_btn.setAttribute("data-sigil", "remove");
close_btn.text = "x";
close_btn.onclick = function() {
close_btn.parentNode.remove();
};
el.appendChild(close_btn);
return {
name: option.textContent,
href: option.attributes["data-src"].value,
props: {
purchase_cost: {
value: option.attributes["data-purchase-cost"].value,
label: "Purchase cost"
let items = Array.from(assets_element.selectedOptions).map((option) => {
return {
name: option.textContent,
href: asset_details[option.value].href,
props: {
purchase_cost: {
value: asset_details[option.value].purchase_cost,
label: "Purchase cost",
},
currency: {
value: asset_details[option.value].currency,
label: "Currency",
},
country_of_origin: {
value: asset_details[option.value].country_of_origin,
label: "Country of origin",
},
},
currency: {
value: option.attributes["data-currency"].value,
label: "Currency"
},
country_of_origin: {
value: option.attributes["data-country-of-origin"].value,
label: "Country of origin"
}
};
});
// Create item card when user select an item from the list
items.forEach(function (item) {
item_element = document.createElement("div");
item_element.className = "item_card";
item_url = document.createElement("a");
item_url.textContent = item["name"];
item_url.setAttribute("target", "_blank");
item_url.setAttribute("href", item["href"]);
item_element.appendChild(item_url);
el_description.value = el_description.value + item["name"];
for (var key in item.props) {
prop = document.createElement("p");
prop.textContent =
item.props[key].label + ": " + item.props[key].value;
item_element.appendChild(prop);
el_description.value = el_description.value + "\n" + prop.textContent;
}
};
});
items.forEach(function(item) {
item_element = document.createElement("div");
item_element.className = "item_card";
item_url = document.createElement("a");
item_url.textContent = item["name"];
item_url.setAttribute("target", "blank");
item_url.setAttribute("href", item["href"]);
item_element.appendChild(item_url);
el_description.value = el_description.value + item["name"];
for (var key in item.props) {
prop = document.createElement("p");
prop.textContent = item.props[key].label + ": " + item.props[key].value;
item_element.appendChild(prop);
el_description.value = el_description.value + "\n" + prop.textContent;
}
items_container.appendChild(item_element);
el_description.value = el_description.value + "\n\n";
items_container.appendChild(item_element);
el_description.value = el_description.value + "\n\n";
if (items.length == 1) {
el_country_of_origin.value = item.props.country_of_origin.value;
el_currency.value = item.props.currency.value;
}
});
if (items.length == 1) {
el_country_of_origin.value = item.props.country_of_origin.value;
el_currency.value = item.props.currency.value;
if (items.length > 1) {
el_country_of_origin.value = "";
el_currency.value = "";
}
});
if (items.length > 1) {
el_country_of_origin.value = "";
el_currency.value = "";
}
assets_element.parentNode.parentNode.parentNode.appendChild(
items_container
);
el_assets_value.value = items.reduce(function (sum, i) {
return sum + Number(i.props.purchase_cost.value);
}, 0);
asset_id.value = values;
},
false
);
assets.parentNode.appendChild(items_container);
// if is shipped to customer, hide the Recipient user field
let ship_to_customer = document.getElementsByName(
"std:maniphest:shipping:ship-to-customer"
)[0];
ship_to_customer.onchange = function () {
if (ship_to_customer.checked) {
ship_to_customer.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.nextSibling.style.display =
"none";
} else {
ship_to_customer.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.nextSibling.style.display =
"block";
}
};
el_assets_value.value = items.reduce(function(sum, i) {
return sum + Number(i.props.purchase_cost.value);
}, 0);
asset_id.value = values;
// Hide Snipe-IT related fields if user does not intend to import details
// from there.
if (!import_asset.checked) {
assets_element.parentNode.parentNode.parentNode.parentNode.style.display =
"none";
}
import_asset.onchange = function () {
if (import_asset.checked) {
items_container.style.display = "block";
assets_element.parentNode.parentNode.parentNode.parentNode.style.display =
"block";
} else {
items_container.style.display = "none";
assets_element.parentNode.parentNode.parentNode.parentNode.style.display =
"none";
items_container.innerText = "";
assets_element.value = "";
asset_id.value = "";
}
};
}
......@@ -210,11 +285,11 @@ function fetch_and_hide_extra_assets_elements(index, unique_items) {
"std:maniphest:purchasing:currency" + index
)[0].parentNode.parentNode;
Object.keys(asset).forEach(i => asset[i].classList.add("asset_property"));
Object.keys(asset).forEach((i) => asset[i].classList.add("asset_property"));
// Hide all extra items at first
if (index > 1 && index > unique_items) {
Object.keys(asset).forEach(i => (asset[i].style.display = "none"));
Object.keys(asset).forEach((i) => (asset[i].style.display = "none"));
}
return asset;
......@@ -264,7 +339,7 @@ function purchasing_validations() {
}
}
should_create.onchange = function() {
should_create.onchange = function () {
if (should_create.checked) {
for (let i = 0; i < num_asset_forms.value; i++) {
for (let key in assets_list[i]) {
......@@ -292,7 +367,7 @@ function purchasing_validations() {
add_new_asset_btn.innerHTML = "Add another item to this ticket";
add_new_asset.appendChild(add_new_asset_btn);
add_new_asset_btn.onclick = function() {
add_new_asset_btn.onclick = function () {
if (num_asset_forms.value < MAX_ALLOWED_ASSETS) {
for (let key in assets_list[num_asset_forms.value - 1]) {
if (
......@@ -325,7 +400,7 @@ function purchasing_validations() {
submit_parent.appendChild(add_new_asset);
}
document.addEventListener("DOMContentLoaded", function(event) {
document.addEventListener("DOMContentLoaded", function (event) {
/* Make sure this will load only in the Purchase and Shipping forms */
let purchasing_element = document.getElementsByName(
"std:maniphest:purchasing:asset-name1"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment