UI/UX improvements

pull/209/head
larteyoh 8 months ago
parent 101502e4d6
commit fd85ca9d26

Binary file not shown.

After

Width:  |  Height:  |  Size: 534 B

@ -77,6 +77,7 @@
<file>assets/images/eye.png</file> <file>assets/images/eye.png</file>
<file>assets/images/eye_slash.png</file> <file>assets/images/eye_slash.png</file>
<file>assets/images/file.png</file> <file>assets/images/file.png</file>
<file>assets/images/filter.png</file>
<file>assets/images/grid.png</file> <file>assets/images/grid.png</file>
<file>assets/images/heart.png</file> <file>assets/images/heart.png</file>
<file>assets/images/image.png</file> <file>assets/images/image.png</file>

@ -3,6 +3,8 @@ import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12 import QtQuick.Layouts 1.12
import Qt.labs.platform 1.1 // FileDialog import Qt.labs.platform 1.1 // FileDialog
import FontAwesome 1.0
import "." as NeroshopComponents import "." as NeroshopComponents
Popup { Popup {
@ -22,14 +24,69 @@ Popup {
background: Rectangle { background: Rectangle {
radius: 8 radius: 8
color: (NeroshopComponents.Style.darkTheme) ? (NeroshopComponents.Style.themeName == "PurpleDust" ? "#0e0e11" : "#101010") : "#f0f0f0" color: (NeroshopComponents.Style.darkTheme) ? (NeroshopComponents.Style.themeName == "PurpleDust" ? "#0e0e11" : "#101010") : "#f0f0f0"
// header
Rectangle {
id: titleBar
color: "#202020"
height: 40
width: parent.width
anchors.left: parent.left
anchors.right: parent.right
radius: 6
// Rounded top corners
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: parent.height / 2
color: parent.color
}
Label {
text: "Add item"
color: "#ffffff"
font.bold: true
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
Button {
id: closeButton
width: 25
height: this.width
anchors.verticalCenter: titleBar.verticalCenter
anchors.right: titleBar.right
anchors.rightMargin: 10
text: qsTr(FontAwesome.xmark)
contentItem: Text {
text: closeButton.text
color: "#ffffff"
font.bold: true
font.family: FontAwesome.fontFamily
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
background: Rectangle {
color: "#ff4d4d"
radius: 100
}
onClicked: {
productDialog.close()
mainScrollView.ScrollBar.vertical.position = 0.0 // reset scrollbar
}
}
}
} }
contentItem: ScrollView { contentItem: ScrollView {
id: mainScrollView id: mainScrollView
anchors.fill: parent anchors.fill: parent
anchors.topMargin: 20; anchors.bottomMargin: anchors.topMargin////anchors.margins: 20 anchors.topMargin: titleBar.height + 20; anchors.bottomMargin: 20//anchors.topMargin////anchors.margins: 20
clip: true clip: true
ScrollBar.vertical.policy: ScrollBar.AsNeeded ScrollBar.vertical.policy: ScrollBar.AlwaysOn//AsNeeded
ColumnLayout { ColumnLayout {
width: productDialog.availableWidth; height: productDialog.availableHeight width: productDialog.availableWidth; height: productDialog.availableHeight
spacing: 30 spacing: 30
@ -41,7 +98,7 @@ Popup {
Column { Column {
spacing: productDialog.titleSpacing spacing: productDialog.titleSpacing
Text { Text {
text: "Product name" text: "Name / Title"
color: productDialog.palette.text color: productDialog.palette.text
font.bold: true font.bold: true
} }
@ -124,11 +181,34 @@ Popup {
Column { Column {
spacing: productDialog.titleSpacing spacing: productDialog.titleSpacing
Text { Row {
text: "Quantity" spacing: 10
color: productDialog.palette.text Text {
font.bold: true text: qsTr("Quantity")
//visible: false color: productDialog.palette.text
font.bold: true
}
Text {
text: qsTr(FontAwesome.circleInfo)
color: productDialog.optTextColor
font.bold: true
//font.pointSize:
anchors.verticalCenter: parent.children[0].verticalCenter
property bool hovered: false
NeroshopComponents.Hint {
x: parent.width + 10; y: ((parent.height - height) / 2) - 3
visible: parent.hovered
height: contentHeight + 20; width: contentWidth + 20
text: qsTr("The total number of items in stock")
pointer.visible: false;// delay: 0
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: parent.hovered = true
onExited: parent.hovered = false
}
}
} }
TextField { TextField {
@ -250,298 +330,298 @@ Popup {
} }
} }
Row { Row {
spacing: 5 spacing: 5
TextField { TextField {
id: productCodeField id: productCodeField
width: 500 - parent.children[1].width - parent.spacing; height: 50 width: 500 - parent.children[1].width - parent.spacing; height: 50
placeholderText: qsTr("Enter product code") placeholderText: qsTr("Enter product code")
color: productDialog.inputTextColor color: productDialog.inputTextColor
selectByMouse: true selectByMouse: true
background: Rectangle { background: Rectangle {
color: "transparent" color: "transparent"
border.color: productDialog.inputBorderColor border.color: productDialog.inputBorderColor
border.width: parent.activeFocus ? 2 : 1 border.width: parent.activeFocus ? 2 : 1
radius: productDialog.inputRadius radius: productDialog.inputRadius
}
}
NeroshopComponents.ComboBox {
id: productCodeType
height: parent.children[0].height//Layout.preferredWidth: 100; Layout.preferredHeight: parent.children[0].height
model: ["EAN", "ISBN", "JAN", "SKU", "UPC"] // default is UPC (each code will be validated before product is listed)
Component.onCompleted: currentIndex = find("UPC")
radius: productDialog.inputRadius
color: productDialog.inputBaseColor
textColor: productDialog.inputTextColor
}
} }
} }
NeroshopComponents.ComboBox {
id: productCodeType
height: parent.children[0].height//Layout.preferredWidth: 100; Layout.preferredHeight: parent.children[0].height
model: ["EAN", "ISBN", "JAN", "SKU", "UPC"] // default is UPC (each code will be validated before product is listed)
Component.onCompleted: currentIndex = find("UPC")
radius: productDialog.inputRadius
color: productDialog.inputBaseColor
textColor: productDialog.inputTextColor
}
}
}
} }
// Product categories // Product categories
Item { Item {
//Layout.row: //Layout.row:
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: childrenRect.width Layout.preferredWidth: childrenRect.width
Layout.preferredHeight: childrenRect.height Layout.preferredHeight: childrenRect.height
function getCategoryStringList() { function getCategoryStringList() {
let categoryStringList = [] let categoryStringList = []
let categories = Backend.getCategoryList(true) let categories = Backend.getCategoryList(true)
for(let i = 0; i < categories.length; i++) { for(let i = 0; i < categories.length; i++) {
categoryStringList[i] = categories[i].name//console.log(parent.parent.parent.categoryStringList[i])//console.log(categories[i].name) categoryStringList[i] = categories[i].name//console.log(parent.parent.parent.categoryStringList[i])//console.log(categories[i].name)
}
return categoryStringList;
}
Column {
spacing: productDialog.titleSpacing
Text {
text: "Category"
color: productDialog.palette.text
font.bold: true
}
Row {
spacing: 5
NeroshopComponents.ComboBox {
id: productCategoryBox
width: addSubCategoryButton.visible ? (500 - addSubCategoryButton.width - parent.spacing) : 500; height: 50
model: parent.parent.parent.getCategoryStringList()
Component.onCompleted: {
currentIndex = find("Miscellaneous")
}
function reset() {
let subcategories = Backend.getSubCategoryList(Backend.getCategoryIdByName(productCategoryBox.currentText), true)
addSubCategoryButton.visible = (subcategories.length > 0)
subCategoryRepeater.model = 0 // reset
}
onActivated: {
productCategoryBox.reset()
} }
return categoryStringList; radius: productDialog.inputRadius
color: productDialog.inputBaseColor
textColor: productDialog.inputTextColor
} }
Button {
Column { id: addSubCategoryButton
spacing: productDialog.titleSpacing width: 50; height: 50
Text { text: qsTr("+")
text: "Category" visible: Backend.hasSubCategory(Backend.getCategoryIdByName(productCategoryBox.currentText))
color: productDialog.palette.text background: Rectangle {
font.bold: true color: parent.hovered ? "#698b22" : "#506a1a"//"#605185"
radius: productDialog.inputRadius
} }
contentItem: Text {
Row { text: parent.text
spacing: 5 color: "#ffffff"
NeroshopComponents.ComboBox { verticalAlignment: Text.AlignVCenter
id: productCategoryBox horizontalAlignment: Text.AlignHCenter
width: addSubCategoryButton.visible ? (500 - addSubCategoryButton.width - parent.spacing) : 500; height: 50 }
model: parent.parent.parent.getCategoryStringList() onClicked: {
Component.onCompleted: { let subcategories = Backend.getSubCategoryList(Backend.getCategoryIdByName(productCategoryBox.currentText), true)
currentIndex = find("Miscellaneous") let max_subcategories = Math.min(2, subcategories.length)
} if(subCategoryRepeater.count == max_subcategories) {
function reset() { console.log("Cannot add no more than " + max_subcategories + " subcategories")
let subcategories = Backend.getSubCategoryList(Backend.getCategoryIdByName(productCategoryBox.currentText), true) return
addSubCategoryButton.visible = (subcategories.length > 0)
subCategoryRepeater.model = 0 // reset
}
onActivated: {
productCategoryBox.reset()
}
radius: productDialog.inputRadius
color: productDialog.inputBaseColor
textColor: productDialog.inputTextColor
}
Button {
id: addSubCategoryButton
width: 50; height: 50
text: qsTr("+")
visible: Backend.hasSubCategory(Backend.getCategoryIdByName(productCategoryBox.currentText))
background: Rectangle {
color: parent.hovered ? "#698b22" : "#506a1a"//"#605185"
radius: productDialog.inputRadius
}
contentItem: Text {
text: parent.text
color: "#ffffff"
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
onClicked: {
let subcategories = Backend.getSubCategoryList(Backend.getCategoryIdByName(productCategoryBox.currentText), true)
let max_subcategories = Math.min(2, subcategories.length)
if(subCategoryRepeater.count == max_subcategories) {
console.log("Cannot add no more than " + max_subcategories + " subcategories")
return
}
subCategoryRepeater.model = subCategoryRepeater.model + 1
}
} }
subCategoryRepeater.model = subCategoryRepeater.model + 1
} }
} }
} }
// Subcategories (will be determined based on selected categories) }
Item { }
id: subCategoryItem // Subcategories (will be determined based on selected categories)
Layout.alignment: Qt.AlignHCenter Item {
Layout.preferredWidth: childrenRect.width id: subCategoryItem
Layout.preferredHeight: childrenRect.height Layout.alignment: Qt.AlignHCenter
visible: (subCategoryRepeater.count > 0)//Backend.hasSubCategory(Backend.getCategoryIdByName(productCategoryBox.currentText)) Layout.preferredWidth: childrenRect.width
Layout.preferredHeight: childrenRect.height
function getSubCategoryStringList() { visible: (subCategoryRepeater.count > 0)//Backend.hasSubCategory(Backend.getCategoryIdByName(productCategoryBox.currentText))
let subCategoryStringList = []
let subcategories = Backend.getSubCategoryList(Backend.getCategoryIdByName(productCategoryBox.currentText), true)
for(let i = 0; i < subcategories.length; i++) {
subCategoryStringList[i] = subcategories[i].name//console.log(parent.parent.parent.categoryStringList[i])//console.log(categories[i].name)
}
return subCategoryStringList;
}
Column { function getSubCategoryStringList() {
spacing: productDialog.titleSpacing let subCategoryStringList = []
Text { let subcategories = Backend.getSubCategoryList(Backend.getCategoryIdByName(productCategoryBox.currentText), true)
text: "Subcategory" for(let i = 0; i < subcategories.length; i++) {
color: productDialog.palette.text subCategoryStringList[i] = subcategories[i].name//console.log(parent.parent.parent.categoryStringList[i])//console.log(categories[i].name)
font.bold: true }
} return subCategoryStringList;
}
Repeater { Column {
id: subCategoryRepeater spacing: productDialog.titleSpacing
model: 0 Text {
delegate: Row { text: "Subcategory"
spacing: 5 color: productDialog.palette.text
NeroshopComponents.ComboBox { font.bold: true
id: productSubCategoryBox
width: removeSubCategoryButton.visible ? (500 - removeSubCategoryButton.width - parent.spacing) : 500; height: 50
model: parent.parent.parent.getSubCategoryStringList()
currentIndex: 0
radius: productDialog.inputRadius
color: productDialog.inputBaseColor
textColor: productDialog.inputTextColor
}
Button {
id: removeSubCategoryButton
width: 50; height: 50
text: qsTr("x")
background: Rectangle {
color: parent.hovered ? "#b22222" : "#921c1c"
radius: productDialog.inputRadius
}
contentItem: Text {
text: parent.text
color: "#ffffff"
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
onClicked: {
subCategoryRepeater.model = subCategoryRepeater.model - 1
}
}
} // Row
}
}
} }
// Weight
Item {
//Layout.row:
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: childrenRect.width
Layout.preferredHeight: childrenRect.height
Column { Repeater {
spacing: productDialog.titleSpacing id: subCategoryRepeater
Row { model: 0
spacing: 10 delegate: Row {
Text { spacing: 5
text: "Weight" NeroshopComponents.ComboBox {
color: productDialog.palette.text id: productSubCategoryBox
font.bold: true width: removeSubCategoryButton.visible ? (500 - removeSubCategoryButton.width - parent.spacing) : 500; height: 50
} model: parent.parent.parent.getSubCategoryStringList()
Text { currentIndex: 0
text: "(OPTIONAL)" radius: productDialog.inputRadius
color: productDialog.optTextColor color: productDialog.inputBaseColor
font.bold: true textColor: productDialog.inputTextColor
font.pointSize: 8
anchors.verticalCenter: parent.children[0].verticalCenter
}
} }
Button {
Row { id: removeSubCategoryButton
spacing: 5 width: 50; height: 50
TextField { text: qsTr("x")
id: productWeightField
width: 500 - parent.children[1].width - parent.spacing; height: 50
placeholderText: qsTr("Enter weight")
color: productDialog.inputTextColor
selectByMouse: true
validator: RegExpValidator{ regExp: new RegExp("^-?[0-9]+(\\.[0-9]{1," + 8 + "})?$") }
background: Rectangle { background: Rectangle {
color: "transparent" color: parent.hovered ? "#b22222" : "#921c1c"
border.color: productDialog.inputBorderColor
border.width: parent.activeFocus ? 2 : 1
radius: productDialog.inputRadius
}
}
NeroshopComponents.ComboBox {
id: weightMeasurementUnit
height: parent.children[0].height
model: ["kg", "lb"] // default is kg (every unit of measurement will be converted to kg)
Component.onCompleted: currentIndex = find("kg")
radius: productDialog.inputRadius radius: productDialog.inputRadius
color: productDialog.inputBaseColor
textColor: productDialog.inputTextColor
} }
} contentItem: Text {
} text: parent.text
} color: "#ffffff"
// Size verticalAlignment: Text.AlignVCenter
/*Item { horizontalAlignment: Text.AlignHCenter
//Layout.row:
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: childrenRect.width
Layout.preferredHeight: childrenRect.height
Column {
spacing: productDialog.titleSpacing
Row {
spacing: 10
Text {
text: "Size"
color: productDialog.palette.text
font.bold: true
} }
Text { onClicked: {
text: "(OPTIONAL)" subCategoryRepeater.model = subCategoryRepeater.model - 1
color: productDialog.optTextColor
font.bold: true
font.pointSize: 8
anchors.verticalCenter: parent.children[0].verticalCenter
} }
} }
} // Row
}
}
}
// Weight
Item {
//Layout.row:
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: childrenRect.width
Layout.preferredHeight: childrenRect.height
Row { Column {
spacing: 5 spacing: productDialog.titleSpacing
TextField { Row {
id: productSizeField spacing: 10
width: 500; height: 50 Text {
placeholderText: qsTr("Enter size") text: "Weight"
color: productDialog.inputTextColor color: productDialog.palette.text
selectByMouse: true font.bold: true
background: Rectangle {
color: "transparent"
border.color: productDialog.inputBorderColor
border.width: parent.activeFocus ? 2 : 1
radius: productDialog.inputRadius
}
}
//ComboBox
}
} }
}*/ Text {
// Variations/Attributes (i.e. Color, Size, Type, Model, etc. options to choose from - optional) text: "(OPTIONAL)"
// Product location (ship to and ship from) color: productDialog.optTextColor
Item { font.bold: true
Layout.alignment: Qt.AlignHCenter font.pointSize: 8
Layout.preferredWidth: childrenRect.width anchors.verticalCenter: parent.children[0].verticalCenter
Layout.preferredHeight: childrenRect.height }
property var countriesModel: ["Afghanistan", "Albania", "Algeria", "Andorra", "Angola", "Antigua & Deps", "Argentina", "Armenia", "Australia", "Austria", "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia", "Bosnia Herzegovina", "Botswana", "Brazil", "Brunei", "Bulgaria", "Burkina", "Burundi", "Cambodia", "Cameroon", "Canada", "Cape Verde", "Central African Rep", "Chad", "Chile", "China", "Colombia", "Comoros", "Congo", "Congo (Democratic Rep)", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic", "Denmark", "Djibouti", "Dominica", "Dominican Republic", "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Eswatini", "Ethiopia", "Fiji", "Finland", "France", "Gabon", "Gambia", "Georgia", "Germany", "Ghana", "Greece", "Grenada", "Guatemala", "Guinea", "Guinea-Bissau", "Guyana", "Haiti", "Honduras", "Hungary", "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland (Republic)", "Israel", "Italy", "Ivory Coast", "Jamaica", "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Korea North", "Korea South", "Kosovo", "Kuwait", "Kyrgyzstan", "Laos", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg", "Macedonia", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Mauritania", "Mauritius", "Mexico", "Micronesia", "Moldova", "Monaco", "Mongolia", "Montenegro", "Morocco", "Mozambique", "Myanmar", "Namibia", "Nauru", "Nepal", "Netherlands", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Norway", "Oman", "Pakistan", "Palau", "Palestine", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Poland", "Portugal", "Qatar", "Romania", "Russian Federation", "Rwanda", "St Kitts & Nevis", "St Lucia", "Saint Vincent & the Grenadines", "Samoa", "San Marino", "Sao Tome & Principe", "Saudi Arabia", "Senegal", "Serbia", "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands", "Somalia", "South Africa", "South Sudan", "Spain", "Sri Lanka", "Sudan", "Suriname", "Sweden", "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "Togo", "Tonga", "Trinidad & Tobago", "Tunisia", "Turkey", "Turkmenistan", "Tuvalu", "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States", "Unspecified", "Uruguay", "Uzbekistan", "Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Yemen", "Zambia", "Zimbabwe", "Worldwide",] }
Column {
spacing: productDialog.titleSpacing
Text {
text: "Location"
color: productDialog.palette.text
font.bold: true
}
NeroshopComponents.ComboBox { Row {
id: productLocationBox spacing: 5
width: 500; height: 50 TextField {
model: parent.parent.countriesModel id: productWeightField
Component.onCompleted: { width: 500 - parent.children[1].width - parent.spacing; height: 50
contentItem.selectByMouse = true placeholderText: qsTr("Enter weight")
currentIndex = find("Unspecified")//find("Worldwide") color: productDialog.inputTextColor
} selectByMouse: true
editable: true validator: RegExpValidator{ regExp: new RegExp("^-?[0-9]+(\\.[0-9]{1," + 8 + "})?$") }
onAccepted: { background: Rectangle {
if(find(editText) === -1) color: "transparent"
model.append({text: editText}) border.color: productDialog.inputBorderColor
} border.width: parent.activeFocus ? 2 : 1
radius: productDialog.inputRadius radius: productDialog.inputRadius
color: productDialog.inputBaseColor
textColor: productDialog.inputTextColor
} }
} }
NeroshopComponents.ComboBox {
id: weightMeasurementUnit
height: parent.children[0].height
model: ["kg", "lb"] // default is kg (every unit of measurement will be converted to kg)
Component.onCompleted: currentIndex = find("kg")
radius: productDialog.inputRadius
color: productDialog.inputBaseColor
textColor: productDialog.inputTextColor
}
}
}
}
// Size
/*Item {
//Layout.row:
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: childrenRect.width
Layout.preferredHeight: childrenRect.height
Column {
spacing: productDialog.titleSpacing
Row {
spacing: 10
Text {
text: "Size"
color: productDialog.palette.text
font.bold: true
}
Text {
text: "(OPTIONAL)"
color: productDialog.optTextColor
font.bold: true
font.pointSize: 8
anchors.verticalCenter: parent.children[0].verticalCenter
}
}
Row {
spacing: 5
TextField {
id: productSizeField
width: 500; height: 50
placeholderText: qsTr("Enter size")
color: productDialog.inputTextColor
selectByMouse: true
background: Rectangle {
color: "transparent"
border.color: productDialog.inputBorderColor
border.width: parent.activeFocus ? 2 : 1
radius: productDialog.inputRadius
}
}
//ComboBox
}
}
}*/
// Variations/Attributes (i.e. Color, Size, Type, Model, etc. options to choose from - optional)
// Product location (ship to and ship from)
Item {
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: childrenRect.width
Layout.preferredHeight: childrenRect.height
property var countriesModel: ["Afghanistan", "Albania", "Algeria", "Andorra", "Angola", "Antigua & Deps", "Argentina", "Armenia", "Australia", "Austria", "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia", "Bosnia Herzegovina", "Botswana", "Brazil", "Brunei", "Bulgaria", "Burkina", "Burundi", "Cambodia", "Cameroon", "Canada", "Cape Verde", "Central African Rep", "Chad", "Chile", "China", "Colombia", "Comoros", "Congo", "Congo (Democratic Rep)", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic", "Denmark", "Djibouti", "Dominica", "Dominican Republic", "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Eswatini", "Ethiopia", "Fiji", "Finland", "France", "Gabon", "Gambia", "Georgia", "Germany", "Ghana", "Greece", "Grenada", "Guatemala", "Guinea", "Guinea-Bissau", "Guyana", "Haiti", "Honduras", "Hungary", "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland (Republic)", "Israel", "Italy", "Ivory Coast", "Jamaica", "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Korea North", "Korea South", "Kosovo", "Kuwait", "Kyrgyzstan", "Laos", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg", "Macedonia", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Mauritania", "Mauritius", "Mexico", "Micronesia", "Moldova", "Monaco", "Mongolia", "Montenegro", "Morocco", "Mozambique", "Myanmar", "Namibia", "Nauru", "Nepal", "Netherlands", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Norway", "Oman", "Pakistan", "Palau", "Palestine", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Poland", "Portugal", "Qatar", "Romania", "Russian Federation", "Rwanda", "St Kitts & Nevis", "St Lucia", "Saint Vincent & the Grenadines", "Samoa", "San Marino", "Sao Tome & Principe", "Saudi Arabia", "Senegal", "Serbia", "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands", "Somalia", "South Africa", "South Sudan", "Spain", "Sri Lanka", "Sudan", "Suriname", "Sweden", "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "Togo", "Tonga", "Trinidad & Tobago", "Tunisia", "Turkey", "Turkmenistan", "Tuvalu", "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States", "Unspecified", "Uruguay", "Uzbekistan", "Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Yemen", "Zambia", "Zimbabwe", "Worldwide",]
Column {
spacing: productDialog.titleSpacing
Text {
text: "Location"
color: productDialog.palette.text
font.bold: true
}
NeroshopComponents.ComboBox {
id: productLocationBox
width: 500; height: 50
model: parent.parent.countriesModel
Component.onCompleted: {
contentItem.selectByMouse = true
currentIndex = find("Unspecified")//find("Worldwide")
}
editable: true
onAccepted: {
if(find(editText) === -1)
model.append({text: editText})
}
radius: productDialog.inputRadius
color: productDialog.inputBaseColor
textColor: productDialog.inputTextColor
} }
}
}
//Product description and bullet points //Product description and bullet points
Item { Item {
//Layout.row: //Layout.row:
@ -625,7 +705,7 @@ Popup {
contentWidth: (210 * productImageRepeater.count) + (5 * (productImageRepeater.count - 1))//<- 5 is the Flow.spacing//; contentHeight: 210//<- contentHeight is not needed unless a newline is supported contentWidth: (210 * productImageRepeater.count) + (5 * (productImageRepeater.count - 1))//<- 5 is the Flow.spacing//; contentHeight: 210//<- contentHeight is not needed unless a newline is supported
clip: true clip: true
ScrollBar.horizontal: ScrollBar { ScrollBar.horizontal: ScrollBar {
policy: ScrollBar.AsNeeded policy: ScrollBar.AlwaysOn//AsNeeded
} }
Flow { Flow {
width: parent.contentWidth; height: parent.height//anchors.fill: parent// Note: Flow width must be large enough to fit all items horizontally so that there won't be a need to move an item to a newline width: parent.contentWidth; height: parent.height//anchors.fill: parent// Note: Flow width must be large enough to fit all items horizontally so that there won't be a need to move an item to a newline
@ -662,6 +742,44 @@ Popup {
//if(this.status == Image.Null) console.log("No image has been set" + parent.parent.index) //if(this.status == Image.Null) console.log("No image has been set" + parent.parent.index)
} }
} }
// Position the close button
Button {
id: removeImageButton
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: 8
width: 20; height: 20//32
text: qsTr(FontAwesome.xmark)
hoverEnabled: true
visible: (parent.children[0].status === Image.Ready)
contentItem: Text {
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: removeImageButton.text
color: removeImageButton.hovered ? "#ffffff" : "#000000"
font.bold: true
font.family: FontAwesome.fontFamily
}
background: Rectangle {
width: parent.width
height: parent.height
radius: 5//50
color: removeImageButton.hovered ? "firebrick" : "transparent"
opacity: 0.7
}
onClicked: {
parent.children[0].source = ""
}
MouseArea {
anchors.fill: parent
onPressed: mouse.accepted = false
cursorShape: Qt.PointingHandCursor
}
}
} }
Button { Button {
@ -735,7 +853,7 @@ Popup {
id: listProductButton id: listProductButton
width: 333.333333333; height: contentItem.contentHeight + 30 width: 333.333333333; height: contentItem.contentHeight + 30
hoverEnabled: true hoverEnabled: true
text: qsTr("Add") text: qsTr("Submit")
background: Rectangle { background: Rectangle {
color: parent.hovered ? "#698b22" : "#506a1a" color: parent.hovered ? "#698b22" : "#506a1a"
radius: productDialog.inputRadius radius: productDialog.inputRadius
@ -750,6 +868,12 @@ Popup {
// Check input fields to see if entered info is valid // Check input fields to see if entered info is valid
// ... // ...
//--------------------------------------- //---------------------------------------
if(productNameField.text.length < 3) {
messageBox.text = qsTr("Product name is too short")
messageBox.open()
return; // exit function
}
//---------------------------------------
let subcategory_ids = []//let subcategories = [] let subcategory_ids = []//let subcategories = []
for (let i = 0; i < subCategoryRepeater.count; i++) { for (let i = 0; i < subCategoryRepeater.count; i++) {
subcategory_ids.push(Backend.getSubCategoryIdByName(subCategoryRepeater.itemAt(i).children[0].currentText))//subcategories.push(subCategoryRepeater.itemAt(i).children[0].currentText)//console.log("Added subcategory: ", subcategories[i]) subcategory_ids.push(Backend.getSubCategoryIdByName(subCategoryRepeater.itemAt(i).children[0].currentText))//subcategories.push(subCategoryRepeater.itemAt(i).children[0].currentText)//console.log("Added subcategory: ", subcategories[i])
@ -767,7 +891,12 @@ Popup {
let attributes = []; let attributes = [];
let attribute_object = {}; let attribute_object = {};
if(productWeightField.text.length > 0 && Number(productWeightField.text) > 0.00) { if(productWeightField.text.length > 0 && Number(productWeightField.text) > 0.00) {
attribute_object.weight = productWeightField.text if(weightMeasurementUnit.currentText !== "kg") {
console.log("weight is in " + weightMeasurementUnit.currentText + ". Converting to kg ...")
attribute_object.weight = Backend.weightToKg(Number(productWeightField.text), weightMeasurementUnit.currentText)
} else {
attribute_object.weight = Number(productWeightField.text)
}
} }
// Add attribute obj to list as long as its filled with properties // Add attribute obj to list as long as its filled with properties
if (Object.keys(attribute_object).length > 0) { if (Object.keys(attribute_object).length > 0) {
@ -799,7 +928,7 @@ Popup {
productNameField.text, productNameField.text,
productDescriptionEdit.text, productDescriptionEdit.text,
attributes, attributes,
productCodeField.text, productCodeType.currentText.toLowerCase() + ":" + productCodeField.text,
Backend.getCategoryIdByName(productCategoryBox.currentText), Backend.getCategoryIdByName(productCategoryBox.currentText),
(subCategoryRepeater.count > 0) ? subcategory_ids : [], // subcategoryIds (subCategoryRepeater.count > 0) ? subcategory_ids : [], // subcategoryIds
productTagsField.tags(), productTagsField.tags(),

@ -75,47 +75,91 @@ Page {
} }
//GroupBox { //GroupBox {
// title: qsTr("Sort") // title: qsTr("Sort")
// SortComboBox Row {
NeroshopComponents.ComboBox {
id: sortByBox
anchors.right: parent.right anchors.right: parent.right
anchors.verticalCenter: viewToggle.verticalCenter anchors.verticalCenter: viewToggle.verticalCenter
width: 250 spacing: 3
model: ["None", "Latest", "Oldest", "Alphabetical order", "Price - Lowest", "Price - Highest"] // Filter button
Component.onCompleted: currentIndex = find("None") Button {
displayText: "Sort: " + currentText id: filterButton
indicatorDoNotPassBorder: true text: qsTr("Filter")
onActivated: { //anchors.verticalCenter: parent.verticalCenter
if(currentIndex == find("None")) { //height: sortBox.height
catalogPage.model = Backend.sortBy(catalogPage.model, Enum.Sorting.SortByOldest)//Enum.Sorting.SortNone) checkable: true
settingsDialog.lastUsedListingSorting = Enum.Sorting.SortNone checked: filterPopUp.visible
display: AbstractButton.IconOnly
icon.source: "qrc:/assets/images/filter.png"
icon.color: !this.checked ? "#605185" : "#ffffff"
background: Rectangle {
radius: 3
color: parent.checked ? "#605185" : "#e0e0e0"
} }
if(currentIndex == find("Oldest")) { onClicked: {
catalogPage.model = Backend.sortBy(catalogPage.model, Enum.Sorting.SortByOldest) filterPopUp.visible = true
settingsDialog.lastUsedListingSorting = Enum.Sorting.SortByOldest
} }
if(currentIndex == find("Latest")) {
console.log("Showing most recent items") Popup {
catalogPage.model = Backend.sortBy(catalogPage.model, Enum.Sorting.SortByMostRecent) id: filterPopUp
settingsDialog.lastUsedListingSorting = Enum.Sorting.SortByMostRecent visible: false
} x: (parent.width - width) / 2
if(currentIndex == find("Alphabetical order")) { y: parent.height + 1
catalogPage.model = Backend.sortBy(catalogPage.model, Enum.Sorting.SortByAlphabeticalOrder) width: 200
settingsDialog.lastUsedListingSorting = Enum.Sorting.SortByAlphabeticalOrder height: 300//implicitHeight: contentItem.implicitHeight
}
if(currentIndex == find("Price - Lowest")) { background: Rectangle {
catalogPage.model = Backend.sortBy(catalogPage.model, Enum.Sorting.SortByPriceLowest) radius: 5
settingsDialog.lastUsedListingSorting = Enum.Sorting.SortByPriceLowest color: "#e0e0e0"
}
contentItem: /*NeroshopComponents.FilterBox {*/Item {
Text {
text: qsTr("Coming soon!")
anchors.centerIn: parent
}
}
} }
if(currentIndex == find("Price - Highest")) { }
catalogPage.model = Backend.sortBy(catalogPage.model, Enum.Sorting.SortByPriceHighest) // SortComboBox
settingsDialog.lastUsedListingSorting = Enum.Sorting.SortByPriceHighest NeroshopComponents.ComboBox {
id: sortBox
//anchors.verticalCenter: parent.verticalCenter
width: 250; height: viewToggle.height
model: ["None", "Latest", "Oldest", "Alphabetical order", "Price - Lowest", "Price - Highest"]
Component.onCompleted: currentIndex = find("None")
displayText: "Sort: " + currentText
indicatorDoNotPassBorder: true
onActivated: {
if(currentIndex == find("None")) {
catalogPage.model = Backend.sortBy(catalogPage.model, Enum.Sorting.SortByOldest)//Enum.Sorting.SortNone)
settingsDialog.lastUsedListingSorting = Enum.Sorting.SortNone
}
if(currentIndex == find("Oldest")) {
catalogPage.model = Backend.sortBy(catalogPage.model, Enum.Sorting.SortByOldest)
settingsDialog.lastUsedListingSorting = Enum.Sorting.SortByOldest
}
if(currentIndex == find("Latest")) {
console.log("Showing most recent items")
catalogPage.model = Backend.sortBy(catalogPage.model, Enum.Sorting.SortByMostRecent)
settingsDialog.lastUsedListingSorting = Enum.Sorting.SortByMostRecent
}
if(currentIndex == find("Alphabetical order")) {
catalogPage.model = Backend.sortBy(catalogPage.model, Enum.Sorting.SortByAlphabeticalOrder)
settingsDialog.lastUsedListingSorting = Enum.Sorting.SortByAlphabeticalOrder
}
if(currentIndex == find("Price - Lowest")) {
catalogPage.model = Backend.sortBy(catalogPage.model, Enum.Sorting.SortByPriceLowest)
settingsDialog.lastUsedListingSorting = Enum.Sorting.SortByPriceLowest
}
if(currentIndex == find("Price - Highest")) {
catalogPage.model = Backend.sortBy(catalogPage.model, Enum.Sorting.SortByPriceHighest)
settingsDialog.lastUsedListingSorting = Enum.Sorting.SortByPriceHighest
}
/*if(currentIndex == find("")) {
catalogPage.model = Backend.
}*/
} }
/*if(currentIndex == find("")) {
catalogPage.model = Backend.
}*/
} }
} } // Row
} // Rectangle } // Rectangle
StackLayout { StackLayout {
id: catalogStack id: catalogStack

@ -257,7 +257,7 @@ Page {
Button { Button {
id: addProductButton id: addProductButton
////anchors.right: parent.right // <- uncomment if not enclosed in row ////anchors.right: parent.right // <- uncomment if not enclosed in row
text: qsTr("+ Add Product") text: qsTr("+ Add Item")
width: 304/*inventoryManager.width*/; height: 100//width: 200; height: 100//width: 100; height: width width: 304/*inventoryManager.width*/; height: 100//width: 200; height: 100//width: 100; height: width
hoverEnabled: true hoverEnabled: true
background: Rectangle { background: Rectangle {
@ -409,7 +409,7 @@ Page {
id: removeProductsMessageBox id: removeProductsMessageBox
x: mainWindow.x + (mainWindow.width - this.width) / 2 x: mainWindow.x + (mainWindow.width - this.width) / 2
y: mainWindow.y + (mainWindow.height - this.height) / 2 y: mainWindow.y + (mainWindow.height - this.height) / 2
title: qsTr("Remove product") title: qsTr("Remove items")
text: qsTr("Are you sure you want to permanently remove the selected item(s)?") text: qsTr("Are you sure you want to permanently remove the selected item(s)?")
buttonModel: ["No", "Yes"] buttonModel: ["No", "Yes"]
buttonRow.state: "centered"; buttonRow.width: 300 // buttons should fill the row width buttonRow.state: "centered"; buttonRow.width: 300 // buttons should fill the row width

@ -17,7 +17,7 @@
std::string neroshop::Converter::json_string (""); std::string neroshop::Converter::json_string ("");
//------------------------------------------------------- //-------------------------------------------------------
//------------------------------------------------------- //-------------------------------------------------------
double neroshop::Converter::to_kg(double amount, const std::string& unit_name) const { double neroshop::Converter::to_kg(double amount, const std::string& unit_name) {
if(neroshop::string::lower(unit_name) == "lb" || neroshop::string::lower(unit_name) == "lbs" || neroshop::string::lower(unit_name) == "pound") {return lb_to_kg(amount);} if(neroshop::string::lower(unit_name) == "lb" || neroshop::string::lower(unit_name) == "lbs" || neroshop::string::lower(unit_name) == "pound") {return lb_to_kg(amount);}
return 0.0; return 0.0;
} }

@ -24,7 +24,7 @@ namespace neroshop {
class Converter { class Converter {
public: public:
// weight (mass) // weight (mass)
double to_kg(double amount, const std::string& unit_name) const; static double to_kg(double amount, const std::string& unit_name);
static double lb_to_kg(double lb); //static double pound_to_kilogram(double pound); // The correct way of abbreviation in expressing singular or plural pounds is “lb.” though “lbs.”, which stands for libra, is the common abbreviation used in expressing pounds static double lb_to_kg(double lb); //static double pound_to_kilogram(double pound); // The correct way of abbreviation in expressing singular or plural pounds is “lb.” though “lbs.”, which stands for libra, is the common abbreviation used in expressing pounds
static std::unique_ptr<PriceApi> make_price_source(PriceSource source); static std::unique_ptr<PriceApi> make_price_source(PriceSource source);

@ -999,7 +999,7 @@ bool neroshop::Node::validate(const std::string& key, const std::string& value)
assert(json["expiration_date"].is_string()); assert(json["expiration_date"].is_string());
std::string expiration_date = json["expiration_date"].get<std::string>(); std::string expiration_date = json["expiration_date"].get<std::string>();
if(neroshop_timestamp::is_expired(expiration_date)) { if(neroshop_timestamp::is_expired(expiration_date)) {
std::cerr << "Data has expired (exp date: " << expiration_date << " UTC)\n"; std::cerr << "Data has expired (exp date: " << expiration_date << ")\n";
// Notify the other nodes that this data has expired (so that once they receive a put with the expired data, it will be removed from their local hash table as soon as it goes through the validate function) // Notify the other nodes that this data has expired (so that once they receive a put with the expired data, it will be removed from their local hash table as soon as it goes through the validate function)
////send_put(key, value); // this should propagate the expiration information to other nodes in the DHT until the expired data is removed once and for all. Hmmm this could cause an endless loop ... ////send_put(key, value); // this should propagate the expiration information to other nodes in the DHT until the expired data is removed once and for all. Hmmm this could cause an endless loop ...
// This won't work unless all data contain a mandatory expiration date set on creation. A consensus mechanism may be necessary // This won't work unless all data contain a mandatory expiration date set on creation. A consensus mechanism may be necessary

@ -86,6 +86,15 @@ QImage neroshop::Backend::base64ToImage(const QString& base64Data) {
} }
//---------------------------------------------------------------- //----------------------------------------------------------------
//---------------------------------------------------------------- //----------------------------------------------------------------
double neroshop::Backend::weightToKg(double amount, const QString& unit_name) const {
return neroshop::Converter::to_kg(amount, unit_name.toStdString());
}
double neroshop::Backend::lgToKg(double amount) const {
return neroshop::Converter::lb_to_kg(amount);
}
//----------------------------------------------------------------
//----------------------------------------------------------------
QStringList neroshop::Backend::getCurrencyList() const QStringList neroshop::Backend::getCurrencyList() const
{ {
QStringList currency_list; QStringList currency_list;

@ -29,6 +29,9 @@ public:
QString imageToBase64(const QImage& image); // un-tested QString imageToBase64(const QImage& image); // un-tested
QImage base64ToImage(const QString& base64Data); // un-tested QImage base64ToImage(const QString& base64Data); // un-tested
Q_INVOKABLE double weightToKg(double amount, const QString& unit_name) const;
Q_INVOKABLE double lgToKg(double amount) const;
Q_INVOKABLE QStringList getCurrencyList() const; Q_INVOKABLE QStringList getCurrencyList() const;
Q_INVOKABLE int getCurrencyDecimals(const QString& currency) const; Q_INVOKABLE int getCurrencyDecimals(const QString& currency) const;
Q_INVOKABLE QString getCurrencySign(const QString& currency) const; Q_INVOKABLE QString getCurrencySign(const QString& currency) const;

Loading…
Cancel
Save