UI/UX improvements

pull/209/head
larteyoh 7 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_slash.png</file>
<file>assets/images/file.png</file>
<file>assets/images/filter.png</file>
<file>assets/images/grid.png</file>
<file>assets/images/heart.png</file>
<file>assets/images/image.png</file>

@ -3,6 +3,8 @@ import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import Qt.labs.platform 1.1 // FileDialog
import FontAwesome 1.0
import "." as NeroshopComponents
Popup {
@ -22,14 +24,69 @@ Popup {
background: Rectangle {
radius: 8
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 {
id: mainScrollView
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
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ScrollBar.vertical.policy: ScrollBar.AlwaysOn//AsNeeded
ColumnLayout {
width: productDialog.availableWidth; height: productDialog.availableHeight
spacing: 30
@ -41,7 +98,7 @@ Popup {
Column {
spacing: productDialog.titleSpacing
Text {
text: "Product name"
text: "Name / Title"
color: productDialog.palette.text
font.bold: true
}
@ -124,11 +181,34 @@ Popup {
Column {
spacing: productDialog.titleSpacing
Text {
text: "Quantity"
color: productDialog.palette.text
font.bold: true
//visible: false
Row {
spacing: 10
Text {
text: qsTr("Quantity")
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 {
@ -250,298 +330,298 @@ Popup {
}
}
Row {
spacing: 5
TextField {
id: productCodeField
width: 500 - parent.children[1].width - parent.spacing; height: 50
placeholderText: qsTr("Enter product code")
color: productDialog.inputTextColor
selectByMouse: true
background: Rectangle {
color: "transparent"
border.color: productDialog.inputBorderColor
border.width: parent.activeFocus ? 2 : 1
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
}
}
Row {
spacing: 5
TextField {
id: productCodeField
width: 500 - parent.children[1].width - parent.spacing; height: 50
placeholderText: qsTr("Enter product code")
color: productDialog.inputTextColor
selectByMouse: true
background: Rectangle {
color: "transparent"
border.color: productDialog.inputBorderColor
border.width: parent.activeFocus ? 2 : 1
radius: productDialog.inputRadius
}
}
}
// Product categories
Item {
//Layout.row:
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: childrenRect.width
Layout.preferredHeight: childrenRect.height
function getCategoryStringList() {
let categoryStringList = []
let categories = Backend.getCategoryList(true)
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)
}
return categoryStringList;
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
Item {
//Layout.row:
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: childrenRect.width
Layout.preferredHeight: childrenRect.height
function getCategoryStringList() {
let categoryStringList = []
let categories = Backend.getCategoryList(true)
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)
}
return categoryStringList;
}
Column {
spacing: productDialog.titleSpacing
Text {
text: "Category"
color: productDialog.palette.text
font.bold: true
}
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()
}
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
}
}
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")
}
}
}
// Subcategories (will be determined based on selected categories)
Item {
id: subCategoryItem
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: childrenRect.width
Layout.preferredHeight: childrenRect.height
visible: (subCategoryRepeater.count > 0)//Backend.hasSubCategory(Backend.getCategoryIdByName(productCategoryBox.currentText))
function getSubCategoryStringList() {
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 {
spacing: productDialog.titleSpacing
Text {
text: "Subcategory"
color: productDialog.palette.text
font.bold: true
function reset() {
let subcategories = Backend.getSubCategoryList(Backend.getCategoryIdByName(productCategoryBox.currentText), true)
addSubCategoryButton.visible = (subcategories.length > 0)
subCategoryRepeater.model = 0 // reset
}
Repeater {
id: subCategoryRepeater
model: 0
delegate: Row {
spacing: 5
NeroshopComponents.ComboBox {
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
onActivated: {
productCategoryBox.reset()
}
radius: productDialog.inputRadius
color: productDialog.inputBaseColor
textColor: productDialog.inputTextColor
}
}
// Weight
Item {
//Layout.row:
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: childrenRect.width
Layout.preferredHeight: childrenRect.height
Column {
spacing: productDialog.titleSpacing
Row {
spacing: 10
Text {
text: "Weight"
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
}
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
}
Row {
spacing: 5
TextField {
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 {
color: "transparent"
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
color: productDialog.inputBaseColor
textColor: productDialog.inputTextColor
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
}
}
}
// Size
/*Item {
//Layout.row:
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: childrenRect.width
Layout.preferredHeight: childrenRect.height
}
}
}
// Subcategories (will be determined based on selected categories)
Item {
id: subCategoryItem
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: childrenRect.width
Layout.preferredHeight: childrenRect.height
visible: (subCategoryRepeater.count > 0)//Backend.hasSubCategory(Backend.getCategoryIdByName(productCategoryBox.currentText))
Column {
spacing: productDialog.titleSpacing
Row {
spacing: 10
Text {
text: "Size"
color: productDialog.palette.text
font.bold: true
function getSubCategoryStringList() {
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 {
spacing: productDialog.titleSpacing
Text {
text: "Subcategory"
color: productDialog.palette.text
font.bold: true
}
Repeater {
id: subCategoryRepeater
model: 0
delegate: Row {
spacing: 5
NeroshopComponents.ComboBox {
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
}
Text {
text: "(OPTIONAL)"
color: productDialog.optTextColor
font.bold: true
font.pointSize: 8
anchors.verticalCenter: parent.children[0].verticalCenter
contentItem: Text {
text: parent.text
color: "#ffffff"
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
}
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
}
onClicked: {
subCategoryRepeater.model = subCategoryRepeater.model - 1
}
//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",]
} // Row
}
}
}
// Weight
Item {
//Layout.row:
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: childrenRect.width
Layout.preferredHeight: childrenRect.height
Column {
spacing: productDialog.titleSpacing
Text {
text: "Location"
color: productDialog.palette.text
font.bold: true
}
Column {
spacing: productDialog.titleSpacing
Row {
spacing: 10
Text {
text: "Weight"
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
}
}
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})
}
Row {
spacing: 5
TextField {
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 {
color: "transparent"
border.color: productDialog.inputBorderColor
border.width: parent.activeFocus ? 2 : 1
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
Item {
//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
clip: true
ScrollBar.horizontal: ScrollBar {
policy: ScrollBar.AsNeeded
policy: ScrollBar.AlwaysOn//AsNeeded
}
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
@ -662,6 +742,44 @@ Popup {
//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 {
@ -735,7 +853,7 @@ Popup {
id: listProductButton
width: 333.333333333; height: contentItem.contentHeight + 30
hoverEnabled: true
text: qsTr("Add")
text: qsTr("Submit")
background: Rectangle {
color: parent.hovered ? "#698b22" : "#506a1a"
radius: productDialog.inputRadius
@ -750,6 +868,12 @@ Popup {
// 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 = []
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])
@ -767,7 +891,12 @@ Popup {
let attributes = [];
let attribute_object = {};
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
if (Object.keys(attribute_object).length > 0) {
@ -799,7 +928,7 @@ Popup {
productNameField.text,
productDescriptionEdit.text,
attributes,
productCodeField.text,
productCodeType.currentText.toLowerCase() + ":" + productCodeField.text,
Backend.getCategoryIdByName(productCategoryBox.currentText),
(subCategoryRepeater.count > 0) ? subcategory_ids : [], // subcategoryIds
productTagsField.tags(),

@ -75,47 +75,91 @@ Page {
}
//GroupBox {
// title: qsTr("Sort")
// SortComboBox
NeroshopComponents.ComboBox {
id: sortByBox
Row {
anchors.right: parent.right
anchors.verticalCenter: viewToggle.verticalCenter
width: 250
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
spacing: 3
// Filter button
Button {
id: filterButton
text: qsTr("Filter")
//anchors.verticalCenter: parent.verticalCenter
//height: sortBox.height
checkable: true
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")) {
catalogPage.model = Backend.sortBy(catalogPage.model, Enum.Sorting.SortByOldest)
settingsDialog.lastUsedListingSorting = Enum.Sorting.SortByOldest
onClicked: {
filterPopUp.visible = true
}
if(currentIndex == find("Latest")) {
console.log("Showing most recent items")
catalogPage.model = Backend.sortBy(catalogPage.model, Enum.Sorting.SortByMostRecent)
settingsDialog.lastUsedListingSorting = Enum.Sorting.SortByMostRecent
Popup {
id: filterPopUp
visible: false
x: (parent.width - width) / 2
y: parent.height + 1
width: 200
height: 300//implicitHeight: contentItem.implicitHeight
background: Rectangle {
radius: 5
color: "#e0e0e0"
}
contentItem: /*NeroshopComponents.FilterBox {*/Item {
Text {
text: qsTr("Coming soon!")
anchors.centerIn: parent
}
}
}
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
}
// SortComboBox
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
StackLayout {
id: catalogStack

@ -257,7 +257,7 @@ Page {
Button {
id: addProductButton
////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
hoverEnabled: true
background: Rectangle {
@ -409,7 +409,7 @@ Page {
id: removeProductsMessageBox
x: mainWindow.x + (mainWindow.width - this.width) / 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)?")
buttonModel: ["No", "Yes"]
buttonRow.state: "centered"; buttonRow.width: 300 // buttons should fill the row width

@ -17,7 +17,7 @@
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);}
return 0.0;
}

@ -24,7 +24,7 @@ namespace neroshop {
class Converter {
public:
// 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 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());
std::string expiration_date = json["expiration_date"].get<std::string>();
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)
////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

@ -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 currency_list;

@ -28,6 +28,9 @@ public:
QString imageToBase64(const QImage& image); // 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 int getCurrencyDecimals(const QString& currency) const;

Loading…
Cancel
Save