diff --git a/ClasstimeInterface.qml b/ClasstimeInterface.qml index 4c8d96a..f15672a 100644 --- a/ClasstimeInterface.qml +++ b/ClasstimeInterface.qml @@ -14,6 +14,8 @@ Item { Classtime { id: classtime onUpdateTimer: { + + // {seconds} => {hours}::{minutes}::{seconds} let tempTime = timeInSeconds; let hours, minutes, seconds; @@ -28,9 +30,23 @@ Item { classtimeUi.timeText.text = hours + " Hours and " + minutes + " minutes and " + seconds + " seconds"; } onUpdateComponents: { - console.log("here") + classtimeUi.participants.text = numOfParticipants; classtimeUi.lessonHeader.text = lessonHeader; + classtimeUi.webView.url = lessonResource; + + } + onEndClasstime: { + stackView.push('Modules.qml'); + } + + onMessageSentConfirmed: { + classtimeUi.messageSent = true; + + } + onMessageSentFailed: { + classtimeUi.messageFailed = true; + } } @@ -42,10 +58,18 @@ Item { color:"#F5F5F5" } leaveButtonMouseArea.onPressed: { -// backgroundRect.color = "#550bb3" - console.log("here") - classtime.leaveClasstime(); stackView.push("Modules.qml"); + classtime.leaveClasstime(); + } + askButtonMouseArea.onPressed: { + if (classtimeUi.questionField.text !== "") { + classtimeUi.noInputInQuestionField = false; + classtime.postQuestion(questionField.text, classtimeUi.anonSwitch.position == 0.0 ? false : true); + } else { + classtimeUi.noInputInQuestionField = true; + } + + } } diff --git a/ClasstimeUI.ui.qml b/ClasstimeUI.ui.qml index 92b7b90..4fac819 100644 --- a/ClasstimeUI.ui.qml +++ b/ClasstimeUI.ui.qml @@ -1,7 +1,6 @@ import QtQuick 2.14 import QtQuick.Controls 2.5 import QtQuick.Layouts 1.3 -import com.classmoor.classmoor 1.0 import com.classmoor.modules 1.0 import QtGraphicalEffects 1.0 import QtWebView 1.1 @@ -10,13 +9,19 @@ Page { id: page width: 1310 height: 768 + // WebView: PDF Viewer + property alias webView: webView + property alias anonSwitch: anonSwitch + property alias askButtonMouseArea: askButtonMouseArea + property alias questionField: questionField property alias leaveButton: leaveButton + property bool noInputInQuestionField: false + property bool messageSent: false + property bool messageFailed: false property alias leaveButtonMouseArea: leaveButtonMouseArea property alias participants: participants property alias lessonHeader: lessonHeader property alias timeText: timeText - //FIX LOADING -// property bool isDoneLoading: true contentWidth: 4 title: qsTr("Classtime") background: Rectangle { @@ -51,7 +56,7 @@ Page { id: scrollView1 anchors.fill: parent clip: true - contentHeight: parent.height + 300 + contentHeight: parent.height + 700 RowLayout { id: rowLayout0 @@ -187,183 +192,242 @@ Page { id: rowLayout1 spacing: 0 anchors.bottom: columnLayout.top - anchors.bottomMargin: 0 + anchors.bottomMargin: 10 anchors.top: rowLayout0.bottom - anchors.topMargin: 30 + anchors.topMargin: 5 anchors.right: parent.right anchors.rightMargin: 40 anchors.left: parent.left anchors.leftMargin: 40 - - ColumnLayout { - id: questionColumn - width: 698 - height: 179 + Rectangle { + id: rectangle1 + width: 590 + height: 200 + color: "#ffffff" + radius: 8 + visible: false Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillHeight: false Layout.fillWidth: false - spacing: 17.3 - Layout.fillHeight: true + } + + DropShadow { + id: dropShadow1 + width: 590 + height: 200 + horizontalOffset: 0 + verticalOffset: 3 + radius: 13.0 + Layout.alignment: Qt.AlignLeft | Qt.AlignTop visible: true + samples: 17 + color: "#c4bbbb" + source: rectangle1 - RowLayout { - id: subLayout1 - Text { - id: element4 - width: 169 - height: 85 - text: qsTr("Class") - font.family: "Lato" - font.bold: true - font.pixelSize: 30 - } + Rectangle { + id: rectangle2 + color: "#2c2f33" + radius: 8 + border.width: 0 + anchors.fill: parent - Text { - id: element5 - width: 169 - height: 85 - color: "#018d8d" - text: qsTr("Ask") - font.family: "Lato" - font.bold: true - font.pixelSize: 30 - } - spacing: 0 - Layout.alignment: Qt.AlignLeft | Qt.AlignTop - } + ColumnLayout { + id: questionColumn + x: -695 + y: -35 + anchors.leftMargin: 14 + anchors.bottomMargin: 14 + anchors.topMargin: 14 + anchors.rightMargin: 14 + anchors.fill: parent + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillWidth: false + spacing: 9 + Layout.fillHeight: true + visible: true - ColumnLayout { - id: askQuestionInfoColumn - width: 100 - height: 100 + ColumnLayout { + id: columnLayout2 + width: 100 + height: 100 + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + + RowLayout { + id: subLayout1 + Text { + id: element4 + width: 169 + height: 85 + color: "#fbfbfb" + text: qsTr("Class") + font.family: "Lato" + font.bold: true + font.pixelSize: 30 + } - Text { - id: questionBody - text: qsTr("You can ask your question anonymously or not, and it will give them a push notification instantaneously") - Layout.fillWidth: false - wrapMode: Text.WordWrap - font.pixelSize: 12 - } + Text { + id: element5 + width: 169 + height: 85 + color: "#018d8d" + text: qsTr("Ask") + font.family: "Lato" + font.bold: true + font.pixelSize: 30 + } + spacing: 0 + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + } + ColumnLayout { + id: askQuestionInfoColumn + width: 100 + height: 100 + + Text { + id: questionBody + width: 430 + color: "#ada7a7" + Layout.preferredWidth: 430 + text: qsTr("You can ask your question anonymously or not, and it will give them a push notification instantaneously") + Layout.fillWidth: false + wrapMode: Text.WordWrap + font.pixelSize: 12 + } - } - RowLayout { - id: questionActionRow - width: 698 - height: 100 - spacing: 30 - Layout.fillWidth: true + } - ColumnLayout { - id: questionAnonColumn - width: 100 - height: 100 - - Label { - id: anonymousSwitch - color: "#47360b" - text: qsTr("ANONYMOUS") - font.bold: false - font.weight: Font.Medium - font.pointSize: 9 - font.family: "Lato" - } - Switch { - id: anonSwitch - text: qsTr("") - } - } - ColumnLayout { - id: questionFieldColumn - width: 171 - height: 100 - Layout.alignment: Qt.AlignRight | Qt.AlignVCenter - Layout.fillWidth: true - - Label { - id: anonymousSwitch1 - color: "#47360b" - text: qsTr("YOUR QUESTION") - font.pointSize: 9 - font.weight: Font.Normal - font.family: "Lato" - font.letterSpacing: 1.2 } RowLayout { - id: textFieldRow - width: 100 + id: questionActionRow + width: 698 height: 100 - Layout.fillHeight: true + spacing: 30 Layout.fillWidth: true - TextField { - id: textField - height: 50 - font.pointSize: 11 - Layout.fillHeight: false - rightPadding: 16 - Layout.fillWidth: true - placeholderText: qsTr("Can you explain that?") - } - Button { - id: askButton - width: 400 - height: 30 - text: qsTr("Join Classroom") - Layout.alignment: Qt.AlignLeft | Qt.AlignTop - contentItem: Text { - id: element103 - color: askButton.down ? "#e6f0ff" : "white" - text: "Ask" - opacity: enabled ? 1.0 : 0.3 - font.bold: true - horizontalAlignment: Text.AlignHCenter - elide: Text.ElideRight - font.family: "Lato" - verticalAlignment: Text.AlignVCenter + ColumnLayout { + id: questionAnonColumn + width: 100 + height: 100 + + Label { + id: anonymousSwitch + color: "#c5c3bf" + text: qsTr("ANONYMOUS") + font.bold: false font.weight: Font.Medium - font.pointSize: 11 + font.pointSize: 9 + font.family: "Lato" } - padding: 11 - Layout.fillHeight: false - background: Rectangle { - id: backgroundRect2 - color: "#7131bf" - radius: 6 + + Switch { + id: anonSwitch + text: qsTr("") } - font.family: "Lato" + } + + ColumnLayout { + id: questionFieldColumn + width: 430 + height: 100 + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter Layout.fillWidth: true - flat: false - font.pointSize: 20 - - MouseArea { - id: askButtonMouseArea - height: 40 - anchors.bottomMargin: 0 - anchors.fill: parent - hoverEnabled: true - cursorShape: Qt.PointingHandCursor + + Label { + id: label + text: qsTr("Label") + visible: false + } + + Label { + id: anonymousSwitch1 + color: "#c5c3bf" + text: qsTr("YOUR QUESTION") + font.pointSize: 9 + font.weight: Font.Normal + font.family: "Lato" + font.letterSpacing: 1.2 } - Connections { - target: askButtonMouseArea - onEntered: { - backgroundRect2.color = "#7b38cf" + RowLayout { + id: textFieldRow + width: 400 + height: 100 + Layout.fillHeight: true + Layout.fillWidth: true + + TextField { + id: questionField + width: 300 + height: 50 + font.pointSize: 11 + Layout.fillHeight: false + rightPadding: 16 + Layout.fillWidth: true + placeholderText: qsTr("Can you explain that?") } - onExited: { - backgroundRect2.color = "#7131bf" + Button { + id: askButton + width: 400 + height: 30 + text: qsTr("Join Classroom") + contentItem: Text { + id: element103 + color: askButton.down ? "#e6f0ff" : "white" + text: "Ask" + opacity: enabled ? 1.0 : 0.3 + font.bold: true + horizontalAlignment: Text.AlignHCenter + elide: Text.ElideRight + font.family: "Lato" + verticalAlignment: Text.AlignVCenter + font.weight: Font.Medium + font.pointSize: 11 + } + padding: 11 + Layout.fillHeight: false + background: Rectangle { + id: backgroundRect2 + color: "#7131bf" + radius: 6 + } + font.family: "Lato" + Layout.fillWidth: true + flat: false + font.pointSize: 20 + + MouseArea { + id: askButtonMouseArea + height: 40 + anchors.bottomMargin: 0 + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + } + + + Connections { + target: askButtonMouseArea + onEntered: { + backgroundRect2.color = "#7b38cf" + } + onExited: { + backgroundRect2.color = "#7131bf" + } + } } } + + } } - } - } @@ -373,55 +437,136 @@ Page { + + } + } + + + } - ColumnLayout { - id: columnLayout1 - width: 100 - height: 100 + Rectangle { + id: rectangle4 + width: 590 + height: 200 + color: "#ffffff" + radius: 8 Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillWidth: false + visible: false + Layout.fillHeight: false + } + DropShadow { + id: dropShadow2 + width: 590 + height: 200 + color: "#c4bbbb" + radius: 13 + verticalOffset: 3 + Layout.alignment: Qt.AlignRight | Qt.AlignTop + horizontalOffset: 0 + visible: true - RowLayout { - id: subLayout3 - Text { - id: element9 - width: 169 - height: 85 - text: qsTr("Class") - font.family: "Lato" - font.bold: true - font.pixelSize: 30 - } + Rectangle { + id: rectangle3 + color: "#2c2f33" + radius: 8 + border.width: 0 + anchors.fill: parent - Text { - id: element11 - width: 169 - height: 85 - color: "#e3061d" - text: qsTr("Test") - font.family: "Lato" - font.bold: true - font.pixelSize: 30 - } - spacing: 0 - Layout.alignment: Qt.AlignLeft | Qt.AlignTop - } + ColumnLayout { + id: columnLayout1 + spacing: 0 + anchors.rightMargin: 14 + anchors.leftMargin: 14 + anchors.bottomMargin: 14 + anchors.topMargin: 14 + anchors.fill: parent + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + + + ColumnLayout { + id: columnLayout7 + width: 100 + height: 100 + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + spacing: 9 + RowLayout { + id: subLayout2 + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Text { + id: element7 + width: 169 + height: 85 + color: "#fbfbfb" + text: qsTr("Class") + font.family: "Lato" + font.bold: true + font.pixelSize: 30 + } - Text { - id: element6 - width: 169 - height: 85 - color: "#88838d" - text: qsTr("No assigned test or avaliable ") - Layout.alignment: Qt.AlignLeft | Qt.AlignTop - font.family: "Lato" - font.bold: true - font.pixelSize: 20 + Text { + id: element15 + width: 169 + height: 85 + color: "#cc0c0c" + text: qsTr("Test") + font.family: "Lato" + font.bold: true + font.pixelSize: 30 + } + spacing: 0 + } + + ColumnLayout { + id: askQuestionInfoColumn1 + width: 100 + height: 100 + Text { + id: questionBody1 + width: 430 + color: "#ada7a7" + text: qsTr("Classtest is a realtime service which provides intensive testing and the ablities to test on the fly") + wrapMode: Text.WordWrap + Layout.fillWidth: false + Layout.preferredWidth: 430 + font.pixelSize: 12 + } + } + } + + RowLayout { + id: rowLayout + width: 100 + height: 100 + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + + Text { + id: element6 + width: 169 + height: 100 + color: "#88838d" + text: qsTr("No assigned test or avaliable ") + Layout.fillWidth: true + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + font.family: "Lato" + font.bold: true + font.pixelSize: 30 + } + } + + + } } + samples: 17 + source: rectangle4 } + + + } @@ -429,11 +574,13 @@ Page { + ColumnLayout { id: columnLayout x: 40 y: 468 - height: 398 + width: 1500 + height: 600 anchors.right: parent.right anchors.rightMargin: 40 anchors.left: parent.left @@ -467,9 +614,9 @@ Page { Item { id: element width: 700 - height: 200 + height: 900 Layout.fillHeight: true - Layout.fillWidth: false + Layout.fillWidth: true WebView { id: webView @@ -485,6 +632,8 @@ Page { } } + + } ColumnLayout { @@ -640,7 +789,7 @@ Page { states: [ State { name: "LoadingApp" - when: !isDoneLoading + when: isDoneLoading == false PropertyChanges { target: busyIndicator @@ -675,38 +824,145 @@ Page { }, State { name: "State1" + + PropertyChanges { + target: label + visible: false + } + }, + State { + name: "State2" + when: noInputInQuestionField === true + + PropertyChanges { + target: label + color: "#e51111" + text: qsTr("Please enter a question in the field") + font.letterSpacing: 1.2 + font.bold: true + visible: true + } + + PropertyChanges { + target: page + visible: true + } + + PropertyChanges { + target: element4 + font.letterSpacing: 0.5 + } + + PropertyChanges { + target: element5 + font.letterSpacing: 0.5 + } + + PropertyChanges { + target: element7 + font.letterSpacing: 0.5 + } + + PropertyChanges { + target: element15 + font.letterSpacing: 0.5 + } + }, + State { + name: "Message Sent!" + when: messageSent === true + PropertyChanges { + target: label + color: "#5cd34a" + text: qsTr("Message Sent!") + font.bold: true + visible: true + } + + PropertyChanges { + target: page + visible: true + } + }, + State { + name: "failed to send" + when: messageFailed === true + PropertyChanges { + target: label + color: "#e51111" + text: qsTr("Failed to send the message, try again!") + font.letterSpacing: 1.2 + visible: true + font.bold: true + } + + PropertyChanges { + target: page + visible: true + } + + PropertyChanges { + target: element4 + font.letterSpacing: 0.5 + } + + PropertyChanges { + target: element5 + font.letterSpacing: 0.5 + } + + PropertyChanges { + target: element7 + font.letterSpacing: 0.5 + } + + PropertyChanges { + target: element15 + font.letterSpacing: 0.5 + } } ] } /*##^## Designer { - D{i:0;customId:"";formeditorZoom:0.6600000262260437}D{i:9;anchors_height:200;anchors_width:200;invisible:true} + D{i:0;customId:"";formeditorZoom:0.5}D{i:75;invisible:true}D{i:9;anchors_height:200;anchors_width:200;invisible:true} D{i:10;invisible:true}D{i:8;anchors_height:200;anchors_width:200;invisible:true}D{i:11;invisible:true} D{i:17;anchors_height:200;anchors_width:100;anchors_x:36;anchors_y:242}D{i:13;invisible:true} -D{i:6;anchors_height:163;anchors_width:1920;anchors_x:0;anchors_y:0}D{i:22;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} -D{i:20;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118}D{i:24;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} -D{i:23;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118}D{i:27;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} -D{i:28;anchors_height:200;anchors_width:200;anchors_x:36;anchors_y:118}D{i:26;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} -D{i:30;anchors_height:200;anchors_width:100;anchors_x:83;anchors_y:367}D{i:32;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} -D{i:37;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118}D{i:31;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} -D{i:29;anchors_height:200;anchors_width:100;anchors_x:83;anchors_y:242}D{i:25;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} -D{i:19;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118}D{i:40;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} -D{i:41;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118}D{i:39;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} -D{i:42;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118}D{i:38;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} -D{i:18;anchors_height:200;anchors_width:100;anchors_x:36;anchors_y:242}D{i:45;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} -D{i:46;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118}D{i:44;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} -D{i:48;anchors_height:200;anchors_width:200;anchors_x:36;anchors_y:118}D{i:47;anchors_x:36} -D{i:43;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118}D{i:5;anchors_height:163;anchors_width:1920;anchors_x:0;anchors_y:0} -D{i:50;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118;invisible:true} -D{i:51;invisible:true}D{i:49;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118;invisible:true} -D{i:55;anchors_height:163;anchors_width:1920;anchors_x:0;anchors_y:0}D{i:56;anchors_height:163;anchors_width:1920;anchors_x:0;anchors_y:0} -D{i:54;anchors_height:100;anchors_width:100;anchors_x:312;anchors_y:214}D{i:58;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118;invisible:true} -D{i:59;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118;invisible:true} -D{i:57;anchors_height:163;anchors_width:1920;anchors_x:0;anchors_y:0}D{i:61;invisible:true} -D{i:62;invisible:true}D{i:60;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118;invisible:true} -D{i:53;anchors_height:100;anchors_width:100;anchors_x:312;anchors_y:214}D{i:52;anchors_height:100;anchors_width:100;anchors_x:312;anchors_y:214;invisible:true} -D{i:63;invisible:true} +D{i:6;anchors_height:163;anchors_width:1920;anchors_x:0;anchors_y:0}D{i:19;anchors_height:179;anchors_width:698;anchors_x:8;anchors_y:"-49"} +D{i:25;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118}D{i:26;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} +D{i:24;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118}D{i:28;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} +D{i:27;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118}D{i:23;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} +D{i:31;anchors_height:200;anchors_width:200;anchors_x:36;anchors_y:118}D{i:32;anchors_height:200;anchors_width:100;anchors_x:83;anchors_y:242} +D{i:30;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118}D{i:35;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} +D{i:40;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118}D{i:41;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} +D{i:42;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118}D{i:36;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} +D{i:33;anchors_height:200;anchors_width:100;anchors_x:83;anchors_y:367}D{i:29;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} +D{i:21;anchors_height:200;anchors_width:200;anchors_x:705;anchors_y:45}D{i:20;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} +D{i:43;anchors_height:179;anchors_width:698;anchors_x:8;anchors_y:"-49"}D{i:49;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} +D{i:50;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118}D{i:48;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} +D{i:52;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118}D{i:51;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} +D{i:47;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118}D{i:54;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} +D{i:46;anchors_height:100;anchors_width:615;anchors_x:"-258";anchors_y:0}D{i:45;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118} +D{i:44;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118}D{i:18;anchors_height:200;anchors_width:100;anchors_x:36;anchors_y:242} +D{i:57;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118;invisible:true} +D{i:58;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118;invisible:true} +D{i:56;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118;invisible:true} +D{i:60;anchors_height:200;anchors_width:200;anchors_x:36;anchors_y:118;invisible:true} +D{i:59;anchors_height:200;anchors_width:200;anchors_x:36;anchors_y:118;invisible:true} +D{i:55;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118}D{i:5;anchors_height:163;anchors_width:1920;anchors_x:0;anchors_y:0} +D{i:62;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118;invisible:true} +D{i:63;anchors_height:100;anchors_width:100;anchors_x:312;anchors_y:214;invisible:true} +D{i:61;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118;invisible:true} +D{i:67;anchors_height:163;anchors_width:1920;anchors_x:0;anchors_y:0;invisible:true} +D{i:68;anchors_height:163;anchors_width:1920;anchors_x:0;anchors_y:0;invisible:true} +D{i:66;anchors_height:100;anchors_width:100;anchors_x:312;anchors_y:214;invisible:true} +D{i:70;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118;invisible:true} +D{i:71;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118;invisible:true} +D{i:69;anchors_height:163;anchors_width:1920;anchors_x:0;anchors_y:0;invisible:true} +D{i:73;invisible:true}D{i:74;invisible:true}D{i:72;anchors_height:200;anchors_width:200;anchors_x:261;anchors_y:118;invisible:true} +D{i:65;anchors_height:100;anchors_width:100;anchors_x:312;anchors_y:214;invisible:true} +D{i:64;anchors_height:100;anchors_width:100;anchors_x:312;anchors_y:214;invisible:true} } ##^##*/ diff --git a/Modules.qml b/Modules.qml index 4169dd2..96296bd 100644 --- a/Modules.qml +++ b/Modules.qml @@ -31,7 +31,6 @@ Item { modulesForm.isStateFour = false; if (!isDoneLoading) { - modules.joinClasstime(); stackView.push("ClasstimeInterface.qml"); } } @@ -63,9 +62,8 @@ Item { } modulesForm.time.text = hours + ":" + minutes + ":" + seconds; } - onChangeState: { - console.log("here2") + modulesForm.lastCheckInMessage.text = classCheck_message; modulesForm.lastClasstimeMessage.text = classTime_message; @@ -99,11 +97,16 @@ Item { modulesForm.isStateTwo = false modulesForm.isStateThree = false break; + case 5: + modulesForm.isDoneLoading = true; + modulesForm.isStateFour = false; + modulesForm.isStateOne = false; + modulesForm.isStateTwo = false + modulesForm.isStateThree = false + break; default: - modulesForm.isDoneLoading = false; } - console.log(modulesForm.isDoneLoading) } } diff --git a/ModulesForm.ui.qml b/ModulesForm.ui.qml index 0f1b454..7900021 100644 --- a/ModulesForm.ui.qml +++ b/ModulesForm.ui.qml @@ -1,7 +1,6 @@ import QtQuick 2.14 import QtQuick.Controls 2.5 import QtQuick.Layouts 1.3 -import com.classmoor.classmoor 1.0 import com.classmoor.modules 1.0 import QtGraphicalEffects 1.0 @@ -318,7 +317,7 @@ Page { contentItem: Text { font.bold: true font.family: "Lato" - font.pointSize: 11 + font.pointSize: 16 font.weight: Font.Medium opacity: enabled ? 1.0 : 0.3 color: joinClasstimeButton.down ? "#e6f0ff" : "white" @@ -521,7 +520,7 @@ Page { width: 190 fillMode: Image.PreserveAspectFit sourceSize.width: 204 - source: "cal.svg" + source: "./cal.svg" sourceSize.height: 150 } } @@ -543,7 +542,7 @@ Page { font.family: "Lato" verticalAlignment: Text.AlignVCenter font.weight: Font.Medium - font.pointSize: 11 + font.pointSize: 16 } padding: 14 Layout.fillHeight: false @@ -681,7 +680,17 @@ Page { PropertyChanges { target: rowLayout7 - spacing: 110 + spacing: 130 + } + + PropertyChanges { + target: columnLayout5 + Layout.alignment: Qt.AlignRight | Qt.AlignBottom + } + + PropertyChanges { + target: element10 + font.pointSize: 16 } }, State { @@ -840,6 +849,7 @@ Page { target: time color: "#7131bf" text: qsTr("00:00:00") + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter font.family: "Lato" bottomPadding: 0 Layout.bottomMargin: 0 @@ -869,6 +879,12 @@ Page { target: joinClasstimeButton enabled: true } + + PropertyChanges { + target: columnLayout5 + Layout.fillWidth: false + Layout.alignment: Qt.AlignRight | Qt.AlignBottom + } } ] } diff --git a/SetupForm.ui.qml b/SetupForm.ui.qml index 685a3ea..02301b7 100644 --- a/SetupForm.ui.qml +++ b/SetupForm.ui.qml @@ -3,7 +3,7 @@ import QtQuick.Controls 2.5 import QtGraphicalEffects 1.0 import QtQuick.Layouts 1.3 import com.classmoor.setup 1.0 -import com.classmoor.classmoor 1.0 +import Qt.labs.calendar 1.0 Page { id: page @@ -19,10 +19,6 @@ Page { id: setup } - Classmoor { - id: classmoor - } - property bool isFilledOut: true property bool isFirstTimeSubmitting: false property bool isDone: false diff --git a/classmoor.cpp b/classmoor.cpp index e8893ab..61b1438 100644 --- a/classmoor.cpp +++ b/classmoor.cpp @@ -1,66 +1,10 @@ #include "classmoor.h" -Classmoor::Classmoor(QQmlApplicationEngine* e) { - - engine = e; - - //Prequesites Checking for stable connection to database and SNS subscription and Lambda Functions - try { - Aws::Client::ClientConfiguration clientConfig; - clientConfig.region = "us-west-1"; - - // TODO: Only check if authenticated - if (!isFirstTimeRunning()) { - //Read TOPIC ARN and pass to snsClient - //SnsClient snsClient(clientConfig, topicArn); - //snsClient.checkConnection(); - } - - DynamoClient dynamoClient(clientConfig); - lambdaClient lambda = lambdaClient(clientConfig); - - - dynamoClient.checkConnection(); - - bool isLambdaGood = false; - isLambdaGood = lambda.checkConnection(); - - qDebug() << isFirstTimeRunning(); - if (isFirstTimeRunning()) { - qmlRegisterType("com.classmoor.setup", 1, 0, "Setup"); - qmlRegisterType("com.classmoor.classmoor", 1, 0, "Classmoor"); - engine->load(QStringLiteral("qrc:/Setup.qml")); - - } else { - engine->load(QStringLiteral("qrc:/main.qml")); - } - - } catch (const std::runtime_error& e) { - std::cout << e.what() << std::endl; - } -} - - bool Classmoor::isFirstTimeRunning() { - - QString pathToUserDataFile = "user_data.txt"; QFileInfo check_file(pathToUserDataFile); if (check_file.exists()) { return false; } return true; - } - -void Classmoor::checkIfSetupIsCompleted(bool check) -{ - if (check) { - engine->load(QStringLiteral("qrc:/main.qml")); - } -} - -void Classmoor::intiateSetup() { - -} - diff --git a/classmoor.h b/classmoor.h index 3c79cb5..6b61d44 100644 --- a/classmoor.h +++ b/classmoor.h @@ -2,8 +2,6 @@ #define CLASSMOOR_H #include -#include "dynamoclient.h" -#include "lambdaclient.h" #include #include #include @@ -19,16 +17,12 @@ class Classmoor : public QObject public: Classmoor(){}; Classmoor(QObject *parent) : QObject(parent) {} - Classmoor(QQmlApplicationEngine* e); - void intiateSetup(); - QQmlApplicationEngine getEngine(); bool isFirstTimeRunning(); -private: - QQmlApplicationEngine* engine; + signals: public slots: - void checkIfSetupIsCompleted(bool check); + }; #endif // CLASSMOOR_H diff --git a/classmoor.pro b/classmoor.pro index e294204..59755d5 100644 --- a/classmoor.pro +++ b/classmoor.pro @@ -15,12 +15,11 @@ DEFINES += QT_DEPRECATED_WARNINGS #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 INCLUDEPATH += /usr/local/include -LIBS += -L/usr/local/lib64 -laws-cpp-sdk-core -laws-cpp-sdk-s3 -laws-cpp-sdk-sns -laws-cpp-sdk-lambda -laws-cpp-sdk-dynamodb -laws-cpp-sdk-sqs +LIBS += -L/usr/local/lib -laws-cpp-sdk-core -laws-cpp-sdk-s3 -laws-cpp-sdk-sns -laws-cpp-sdk-lambda -laws-cpp-sdk-dynamodb -laws-cpp-sdk-sqs SOURCES += \ classmoor.cpp \ classtime.cpp \ - dynamoclient.cpp \ lambdaclient.cpp \ main.cpp \ modules.cpp \ @@ -50,7 +49,6 @@ HEADERS += \ NodeIterator.h \ classmoor.h \ classtime.h \ - dynamoclient.h \ lambdaclient.h \ linkedlist.h \ modules.h \ diff --git a/classmoor.pro.user b/classmoor.pro.user index d9bcaa4..ebfeb7f 100644 --- a/classmoor.pro.user +++ b/classmoor.pro.user @@ -1,10 +1,10 @@ - + EnvironmentId - {b3545020-debd-4c69-8e71-390edbc7f8f2} + {026e9c65-3292-4356-a33b-9413d660f401} ProjectExplorer.Project.ActiveTarget @@ -72,17 +72,17 @@ ProjectExplorer.Project.Target.0 - Desktop Qt 5.14.2 GCC 64bit - Desktop Qt 5.14.2 GCC 64bit - qt.qt5.5142.gcc_64_kit + Desktop Qt 5.15.0 clang 64bit + Desktop Qt 5.15.0 clang 64bit + qt.qt5.5150.clang_64_kit 0 0 0 true 0 - /home/andrewpaulino/build-classmoor-Desktop_Qt_5_14_2_GCC_64bit-Debug - /home/andrewpaulino/build-classmoor-Desktop_Qt_5_14_2_GCC_64bit-Debug + /Users/andrewpaulino/Desktop/classmoor/build-classmoor-Desktop_Qt_5_15_0_clang_64bit-Debug + /Users/andrewpaulino/Desktop/classmoor/build-classmoor-Desktop_Qt_5_15_0_clang_64bit-Debug true @@ -132,8 +132,8 @@ true 2 - /home/andrewpaulino/build-classmoor-Desktop_Qt_5_14_2_GCC_64bit-Release - /home/andrewpaulino/build-classmoor-Desktop_Qt_5_14_2_GCC_64bit-Release + /Users/andrewpaulino/Desktop/classmoor/build-classmoor-Desktop_Qt_5_15_0_clang_64bit-Release + /Users/andrewpaulino/Desktop/classmoor/build-classmoor-Desktop_Qt_5_15_0_clang_64bit-Release true @@ -183,8 +183,8 @@ true 0 - /home/andrewpaulino/build-classmoor-Desktop_Qt_5_14_2_GCC_64bit-Profile - /home/andrewpaulino/build-classmoor-Desktop_Qt_5_14_2_GCC_64bit-Profile + /Users/andrewpaulino/Desktop/classmoor/build-classmoor-Desktop_Qt_5_15_0_clang_64bit-Profile + /Users/andrewpaulino/Desktop/classmoor/build-classmoor-Desktop_Qt_5_15_0_clang_64bit-Profile true @@ -306,19 +306,20 @@ 2 - Qt4ProjectManager.Qt4RunConfiguration:/home/andrewpaulino/classmoor/classmoor.pro - /home/andrewpaulino/classmoor/classmoor.pro + Qt4ProjectManager.Qt4RunConfiguration:/Users/andrewpaulino/Desktop/classmoor/Classmoor/classmoor.pro + /Users/andrewpaulino/Desktop/classmoor/Classmoor/classmoor.pro false false true - true + false + false false false true - /home/andrewpaulino/build-classmoor-Desktop_Qt_5_14_2_GCC_64bit-Debug + /Users/andrewpaulino/Desktop/classmoor/build-classmoor-Desktop_Qt_5_15_0_clang_64bit-Debug/classmoor.app/Contents/MacOS 1 diff --git a/classmoor.pro.user.b354502 b/classmoor.pro.user.b354502 new file mode 100644 index 0000000..e0339ce --- /dev/null +++ b/classmoor.pro.user.b354502 @@ -0,0 +1,338 @@ + + + + + + EnvironmentId + {b3545020-debd-4c69-8e71-390edbc7f8f2} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + true + Builtin.Questionable + + true + Builtin.DefaultTidyAndClazy + 2 + + + + true + + + + + ProjectExplorer.Project.Target.0 + + Desktop Qt 5.14.2 GCC 64bit + Desktop Qt 5.14.2 GCC 64bit + qt.qt5.5142.gcc_64_kit + 0 + 0 + 0 + + true + 0 + /home/andrewpaulino/build-classmoor-Desktop_Qt_5_14_2_GCC_64bit-Debug + /home/andrewpaulino/build-classmoor-Desktop_Qt_5_14_2_GCC_64bit-Debug + + + true + QtProjectManager.QMakeBuildStep + + false + + + + true + Qt4ProjectManager.MakeStep + + false + + + false + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + + true + clean + + false + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + 2 + 2 + + + true + 2 + /home/andrewpaulino/build-classmoor-Desktop_Qt_5_14_2_GCC_64bit-Release + /home/andrewpaulino/build-classmoor-Desktop_Qt_5_14_2_GCC_64bit-Release + + + true + QtProjectManager.QMakeBuildStep + + false + + + + true + Qt4ProjectManager.MakeStep + + false + + + false + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + + true + clean + + false + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + 2 + + + true + 0 + /home/andrewpaulino/build-classmoor-Desktop_Qt_5_14_2_GCC_64bit-Profile + /home/andrewpaulino/build-classmoor-Desktop_Qt_5_14_2_GCC_64bit-Profile + + + true + QtProjectManager.QMakeBuildStep + + false + + + + true + Qt4ProjectManager.MakeStep + + false + + + false + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + + true + clean + + false + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Profile + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + 0 + + 3 + + + 0 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + dwarf + + cpu-cycles + + + 250 + + -e + cpu-cycles + --call-graph + dwarf,4096 + -F + 250 + + -F + true + 4096 + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + kcachegrind + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 2 + + Qt4ProjectManager.Qt4RunConfiguration:/home/andrewpaulino/classmoor/classmoor.pro + /home/andrewpaulino/classmoor/classmoor.pro + + false + + false + true + true + false + false + true + + /home/andrewpaulino/build-classmoor-Desktop_Qt_5_14_2_GCC_64bit-Debug + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + + diff --git a/classtime.cpp b/classtime.cpp index a87a0d6..36da46e 100644 --- a/classtime.cpp +++ b/classtime.cpp @@ -7,6 +7,7 @@ Classtime::Classtime(QObject *parent) : QObject(parent) lambda_client = new lambdaClient(clientConfig); + // Setting Request Timeout clientConfig.requestTimeoutMs = 30000000; sqs_client = new SqsClient(clientConfig); @@ -17,20 +18,29 @@ void Classtime::retrieveClasstimeDetails() { try { + + // Read User file credentials readFromFile(); - // Step 1: Retrieve the details for classtime + + // Retrieve User Data intialLoad = lambda_client->getClasstimeDetails(creds); - qint64 d = QDateTime::currentSecsSinceEpoch(); - timeInSeconds = d - intialLoad.timeElapsed; + qint64 secondsSinceMS = QDateTime::currentSecsSinceEpoch(); + // Time in seconds to count UP based on elapsed + timeInSeconds = secondsSinceMS - intialLoad.timeElapsed; + + // Activiating Timer activateTimer(); + // New UI Change emit updateComponents( util.convertStdStringToQString(intialLoad.classtimeLessonHeader), util.convertStdStringToQString(intialLoad.classtimeLessonResource), intialLoad.numOfParticipants ); + // Handling Signal and Slots, making sure new message will be directed to -> recievedMessage connect(&(*sqs_client), &SqsClient::newMessage, this, &Classtime::recievedMessage, Qt::QueuedConnection); - sqs_client->startPolling(creds.client_sqs); + sqs_client->startPolling( util.convertStdStringToAWSString( intialLoad.classtimeSQSUrl)); + } catch (std::exception e) { - std::cout << e.what() << std::endl; + qDebug() << e.what() << endl; } @@ -38,18 +48,39 @@ void Classtime::retrieveClasstimeDetails() void Classtime::updateTime() { + + //Updating State timeInSeconds += 1; emit updateTimer(timeInSeconds); } +void Classtime::postQuestion(QString questionText, bool isAnon) { + + try { + classaskResponsePayload response; + + // Posting a question to the backend from qml file + response = lambda_client->postQuestion( util.convertQStringToAWSString(questionText), isAnon, util.convertStdStringToAWSString( intialLoad.classtimeId), creds); + + // User validation + if (response.statusCode == 200) { + emit messageSentConfirmed(); + } else { + emit messageSentFailed(); + } + } catch (std::exception e){ + qDebug() << e.what() << endl; + } +} + void Classtime::leaveClasstime() { try { bool result = false; - result = lambda_client->leaveClasstime( creds.studentId, util.convertStdStringToAWSString( intialLoad.classtimeId ), creds.client_sqs); - if (result) { - } + // Tell backend, we are not online. + result = lambda_client->leaveClasstime( creds.studentId, util.convertStdStringToAWSString( intialLoad.classtimeId ), creds.classroomId, util.convertStdStringToAWSString(intialLoad.classtimeSQSUrl)); + } catch (std::exception e) { qDebug() << e.what() << endl; } @@ -57,37 +88,50 @@ void Classtime::leaveClasstime() void Classtime::recievedMessage(QString m) { - qDebug() << "Recieved Message: " << m << endl; + // Our Slot from, SQSClient class. + qDebug() << "Classtime: New Message " << m << endl; if (m == "updateClasstime") { - // Create new thread to handle this as it will timeout before finished as the polling will the - + // Getting Credentials Aws::String classtime_id = util.convertStdStringToAWSString( intialLoad.classtimeId); Aws::String classroom_id = creds.classroomId; + // Watcher for future values QFutureWatcher watcher; + // Multi-threaded Process, handling using concurrency based. + // Putting thread in different thread pool so non-blocking process + // can continue. QFuture future = QtConcurrent::run(this, &Classtime::runUpdateThreadedFunction, classtime_id, classroom_id); - watcher.setFuture(future); - watcher.waitForFinished(); + + // Retriving values from our watcher after completed function + // This is meant for a handshake between our serverless lambda's and + // our databases. + // Note: Lambda Could timeout, 15 second timeout intialLoad.numOfParticipants = future.result().numOfParticipants; intialLoad.classtimeLessonHeader = future.result().classtimeLessonHeader; intialLoad.classtimeLessonResource = future.result().classtimeLessonResource; - qDebug() << future.result().numOfParticipants; + // Awaiting Future of Lambda Handshake between SQS and confirmation SQS Queue. emit updateComponents( util.convertStdStringToQString(intialLoad.classtimeLessonHeader), util.convertStdStringToQString(intialLoad.classtimeLessonResource), intialLoad.numOfParticipants ); - - } else if (m == "ping") { + + // Once we recieve Ping we send back in different thread sqs_client->sendMessage( creds.confirmation_client_sqs, creds.studentId ); + } else if (m == "endClasstime") { + // Close polling & Clean up + sqs_client->closePolling(); + + // Leave Stack View + emit endClasstime(); } } clastimeUpdatePayload Classtime::runUpdateThreadedFunction( Aws::String classtimeId, Aws::String classroomId ) { - qDebug() << "In Update Classtime" << QThread::currentThread(); + qDebug() << "Classtime: Threading, await for updating from AWS Lambda non-blocking" << QThread::currentThread(); return lambda_client->updateClasstime( classtimeId, classroomId ); } @@ -101,11 +145,17 @@ bool Classtime::readFromFile() QTextStream in(&inputFile); while (!in.atEnd()) { + // Read Line list.push(in.readLine()); } inputFile.close(); } + // Extracting from linked List + // - ClassroomId + // - Client SQS + // - Confirmation Client SQS + // - StudentId creds.classroomId = util.convertQStringToAWSString( list[2]); creds.client_sqs = util.convertQStringToAWSString(list[3]); @@ -114,15 +164,23 @@ bool Classtime::readFromFile() return true; } catch (std::exception e) { - std::cout << e.what() << std::endl; + qDebug() << e.what() << endl; return false; } } +Classtime::~Classtime() +{ + qDebug() << "Classtime: Exiting Polling" << endl; + sqs_client->closePolling(); +} + void Classtime::activateTimer() { + + // Initializing QT Timer activeTimer = new QTimer(this); activeTimer->setInterval(1000); connect(activeTimer, SIGNAL(timeout()), this, SLOT(updateTime())); diff --git a/classtime.h b/classtime.h index 2059652..4469a66 100644 --- a/classtime.h +++ b/classtime.h @@ -1,7 +1,6 @@ #ifndef CLASSTIME_H #define CLASSTIME_H #include -#include "dynamoclient.h" #include "lambdaclient.h" #include #include @@ -23,31 +22,50 @@ #include #include +// Classtime: +// * Concurrency + SQS Confirmation QUEUE +// * Threading with QTConcurrency +// * Signal and slots to our classtime functions +// * Watcher will then find the value and assign it + class Classtime : public QObject { Q_OBJECT public: explicit Classtime(QObject *parent = nullptr); - + ~Classtime(); private: - DynamoClient* dynamo_client; - UtilityFunctions util; + + // AWS CLIENTS lambdaClient* lambda_client; + SqsClient* sqs_client; + + // Payloads + UtilityFunctions util; userCredentials creds; + intitalizeClasstimePayload intialLoad; + clastimeUpdatePayload runUpdateThreadedFunction(Aws::String classtimeId, Aws::String classroomId ); + + // General Functions bool readFromFile(); void intalizeState(); - intitalizeClasstimePayload intialLoad; - SqsClient* sqs_client; void activateTimer(); int timeInSeconds = 0; QTimer* activeTimer; - clastimeUpdatePayload runUpdateThreadedFunction(Aws::String classtimeId, Aws::String classroomId ); signals: void updateComponents(QString lessonHeader, QString lessonResource, int numOfParticipants); void updateTimer(int timeInSeconds); + + // User Validation + void messageSentConfirmed(); + void messageSentFailed(); + + // Ending the classtime + void endClasstime(); public slots: void retrieveClasstimeDetails(); void updateTime(); + void postQuestion(QString questionText, bool isAnon); void leaveClasstime(); void recievedMessage(QString m); }; diff --git a/dynamoclient.cpp b/dynamoclient.cpp deleted file mode 100644 index b1de1f2..0000000 --- a/dynamoclient.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "dynamoclient.h" - -DynamoClient::DynamoClient() -{ - -} - -void DynamoClient::checkConnection() { - Aws::DynamoDB::Model::ListTablesRequest ltr; - ltr.SetLimit(50); - - const Aws::DynamoDB::Model::ListTablesOutcome& lto = ListTables(ltr); - - if (!lto.IsSuccess()){ - throw std::runtime_error("Unable to connect to DynamoDB"); - } - - std::cout << "DynamoDB Client Connected to US-West-1" << std::endl; - -} diff --git a/dynamoclient.h b/dynamoclient.h deleted file mode 100644 index 2f18cd9..0000000 --- a/dynamoclient.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef DYNAMOCLIENT_H -#define DYNAMOCLIENT_H -#include -#include -#include -#include -#include - -#include - - -class DynamoClient : public Aws::DynamoDB::DynamoDBClient { -public: - DynamoClient(); - DynamoClient(Aws::Client::ClientConfiguration config) : Aws::DynamoDB::DynamoDBClient(config) { - //do nothing - }; - void checkConnection(); -}; - -#endif // DYNAMOCLIENT_H diff --git a/lambdaclient.cpp b/lambdaclient.cpp index e11248e..d0dff82 100644 --- a/lambdaclient.cpp +++ b/lambdaclient.cpp @@ -329,7 +329,57 @@ clastimeUpdatePayload lambdaClient::updateClasstime(Aws::String classtimeId, Aws } } -bool lambdaClient::leaveClasstime(Aws::String studentId, Aws::String classtimeId, Aws::String sqsUrl) +classaskResponsePayload lambdaClient::postQuestion(Aws::String questionText, bool isAnon, Aws::String classtimeId, userCredentials creds) +{ + Aws::String functionName = "classmoor-api-prod"; + + + Aws::Lambda::Model::InvokeRequest invokeRequest; + invokeRequest.SetFunctionName(functionName); + invokeRequest.SetInvocationType(Aws::Lambda::Model::InvocationType::RequestResponse); + invokeRequest.SetLogType(Aws::Lambda::Model::LogType::Tail); + std::shared_ptr payload = Aws::MakeShared("body"); + qDebug() << util.convertStdStringToQString(util.convertAWSStringToStdString( classtimeId) ) << endl; + Aws::Utils::Json::JsonValue bodyObject; + bodyObject.WithString("clientPath", "newQuestion"); + bodyObject.WithString("question", questionText); + bodyObject.WithBool("isAnonymous", isAnon); + bodyObject.WithString("studentId", creds.studentId); + bodyObject.WithString("classroomId", creds.classroomId); + bodyObject.WithString("classtimeId", classtimeId); + + Aws::Utils::Json::JsonValue jsonPayload; + jsonPayload.WithObject("body", bodyObject); + + + *payload << jsonPayload.View().WriteReadable(); + + invokeRequest.SetBody(payload); + invokeRequest.SetContentType("application/javascript"); + + auto outcome = Invoke(invokeRequest); + + if (outcome.IsSuccess()) { + auto &result = outcome.GetResult(); + Aws::Utils::Json::JsonValue resultObj; + Aws::IOStream& payload = result.GetPayload(); + resultObj = payload; + + Aws::String statusCode; + + classaskResponsePayload response; + qDebug() << "Testing FUNCTION" < - +#include #include #include #include @@ -33,17 +33,17 @@ int main(int argc, char *argv[]) QQmlApplicationEngine engine; - - Classmoor mainExecutive; QUrl url; //Register QML Types + + // Instantiating Classes in the QML and UI Files. qmlRegisterType("com.classmoor.setup", 1, 0, "Setup"); - qmlRegisterType("com.classmoor.classmoor", 1, 0, "Classmoor"); qmlRegisterType("com.classmoor.modules", 1, 0, "Modules"); qmlRegisterType("com.classmoor.classtime", 1, 0, "Classtime"); + qmlRegisterType("com.classmoor.classmoor", 1, 0, "Classmoor"); if (mainExecutive.isFirstTimeRunning()) { url = (QStringLiteral("qrc:/Setup.qml")); @@ -52,7 +52,7 @@ int main(int argc, char *argv[]) } - + // Loadings QObject::connect(&(engine), &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); diff --git a/main.qml b/main.qml index 4fefaab..4ca5e90 100644 --- a/main.qml +++ b/main.qml @@ -22,7 +22,6 @@ ApplicationWindow { width: 1310 height: 768 anchors.horizontalCenter: parent.horizontalCenter - // anchors.verticalCenter: parent.verticalCenter initialItem: "Modules.qml" } diff --git a/modules.cpp b/modules.cpp index b210030..b94890d 100644 --- a/modules.cpp +++ b/modules.cpp @@ -15,8 +15,8 @@ Modules::Modules(QObject *parent) : QObject(parent) { Modules::~Modules() { - qDebug() << "Deleting Threads" << endl; - delete sqs_client; + qDebug() << "DESTROYING MODULES" << endl; + sqs_client->closePolling(); } @@ -63,6 +63,7 @@ void Modules::runIntialization() void Modules::intalizeState() { + // Initializing States For View Port if (intialLoad.isClasstime && intialLoad.isCheckedIn) { qDebug() << "ClassTime Is in session and you should be eligible to check in" << endl; emit changeState(1, util.convertStdStringToQString(intialLoad.lastCheckin), util.convertStdStringToQString(intialLoad.lastClasstime), intialLoad.timeRemaining); @@ -79,21 +80,27 @@ void Modules::intalizeState() } - void Modules::activateTimer() { + // Intialized a timer from qt Library activeTimer = new QTimer(this); activeTimer->setInterval(1000); + + // Connect SIGNAL to SLOT + // When timeout is reached, then time will be updated through class connect(activeTimer, SIGNAL(timeout()), this, SLOT(updateTime())); activeTimer->start(); } + bool Modules::readFromFile() { try { LinkedList list; QFile inputFile("user_data.txt"); + QFileInfo fi("user_data.txt"); + qDebug() << fi.path() << endl; if (inputFile.open(QIODevice::ReadOnly)) { QTextStream in(&inputFile); @@ -132,12 +139,18 @@ void Modules::intialize() runIntialization(); } -void Modules::joinClasstime() -{ +//void Modules::joinClasstime() +//{ - sqs_client->closePolling(); - // delete sqs_client; -} +// //Create new thread to wait for closing +// future = QtConcurrent::run(this, &Modules::waitForClosingPollOnThread); + +// watcher.setFuture(future); + +// watcher.waitForFinished(); + +// // delete sqs_client; +//} void Modules::updateTime() { @@ -149,7 +162,7 @@ void Modules::updateTime() void Modules::recievedMessage(QString m) { - qDebug() << "Recieved Message: " << m << endl; + qDebug() << "Recieved Message IN Modules Polling:" << m << endl; if (m == "newClasstime" && intialLoad.isCheckedIn) { emit changeState(1, util.convertStdStringToQString(intialLoad.lastCheckin), util.convertStdStringToQString(intialLoad.lastClasstime), 32323); } else if (m == "newClasstime" && !intialLoad.isCheckedIn) { @@ -176,4 +189,3 @@ void Modules::handleCheckin() } } - diff --git a/modules.h b/modules.h index 1902978..142b2e7 100644 --- a/modules.h +++ b/modules.h @@ -2,7 +2,6 @@ #define MODULES_H #include -#include "dynamoclient.h" #include "lambdaclient.h" #include #include @@ -34,18 +33,18 @@ class Modules : public QObject private: QFutureWatcher watcher; QFuture future; - DynamoClient* dynamo_client; UtilityFunctions util; lambdaClient* lambda_client; userCredentials creds; - void intalizeState(); intitalizeClassroomPayload intialLoad; + void intalizeState(); bool readFromFile(); SqsClient* sqs_client; void runMessageUpdates(); void startPolling( ); void activateTimer(); int timeInSeconds = 0; + void waitForClosingPollOnThread(); QTimer* activeTimer; signals: void changeState(QVariant stateSetting, QVariant classCheck_message, QVariant classTime_message, int timeInSec); @@ -53,7 +52,6 @@ class Modules : public QObject void updateTimer(int timeInSec); public slots: void intialize(); - void joinClasstime(); void updateTime(); void recievedMessage(QString m); void handleCheckin(); diff --git a/qml.qrc b/qml.qrc index 362d35d..789f095 100644 --- a/qml.qrc +++ b/qml.qrc @@ -8,7 +8,6 @@ SetupForm.ui.qml time.svg classtimereal.svg - ../Downloads/cal.svg cal.svg ClasstimeUI.ui.qml Modules.qml diff --git a/setup.cpp b/setup.cpp index 2a9398c..c6f1673 100644 --- a/setup.cpp +++ b/setup.cpp @@ -10,6 +10,8 @@ Setup::Setup(QObject *parent) : QObject(parent) bool Setup::writeToFile(joinClassroomPayload v) { + // Find User_Data in Cached Session Storage + // Temporary Solution... QString filename = "user_data.txt"; QFile file(filename); if (file.open(QIODevice::ReadWrite)) { @@ -28,14 +30,21 @@ void Setup::joinClassroom(QString code, QString name) if (_classCode != "" && _name != "") { emit filledOut(true); + + // String Conversion std::string n = name.toStdString(); std::string c = code.toStdString(); + QString result; + + // String Conversion Aws::String awsName(n.c_str(), n.size()); Aws::String awsCode(c.c_str(), c.size()); bool isDone = false; try { + + // Awaiting Payload joinClassroomPayload res = lambda_client->joinClassroom(awsName, awsCode); if (isDone && res.statusCode == 404) { emit results(false, true); @@ -52,12 +61,10 @@ void Setup::joinClassroom(QString code, QString name) } } catch (std::runtime_error e) { - std::cout << e.what() << std::endl; + qDebug() << e.what() << endl; } - - - } else { + // User Validation emit filledOut(false); } @@ -66,6 +73,7 @@ void Setup::joinClassroom(QString code, QString name) void Setup::restartApplication() { + // This Will Retstart the appllication qApp->quit(); QProcess::startDetached(qApp->arguments()[0], qApp->arguments()); } diff --git a/setup.h b/setup.h index ce89ef6..ba64608 100644 --- a/setup.h +++ b/setup.h @@ -2,7 +2,6 @@ #define SETUP_H #include -#include "dynamoclient.h" #include "lambdaclient.h" #include #include diff --git a/sqsclient.cpp b/sqsclient.cpp index c6ed30d..651943b 100644 --- a/sqsclient.cpp +++ b/sqsclient.cpp @@ -8,28 +8,30 @@ SqsClient::SqsClient(QObject *parent) : QObject(parent) void SqsClient::startPolling(Aws::String queueUrl) { sqsUrl = queueUrl; - future = QtConcurrent::run(this, &SqsClient::start); + future = QtConcurrent::run(this, &SqsClient::start); + watcher.setFuture(future); } SqsClient::~SqsClient() { - qDebug() << "Cancelling Polling Thread" << endl; - future.cancel(); + watcher.waitForFinished(); + qDebug() << "SQS: Cancelling Polling Thread" << endl; } void SqsClient::closePolling() { + qDebug() << "SQS: Closing Polls" << endl; closeThread = true; - if(future.isRunning()) { - qDebug() << "Clean Exit"; - future.waitForFinished(); - } - qDebug() << future.isFinished() << endl; + watcher.waitForFinished(); + qDebug() << "SQS: Is Thread Still Running? " << watcher.isFinished() << endl; } -void SqsClient::start() { +bool SqsClient::start() { + if (closeThread) { + return true; + } Aws::String queue_url = sqsUrl; Aws::SQS::Model::ReceiveMessageRequest rm_req; Aws::SQS::Model::SetQueueAttributesRequest request; @@ -41,41 +43,38 @@ void SqsClient::start() { auto outcome = SetQueueAttributes(request); if (outcome.IsSuccess()) { - std::cout << "Successfully updated long polling time for queue " << + std::cout << "SQS: Successfully updated long polling time for queue " << queue_url << " to " << poll_time << std::endl; } else { - std::cout << "Error updating long polling time for queue " << + std::cout << "SQS: Error updating long polling time for queue " << queue_url << ": " << outcome.GetError().GetMessage() << std::endl; } do { - + if (closeThread) { + break; + } auto rm_out = ReceiveMessage(rm_req); if (!rm_out.IsSuccess()) { - std::cout << "Error receiving message from queue " << queue_url << ": " + std::cout << "SQS: Error receiving message from queue " << queue_url << ": " << rm_out.GetError().GetMessage() << std::endl; - return; + return false; } const auto& messages = rm_out.GetResult().GetMessages(); - if (closeThread) { - break; - } + if (messages.size() == 0) { - - std::cout << "No messages received from queue " << queue_url << - std::endl; } else { const auto& message = messages[0]; @@ -84,8 +83,8 @@ void SqsClient::start() { Aws::String a = message.GetBody(); Aws::Utils::Json::JsonValue bodyObject(message.GetBody()); - std::cout << util.convertAWSStringToStdString(bodyObject.View().GetString("Message")) << std::endl; - qDebug() << "HERE:" << util.convertStdStringToQString( util.convertAWSStringToStdString(bodyObject.View().GetString("Message"))); + + // Emits message to signal emit newMessage( util.convertStdStringToQString( util.convertAWSStringToStdString(bodyObject.View().GetString("Message")))); Aws::SQS::Model::DeleteMessageRequest dm_req; @@ -95,9 +94,9 @@ void SqsClient::start() { auto dm_out = DeleteMessage(dm_req); if (dm_out.IsSuccess()) { - std::cout << "Successfully deleted message " << message.GetMessageId() - << " from queue " << queue_url << std::endl; - } + qDebug() << "Message Deleted" << endl; + // Delete each message from QUEUE. + } else { std::cout << "Error deleting message " << message.GetMessageId() << @@ -110,14 +109,14 @@ void SqsClient::start() { } while (closeThread == false); - return; + return true; } void SqsClient::sendMessage(Aws::String url, Aws::String message) { - + // This is to send a message to confirmation SQS Queue Aws::SQS::Model::SendMessageRequest sm_req; sm_req.SetQueueUrl(url); sm_req.SetMessageBody(message); @@ -137,6 +136,9 @@ void SqsClient::sendMessage(Aws::String url, Aws::String message) void SqsClient::purgeQueue(Aws::String url) { + // We purge the queue so we don't get unnessecary + // Updates from either classtime or automated + // Updates Aws::SQS::Model::PurgeQueueRequest pq_req; pq_req.SetQueueUrl(url); diff --git a/sqsclient.h b/sqsclient.h index 509d6ba..0b0409a 100644 --- a/sqsclient.h +++ b/sqsclient.h @@ -33,23 +33,30 @@ #include #include +// SQS Client is inheriting the AWS Client. We do this, so we +// can create multiple instances depending on what is nessecary for our +// users. class SqsClient : public QObject, public Aws::SQS::SQSClient { Q_OBJECT public: explicit SqsClient(QObject *parent = nullptr); + + // Polling SNS Class topic void startPolling(Aws::String queueUrl); SqsClient(Aws::Client::ClientConfiguration c) : Aws::SQS::SQSClient(c){ }; + // Close Polling ~SqsClient(); void closePolling(); - void start(); + bool start(); void sendMessage(Aws::String url,Aws::String message); void purgeQueue(Aws::String url); private: - QFuture future; + QFuture future; + QFutureWatcher watcher; UtilityFunctions util; Aws::String sqsUrl; bool closeThread = false; diff --git a/utilityfunctions.h b/utilityfunctions.h index 8bccda3..b02bf01 100644 --- a/utilityfunctions.h +++ b/utilityfunctions.h @@ -2,26 +2,22 @@ #define UTILITYFUNCTIONS_H #include -//#include -//#include -//#include -//#include -//#include -//#include #include #include + +// Payload Definitions typedef struct normalPayload { - int statusCode; - std::string bodyResponse; + int statusCode; + std::string bodyResponse; } normalPayload; typedef struct joinClassroomPayload { - int statusCode; - std::string classroomId; - std::string classSNSArn; - std::string bodyResponse; - std::string studentId; - std::string classConfirmationSNSArn; + int statusCode; + std::string classroomId; + std::string classSNSArn; + std::string bodyResponse; + std::string studentId; + std::string classConfirmationSNSArn; } joinClassroomPayload; typedef struct intitalizeClasstimePayload { @@ -44,13 +40,13 @@ typedef struct clastimeUpdatePayload { }clastimeUpdatePayload; typedef struct intitalizeClassroomPayload { - bool isClasstime; - bool isCheckedIn; - std::string bodyResponse; - int statusCode; - std::string lastCheckin; - std::string lastClasstime; - int timeRemaining; + bool isClasstime; + bool isCheckedIn; + std::string bodyResponse; + int statusCode; + std::string lastCheckin; + std::string lastClasstime; + int timeRemaining; } intitalizeClassroomPayload; typedef struct classCheckPayload { @@ -59,6 +55,12 @@ typedef struct classCheckPayload { std::string classCheckMessage; } classCheckPayload; + +typedef struct classaskResponsePayload { + std::string bodyResponse; + int statusCode; +}classaskResponsePayload; + typedef struct userCredentials { Aws::String client_sqs; Aws::String classroomId; @@ -70,7 +72,8 @@ class UtilityFunctions { public: UtilityFunctions(); -// Aws::String convertPayload(Aws::Utils::Json::JsonValue* v, int setting); + + // String Conversation for different namespsaces (AWS, QString, std::string) std::string convertAWSStringToStdString (Aws::String v); QString convertStdStringToQString(std::string v); Aws::String convertStdStringToAWSString(std::string v);