diff --git a/CMakeLists.txt b/CMakeLists.txt index eb38d5d..f3f05e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,11 +19,16 @@ option(BUILD_IDHAN_CLIENT "Builds the shared library for the IDHANClient" ON) option(BUILD_IDHAN_TESTS "Builds all tests relating to IDHAN" ON) option(BUILD_HYDRUS_IMPORTER "Builds the hydrus importer" ON) option(BUILD_IDHAN_DOCS "Builds the API and source docs" ON) +option(BUILD_IDHAN_WEBUI "Builds the WASM WebUI for IDHAN server" ON) if (BUILD_HYDRUS_IMPORTER) set(BUILD_IDHAN_CLIENT ON) endif () +if (BUILD_IDHAN_WEBUI) + set(BUILD_IDHAN_SERVER ON) +endif () + set(CMAKE_POSITION_INDEPENDENT_CODE ON) #IDHANServer/IDHANClient @@ -38,6 +43,40 @@ add_subdirectory(tools/TagEditor) add_subdirectory(docs) +if (BUILD_IDHAN_WEBUI) + include(ExternalProject) + + if (NOT DEFINED QT_WASM) + message(FATAL_ERROR "You must define QT_WASM during cmake config") + endif () + + set(EMSDK ${QT_WASM}/emsdk) + + find_program(QTCMAKE_EXECUTABLE qt-cmake + PATHS "${QT_WASM}/bin" + NO_DEFAULT_PATH) + + set(WEBUI_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/IDHANWebUI) + set(WEBUI_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/IDHANWebUI) + + ExternalProject_Add( + IDHANWebUI_WASM + SOURCE_DIR ${WEBUI_SOURCE_DIR} + BINARY_DIR ${WEBUI_BUILD_DIR} + CONFIGURE_COMMAND ${QTCMAKE_EXECUTABLE} + -S ${WEBUI_SOURCE_DIR} + -B ${WEBUI_BUILD_DIR} + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DWASM_OUT_DIR=${CMAKE_CURRENT_BINARY_DIR}/bin/static + BUILD_COMMAND ${CMAKE_COMMAND} --build ${WEBUI_BUILD_DIR} + INSTALL_COMMAND "" + BUILD_ALWAYS YES + ) + + add_custom_target(IDHANWebUIFiles DEPENDS ${WEBUI_FILES_OUTPUT}) + add_dependencies(IDHANServer IDHANWebUI_WASM IDHANWebUIFiles) +endif () + if (BUILD_IDHAN_TESTS) #IDHANTests add_subdirectory(tests) diff --git a/IDHANServer/CMakeLists.txt b/IDHANServer/CMakeLists.txt index 3d7e551..a866893 100644 --- a/IDHANServer/CMakeLists.txt +++ b/IDHANServer/CMakeLists.txt @@ -39,7 +39,7 @@ endif () # Copy page info to the output directory -file(GLOB_RECURSE PAGE_FILES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/pages/*") +file(GLOB_RECURSE PAGE_FILES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/static/*") set(PAGE_OUTPUTS "") foreach (PAGE ${PAGE_FILES}) @@ -99,4 +99,8 @@ add_custom_command( add_custom_target(IDHANConfig DEPENDS ${CONFIG_OUTPUT}) add_dependencies(IDHANServer IDHANConfig) -add_dependencies(IDHANServer IDHANPremadeModules) \ No newline at end of file +add_dependencies(IDHANServer IDHANPremadeModules) + +if (DEFINED IDHAN_WEBUI AND IDHAN_WEBUI EQUAL ON) + add_dependencies(IDHANServer IDHANWebUI) +endif () \ No newline at end of file diff --git a/IDHANServer/src/ServerContext.cpp b/IDHANServer/src/ServerContext.cpp index e2a37e8..321a298 100644 --- a/IDHANServer/src/ServerContext.cpp +++ b/IDHANServer/src/ServerContext.cpp @@ -31,7 +31,7 @@ void ServerContext::setupCORSSupport() const if ( args.testmode ) log::info( "Handling query: {}:{}", request->getMethodString(), request->getPath() ); else - log::debug( "Handling query: {}:{}", request->getMethodString(), request->getPath() ); + log::info( "Handling query: {}:{}", request->getMethodString(), request->getPath() ); if ( !request->path().starts_with( "/hyapi" ) || request->method() != drogon::Options ) { @@ -146,10 +146,14 @@ ServerContext::ServerContext( const ConnectionArguments& arguments ) : .setLogLevel( trantor::Logger::kInfo ) .setThreadNum( io_threads ) .setClientMaxBodySize( std::numeric_limits< std::uint64_t >::max() ) - .setDocumentRoot( "./pages" ) + .setDocumentRoot( "./static" ) .setExceptionHandler( exceptionHandler ) .setLogPath( std::string( log_directory ), "", 1024 * 1024 * 1024, 8, true ); + app.registerCustomExtensionMime( "wasm", "application/wasm" ); + + app.setFileTypes( { "html", "wasm", "svg", "js", "png", "jpg" } ); + if ( true ) { app.addListener( "127.0.0.1", IDHAN_DEFAULT_PORT ); diff --git a/IDHANServer/src/api/Ui.cpp b/IDHANServer/src/api/Ui.cpp new file mode 100644 index 0000000..a76aeaf --- /dev/null +++ b/IDHANServer/src/api/Ui.cpp @@ -0,0 +1,14 @@ +// +// Created by kj16609 on 7/28/25. +// +#include "Ui.hpp" + +namespace idhan +{ + +drogon::Task< drogon::HttpResponsePtr > Ui::index( drogon::HttpRequestPtr ) +{ + co_return drogon::HttpResponse::newFileResponse( "./static/IDHANWebUI.html" ); +} + +} // namespace idhan \ No newline at end of file diff --git a/IDHANServer/src/api/Ui.hpp b/IDHANServer/src/api/Ui.hpp new file mode 100644 index 0000000..460ddcb --- /dev/null +++ b/IDHANServer/src/api/Ui.hpp @@ -0,0 +1,23 @@ +// +// Created by kj16609 on 7/28/25. +// +#pragma once +#include + +namespace idhan +{ + +class Ui : public drogon::HttpController< Ui > +{ + drogon::Task< drogon::HttpResponsePtr > index( drogon::HttpRequestPtr ); + + public: + + METHOD_LIST_BEGIN + + ADD_METHOD_TO( Ui::index, "/" ); + + METHOD_LIST_END +}; + +} // namespace idhan \ No newline at end of file diff --git a/IDHANServer/src/api/docs.cpp b/IDHANServer/src/api/docs.cpp index 4b079b0..4956ff6 100644 --- a/IDHANServer/src/api/docs.cpp +++ b/IDHANServer/src/api/docs.cpp @@ -17,31 +17,12 @@ void IDHANApi::apiDocs( const drogon::HttpRequestPtr& request, ResponseFunction& // log::info( "Attempted to get {}", path ); - callback( drogon::HttpResponse::newFileResponse( "./pages" + path ) ); + callback( drogon::HttpResponse::newFileResponse( "./static" + path ) ); } void IDHANApi::api( const drogon::HttpRequestPtr& request, ResponseFunction&& callback ) { - if ( auto ifs = std::ifstream( "./pages/apidocs.html", std::ios::ate ); ifs ) - { - const std::streamoff size { ifs.tellg() }; - ifs.seekg( 0, std::ios::beg ); - - std::string str {}; - str.resize( static_cast< std::size_t >( size ) ); - ifs.read( str.data(), size ); - - // create http response - const auto response { drogon::HttpResponse::newHttpResponse() }; - response->setContentTypeCode( drogon::ContentType::CT_TEXT_HTML ); - - response->setBody( str ); - - callback( response ); - return; - } - - callback( createInternalError( "API docs not provided" ) ); + callback( drogon::HttpResponse::newFileResponse( "./static/apidocs.html" ) ); } } // namespace idhan::api diff --git a/IDHANServer/src/pages/Titorv2.png b/IDHANServer/src/static/Titorv2.png similarity index 100% rename from IDHANServer/src/pages/Titorv2.png rename to IDHANServer/src/static/Titorv2.png diff --git a/IDHANServer/src/pages/apidocs.html b/IDHANServer/src/static/apidocs.html similarity index 100% rename from IDHANServer/src/pages/apidocs.html rename to IDHANServer/src/static/apidocs.html diff --git a/IDHANServer/src/pages/index.html b/IDHANServer/src/static/index.html similarity index 100% rename from IDHANServer/src/pages/index.html rename to IDHANServer/src/static/index.html diff --git a/IDHANServer/src/pages/sunburst.html b/IDHANServer/src/static/sunburst.html similarity index 100% rename from IDHANServer/src/pages/sunburst.html rename to IDHANServer/src/static/sunburst.html diff --git a/IDHANWebUI/CMakeLists.txt b/IDHANWebUI/CMakeLists.txt new file mode 100644 index 0000000..c66afac --- /dev/null +++ b/IDHANWebUI/CMakeLists.txt @@ -0,0 +1,44 @@ +cmake_minimum_required(VERSION 3.16) + +project(IDHANWebUI LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(Qt6 REQUIRED COMPONENTS Core Widgets Network) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +file(GLOB_RECURSE CPP_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/src/**.cpp) + +qt_add_executable(IDHANWebUI ${CPP_SOURCES}) + +if (DEFINED WASM_OUT_DIR) + set(OUT_DIR ${WASM_OUT_DIR}) +else () + set(OUT_DIR ${CMAKE_BINARY_DIR}) +endif () + +file(MAKE_DIRECTORY ${OUT_DIR}) + +if (EMSCRIPTEN) + target_link_options(IDHANWebUI PUBLIC -sASYNCIFY -Os) + set_target_properties(IDHANWebUI PROPERTIES QT_WASM_INITAL_MEMORY "64MB") + + # Set output directory for all WASM-related files + set_target_properties(IDHANWebUI PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${OUT_DIR} + ARCHIVE_OUTPUT_DIRECTORY ${OUT_DIR} + LIBRARY_OUTPUT_DIRECTORY ${OUT_DIR} + ) + + # For Qt WASM, also set the specific output directory + set_target_properties(IDHANWebUI PROPERTIES + QT_WASM_OUTPUT_DIRECTORY ${OUT_DIR} + ) +endif () + +target_link_libraries(IDHANWebUI PRIVATE Qt6::Widgets Qt6::Network) \ No newline at end of file diff --git a/IDHANWebUI/src/WebUI.cpp b/IDHANWebUI/src/WebUI.cpp new file mode 100644 index 0000000..79d8604 --- /dev/null +++ b/IDHANWebUI/src/WebUI.cpp @@ -0,0 +1,21 @@ +// +// Created by kj16609 on 7/27/25. +// +// You may need to build the project (run Qt uic code generator) to get "ui_WebUI.h" resolved + +#include "WebUI.hpp" + +#include "ui_WebUI.h" + +namespace idhan +{ +WebUI::WebUI( QWidget* parent ) : QMainWindow( parent ), ui( new Ui::WebUI ) +{ + ui->setupUi( this ); +} + +WebUI::~WebUI() +{ + delete ui; +} +} // namespace idhan diff --git a/IDHANWebUI/src/WebUI.hpp b/IDHANWebUI/src/WebUI.hpp new file mode 100644 index 0000000..1b867d6 --- /dev/null +++ b/IDHANWebUI/src/WebUI.hpp @@ -0,0 +1,35 @@ +// +// Created by kj16609 on 7/27/25. +// +#ifndef IDHAN_WEBUI_HPP +#define IDHAN_WEBUI_HPP + +#include + +namespace idhan +{ +QT_BEGIN_NAMESPACE + +namespace Ui +{ +class WebUI; +} + +QT_END_NAMESPACE + +class WebUI : public QMainWindow +{ + Q_OBJECT + + public: + + explicit WebUI( QWidget* parent = nullptr ); + ~WebUI() override; + + private: + + Ui::WebUI* ui; +}; +} // namespace idhan + +#endif //IDHAN_WEBUI_HPP diff --git a/IDHANWebUI/src/WebUI.ui b/IDHANWebUI/src/WebUI.ui new file mode 100644 index 0000000..0e69ade --- /dev/null +++ b/IDHANWebUI/src/WebUI.ui @@ -0,0 +1,41 @@ + + + idhan::WebUI + + + + 0 + 0 + 400 + 300 + + + + WebUI + + + + + + + WEBASM wurks + + + + + + + + + 0 + 0 + 400 + 30 + + + + + + + + diff --git a/IDHANWebUI/src/main.cpp b/IDHANWebUI/src/main.cpp new file mode 100644 index 0000000..5f12027 --- /dev/null +++ b/IDHANWebUI/src/main.cpp @@ -0,0 +1,20 @@ +// +// Created by kj16609 on 7/27/25. +// + +#include + +#include "WebUI.hpp" + +QApplication* app { nullptr }; +idhan::WebUI* webui { nullptr }; + +int main( int argc, char** argv ) +{ + app = new QApplication( argc, argv ); + webui = new idhan::WebUI(); + + webui->show(); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index 85f5c42..4273607 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -21,7 +21,7 @@ if (BUILD_IDHAN_DOCS) endif (doxygen_FOUND) set(API_YAML ${CMAKE_CURRENT_SOURCE_DIR}/api) - set(API_YAML_OUT ${CMAKE_BINARY_DIR}/bin/pages/api) + set(API_YAML_OUT ${CMAKE_BINARY_DIR}/bin/static/api) file(GLOB_RECURSE YAML_FILES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/api/*.yaml" )