Almost done, just the answer system and query is missing

Took 4 hours 10 minutes
This commit is contained in:
Tobias Hopp 2020-10-02 16:23:04 +02:00
parent c37ad92dbc
commit 8559e3388d
18 changed files with 1569 additions and 87 deletions

19
.idea/dataSources.local.xml generated Normal file
View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="dataSourceStorageLocal">
<data-source name="MariaDB - online-faq@localhost" uuid="65fbffc3-50a7-47a2-a01c-f1ba428cec6e">
<database-info product="MariaDB" version="10.4.14-MariaDB" jdbc-version="4.2" driver-name="MariaDB Connector/J" driver-version="2.6.0" dbms="MARIADB" exact-version="10.4.14" exact-driver-version="2.6">
<extra-name-characters>#@</extra-name-characters>
<identifier-quote-string>`</identifier-quote-string>
</database-info>
<case-sensitivity plain-identifiers="exact" quoted-identifiers="exact" />
<secret-storage>master_key</secret-storage>
<user-name>online-faq</user-name>
<schema-mapping>
<introspection-scope>
<node kind="schema" qname="@" />
</introspection-scope>
</schema-mapping>
</data-source>
</component>
</project>

11
.idea/dataSources.xml generated Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="MariaDB - online-faq@localhost" uuid="65fbffc3-50a7-47a2-a01c-f1ba428cec6e">
<driver-ref>mariadb</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>org.mariadb.jdbc.Driver</jdbc-driver>
<jdbc-url>jdbc:mariadb://localhost:3306/online-faq</jdbc-url>
</data-source>
</component>
</project>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,2 @@
#n:information_schema
!<md> [null, 0, null, null, -2147483648, -2147483648]

114
.idea/workspace.xml generated
View File

@ -20,56 +20,20 @@
</component>
<component name="ChangeListManager">
<list default="true" id="fc13552d-b118-4828-b78f-fc8714e0cfdc" name="Default Changelist" comment="">
<change afterPath="$PROJECT_DIR$/.idea/jsLibraryMappings.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/php.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/classes/Api.class.inc.php" afterDir="false" />
<change afterPath="$PROJECT_DIR$/config.inc.php" afterDir="false" />
<change afterPath="$PROJECT_DIR$/controller/FaqController.class.inc.php" afterDir="false" />
<change afterPath="$PROJECT_DIR$/model/FaqModel.class.inc.php" afterDir="false" />
<change afterPath="$PROJECT_DIR$/templates/faq.tmpl.html" afterDir="false" />
<change afterPath="$PROJECT_DIR$/templates/start.tmpl.html" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/css/bootstrap-grid.css" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/css/bootstrap-grid.css.map" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/css/bootstrap-grid.min.css" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/css/bootstrap-grid.min.css.map" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/css/bootstrap-reboot.css" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/css/bootstrap-reboot.css.map" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/css/bootstrap-reboot.min.css" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/css/bootstrap-reboot.min.css.map" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/css/bootstrap.css" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/css/bootstrap.css.map" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/css/bootstrap.min.css" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/css/bootstrap.min.css.map" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/css/default.css" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/css/sticky-footer-navbar.css" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/js/bootstrap.bundle.js" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/js/bootstrap.bundle.js.map" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/js/bootstrap.bundle.min.js" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/js/bootstrap.bundle.min.js.map" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/js/bootstrap.js" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/js/bootstrap.js.map" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/js/bootstrap.min.js" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/js/bootstrap.min.js.map" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/js/jquery-3.5.1.min.js" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/js/start.js" afterDir="false" />
<change afterPath="$PROJECT_DIR$/views/Apitemplate.class.inc.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/codeStyles/codeStyleConfig.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/codeStyles/codeStyleConfig.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/modules.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/modules.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/online-faq.iml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/online-faq.iml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/vcs.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/LICENSE" beforeDir="false" afterPath="$PROJECT_DIR$/LICENSE" afterDir="false" />
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
<change beforePath="$PROJECT_DIR$/SECURITY.md" beforeDir="false" afterPath="$PROJECT_DIR$/SECURITY.md" afterDir="false" />
<change beforePath="$PROJECT_DIR$/classes/Autoloader.class.inc.php" beforeDir="false" afterPath="$PROJECT_DIR$/classes/Autoloader.class.inc.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/classes/Database.class.inc.php" beforeDir="false" afterPath="$PROJECT_DIR$/classes/Database.class.inc.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/classes/Factory.class.inc.php" beforeDir="false" afterPath="$PROJECT_DIR$/classes/Factory.class.inc.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/classes/Request.class.inc.php" beforeDir="false" afterPath="$PROJECT_DIR$/classes/Request.class.inc.php" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/dataSources.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/vendor/js/faq.js" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/classes/Api.class.inc.php" beforeDir="false" afterPath="$PROJECT_DIR$/classes/Api.class.inc.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/config.inc.php" beforeDir="false" afterPath="$PROJECT_DIR$/config.inc.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/controller/DefaultController.class.inc.php" beforeDir="false" afterPath="$PROJECT_DIR$/controller/DefaultController.class.inc.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/controller/FaqController.class.inc.php" beforeDir="false" afterPath="$PROJECT_DIR$/controller/FaqController.class.inc.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/index.php" beforeDir="false" afterPath="$PROJECT_DIR$/index.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/main.inc.php" beforeDir="false" afterPath="$PROJECT_DIR$/main.inc.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/model/DefaultModel.class.inc.php" beforeDir="false" afterPath="$PROJECT_DIR$/model/DefaultModel.class.inc.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/test.tmpl.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/test.tmpl.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/views/Template.class.inc.php" beforeDir="false" afterPath="$PROJECT_DIR$/views/Template.class.inc.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/model/FaqModel.class.inc.php" beforeDir="false" afterPath="$PROJECT_DIR$/model/FaqModel.class.inc.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/faq.tmpl.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/faq.tmpl.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/start.tmpl.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/start.tmpl.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/views/Apitemplate.class.inc.php" beforeDir="false" afterPath="$PROJECT_DIR$/views/Apitemplate.class.inc.php" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -80,7 +44,7 @@
<execution />
</component>
<component name="DarkyenusTimeTracker">
<option name="totalTimeSeconds" value="8993" />
<option name="totalTimeSeconds" value="24012" />
<option name="gitIntegration" value="true" />
<option name="naggedAbout" value="1" />
</component>
@ -102,11 +66,13 @@
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="DatabaseDriversLRU" value="mysql&#10;mariadb" />
<property name="DefaultHtmlFileTemplate" value="HTML File" />
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/templates" />
<property name="list.type.of.created.stylesheet" value="CSS" />
<property name="settings.editor.selected.configurable" value="reference.settingsdialog.IDE.editor.colors.Database" />
<property name="vue.rearranger.settings.migration" value="true" />
</component>
<component name="RecentsManager">
@ -122,7 +88,7 @@
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1601618466935</updated>
<workItem from="1601618467981" duration="9245000" />
<workItem from="1601618467981" duration="26007000" />
</task>
<task id="LOCAL-00001" summary="Initial commit">
<created>1601618764031</created>
@ -131,7 +97,14 @@
<option name="project" value="LOCAL" />
<updated>1601618764031</updated>
</task>
<option name="localTasksCounter" value="2" />
<task id="LOCAL-00002" summary="Stunden ende, einiges fertig, fehlt nicht mehr viel">
<created>1601628069096</created>
<option name="number" value="00002" />
<option name="presentableId" value="LOCAL-00002" />
<option name="project" value="LOCAL" />
<updated>1601628069096</updated>
</task>
<option name="localTasksCounter" value="3" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
@ -150,9 +123,34 @@
</component>
<component name="VcsManagerConfiguration">
<MESSAGE value="Initial commit" />
<option name="LAST_COMMIT_MESSAGE" value="Initial commit" />
<MESSAGE value="Stunden ende, einiges fertig, fehlt nicht mehr viel" />
<option name="LAST_COMMIT_MESSAGE" value="Stunden ende, einiges fertig, fehlt nicht mehr viel" />
</component>
<component name="WindowStateProjectService">
<state x="728" y="326" width="800" height="683" key="#com.intellij.execution.impl.EditConfigurationsDialog" timestamp="1601632929047">
<screen x="0" y="34" width="1920" height="1046" />
</state>
<state x="728" y="326" width="800" height="683" key="#com.intellij.execution.impl.EditConfigurationsDialog/0.34.1920.1046@0.34.1920.1046" timestamp="1601632929047" />
<state x="200" y="354" width="550" height="412" key="#com.intellij.fileTypes.FileTypeChooser" timestamp="1601642830817">
<screen x="0" y="34" width="1920" height="1046" />
</state>
<state x="200" y="354" width="550" height="412" key="#com.intellij.fileTypes.FileTypeChooser/0.34.1920.1046@0.34.1920.1046" timestamp="1601642830817" />
<state width="616" height="272" key="GridCell.Tab.0.bottom" timestamp="1601643582372">
<screen x="0" y="34" width="1920" height="1046" />
</state>
<state width="616" height="272" key="GridCell.Tab.0.bottom/0.34.1920.1046@0.34.1920.1046" timestamp="1601643582372" />
<state width="616" height="272" key="GridCell.Tab.0.center" timestamp="1601643582369">
<screen x="0" y="34" width="1920" height="1046" />
</state>
<state width="616" height="272" key="GridCell.Tab.0.center/0.34.1920.1046@0.34.1920.1046" timestamp="1601643582369" />
<state width="616" height="272" key="GridCell.Tab.0.left" timestamp="1601643582368">
<screen x="0" y="34" width="1920" height="1046" />
</state>
<state width="616" height="272" key="GridCell.Tab.0.left/0.34.1920.1046@0.34.1920.1046" timestamp="1601643582368" />
<state width="616" height="272" key="GridCell.Tab.0.right" timestamp="1601643582370">
<screen x="0" y="34" width="1920" height="1046" />
</state>
<state width="616" height="272" key="GridCell.Tab.0.right/0.34.1920.1046@0.34.1920.1046" timestamp="1601643582370" />
<state x="1066" y="308" width="499" height="596" key="NewPhpClassDialog" timestamp="1601624640212">
<screen x="0" y="34" width="1920" height="1046" />
</state>
@ -161,17 +159,25 @@
<screen x="0" y="34" width="1920" height="1046" />
</state>
<state x="755" y="479" width="399" height="161" key="NewPhpFileDialog/0.34.1920.1046@0.34.1920.1046" timestamp="1601618925778" />
<state x="555" y="292" width="800" height="535" key="Vcs.Push.Dialog.v2" timestamp="1601618765171">
<state x="441" y="192" width="1037" height="736" key="SettingsEditor" timestamp="1601632853044">
<screen x="0" y="34" width="1920" height="1046" />
</state>
<state x="555" y="292" width="800" height="535" key="Vcs.Push.Dialog.v2/0.34.1920.1046@0.34.1920.1046" timestamp="1601618765171" />
<state x="441" y="192" width="1037" height="736" key="SettingsEditor/0.34.1920.1046@0.34.1920.1046" timestamp="1601632853044" />
<state x="555" y="292" width="800" height="535" key="Vcs.Push.Dialog.v2" timestamp="1601628070210">
<screen x="0" y="34" width="1920" height="1046" />
</state>
<state x="555" y="292" width="800" height="535" key="Vcs.Push.Dialog.v2/0.34.1920.1046@0.34.1920.1046" timestamp="1601628070210" />
<state x="809" y="122" width="639" height="876" key="com.intellij.database.view.ui.AbstractDbRefactoringDialog" timestamp="1601632983240">
<screen x="0" y="34" width="1920" height="1046" />
</state>
<state x="809" y="122" width="639" height="876" key="com.intellij.database.view.ui.AbstractDbRefactoringDialog/0.34.1920.1046@0.34.1920.1046" timestamp="1601632983240" />
<state x="739" y="469" width="432" height="182" key="com.intellij.openapi.vcs.update.UpdateOrStatusOptionsDialogupdate-v2" timestamp="1601624836751">
<screen x="0" y="34" width="1920" height="1046" />
</state>
<state x="739" y="469" width="432" height="182" key="com.intellij.openapi.vcs.update.UpdateOrStatusOptionsDialogupdate-v2/0.34.1920.1046@0.34.1920.1046" timestamp="1601624836751" />
<state x="623" y="264" width="672" height="678" key="search.everywhere.popup" timestamp="1601628017554">
<state x="623" y="264" width="672" height="678" key="search.everywhere.popup" timestamp="1601644839580">
<screen x="0" y="34" width="1920" height="1046" />
</state>
<state x="623" y="264" width="672" height="678" key="search.everywhere.popup/0.34.1920.1046@0.34.1920.1046" timestamp="1601628017554" />
<state x="623" y="264" width="672" height="678" key="search.everywhere.popup/0.34.1920.1046@0.34.1920.1046" timestamp="1601644839580" />
</component>
</project>

View File

@ -11,7 +11,7 @@ class Api
*/
public static function getRequest()
{
self::$request = json_decode( file_get_contents('php://input') );
self::$request = json_decode( file_get_contents('php://input'), true );
return true;
}

View File

@ -4,4 +4,7 @@
define( 'MYSQL_HOST', 'localhost' );
define( 'MYSQL_USER', 'online-faq' );
define( 'MYSQL_PASS', 'RnKVJHcUBIIu1XM2' );
define( 'MYSQL_DB', 'online-faq' );
define( 'MYSQL_DB', 'online-faq' );
define( 'CODE_LENGTH', 4 );
define( 'WASTED_TIME', '5hrs and 51min' );

View File

@ -14,6 +14,15 @@ class DefaultController
public function indexAction()
{
$view = new Template( 'start' );
$Request = new Request();
$view->set_placeholder( 'max_len', CODE_LENGTH );
$view->set_placeholder( 'wasted_time', WASTED_TIME );
$reason = $Request->getVar( 'rsn', false, 'GET' );
if( $reason !== false )
{
$view->set_placeholder( 'error', $reason );
}
// Return the HTML Code to the index.php
return $view->getHtml();
@ -31,7 +40,10 @@ class DefaultController
$Request = new Request();
$room_code = $Request->getVar( 'code', null, 'GET' );
$view->set_placeholder( 'max_len', CODE_LENGTH );
$view->set_placeholder( 'wasted_time', WASTED_TIME );
$room_code = mb_strtoupper( $Request->getVar( 'code', null, 'POST' ) );
if( empty( $room_code ) && !isset( $room_code ) )
{
@ -47,7 +59,7 @@ class DefaultController
if( !$DefaultModel->joinRoom( $room_id ) )
{
$view->set_placeholder( 'error', 'An error occured, please try again later!' );
$view->set_placeholder( 'error', 'An error occurred, please try again later!' );
return $view->getHtml();
}
@ -68,14 +80,24 @@ class DefaultController
$DefaultModel = new DefaultModel();
$Request = new Request();
$room_name = $Request->getVar( 'room-name' );
$view->set_placeholder( 'max_len', CODE_LENGTH );
$view->set_placeholder( 'wasted_time', WASTED_TIME );
$room_name = $Request->getVar( 'room-name', '', 'POST' );
if( !$DefaultModel->createRoom( $room_name ) )
if( empty( $room_name ) || strlen( $room_name) > 15 || strlen( $room_name ) < 3 )
{
$view->set_placeholder( 'error', 'An error occured, please try again later!' );
$view->set_placeholder( 'error', 'The Room-Name must contain 3-15 characters!' );
return $view->getHtml();
}
if( ( $id = $DefaultModel->createRoom( $room_name ) ) === false )
{
$view->set_placeholder( 'error', 'An error occurred, please try again later!' );
return $view->getHtml();
}
$DefaultModel->joinRoom( $id );
return $view->getHtml();
}

View File

@ -10,6 +10,8 @@ class FaqController extends DefaultController
$room = $FAQModel->getRoom();
$view->set_placeholder( 'room_name', $room['name'] );
$view->set_placeholder( 'room_code', $room['code'] );
$view->set_placeholder( 'wasted_time', WASTED_TIME );
return $view->getHtml();
}
@ -34,12 +36,20 @@ class FaqController extends DefaultController
$room = $FAQModel->getRoom();
$question = Api::getVar( 'question' );
if( empty( $question ) || strlen( $question ) > 500 || strlen( $question ) < 10 )
{
$view->setSuccess( false );
$view->setHeaderCode( 903 );
return $view->getResponse();
}
try {
$FAQModel->addQuestion( $room, $question );
$FAQModel->addQuestion( $room['id'], $question );
} catch( Exception $e )
{
$view->setSuccess( false );
$view->setHeaderCode( 901 );
$view->setResponse( array( $e->getMessage() ));
return $view->getResponse();
}

View File

@ -22,5 +22,6 @@ try
catch ( Exception $e )
{
# Please replace it with error template
die( 'An internal error occured while processing your request.' );
echo $e->getMessage();
die( 'An internal error occurred in part 0 while processing your request.' );
}

View File

@ -33,5 +33,5 @@ try
catch ( Exception $e )
{
# Error occured, please replace it with error template
die( 'An internal error occured while proccessing your request' );
die( 'An internal error occurred in part 1 while processing your request' );
}

View File

@ -32,14 +32,26 @@ class DefaultModel
public function createRoom(string $room_name)
{
$room_owner = session_id();
$stmnt = Database::getConnection()->prepare( 'INSERT INTO rooms ( name, owner, code ) VALUES ( :name, :owner, :code )' );
$stmnt->execute( array( 'name' => $room_name, 'owner' => $room_owner, 'code' => $this->generateRandomStr() ) );
$stmnt = Database::getConnection()->prepare( 'INSERT INTO rooms ( name, owner_sid, code ) VALUES ( :name, :owner, :code )' );
$stmnt->execute( array( 'name' => $room_name, 'owner' => $room_owner, 'code' => $this->generateRandomStr( CODE_LENGTH ) ) );
$id = Database::getConnection()->lastInsertId( );
if( empty( $id ) )
{
return false;
}
return $id;
}
public function generateRandomStr( $length = 4 )
{
return 'U2HA';
$characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}

View File

@ -56,14 +56,14 @@ class FaqModel
return $result['id'];
}
public function addQuestion(int $room_id, bool $question)
public function addQuestion(int $room_id, string $question)
{
$stmnt = Database::getConnection()->prepare( 'INSERT INTO questions ( room_id, question, created_by ) VALUES ( :room_id, :question, :created_by )' );
$stmnt->execute( array( 'room_id' => $room_id, $question, 'Anonymous' ) );
$stmnt->execute( array( 'room_id' => $room_id, 'question' => $question, 'created_by' => 'Anonymous' ) );
}
public function addAnswer(int $question_id, bool $answer)
public function addAnswer(int $question_id, string $answer)
{
$stmnt = Database::getConnection()->prepare( 'UPDATE questions SET answer = :answer WHERE id = :id' );
$stmnt->execute( array( 'answer' => $answer, 'id' => $question_id ) );

View File

@ -56,21 +56,100 @@
</nav>
</header>
<div class="modal fade" id="askQuestionModal" tabindex="-1" role="dialog" aria-labelledby="askQuestionModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="askQuestionModalLabel">Ask a question</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<span class="text-danger" id="askErrorMsg"></span>
<div class="form-group">
<label for="question" class="col-form-label">Question</label>
<textarea name="question" class="form-control" id="question" maxlength="500" rows="4"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button type="button" id="askBtn" class="btn btn-primary" onclick="askQuestion();">Ask</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="answerModal" tabindex="-1" role="dialog" aria-labelledby="answerModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="answerModalLabel">Answer a question</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<span class="text-danger" id="answerErrorMsg"></span>
<div class="form-group">
<label for="answer" class="col-form-label">Answer</label>
<textarea name="answer" class="form-control" id="answer" maxlength="500" rows="4"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button type="button" id="answerBtn" class="btn btn-primary" onclick="answer();">Answer</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="errorModal" tabindex="-1" role="dialog" aria-labelledby="errorModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title text-danger" id="errorModalLabel">Error</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<span id="errorMsg"></span>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<!-- Begin page content -->
<main role="main" class="flex-shrink-0">
<div class="container">
<h1 class="mt-5">Online-FAQ</h1>
<p class="lead">Room [[ROOM_NAME]]</p>
<br>
<div class="row">
<div class="col-lg>">
<p class="lead">Room <span class="text-info">[[ROOM_NAME]]</span> -
Code <span class="text-info">[[ROOM_CODE]]</span></p>
</div>
<br>
<div class="col-lg">
<button type="button" class="btn btn-primary float-right" data-toggle="modal" data-target="#askQuestionModal">Ask a question</button>
</div>
</div>
</div>
<div id="questions">
<div class="container">
<div class="row" id="questions">
</div>
</div>
</main>
<footer class="footer mt-auto py-3">
<div class="container">
<span class="text-muted">Online-FAQ<br>Programmed by Tobias Hopp</span>
<span class="text-muted">Online-FAQ<br>Programmed by Tobias Hopp<br><br>Already wasted [[WASTED_TIME]] on this project!</span>
</div>
</footer>
<script src="vendor/js/jquery-3.5.1.min.js"></script>

View File

@ -48,8 +48,8 @@
<a class="nav-link" href="#" data-toggle="modal" data-target="#createFAQModal">Create new FAQ</a>
</li>
</ul>
<form class="form-inline mt-2 mt-md-0" action="?c=default&a=JoinFAQ" method="get">
<input class="form-control mr-sm-2" type="text" name="code" placeholder="FAQ-Code" aria-label="Join">
<form class="form-inline mt-2 mt-md-0" action="?c=default&a=JoinFAQ" method="post">
<input class="form-control mr-sm-2" type="text" maxlength="[[MAX_LEN]]" name="code" placeholder="FAQ-Code" aria-label="Join">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Join FAQ</button>
</form>
</div>
@ -63,21 +63,19 @@
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="createFAQModalLabel">Create a FAQ</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form>
<form action="?c=default&a=createFAQ" method="post" id="createFAQ">
<div class="form-group">
<label for="room-name" class="col-form-label">Custom Room-Name:</label>
<input type="text" class="form-control" id="room-name">
<input type="text" name="room-name" class="form-control" id="room-name">
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Create</button>
<button type="button" class="btn btn-primary" onclick="$('#createFAQ').submit();">Create</button>
</div>
</div>
</div>
@ -94,13 +92,14 @@
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#createFAQModal">Create an FAQ</button>
</div>
<div class="col-lg">
<form class="form-inline mt-2 mt-md-0" action="?c=default&a=JoinFAQ" method="get">
<input class="form-control mr-sm-2" type="text" name="code" placeholder="FAQ-Code" aria-label="Join">
<form class="form-inline mt-2 mt-md-0" action="?c=default&a=JoinFAQ" method="post">
<input class="form-control mr-sm-2" type="text" maxlength="[[MAX_LEN]]" name="code" placeholder="FAQ-Code" aria-label="Join">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Join FAQ</button>
</form>
</div>
</div>
<br>
<h4 style="color:red">[[ERROR]]</h4>
</div>
<br><br>
@ -111,7 +110,7 @@
<footer class="footer mt-auto py-3">
<div class="container">
<span class="text-muted">Online-FAQ<br>Programmed by Tobias Hopp</span>
<span class="text-muted">Online-FAQ<br>Programmed by Tobias Hopp<br><br>Already wasted [[WASTED_TIME]] on this project!</span>
</div>
</footer>
<script src="vendor/js/jquery-3.5.1.min.js"></script>

191
vendor/js/faq.js vendored Normal file
View File

@ -0,0 +1,191 @@
errorModal = $( '#errorModal' );
askQuestionModal = $( '#askQuestionModal' );
readMoreModal = $( '#readMoreModal' );
answerModal = $( '#answerModal' );
answerText = $('#answer' );
answerModalTitle = $('#answerModalTitle');
readMoreModalText = $('#readMoreModalText' );
readMoreModalTitle = $('#readMoreModalTitle' );
errorMsg = $( '#errorMsg' );
askErrorMsg = $('#askErrorMsg')
answerErrorMsg = $('#answerErrorMsg' );
questions = $( '#questions' )
question = $('#question' );
askButton = $('#askBtn' );
function request( a_uri, a_data, a_successhandler, a_errorhandler )
{
$.ajax(
{
url: "?c=Faq&a=" + a_uri,
type: 'POST',
data: JSON.stringify( a_data ),
dataType: 'json',
success: function (result)
{
a_successhandler(result);
},
error: function ( result, errorcode )
{
if( errorcode === "parseerror" )
{
$('.modal').modal( 'hide' );
setTimeout( function(){
$('.modal').modal('hide');
errorMsg.html( 'The action was not successfully.<br>Our server sent a weird response. Cannot parse this shit lmao' );
errorModal.modal( 'show' );
askButton.prop( 'disabled', false );
}, 500 );
}
a_errorhandler( result, errorcode );
},
});
}
function askQuestion()
{
askButton.prop( 'disabled', true );
if ( !question.val() )
{
askErrorMsg.html( 'Please enter a question first!' );
askButton.prop( 'disabled', false );
return;
}
if( question.val().length > 500 || question.val().length < 10 )
{
askErrorMsg.html( 'The question should be 15-50 characters long.' );
askButton.prop( 'disabled', false );
return;
}
request( 'addQuestion', {"question":question.val()},
function( result ){
askErrorMsg.html( '' );
askButton.prop( 'disabled', false );
askQuestionModal.modal( 'hide' );
}, function( result ) {
askButton.prop( 'disabled', false );
switch( result.status )
{
case 901:
case 902:
askErrorMsg.html( "Something wrong happened. We don't know why...<br>Try again later please!" );
break;
case 903:
askErrorMsg.html( "The question should contain at least 10 up to 500 characters!<br>Just not romans, but also not just 'help'." );
break;
default:
$('.modal').modal('hide');
setTimeout( function( result ){
errorMsg.html( "The action was not successfully.<br>Maybe the room doesn't exist anymore.<br>Also may check your internet connection." );
errorModal.modal( 'show' );
}, 500 );
}
}
);
}
function openReadMoreModal( id )
{
readMoreModal.modal( 'show' );
readMoreModalText.html( 'Loading...' );
readMoreModalTitle.html( 'Question from: Anonymous' );
request( 'getQuestion', {"id":id}, function( result )
{
readMoreModalTitle.html( 'Question from: ' + result.data.created_by );
readMoreModalText.html( result.data.question );
}, function() {
readMoreModalText.html( 'An error occurred, please try again later!' );
});
}
let answer_id = 0;
function openAnswerModal( id )
{
answerModalTitle.html( 'Answer ' + 'Anonymous' + " question" );
answerErrorMsg.html( '' );
answerModal.modal( 'show' );
request( 'getQuestion', {"id":id}, function( result )
{
readMoreModalTitle.html( 'Answer ' + result.data.created_by + " question" );
answer_id = result.data.id;
}, function() {
answerErrorMsg.html( 'An error occurred, please try again!' );
});
}
function answer()
{
answerErrorMsg.html( '' );
if( answer_id === 0 )
{
return;
}
if( answerText.val().length < 5 || answerText.val().length > 500 )
{
answerErrorMsg.html( 'The answer should contain 10-500 characters!' );
return;
}
request( 'addAnswer', {"question_id":answer_id,"answer":answerText.val()}, function( result )
{
answerErrorMsg.html( '' );
answerModal.modal( 'hide' );
}, function() {
answerErrorMsg.html( 'An error occurred. Please try again later!' );
});
}
function getQuestions()
{
request( 'getQuestions', {}, function (result)
{
let questions_list = [];
for (let i = 0; i < result.data.questions.length; i++)
{
questions_list.push( 'q_' + result.data.questions[i].id );
if( $('#q_' + result.data.questions[i].id ).length < 1 )
{
questions.append( '<div class="col-sm-6 col-lg-4 col-md-5"><div class="card" id="q_' + result.data.questions[i].id + '" style=" margin-bottom: 10px;">' +
' <div class="card-body">' +
' <h5 class="card-title">Subject</h5>' +
' <h6 class="card-subtitle mb-2 text-muted">Creator</h6>' +
' <p class="card-text">Text up to 100 characters</p>' +
' <a onclick="openReadMoreModal(\''+ result.data.questions[i].id + '\');" class="card-link">Read more</a>' +
' <a onclick="openAnswerModal(\'' + result.data.questions[i].id + '\');" class="card-link">Answer</a>' +
' </div>' +
' </div>' +
'</div> ' )
}
}
/* FIX! $('#questions').children('div').forEach( function()
{
if( jQuery.inArray( this.id, questions_list ) === -1 )
{
$(this).remove();
}
} );*/
},
function ( result )
{
}
);
}
getQuestions();

9
vendor/js/sd vendored Normal file
View File

@ -0,0 +1,9 @@
<div class="card" style="width: 18rem;">
<div class="card-body">
<h5 class="card-title">Subject</h5>
<h6 class="card-subtitle mb-2 text-muted">Creator</h6>
<p class="card-text">Text up to 100 characters</p>
<a href="#" data-target="readMoreModal" data-toggle="modal" class="card-link">Read more</a>
<a href="#" data-target="answerModal" data-toggle="modal" class="card-link">Answer</a>
</div>
</div>

View File

@ -30,7 +30,15 @@ class Apitemplate
public function setHeaderCode( $a_code )
{
header("HTTP/1.1 $a_code" );
$codes = array(
500 => 'Internal Server error',
901 => 'Question-cannot-be-asked',
902 => 'Answer-cannot-be-set',
903 => 'wrong-parameters-given',
905 => 'User-is-not-owner',
);
$text = isset( $codes[$a_code] ) ? $codes[$a_code] : "Error";
header("HTTP/1.1 $a_code $text" );
}
public function setSuccess( bool $a_success )