diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index dfe0770..0000000 --- a/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 13566b8..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/.idea/Spring-Framework.iml b/.idea/Spring-Framework.iml new file mode 100644 index 0000000..5d5d390 --- /dev/null +++ b/.idea/Spring-Framework.iml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/artifacts/08_Spring_Web_MVC_Web_exploded.xml b/.idea/artifacts/08_Spring_Web_MVC_Web_exploded.xml deleted file mode 100644 index 328b16c..0000000 --- a/.idea/artifacts/08_Spring_Web_MVC_Web_exploded.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - $PROJECT_DIR$/out/artifacts/08_Spring_Web_MVC_Web_exploded - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/artifacts/09_RestControllers_Web_exploded.xml b/.idea/artifacts/09_RestControllers_Web_exploded.xml deleted file mode 100644 index c7bf76a..0000000 --- a/.idea/artifacts/09_RestControllers_Web_exploded.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - $PROJECT_DIR$/out/artifacts/09_RestControllers_Web_exploded - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/artifacts/10_BackEnd_Web_exploded.xml b/.idea/artifacts/10_BackEnd_Web_exploded.xml deleted file mode 100644 index 0b1343a..0000000 --- a/.idea/artifacts/10_BackEnd_Web_exploded.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - $PROJECT_DIR$/out/artifacts/10_BackEnd_Web_exploded - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/artifacts/12_Spring_Data_JPA_Web_exploded.xml b/.idea/artifacts/12_Spring_Data_JPA_Web_exploded.xml deleted file mode 100644 index 6b8cfa5..0000000 --- a/.idea/artifacts/12_Spring_Data_JPA_Web_exploded.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - $PROJECT_DIR$/out/artifacts/12_Spring_Data_JPA_Web_exploded - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..a55e7a1 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 13f3e99..757c0ec 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -2,33 +2,42 @@ + + - + - - - + + - + + + + + + - - - + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml index 36f1451..2fa46a7 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -3,8 +3,6 @@ - - @@ -13,14 +11,17 @@ - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/.idea/material_theme_project_new.xml b/.idea/material_theme_project_new.xml new file mode 100644 index 0000000..e99ec0d --- /dev/null +++ b/.idea/material_theme_project_new.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 04fe76a..8018085 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -20,6 +20,13 @@ + + + + + + + @@ -28,7 +35,7 @@ - + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index bb92f4d..1200b38 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,8 +2,8 @@ - - + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..439e169 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,215 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + { + "lastFilter": { + "state": "OPEN", + "assignee": "ChamathDilshanC" + } +} + { + "selectedUrlAndAccountId": { + "url": "https://github.com/ChamathDilshanC/Spring-Framework.git", + "accountId": "c78509a1-72d5-470a-8e06-93ca28f027ab" + } +} + { + "customColor": "", + "associatedIndex": 0 +} + + + + + + + + + { + "keyToString": { + "ASKED_ADD_EXTERNAL_FILES": "true", + "DefaultHtmlFileTemplate": "HTML File", + "JavaScript Debug.customer.html.executor": "Run", + "JavaScript Debug.dashboard.html.executor": "Run", + "JavaScript Debug.index.html.executor": "Run", + "JavaScript Debug.login.html.executor": "Run", + "JavaScript Debug.register.html.executor": "Run", + "Node.js.login.js.executor": "Run", + "Node.js.register.js.executor": "Run", + "RequestMappingsPanelOrder0": "0", + "RequestMappingsPanelOrder1": "1", + "RequestMappingsPanelWidth0": "75", + "RequestMappingsPanelWidth1": "75", + "RunOnceActivity.ShowReadmeOnStart": "true", + "SHARE_PROJECT_CONFIGURATION_FILES": "true", + "Spring Boot.Application.executor": "Run", + "Spring Boot.SpringSecurityApplicationWork.executor": "Run", + "Spring Boot.SpringwithjwtApplication.executor": "Run", + "Spring Boot.Z15SpringSequrityApplication.executor": "Run", + "Spring Boot.Z17SpringbootBeanValidationApplication.executor": "Run", + "Spring Boot.Z18SpringbootLoginsApplication.executor": "Run", + "deletionFromPopupRequiresConfirmation": "false", + "git-widget-placeholder": "main", + "jdk.selected.JAVA_MODULE": "21", + "js.last.introduce.type": "CONST", + "kotlin-language-version-configured": "true", + "last_opened_file_path": "C:/Users/dilsh/Desktop/Spring-Framework/Z16_Frontend/src/main/java/lk/ijse/JQuery", + "list.type.of.created.stylesheet": "CSS", + "node.js.detected.package.eslint": "true", + "node.js.detected.package.tslint": "true", + "node.js.selected.package.eslint": "(autodetect)", + "node.js.selected.package.tslint": "(autodetect)", + "nodejs_package_manager_path": "npm", + "project.structure.last.edited": "Modules", + "project.structure.proportion": "0.21679688", + "project.structure.side.proportion": "0.39649844", + "run.configurations.included.in.services": "true", + "settings.editor.selected.configurable": "preferences.pluginManager", + "vue.rearranger.settings.migration": "true" + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1740668802399 + + + 1740668802399 + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..849f79e --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.compile.nullAnalysis.mode": "automatic" +} diff --git a/01_Spring_Core/target/classes/lk/ijse/AppInitializer.class b/01_Spring_Core/target/classes/lk/ijse/AppInitializer.class index bdf7702..a640c7a 100644 Binary files a/01_Spring_Core/target/classes/lk/ijse/AppInitializer.class and b/01_Spring_Core/target/classes/lk/ijse/AppInitializer.class differ diff --git a/01_Spring_Core/target/classes/lk/ijse/MyConnection.class b/01_Spring_Core/target/classes/lk/ijse/MyConnection.class index 55edf2d..bf270b4 100644 Binary files a/01_Spring_Core/target/classes/lk/ijse/MyConnection.class and b/01_Spring_Core/target/classes/lk/ijse/MyConnection.class differ diff --git a/01_Spring_Core/target/classes/lk/ijse/bean/SpringBean.class b/01_Spring_Core/target/classes/lk/ijse/bean/SpringBean.class index 9d6311d..3298c1a 100644 Binary files a/01_Spring_Core/target/classes/lk/ijse/bean/SpringBean.class and b/01_Spring_Core/target/classes/lk/ijse/bean/SpringBean.class differ diff --git a/01_Spring_Core/target/classes/lk/ijse/bean/TestBean1.class b/01_Spring_Core/target/classes/lk/ijse/bean/TestBean1.class index df82505..b4a7e0a 100644 Binary files a/01_Spring_Core/target/classes/lk/ijse/bean/TestBean1.class and b/01_Spring_Core/target/classes/lk/ijse/bean/TestBean1.class differ diff --git a/01_Spring_Core/target/classes/lk/ijse/bean/TestBean2.class b/01_Spring_Core/target/classes/lk/ijse/bean/TestBean2.class index 3721e55..53b7f4b 100644 Binary files a/01_Spring_Core/target/classes/lk/ijse/bean/TestBean2.class and b/01_Spring_Core/target/classes/lk/ijse/bean/TestBean2.class differ diff --git a/01_Spring_Core/target/classes/lk/ijse/bean/TestBean3.class b/01_Spring_Core/target/classes/lk/ijse/bean/TestBean3.class index b5c9e99..8dc4127 100644 Binary files a/01_Spring_Core/target/classes/lk/ijse/bean/TestBean3.class and b/01_Spring_Core/target/classes/lk/ijse/bean/TestBean3.class differ diff --git a/01_Spring_Core/target/classes/lk/ijse/config/AppConfig.class b/01_Spring_Core/target/classes/lk/ijse/config/AppConfig.class index c7eec0b..7b24974 100644 Binary files a/01_Spring_Core/target/classes/lk/ijse/config/AppConfig.class and b/01_Spring_Core/target/classes/lk/ijse/config/AppConfig.class differ diff --git a/02_Spring_Bean_LifeCycle/target/classes/lk/ijse/AppInitializer.class b/02_Spring_Bean_LifeCycle/target/classes/lk/ijse/AppInitializer.class index e1410e7..a9ad009 100644 Binary files a/02_Spring_Bean_LifeCycle/target/classes/lk/ijse/AppInitializer.class and b/02_Spring_Bean_LifeCycle/target/classes/lk/ijse/AppInitializer.class differ diff --git a/02_Spring_Bean_LifeCycle/target/classes/lk/ijse/bean/MyConnection.class b/02_Spring_Bean_LifeCycle/target/classes/lk/ijse/bean/MyConnection.class index 9343655..4222179 100644 Binary files a/02_Spring_Bean_LifeCycle/target/classes/lk/ijse/bean/MyConnection.class and b/02_Spring_Bean_LifeCycle/target/classes/lk/ijse/bean/MyConnection.class differ diff --git a/02_Spring_Bean_LifeCycle/target/classes/lk/ijse/bean/TestBean1.class b/02_Spring_Bean_LifeCycle/target/classes/lk/ijse/bean/TestBean1.class index 99fc280..ca6a275 100644 Binary files a/02_Spring_Bean_LifeCycle/target/classes/lk/ijse/bean/TestBean1.class and b/02_Spring_Bean_LifeCycle/target/classes/lk/ijse/bean/TestBean1.class differ diff --git a/02_Spring_Bean_LifeCycle/target/classes/lk/ijse/config/AppConfig.class b/02_Spring_Bean_LifeCycle/target/classes/lk/ijse/config/AppConfig.class index 99c1fa4..78b4338 100644 Binary files a/02_Spring_Bean_LifeCycle/target/classes/lk/ijse/config/AppConfig.class and b/02_Spring_Bean_LifeCycle/target/classes/lk/ijse/config/AppConfig.class differ diff --git a/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/AppInitializer.class b/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/AppInitializer.class index 18f79bf..be4c118 100644 Binary files a/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/AppInitializer.class and b/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/AppInitializer.class differ diff --git a/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/bean/Boy.class b/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/bean/Boy.class index bdd7b89..b92685a 100644 Binary files a/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/bean/Boy.class and b/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/bean/Boy.class differ diff --git a/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/bean/Girl1.class b/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/bean/Girl1.class index 5196f5e..596234b 100644 Binary files a/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/bean/Girl1.class and b/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/bean/Girl1.class differ diff --git a/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/bean/Girl2.class b/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/bean/Girl2.class index 338e13e..84ca46d 100644 Binary files a/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/bean/Girl2.class and b/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/bean/Girl2.class differ diff --git a/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/bean/SpringBean.class b/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/bean/SpringBean.class index fe322fd..ff8ae78 100644 Binary files a/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/bean/SpringBean.class and b/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/bean/SpringBean.class differ diff --git a/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/config/AppConfig.class b/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/config/AppConfig.class index 1260b5a..586d1cf 100644 Binary files a/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/config/AppConfig.class and b/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/config/AppConfig.class differ diff --git a/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/di/Boy.class b/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/di/Boy.class index 1f77840..37878b4 100644 Binary files a/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/di/Boy.class and b/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/di/Boy.class differ diff --git a/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/di/Girl.class b/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/di/Girl.class index fc661e4..9195456 100644 Binary files a/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/di/Girl.class and b/03_Spring_Bean_DI _(Dependency_Injection)/target/classes/lk/ijse/di/Girl.class differ diff --git a/04_FullModeVsLightMode/target/classes/lk/ijse/AppInitializer.class b/04_FullModeVsLightMode/target/classes/lk/ijse/AppInitializer.class index c3584d8..3eb0a20 100644 Binary files a/04_FullModeVsLightMode/target/classes/lk/ijse/AppInitializer.class and b/04_FullModeVsLightMode/target/classes/lk/ijse/AppInitializer.class differ diff --git a/04_FullModeVsLightMode/target/classes/lk/ijse/bean/SpringBeanOne.class b/04_FullModeVsLightMode/target/classes/lk/ijse/bean/SpringBeanOne.class index 1d0d3b0..c21d239 100644 Binary files a/04_FullModeVsLightMode/target/classes/lk/ijse/bean/SpringBeanOne.class and b/04_FullModeVsLightMode/target/classes/lk/ijse/bean/SpringBeanOne.class differ diff --git a/04_FullModeVsLightMode/target/classes/lk/ijse/bean/SpringBeanThree.class b/04_FullModeVsLightMode/target/classes/lk/ijse/bean/SpringBeanThree.class index e7a57cf..e071a09 100644 Binary files a/04_FullModeVsLightMode/target/classes/lk/ijse/bean/SpringBeanThree.class and b/04_FullModeVsLightMode/target/classes/lk/ijse/bean/SpringBeanThree.class differ diff --git a/04_FullModeVsLightMode/target/classes/lk/ijse/bean/SpringBeanTwo.class b/04_FullModeVsLightMode/target/classes/lk/ijse/bean/SpringBeanTwo.class index 3ab3358..f0f91d2 100644 Binary files a/04_FullModeVsLightMode/target/classes/lk/ijse/bean/SpringBeanTwo.class and b/04_FullModeVsLightMode/target/classes/lk/ijse/bean/SpringBeanTwo.class differ diff --git a/04_FullModeVsLightMode/target/classes/lk/ijse/config/AppConfig.class b/04_FullModeVsLightMode/target/classes/lk/ijse/config/AppConfig.class index 151e70d..b7caf21 100644 Binary files a/04_FullModeVsLightMode/target/classes/lk/ijse/config/AppConfig.class and b/04_FullModeVsLightMode/target/classes/lk/ijse/config/AppConfig.class differ diff --git a/05_Configuration/target/classes/AppInitializer.class b/05_Configuration/target/classes/AppInitializer.class index 4c87280..8958003 100644 Binary files a/05_Configuration/target/classes/AppInitializer.class and b/05_Configuration/target/classes/AppInitializer.class differ diff --git a/05_Configuration/target/classes/lk/ijse/bean/SpringBean.class b/05_Configuration/target/classes/lk/ijse/bean/SpringBean.class new file mode 100644 index 0000000..ba239dd Binary files /dev/null and b/05_Configuration/target/classes/lk/ijse/bean/SpringBean.class differ diff --git a/05_Configuration/target/classes/lk/ijse/bean/SpringBean1.class b/05_Configuration/target/classes/lk/ijse/bean/SpringBean1.class new file mode 100644 index 0000000..7a82562 Binary files /dev/null and b/05_Configuration/target/classes/lk/ijse/bean/SpringBean1.class differ diff --git a/05_Configuration/target/classes/lk/ijse/config/AppConfig.class b/05_Configuration/target/classes/lk/ijse/config/AppConfig.class new file mode 100644 index 0000000..ce6d538 Binary files /dev/null and b/05_Configuration/target/classes/lk/ijse/config/AppConfig.class differ diff --git a/05_Configuration/target/classes/lk/ijse/config/AppConfig1.class b/05_Configuration/target/classes/lk/ijse/config/AppConfig1.class new file mode 100644 index 0000000..68b0cac Binary files /dev/null and b/05_Configuration/target/classes/lk/ijse/config/AppConfig1.class differ diff --git a/05_Configuration/target/classes/org/example/bean/SpringBean.class b/05_Configuration/target/classes/org/example/bean/SpringBean.class deleted file mode 100644 index 0681532..0000000 Binary files a/05_Configuration/target/classes/org/example/bean/SpringBean.class and /dev/null differ diff --git a/05_Configuration/target/classes/org/example/bean/SpringBean1.class b/05_Configuration/target/classes/org/example/bean/SpringBean1.class deleted file mode 100644 index 4ea2bad..0000000 Binary files a/05_Configuration/target/classes/org/example/bean/SpringBean1.class and /dev/null differ diff --git a/05_Configuration/target/classes/org/example/config/AppConfig.class b/05_Configuration/target/classes/org/example/config/AppConfig.class deleted file mode 100644 index 35a4dac..0000000 Binary files a/05_Configuration/target/classes/org/example/config/AppConfig.class and /dev/null differ diff --git a/05_Configuration/target/classes/org/example/config/AppConfig1.class b/05_Configuration/target/classes/org/example/config/AppConfig1.class deleted file mode 100644 index be33162..0000000 Binary files a/05_Configuration/target/classes/org/example/config/AppConfig1.class and /dev/null differ diff --git a/06_RunTime_Value_Injection/target/classes/lk/ijse/AppInitializer.class b/06_RunTime_Value_Injection/target/classes/lk/ijse/AppInitializer.class index bc7ad62..9fab55f 100644 Binary files a/06_RunTime_Value_Injection/target/classes/lk/ijse/AppInitializer.class and b/06_RunTime_Value_Injection/target/classes/lk/ijse/AppInitializer.class differ diff --git a/06_RunTime_Value_Injection/target/classes/lk/ijse/bean/SpringBeanOne.class b/06_RunTime_Value_Injection/target/classes/lk/ijse/bean/SpringBeanOne.class index dc0abeb..466db7d 100644 Binary files a/06_RunTime_Value_Injection/target/classes/lk/ijse/bean/SpringBeanOne.class and b/06_RunTime_Value_Injection/target/classes/lk/ijse/bean/SpringBeanOne.class differ diff --git a/06_RunTime_Value_Injection/target/classes/lk/ijse/bean/SpringBeanTwo.class b/06_RunTime_Value_Injection/target/classes/lk/ijse/bean/SpringBeanTwo.class index 4570603..bc3af2e 100644 Binary files a/06_RunTime_Value_Injection/target/classes/lk/ijse/bean/SpringBeanTwo.class and b/06_RunTime_Value_Injection/target/classes/lk/ijse/bean/SpringBeanTwo.class differ diff --git a/06_RunTime_Value_Injection/target/classes/lk/ijse/config/AppConfig.class b/06_RunTime_Value_Injection/target/classes/lk/ijse/config/AppConfig.class index 3126b8d..4e6a558 100644 Binary files a/06_RunTime_Value_Injection/target/classes/lk/ijse/config/AppConfig.class and b/06_RunTime_Value_Injection/target/classes/lk/ijse/config/AppConfig.class differ diff --git a/07_Spring_Environment/target/classes/lk/ijse/AppInitializer.class b/07_Spring_Environment/target/classes/lk/ijse/AppInitializer.class index cbabbc6..1173672 100644 Binary files a/07_Spring_Environment/target/classes/lk/ijse/AppInitializer.class and b/07_Spring_Environment/target/classes/lk/ijse/AppInitializer.class differ diff --git a/07_Spring_Environment/target/classes/lk/ijse/bean/SpringBean.class b/07_Spring_Environment/target/classes/lk/ijse/bean/SpringBean.class index 9e3602a..ed8cea7 100644 Binary files a/07_Spring_Environment/target/classes/lk/ijse/bean/SpringBean.class and b/07_Spring_Environment/target/classes/lk/ijse/bean/SpringBean.class differ diff --git a/07_Spring_Environment/target/classes/lk/ijse/config/AppConfig.class b/07_Spring_Environment/target/classes/lk/ijse/config/AppConfig.class index f98ebd2..5e4aa6e 100644 Binary files a/07_Spring_Environment/target/classes/lk/ijse/config/AppConfig.class and b/07_Spring_Environment/target/classes/lk/ijse/config/AppConfig.class differ diff --git a/08_Spring_Web_MVC.iml b/08_Spring_Web_MVC.iml deleted file mode 100644 index 3c63a80..0000000 --- a/08_Spring_Web_MVC.iml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/08_Spring_Web_MVC/08_Spring_Web_MVC.iml b/08_Spring_Web_MVC/08_Spring_Web_MVC.iml new file mode 100644 index 0000000..4e61727 --- /dev/null +++ b/08_Spring_Web_MVC/08_Spring_Web_MVC.iml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/08_Spring_Web_MVC/target/classes/lk/ijse/Controller/CustomerController.class b/08_Spring_Web_MVC/target/classes/lk/ijse/Controller/CustomerController.class index 05a6774..6ae3caa 100644 Binary files a/08_Spring_Web_MVC/target/classes/lk/ijse/Controller/CustomerController.class and b/08_Spring_Web_MVC/target/classes/lk/ijse/Controller/CustomerController.class differ diff --git a/08_Spring_Web_MVC/target/classes/lk/ijse/Controller/HelloController.class b/08_Spring_Web_MVC/target/classes/lk/ijse/Controller/HelloController.class index 6990072..ee04b9c 100644 Binary files a/08_Spring_Web_MVC/target/classes/lk/ijse/Controller/HelloController.class and b/08_Spring_Web_MVC/target/classes/lk/ijse/Controller/HelloController.class differ diff --git a/08_Spring_Web_MVC/target/classes/lk/ijse/WebAppInitializer.class b/08_Spring_Web_MVC/target/classes/lk/ijse/WebAppInitializer.class index c5a11fe..b633ac7 100644 Binary files a/08_Spring_Web_MVC/target/classes/lk/ijse/WebAppInitializer.class and b/08_Spring_Web_MVC/target/classes/lk/ijse/WebAppInitializer.class differ diff --git a/08_Spring_Web_MVC/target/classes/lk/ijse/bean/SpringBean.class b/08_Spring_Web_MVC/target/classes/lk/ijse/bean/SpringBean.class index 92618e9..062bba2 100644 Binary files a/08_Spring_Web_MVC/target/classes/lk/ijse/bean/SpringBean.class and b/08_Spring_Web_MVC/target/classes/lk/ijse/bean/SpringBean.class differ diff --git a/08_Spring_Web_MVC/target/classes/lk/ijse/config/WebAppConfig.class b/08_Spring_Web_MVC/target/classes/lk/ijse/config/WebAppConfig.class index 2f57ce1..a52814b 100644 Binary files a/08_Spring_Web_MVC/target/classes/lk/ijse/config/WebAppConfig.class and b/08_Spring_Web_MVC/target/classes/lk/ijse/config/WebAppConfig.class differ diff --git a/08_Spring_Web_MVC/target/classes/lk/ijse/config/WebRootConfig.class b/08_Spring_Web_MVC/target/classes/lk/ijse/config/WebRootConfig.class index 5c90bc7..4d52802 100644 Binary files a/08_Spring_Web_MVC/target/classes/lk/ijse/config/WebRootConfig.class and b/08_Spring_Web_MVC/target/classes/lk/ijse/config/WebRootConfig.class differ diff --git a/09_RestControllers.iml b/09_RestControllers.iml deleted file mode 100644 index fede81d..0000000 --- a/09_RestControllers.iml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/09_RestControllers/09_RestControllers.iml b/09_RestControllers/09_RestControllers.iml new file mode 100644 index 0000000..966985a --- /dev/null +++ b/09_RestControllers/09_RestControllers.iml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/09_RestControllers/target/classes/lk/ijse/Controller/CharacterMapping.class b/09_RestControllers/target/classes/lk/ijse/Controller/CharacterMapping.class index 6b8a90a..70d8276 100644 Binary files a/09_RestControllers/target/classes/lk/ijse/Controller/CharacterMapping.class and b/09_RestControllers/target/classes/lk/ijse/Controller/CharacterMapping.class differ diff --git a/09_RestControllers/target/classes/lk/ijse/Controller/CustomerController.class b/09_RestControllers/target/classes/lk/ijse/Controller/CustomerController.class index 05a6774..6ae3caa 100644 Binary files a/09_RestControllers/target/classes/lk/ijse/Controller/CustomerController.class and b/09_RestControllers/target/classes/lk/ijse/Controller/CustomerController.class differ diff --git a/09_RestControllers/target/classes/lk/ijse/Controller/ExactMappingController.class b/09_RestControllers/target/classes/lk/ijse/Controller/ExactMappingController.class index a2aff9d..b1c060d 100644 Binary files a/09_RestControllers/target/classes/lk/ijse/Controller/ExactMappingController.class and b/09_RestControllers/target/classes/lk/ijse/Controller/ExactMappingController.class differ diff --git a/09_RestControllers/target/classes/lk/ijse/Controller/FormDataController.class b/09_RestControllers/target/classes/lk/ijse/Controller/FormDataController.class index 4fc80cb..a5f1543 100644 Binary files a/09_RestControllers/target/classes/lk/ijse/Controller/FormDataController.class and b/09_RestControllers/target/classes/lk/ijse/Controller/FormDataController.class differ diff --git a/09_RestControllers/target/classes/lk/ijse/Controller/HelloController.class b/09_RestControllers/target/classes/lk/ijse/Controller/HelloController.class index a0076b2..d83afcb 100644 Binary files a/09_RestControllers/target/classes/lk/ijse/Controller/HelloController.class and b/09_RestControllers/target/classes/lk/ijse/Controller/HelloController.class differ diff --git a/09_RestControllers/target/classes/lk/ijse/Controller/JsonController.class b/09_RestControllers/target/classes/lk/ijse/Controller/JsonController.class index 6d384e4..2d5471c 100644 Binary files a/09_RestControllers/target/classes/lk/ijse/Controller/JsonController.class and b/09_RestControllers/target/classes/lk/ijse/Controller/JsonController.class differ diff --git a/09_RestControllers/target/classes/lk/ijse/Controller/ParamsController.class b/09_RestControllers/target/classes/lk/ijse/Controller/ParamsController.class index c5fb1af..51c5667 100644 Binary files a/09_RestControllers/target/classes/lk/ijse/Controller/ParamsController.class and b/09_RestControllers/target/classes/lk/ijse/Controller/ParamsController.class differ diff --git a/09_RestControllers/target/classes/lk/ijse/Controller/PathVariableController.class b/09_RestControllers/target/classes/lk/ijse/Controller/PathVariableController.class index 5bb55d1..3a3b317 100644 Binary files a/09_RestControllers/target/classes/lk/ijse/Controller/PathVariableController.class and b/09_RestControllers/target/classes/lk/ijse/Controller/PathVariableController.class differ diff --git a/09_RestControllers/target/classes/lk/ijse/Controller/WildCardMappingController.class b/09_RestControllers/target/classes/lk/ijse/Controller/WildCardMappingController.class index d311620..023dbdc 100644 Binary files a/09_RestControllers/target/classes/lk/ijse/Controller/WildCardMappingController.class and b/09_RestControllers/target/classes/lk/ijse/Controller/WildCardMappingController.class differ diff --git a/09_RestControllers/target/classes/lk/ijse/DTO/CustomerDTO.class b/09_RestControllers/target/classes/lk/ijse/DTO/CustomerDTO.class index af9fab7..fb478b4 100644 Binary files a/09_RestControllers/target/classes/lk/ijse/DTO/CustomerDTO.class and b/09_RestControllers/target/classes/lk/ijse/DTO/CustomerDTO.class differ diff --git a/09_RestControllers/target/classes/lk/ijse/WebAppInitializer.class b/09_RestControllers/target/classes/lk/ijse/WebAppInitializer.class index c5a11fe..b633ac7 100644 Binary files a/09_RestControllers/target/classes/lk/ijse/WebAppInitializer.class and b/09_RestControllers/target/classes/lk/ijse/WebAppInitializer.class differ diff --git a/09_RestControllers/target/classes/lk/ijse/bean/SpringBean.class b/09_RestControllers/target/classes/lk/ijse/bean/SpringBean.class index 92618e9..062bba2 100644 Binary files a/09_RestControllers/target/classes/lk/ijse/bean/SpringBean.class and b/09_RestControllers/target/classes/lk/ijse/bean/SpringBean.class differ diff --git a/09_RestControllers/target/classes/lk/ijse/config/WebAppConfig.class b/09_RestControllers/target/classes/lk/ijse/config/WebAppConfig.class index 2dcf3d2..a52814b 100644 Binary files a/09_RestControllers/target/classes/lk/ijse/config/WebAppConfig.class and b/09_RestControllers/target/classes/lk/ijse/config/WebAppConfig.class differ diff --git a/09_RestControllers/target/classes/lk/ijse/config/WebRootConfig.class b/09_RestControllers/target/classes/lk/ijse/config/WebRootConfig.class index 5c90bc7..4d52802 100644 Binary files a/09_RestControllers/target/classes/lk/ijse/config/WebRootConfig.class and b/09_RestControllers/target/classes/lk/ijse/config/WebRootConfig.class differ diff --git a/10_BackEnd/10_BackEnd.iml b/10_BackEnd/10_BackEnd.iml index 4d8d734..4e61727 100644 --- a/10_BackEnd/10_BackEnd.iml +++ b/10_BackEnd/10_BackEnd.iml @@ -3,35 +3,93 @@ - - - - - - + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + + + \ No newline at end of file diff --git a/10_BackEnd/target/classes/lk/ijse/WebAppInitializer.class b/10_BackEnd/target/classes/lk/ijse/WebAppInitializer.class index 01aed6d..298d3a4 100644 Binary files a/10_BackEnd/target/classes/lk/ijse/WebAppInitializer.class and b/10_BackEnd/target/classes/lk/ijse/WebAppInitializer.class differ diff --git a/10_BackEnd/target/classes/lk/ijse/config/WebAppConfig.class b/10_BackEnd/target/classes/lk/ijse/config/WebAppConfig.class index a25d541..9a0b6f9 100644 Binary files a/10_BackEnd/target/classes/lk/ijse/config/WebAppConfig.class and b/10_BackEnd/target/classes/lk/ijse/config/WebAppConfig.class differ diff --git a/10_BackEnd/target/classes/lk/ijse/config/WebRootConfig.class b/10_BackEnd/target/classes/lk/ijse/config/WebRootConfig.class index 467fbd4..f5ce395 100644 Binary files a/10_BackEnd/target/classes/lk/ijse/config/WebRootConfig.class and b/10_BackEnd/target/classes/lk/ijse/config/WebRootConfig.class differ diff --git a/10_BackEnd/target/classes/lk/ijse/controller/CustomerController.class b/10_BackEnd/target/classes/lk/ijse/controller/CustomerController.class index 22a7e58..13e5a08 100644 Binary files a/10_BackEnd/target/classes/lk/ijse/controller/CustomerController.class and b/10_BackEnd/target/classes/lk/ijse/controller/CustomerController.class differ diff --git a/10_BackEnd/target/classes/lk/ijse/dto/CustomerDTO.class b/10_BackEnd/target/classes/lk/ijse/dto/CustomerDTO.class index da81ccc..d2bf852 100644 Binary files a/10_BackEnd/target/classes/lk/ijse/dto/CustomerDTO.class and b/10_BackEnd/target/classes/lk/ijse/dto/CustomerDTO.class differ diff --git a/12_Spring_Data_JPA.iml b/12_Spring_Data_JPA.iml deleted file mode 100644 index 2a8c983..0000000 --- a/12_Spring_Data_JPA.iml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/12_Spring_Data_JPA/12_Spring_Data_JPA.iml b/12_Spring_Data_JPA/12_Spring_Data_JPA.iml new file mode 100644 index 0000000..98551db --- /dev/null +++ b/12_Spring_Data_JPA/12_Spring_Data_JPA.iml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/12_Spring_Data_JPA/target/classes/lk/ijse/WebAppInitializer.class b/12_Spring_Data_JPA/target/classes/lk/ijse/WebAppInitializer.class index a07fee3..8ade13c 100644 Binary files a/12_Spring_Data_JPA/target/classes/lk/ijse/WebAppInitializer.class and b/12_Spring_Data_JPA/target/classes/lk/ijse/WebAppInitializer.class differ diff --git a/12_Spring_Data_JPA/target/classes/lk/ijse/config/JPAConfig.class b/12_Spring_Data_JPA/target/classes/lk/ijse/config/JPAConfig.class index 66e147c..0b03681 100644 Binary files a/12_Spring_Data_JPA/target/classes/lk/ijse/config/JPAConfig.class and b/12_Spring_Data_JPA/target/classes/lk/ijse/config/JPAConfig.class differ diff --git a/12_Spring_Data_JPA/target/classes/lk/ijse/config/WebAppConfig.class b/12_Spring_Data_JPA/target/classes/lk/ijse/config/WebAppConfig.class index f81d9bf..c501062 100644 Binary files a/12_Spring_Data_JPA/target/classes/lk/ijse/config/WebAppConfig.class and b/12_Spring_Data_JPA/target/classes/lk/ijse/config/WebAppConfig.class differ diff --git a/12_Spring_Data_JPA/target/classes/lk/ijse/config/WebRootConfig.class b/12_Spring_Data_JPA/target/classes/lk/ijse/config/WebRootConfig.class index cb1df29..09c91e6 100644 Binary files a/12_Spring_Data_JPA/target/classes/lk/ijse/config/WebRootConfig.class and b/12_Spring_Data_JPA/target/classes/lk/ijse/config/WebRootConfig.class differ diff --git a/12_Spring_Data_JPA/target/classes/lk/ijse/controller/CustomerController.class b/12_Spring_Data_JPA/target/classes/lk/ijse/controller/CustomerController.class index 08bce51..041c9e3 100644 Binary files a/12_Spring_Data_JPA/target/classes/lk/ijse/controller/CustomerController.class and b/12_Spring_Data_JPA/target/classes/lk/ijse/controller/CustomerController.class differ diff --git a/12_Spring_Data_JPA/target/classes/lk/ijse/dto/CustomerDTO.class b/12_Spring_Data_JPA/target/classes/lk/ijse/dto/CustomerDTO.class index 3271b08..05e0420 100644 Binary files a/12_Spring_Data_JPA/target/classes/lk/ijse/dto/CustomerDTO.class and b/12_Spring_Data_JPA/target/classes/lk/ijse/dto/CustomerDTO.class differ diff --git a/12_Spring_Data_JPA/target/classes/lk/ijse/entity/Customer.class b/12_Spring_Data_JPA/target/classes/lk/ijse/entity/Customer.class index deeb44f..b03ad71 100644 Binary files a/12_Spring_Data_JPA/target/classes/lk/ijse/entity/Customer.class and b/12_Spring_Data_JPA/target/classes/lk/ijse/entity/Customer.class differ diff --git a/12_Spring_Data_JPA/target/classes/lk/ijse/repository/CustomerRepository.class b/12_Spring_Data_JPA/target/classes/lk/ijse/repository/CustomerRepository.class index 1adfc45..7b0abb1 100644 Binary files a/12_Spring_Data_JPA/target/classes/lk/ijse/repository/CustomerRepository.class and b/12_Spring_Data_JPA/target/classes/lk/ijse/repository/CustomerRepository.class differ diff --git a/13_Spring_Boot.zip b/13_Spring_Boot.zip deleted file mode 100644 index e7fe88b..0000000 Binary files a/13_Spring_Boot.zip and /dev/null differ diff --git a/13_Spring_Boot/pom.xml b/13_Spring_Boot/pom.xml index 0cb3b2b..412f63b 100644 --- a/13_Spring_Boot/pom.xml +++ b/13_Spring_Boot/pom.xml @@ -52,6 +52,11 @@ mysql-connector-j runtime + + org.modelmapper + modelmapper + 3.0.0 + diff --git a/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/Controller/CustomerController.java b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/Controller/CustomerController.java index f5dcde0..e3e8706 100644 --- a/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/Controller/CustomerController.java +++ b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/Controller/CustomerController.java @@ -1,40 +1,55 @@ package lk.ijse.spring_boot.Controller; import lk.ijse.spring_boot.dto.CustomerDTO; -import lk.ijse.spring_boot.service.CustomerService; +import lk.ijse.spring_boot.service.Impl.CustomerServiceImpl; +import lk.ijse.spring_boot.util.ResponseUtil; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.List; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + @RestController @RequestMapping("api/v1/customer") +@CrossOrigin(origins = "*") public class CustomerController { // Property Injection @Autowired - private CustomerService customerService; + private CustomerServiceImpl customerService; @GetMapping(path = "getAll") - public List getCustomer(){ - List allCustomers = customerService.getAllCustomers(); - return allCustomers; - + public ResponseUtil getCustomer() { + System.out.println(customerService.getAllCustomers()); + return new ResponseUtil(200, "Customer List", customerService.getAllCustomers()); } @PostMapping(path = "save" , consumes = "application/json") - public boolean saveCustomer(@RequestBody CustomerDTO customerDTO){ - return customerService.addCustomer(customerDTO); + public ResponseUtil saveCustomer(@RequestBody CustomerDTO customerDTO) { + customerService.addCustomer(customerDTO); + return new ResponseUtil(201, "Customer Added Successfully", null); } - - @PostMapping(path = "update" , consumes = "application/json") - public boolean updateCustomer(@RequestBody CustomerDTO customerDTO){ - return customerService.updateCustomer(customerDTO); + @PutMapping(path = "update" , consumes = "application/json") + public ResponseUtil updateCustomer(@RequestBody CustomerDTO customerDTO){ + customerService.updateCustomer(customerDTO); + return new ResponseUtil(201, "Customer Updated Successfully", null); } @DeleteMapping(path = "delete/{id}") - public boolean deleteCustomer(@PathVariable("id") String id){ - return customerService.deleteCustomer(id); + public ResponseUtil deleteCustomer(@PathVariable("id") String id){ + customerService.deleteCustomer(id); + return new ResponseUtil(201, "Customer Deleted Successfully", null); } - - + @GetMapping(path = "generateNextId") + public ResponseUtil generateId() { + return new ResponseUtil(201, "Customer Id Generated", customerService.generateNextCustomerId()); + } + @GetMapping(path = "getCustomerCount") + public Integer getCustomerCount() { + Integer customerCount = customerService.getCustomerCount(); + return new ResponseUtil(200, "Customer Count", customerCount).getCode(); + } + } diff --git a/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/Controller/ItemController.java b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/Controller/ItemController.java index 64253f3..d9facb5 100644 --- a/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/Controller/ItemController.java +++ b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/Controller/ItemController.java @@ -1,28 +1,45 @@ package lk.ijse.spring_boot.Controller; import lk.ijse.spring_boot.dto.ItemDTO; -import lk.ijse.spring_boot.service.ItemService; +import lk.ijse.spring_boot.service.Impl.ItemServiceImpl; +import lk.ijse.spring_boot.util.ResponseUtil; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.List; - @RestController @RequestMapping("api/v1/item") +@CrossOrigin public class ItemController { @Autowired - private ItemService itemService; + private ItemServiceImpl itemService; @GetMapping("getAll") - public List getAll (){ - List allItems = itemService.getAllItems(); - return allItems; + public ResponseUtil getAll (){ + return new ResponseUtil(200, "Item List", itemService.getAllItems()); } - @PostMapping("save") - public boolean saveItem(@RequestBody ItemDTO itemDTO){ - return itemService.addItem(itemDTO); + public ResponseUtil saveItem(@RequestBody ItemDTO itemDTO){ + itemService.addItem(itemDTO); + return new ResponseUtil(201, "Item Added Successfully", null); + } + + @PutMapping("update") + public ResponseUtil updateItem(@RequestBody ItemDTO itemDTO){ + itemService.updateItem(itemDTO); + return new ResponseUtil(201, "Item Updated Successfully", null); + } + + @DeleteMapping("delete/{id}") + public ResponseUtil deleteItem(@PathVariable String id){ + itemService.deleteItem(id); + return new ResponseUtil(201, "Item Deleted Successfully", null); + } + @GetMapping(path = "generateNextId") + public ResponseUtil generateId(){ + return new ResponseUtil(201, "Item Id Generated", itemService.generateNextItemId()); } } diff --git a/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/Controller/OrderController.java b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/Controller/OrderController.java index fb659ae..a83855d 100644 --- a/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/Controller/OrderController.java +++ b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/Controller/OrderController.java @@ -1,7 +1,8 @@ package lk.ijse.spring_boot.Controller; import lk.ijse.spring_boot.dto.OrderDTO; -import lk.ijse.spring_boot.service.OrderService; +import lk.ijse.spring_boot.service.Impl.OrderServiceImpl; +import lk.ijse.spring_boot.util.ResponseUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -12,20 +13,21 @@ @CrossOrigin public class OrderController { @Autowired - private OrderService orderService; + private OrderServiceImpl orderService; @PostMapping("/save") - public ResponseEntity saveOrder(@RequestBody OrderDTO orderDTO) { + public ResponseUtil saveOrder(@RequestBody OrderDTO orderDTO) { if (orderDTO.getOrderId() == null || orderDTO.getCustomerId() == null || orderDTO.getOrderDetails() == null || orderDTO.getOrderDetails().isEmpty()) { - return new ResponseEntity<>("Invalid order data", HttpStatus.BAD_REQUEST); + return new ResponseUtil(400, "Invalid Order Details", null); } - boolean saved = orderService.saveOrder(orderDTO); - if (saved) { - return new ResponseEntity<>("Order saved successfully", HttpStatus.CREATED); - } else { - return new ResponseEntity<>("Failed to save order", HttpStatus.INTERNAL_SERVER_ERROR); - } + ResponseUtil response = orderService.saveOrder(orderDTO); + return new ResponseUtil(response.getCode(), response.getMessage(), response.getData()); + } + + @GetMapping("/generateNextId") + public ResponseUtil generateNextId() { + return new ResponseUtil(201, "Order Id Generated", orderService.generateNextOrderId()); } } \ No newline at end of file diff --git a/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/Repo/CustomerRepo.java b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/Repo/CustomerRepo.java index f8ce440..73cbb98 100644 --- a/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/Repo/CustomerRepo.java +++ b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/Repo/CustomerRepo.java @@ -3,9 +3,24 @@ import lk.ijse.spring_boot.entity.Customer; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository public interface CustomerRepo extends JpaRepository { + Customer findFirstByOrderByIdDesc(); + // Query Methods + /* + *//*List findByName(String name); + int countByAddress(String address); + @Query(value = "SELECT * FROM Customer", nativeQuery = true) + void getAllCustomers();*//* + boolean searchById(String id);*/ + // get Customer Count + @Query(value = "SELECT COUNT(id) FROM Customer", nativeQuery = true) + Integer getCustomerCount(); + } diff --git a/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/Repo/ItemRepo.java b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/Repo/ItemRepo.java index 7e95ece..7a740fb 100644 --- a/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/Repo/ItemRepo.java +++ b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/Repo/ItemRepo.java @@ -1,8 +1,11 @@ package lk.ijse.spring_boot.Repo; +import lk.ijse.spring_boot.dto.OrderDetailDTO; import lk.ijse.spring_boot.entity.Item; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository -public interface ItemRepo extends JpaRepository {} +public interface ItemRepo extends JpaRepository { + Item findFirstByOrderByItemCodeDesc(); +} diff --git a/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/Repo/OrderRepo.java b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/Repo/OrderRepo.java index 8c16abc..b5f15d6 100644 --- a/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/Repo/OrderRepo.java +++ b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/Repo/OrderRepo.java @@ -4,6 +4,9 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository public interface OrderRepo extends JpaRepository { + Order findFirstByOrderByOrderIdDesc(); } diff --git a/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/advicer/AppWideExeptionHandler.java b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/advicer/AppWideExeptionHandler.java new file mode 100644 index 0000000..2e17256 --- /dev/null +++ b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/advicer/AppWideExeptionHandler.java @@ -0,0 +1,15 @@ +package lk.ijse.spring_boot.advicer; + +import lk.ijse.spring_boot.util.ResponseUtil; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +@CrossOrigin +public class AppWideExeptionHandler { + @ExceptionHandler(Exception.class) + public ResponseUtil exeptionHandler(Exception e){ + return new ResponseUtil(500,"Intrernel Server Eroor", e.getMessage()); + } +} diff --git a/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/config/WebAppConfig.java b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/config/WebAppConfig.java new file mode 100644 index 0000000..9f007c2 --- /dev/null +++ b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/config/WebAppConfig.java @@ -0,0 +1,13 @@ +package lk.ijse.spring_boot.config; + +import org.modelmapper.ModelMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class WebAppConfig { + @Bean + public ModelMapper mapper(){ + return new ModelMapper(); + } +} diff --git a/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/service/CustomerService.java b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/service/CustomerService.java index c7e3dd6..3034fb3 100644 --- a/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/service/CustomerService.java +++ b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/service/CustomerService.java @@ -1,59 +1,16 @@ package lk.ijse.spring_boot.service; -import lk.ijse.spring_boot.Repo.CustomerRepo; import lk.ijse.spring_boot.dto.CustomerDTO; -import lk.ijse.spring_boot.entity.Customer; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; +import lk.ijse.spring_boot.util.ResponseUtil; -import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; -@Service -public class CustomerService { - @Autowired - private CustomerRepo customerRepo; - public CustomerService() { - System.out.println("CustomerService Instantiated..."); - } +public interface CustomerService { + void addCustomer(CustomerDTO customerDTO); + List getAllCustomers(); + void updateCustomer(CustomerDTO customerDTO); + void deleteCustomer(String id); + String generateNextCustomerId(); + Integer getCustomerCount(); - public boolean addCustomer(CustomerDTO customerDTO){ - if (customerRepo.existsById(customerDTO.getId())){ - return false; - }else{ - Customer customer = new Customer(customerDTO.getId(), customerDTO.getName(), customerDTO.getAddress()); - customerRepo.save(customer); - return true; - } - } - - public List getAllCustomers() { - List all = customerRepo.findAll(); - List customerDTOS = new ArrayList<>(); - for (Customer customer : all) { - CustomerDTO customerDTO = new CustomerDTO(customer.getId(), customer.getName(), customer.getAddress()); - customerDTOS.add(customerDTO); - } - return customerDTOS; - } - - public boolean updateCustomer(CustomerDTO customerDTO) { - if (customerRepo.existsById(customerDTO.getId())){ - Customer customer = new Customer(customerDTO.getId(), customerDTO.getName(), customerDTO.getAddress()); - customerRepo.save(customer); - return true; - }else{ - return false; - } - } - - public boolean deleteCustomer(String id) { - if (customerRepo.existsById(id)){ - customerRepo.deleteById(id); - return true; - }else{ - return false; - } - } } diff --git a/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/service/Impl/CustomerServiceImpl.java b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/service/Impl/CustomerServiceImpl.java new file mode 100644 index 0000000..79f2906 --- /dev/null +++ b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/service/Impl/CustomerServiceImpl.java @@ -0,0 +1,80 @@ +package lk.ijse.spring_boot.service.Impl; + +import lk.ijse.spring_boot.Repo.CustomerRepo; +import lk.ijse.spring_boot.dto.CustomerDTO; +import lk.ijse.spring_boot.entity.Customer; +import lk.ijse.spring_boot.service.CustomerService; +import lk.ijse.spring_boot.util.ResponseUtil; +import org.modelmapper.ModelMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +@Service +public class CustomerServiceImpl implements CustomerService { + @Autowired + private CustomerRepo customerRepo; + @Autowired + private ModelMapper modelMapper; + + @Override + public void addCustomer(CustomerDTO customerDTO){ + if (customerRepo.existsById(customerDTO.getId())){ + throw new RuntimeException("Customer Already Exists"); + } + Customer customer = modelMapper.map(customerDTO, Customer.class); + customerRepo.save(customer); + } + @Override + public List getAllCustomers() { + List customers = customerRepo.findAll(); + List customerDTOS = new ArrayList<>(); + for (Customer customer : customers) { + CustomerDTO customerDTO = modelMapper.map(customer, CustomerDTO.class); + customerDTOS.add(customerDTO); + } + return customerDTOS; + } + @Override + + public void updateCustomer(CustomerDTO customerDTO) { + if (customerRepo.existsById(customerDTO.getId())){ + Customer customer = modelMapper.map(customerDTO, Customer.class); + customerRepo.save(customer); + }else{ + throw new RuntimeException("Customer Not Found"); + } + } + @Override + public void deleteCustomer(String id) { + if (customerRepo.existsById(id)){ + customerRepo.deleteById(id); + }else{ + throw new RuntimeException("Customer Not Found"); + } + } + + @Override + public String generateNextCustomerId() { + Customer customer = customerRepo.findFirstByOrderByIdDesc(); + if (customer == null) { + return "C001"; + } + String lastNumber = customer.getId().substring(1); + int newNumber = Integer.parseInt(lastNumber) + 1; + if (newNumber < 10) { + return "C00" + newNumber; + } else if (newNumber < 100) { + return "C0" + newNumber; + } else { + return "C" + newNumber; + } + } + @Transactional + public Integer getCustomerCount() { + return customerRepo.getCustomerCount(); + } +} diff --git a/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/service/Impl/ItemServiceImpl.java b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/service/Impl/ItemServiceImpl.java new file mode 100644 index 0000000..b51df72 --- /dev/null +++ b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/service/Impl/ItemServiceImpl.java @@ -0,0 +1,73 @@ +package lk.ijse.spring_boot.service.Impl; + +import lk.ijse.spring_boot.Repo.ItemRepo; +import lk.ijse.spring_boot.dto.ItemDTO; +import lk.ijse.spring_boot.entity.Item; +import lk.ijse.spring_boot.service.ItemService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +@Service +public class ItemServiceImpl implements ItemService { + @Autowired + private ItemRepo itemRepo; + + @Override + public List getAllItems() { + List all = itemRepo.findAll(); + List itemDTOS = new ArrayList<>(); + for (Item item : all) { + ItemDTO itemDTO = new ItemDTO(item.getItemCode(), item.getName(), item.getPrice(), item.getQty()); + itemDTOS.add(itemDTO); + } + return itemDTOS; + } + + @Override + public void addItem(ItemDTO itemDTO) { + if (!itemRepo.existsById(itemDTO.getItemCode())) { + Item item = new Item(itemDTO.getItemCode(), itemDTO.getName(), itemDTO.getPrice(), itemDTO.getQty()); + itemRepo.save(item); + } else { + throw new RuntimeException("Item Already Exists"); + } + } + @Override + public void updateItem(ItemDTO itemDTO) { + if (itemRepo.existsById(itemDTO.getItemCode())) { + Item item = new Item(itemDTO.getItemCode(), itemDTO.getName(), itemDTO.getPrice(), itemDTO.getQty()); + itemRepo.save(item); + } else { + throw new RuntimeException("Item Not Found"); + } + } + @Override + public void deleteItem(String id) { + if (itemRepo.existsById(id)) { + itemRepo.deleteById(id); + } else { + throw new RuntimeException("Item Not Found"); + } + } + + @Override + public String generateNextItemId() { + Item item = itemRepo.findFirstByOrderByItemCodeDesc(); + if (item == null) { + return "I001"; + } else { + String lastId = item.getItemCode(); + int newId = Integer.parseInt(lastId.substring(1)) + 1; + if (newId < 10) { + return "I00" + newId; + } else if (newId < 100) { + return "I0" + newId; + } else { + return "I" + newId; + } + } + } +} diff --git a/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/service/Impl/OrderServiceImpl.java b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/service/Impl/OrderServiceImpl.java new file mode 100644 index 0000000..96df79e --- /dev/null +++ b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/service/Impl/OrderServiceImpl.java @@ -0,0 +1,111 @@ +package lk.ijse.spring_boot.service.Impl; + +import lk.ijse.spring_boot.Repo.CustomerRepo; +import lk.ijse.spring_boot.Repo.ItemRepo; +import lk.ijse.spring_boot.Repo.OrderRepo; +import lk.ijse.spring_boot.dto.OrderDTO; +import lk.ijse.spring_boot.dto.OrderDetailDTO; +import lk.ijse.spring_boot.entity.Customer; +import lk.ijse.spring_boot.entity.Item; +import lk.ijse.spring_boot.entity.Order; +import lk.ijse.spring_boot.entity.OrderDetail; +import lk.ijse.spring_boot.service.OrderService; +import lk.ijse.spring_boot.util.ResponseUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +@Service +public class OrderServiceImpl implements OrderService { + @Autowired + private OrderRepo orderRepo; + + @Autowired + private CustomerRepo customerRepo; + + @Autowired + private ItemRepo itemRepo; + + @Override + @Transactional + public ResponseUtil saveOrder(OrderDTO orderDTO) { + // Validate order existence + if (orderRepo.existsById(orderDTO.getOrderId())) { + return new ResponseUtil(400, "Order Already Exists", null); + } + + // Validate customer + Optional customer = customerRepo.findById(orderDTO.getCustomerId()); + if (customer.isEmpty()) { + return new ResponseUtil(404, "Customer Not Found", null); + } + + List orderDetails = new ArrayList<>(); + double totalAmount = 0.0; + + // Process each order detail + for (OrderDetailDTO detailDTO : orderDTO.getOrderDetails()) { + Optional item = itemRepo.findById(detailDTO.getItemCode()); + + if (item.isEmpty()) { + return new ResponseUtil(404, "Item Not Found: " + detailDTO.getItemCode(), null); + } + + Item itemEntity = item.get(); + if (itemEntity.getQty() < detailDTO.getQuantity()) { + return new ResponseUtil(400, "Insufficient Stock for Item: " + itemEntity.getName(), null); + } + + // Update item stock + itemEntity.setQty(itemEntity.getQty() - detailDTO.getQuantity()); + itemRepo.save(itemEntity); + + // Create order detail + OrderDetail detail = new OrderDetail( + itemEntity, + detailDTO.getQuantity(), + detailDTO.getUnitPrice() + ); + orderDetails.add(detail); + + // Calculate total + totalAmount += (detailDTO.getQuantity() * detailDTO.getUnitPrice()); + } + + // Create and save order + Order order = new Order( + orderDTO.getOrderId(), + LocalDateTime.now(), + customer.get(), + orderDetails, + totalAmount + ); + + orderRepo.save(order); + return new ResponseUtil(201, "Order Added Successfully", null); + } + + @Override + public String generateNextOrderId() { + Order order = orderRepo.findFirstByOrderByOrderIdDesc(); + if (order == null) { + return "OD001"; + } else { + String lastId = order.getOrderId(); + int newId = Integer.parseInt(lastId.substring(2)) + 1; + if (newId < 10) { + return "OD00" + newId; + } else if (newId < 100) { + return "OD0" + newId; + } else { + return "OD" + newId; + } + } + + } +} \ No newline at end of file diff --git a/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/service/ItemService.java b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/service/ItemService.java index 6416d58..6370adf 100644 --- a/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/service/ItemService.java +++ b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/service/ItemService.java @@ -1,37 +1,13 @@ package lk.ijse.spring_boot.service; -import lk.ijse.spring_boot.Repo.ItemRepo; import lk.ijse.spring_boot.dto.ItemDTO; -import lk.ijse.spring_boot.entity.Customer; -import lk.ijse.spring_boot.entity.Item; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import java.util.ArrayList; import java.util.List; -@Service -public class ItemService { - @Autowired - private ItemRepo itemRepo; - - public List getAllItems() { - List all = itemRepo.findAll(); - List itemDTOS = new ArrayList<>(); - for (Item item : all) { - ItemDTO itemDTO = new ItemDTO(item.getItemCode(), item.getName(), item.getPrice(), item.getQty()); - itemDTOS.add(itemDTO); - } - return itemDTOS; - } - - public boolean addItem(ItemDTO itemDTO) { - if (itemRepo.existsById(itemDTO.getItemCode())) { - return false; - }else { - Item item = new Item(itemDTO.getItemCode(),itemDTO.getName(),itemDTO.getPrice(),itemDTO.getQty()); - itemRepo.save(item); - return true; - } - } +public interface ItemService { + List getAllItems(); + void addItem(ItemDTO itemDTO); + void updateItem(ItemDTO itemDTO); + void deleteItem(String id); + String generateNextItemId(); } diff --git a/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/service/OrderService.java b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/service/OrderService.java index c369d38..e6c3073 100644 --- a/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/service/OrderService.java +++ b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/service/OrderService.java @@ -1,78 +1,10 @@ package lk.ijse.spring_boot.service; -import lk.ijse.spring_boot.Repo.CustomerRepo; -import lk.ijse.spring_boot.Repo.ItemRepo; -import lk.ijse.spring_boot.Repo.OrderRepo; import lk.ijse.spring_boot.dto.OrderDTO; - -import lk.ijse.spring_boot.dto.OrderDetailDTO; -import lk.ijse.spring_boot.entity.Customer; -import lk.ijse.spring_boot.entity.Item; import lk.ijse.spring_boot.entity.Order; -import lk.ijse.spring_boot.entity.OrderDetail; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -@Service -public class OrderService { - @Autowired - private OrderRepo orderRepo; - - @Autowired - private CustomerRepo customerRepo; - - @Autowired - private ItemRepo itemRepo; - - @Transactional - public boolean saveOrder(OrderDTO orderDTO) { - if (orderRepo.existsById(orderDTO.getOrderId())) { - return false; - } - - Optional customer = customerRepo.findById(orderDTO.getCustomerId()); - if (customer.isEmpty()) { - return false; - } - - List orderDetails = new ArrayList<>(); - - for (OrderDetailDTO detailDTO : orderDTO.getOrderDetails()) { - Optional item = itemRepo.findById(detailDTO.getItemCode()); - - if (item.isEmpty()) { - return false; - } - - Item itemEntity = item.get(); - if (itemEntity.getQty() < detailDTO.getQuantity()) { - return false; - } - itemEntity.setQty(itemEntity.getQty() - detailDTO.getQuantity()); - itemRepo.save(itemEntity); - - OrderDetail detail = new OrderDetail( - itemEntity, - detailDTO.getQuantity(), - detailDTO.getUnitPrice() - ); - orderDetails.add(detail); - } - - Order order = new Order( - orderDTO.getOrderId(), - orderDTO.getOrderDate(), - customer.get(), - orderDetails, - orderDTO.getTotal() - ); +import lk.ijse.spring_boot.util.ResponseUtil; - orderRepo.save(order); - return true; - } -} \ No newline at end of file +public interface OrderService { + ResponseUtil saveOrder(OrderDTO orderDTO); + String generateNextOrderId(); +} diff --git a/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/util/ResponseUtil.java b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/util/ResponseUtil.java new file mode 100644 index 0000000..31cb50d --- /dev/null +++ b/13_Spring_Boot/src/main/java/lk/ijse/spring_boot/util/ResponseUtil.java @@ -0,0 +1,53 @@ +package lk.ijse.spring_boot.util; + +import org.springframework.stereotype.Component; + +@Component +public class ResponseUtil { + + private int code; + private String message; + private Object data; + + public ResponseUtil() { + } + + public ResponseUtil(int code, String message, Object data) { + this.code = code; + this.message = message; + this.data = data; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public Object getData() { + return data; + } + + public void setData(Object data) { + this.data = data; + } + + @Override + public String toString() { + return "ResponseUtil{" + + "code=" + code + + ", message='" + message + '\'' + + ", data=" + data + + '}'; + } +} diff --git a/14_Springboot_Frontend/pom.xml b/14_Springboot_Frontend/pom.xml new file mode 100644 index 0000000..6c48530 --- /dev/null +++ b/14_Springboot_Frontend/pom.xml @@ -0,0 +1,17 @@ + + + 4.0.0 + + lk.ijse + 14_Springboot_Frontend + 1.0-SNAPSHOT + + + 17 + 17 + UTF-8 + + + \ No newline at end of file diff --git a/14_Springboot_Frontend/src/main/java/lk/ijse/Item.html b/14_Springboot_Frontend/src/main/java/lk/ijse/Item.html new file mode 100644 index 0000000..15b1d98 --- /dev/null +++ b/14_Springboot_Frontend/src/main/java/lk/ijse/Item.html @@ -0,0 +1,127 @@ + + + + + + Item Management + + + + + + + + + + + + + + Item Management + + + + + + + Add New Item + + + + + Item ID + + + + Name + + + + Price + + + + + Qty + + + + Save Item + + + + Update Item + + + Clear Form + + + + Dashboard + + + + Are you sure you want to delete this item? This action cannot be undone. + + + Cancel + + + Delete + + + + + + + + + + + Item List + + + + + + + + + Total: 0 items + + + + + + + + ID + Name + Price + Qty + Actions + + + + + + + + + + + No items found + + + + + + + + + + + + + + \ No newline at end of file diff --git a/14_Springboot_Frontend/src/main/java/lk/ijse/componnent/components.js b/14_Springboot_Frontend/src/main/java/lk/ijse/componnent/components.js new file mode 100644 index 0000000..5dd04ba --- /dev/null +++ b/14_Springboot_Frontend/src/main/java/lk/ijse/componnent/components.js @@ -0,0 +1,100 @@ +// Define your navigation component HTML +const navComponent = ` + + + + + + + Chama Store + + + + + + + + + Dashboard + + + + + New Order + + + + + Customers + + + + + Item + + + + + + + +`; + +// Function to load components +function loadComponents() { + // Insert navigation + const navPlaceholder = document.getElementById('nav-placeholder'); + if (navPlaceholder) { + navPlaceholder.innerHTML = navComponent; + } + + // Set active link based on current page + const currentPage = window.location.pathname.split('/').pop(); + const navLinks = document.querySelectorAll('.navbar-nav .nav-link'); + + navLinks.forEach(link => { + const href = link.getAttribute('href'); + if (href === currentPage) { + link.classList.add('active'); + } else { + link.classList.remove('active'); + } + }); +} + +// Load components when DOM is ready +document.addEventListener('DOMContentLoaded', loadComponents); \ No newline at end of file diff --git a/14_Springboot_Frontend/src/main/java/lk/ijse/css/customer.css b/14_Springboot_Frontend/src/main/java/lk/ijse/css/customer.css new file mode 100644 index 0000000..41e9407 --- /dev/null +++ b/14_Springboot_Frontend/src/main/java/lk/ijse/css/customer.css @@ -0,0 +1,324 @@ +:root { + --primary: #2563eb; + --primary-dark: #1d4ed8; + --danger: #ef4444; + --success: #10b981; + --dark: #1e293b; + --light: #f8fafc; + --gray: #e2e8f0; + --text: #334155; + --border: #cbd5e1; + --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); + --radius: 8px; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Segoe UI', system-ui, -apple-system, sans-serif; + background-color: #f1f5f9; + color: var(--text); + line-height: 1.5; + padding: 2rem; +} + +.container { + max-width: 1200px; + margin: 0 auto; +} + +header { + margin-bottom: 2rem; +} + +h1 { + color: var(--dark); + font-size: 1.875rem; + margin-bottom: 0.5rem; +} + +.content-wrapper { + display: grid; + grid-template-columns: 350px 1fr; + gap: 1.5rem; +} + +@media (max-width: 992px) { + .content-wrapper { + grid-template-columns: 1fr; + } +} + +.card { + background-color: white; + border-radius: var(--radius); + box-shadow: var(--shadow); + overflow: hidden; +} + +.card-header { + padding: 1rem; + border-bottom: 1px solid var(--gray); +} + +.card-title { + font-size: 1.25rem; + font-weight: 600; + color: var(--dark); +} + +.card-body { + padding: 1.5rem; +} + +/* Form */ +.form-group { + margin-bottom: 1.25rem; +} + +label { + display: block; + margin-bottom: 0.5rem; + font-weight: 500; + color: var(--dark); + font-size: 0.875rem; +} + +.form-control { + width: 100%; + padding: 0.625rem 0.875rem; + border: 1px solid var(--border); + border-radius: var(--radius); + font-size: 0.875rem; +} + +.form-control:focus { + outline: none; + border-color: var(--primary); + box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1); +} + +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + padding: 0.625rem 1rem; + background-color: var(--primary); + color: white; + border: none; + border-radius: var(--radius); + font-weight: 500; + font-size: 0.875rem; + cursor: pointer; + transition: background-color 0.2s, transform 0.1s; +} + +.btn:hover { + background-color: var(--primary-dark); +} + +.btn:active { + transform: translateY(1px); +} + +.btn i { + margin-right: 0.5rem; +} + +.btn-block { + width: 100%; +} + +.btn-danger { + background-color: var(--danger); +} + +.btn-sm { + padding: 0.375rem 0.75rem; + font-size: 0.75rem; +} + +.btn-icon { + width: 2rem; + height: 2rem; + padding: 0; + display: inline-flex; + align-items: center; + justify-content: center; +} + +.btn-icon i { + margin-right: 0; +} + +/* Table */ +.table-controls { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1rem; +} + +.search-container { + position: relative; + width: 250px; +} + +.search-input { + width: 100%; + padding: 0.5rem 1rem 0.5rem 2.25rem; + border: 1px solid var(--border); + border-radius: var(--radius); + font-size: 0.875rem; +} + +.search-icon { + position: absolute; + left: 0.75rem; + top: 50%; + transform: translateY(-50%); + color: #94a3b8; +} + +table { + width: 100%; + border-collapse: collapse; +} + +th, td { + text-align: left; + padding: 0.75rem 1rem; + border-bottom: 1px solid var(--gray); + font-size: 0.875rem; +} + +th { + font-weight: 600; + color: var(--dark); + background-color: #f8fafc; +} + +tr:last-child td { + border-bottom: none; +} + +tr:hover { + background-color: #f8fafc; +} + +.action-cell { + width: 120px; + white-space: nowrap; +} + +.empty-table { + padding: 3rem 1rem; + text-align: center; + color: #64748b; +} + +.empty-icon { + font-size: 2.5rem; + color: #94a3b8; + margin-bottom: 1rem; +} + +/* Toast Notification */ +.toast-container { + position: fixed; + bottom: 1.5rem; + right: 1.5rem; + z-index: 1010; +} + +.toast { + display: flex; + align-items: center; + padding: 0.75rem 1rem; + background-color: white; + border-radius: var(--radius); + box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); + margin-top: 0.75rem; + transform: translateX(150%); + transition: transform 0.3s; + max-width: 350px; +} + +.toast.show { + transform: translateX(0); +} + +.toast.success .toast-icon { + background-color: #dcfce7; + color: #166534; +} + +.toast.error .toast-icon { + background-color: #fee2e2; + color: #991b1b; +} + +.toast-icon { + width: 2rem; + height: 2rem; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin-right: 0.75rem; + flex-shrink: 0; +} + +.toast-content { + flex-grow: 1; +} + +.toast-title { + font-weight: 600; + font-size: 0.875rem; + margin-bottom: 0.25rem; +} + +.toast-message { + font-size: 0.8125rem; + color: #64748b; +} + +.toast-close { + background: none; + border: none; + color: #94a3b8; + cursor: pointer; + padding: 0.5rem; + margin: -0.5rem; + flex-shrink: 0; +} + +/* Confirmations */ +.confirm-delete { + display: none; + background-color: #fee2e2; + border: 1px solid #fecaca; + border-radius: var(--radius); + padding: 0.75rem; + margin-top: 0.5rem; +} + +.confirm-delete.show { + display: block; +} + +.confirm-message { + color: #991b1b; + font-size: 0.875rem; + margin-bottom: 0.75rem; +} + +.confirm-actions { + display: flex; + gap: 0.5rem; +} diff --git a/14_Springboot_Frontend/src/main/java/lk/ijse/css/dashboard.css b/14_Springboot_Frontend/src/main/java/lk/ijse/css/dashboard.css new file mode 100644 index 0000000..f539a26 --- /dev/null +++ b/14_Springboot_Frontend/src/main/java/lk/ijse/css/dashboard.css @@ -0,0 +1,180 @@ +:root { + --primary: #4361ee; + --dark: #2b2d42; + --light: #f8f9fa; + --gray: #e9ecef; + --shadow: 0 4px 12px rgba(0, 0, 0, 0.1); + --transition: all 0.3s ease; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Segoe UI', system-ui, -apple-system, sans-serif; + background-color: var(--gray); + color: var(--dark); + padding: 2rem; + line-height: 1.5; +} + +.container { + max-width: 1200px; + margin: 0 auto; +} + +header { + text-align: center; + margin-bottom: 3rem; +} + +h1 { + font-size: 2.5rem; + margin-bottom: 0.5rem; + color: var(--dark); +} + +.subtitle { + font-size: 1.1rem; + color: #6c757d; + margin-bottom: 1rem; +} + +.cards-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + gap: 2rem; +} + +.card { + background-color: white; + border-radius: 12px; + box-shadow: var(--shadow); + overflow: hidden; + transition: var(--transition); + cursor: pointer; + text-decoration: none; + color: inherit; + height: 100%; + display: flex; + flex-direction: column; +} + +.card:hover { + transform: translateY(-5px); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); +} + +.card:active { + transform: translateY(-2px); +} + +.card-icon { + background-color: var(--primary); + color: white; + height: 120px; + display: flex; + align-items: center; + justify-content: center; +} + +.card-icon i { + font-size: 3rem; +} + +.card-content { + padding: 1.5rem; + flex: 1; +} + +.card-title { + font-size: 1.4rem; + font-weight: 600; + margin-bottom: 0.5rem; +} + +.card-description { + color: #6c757d; + font-size: 0.95rem; +} + +.card-footer { + display: flex; + align-items: center; + padding: 1rem 1.5rem; + background-color: #f8f9fa; + border-top: 1px solid #e9ecef; +} + +.card-footer span { + color: #6c757d; + font-size: 0.9rem; +} + +.card-footer i { + margin-left: auto; + color: var(--primary); +} + +@media (max-width: 768px) { + body { + padding: 1rem; + } + + .cards-grid { + grid-template-columns: 1fr; + gap: 1.5rem; + } + + h1 { + font-size: 2rem; + } +} + +/* Page Content Styling */ +.page { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: white; + z-index: 100; + overflow-y: auto; + padding: 2rem; +} + +.page.active { + display: block; +} + +.page-header { + display: flex; + align-items: center; + margin-bottom: 2rem; +} + +.back-button { + background: none; + border: none; + color: var(--primary); + font-size: 1.2rem; + cursor: pointer; + display: flex; + align-items: center; + margin-right: 1rem; +} + +.page-title { + font-size: 1.8rem; + font-weight: 600; +} + +.page-content { + max-width: 1000px; + margin: 0 auto; +} diff --git a/14_Springboot_Frontend/src/main/java/lk/ijse/css/item.css b/14_Springboot_Frontend/src/main/java/lk/ijse/css/item.css new file mode 100644 index 0000000..df3be6f --- /dev/null +++ b/14_Springboot_Frontend/src/main/java/lk/ijse/css/item.css @@ -0,0 +1,258 @@ +:root { + --primary: #2563eb; + --primary-dark: #1d4ed8; + --danger: #ef4444; + --success: #10b981; + --dark: #1e293b; + --light: #f8fafc; + --gray: #e2e8f0; + --text: #334155; + --border: #cbd5e1; + --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); + --radius: 8px; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Segoe UI', system-ui, -apple-system, sans-serif; + background-color: #f1f5f9; + color: var(--text); + line-height: 1.5; + padding: 2rem; +} + +.container { + max-width: 1200px; + margin: 0 auto; +} + +header { + margin-bottom: 2rem; +} + +h1 { + color: var(--dark); + font-size: 1.875rem; + margin-bottom: 0.5rem; +} + +.content-wrapper { + display: grid; + grid-template-columns: 350px 1fr; + gap: 1.5rem; +} + +@media (max-width: 992px) { + .content-wrapper { + grid-template-columns: 1fr; + } +} + +.card { + background-color: white; + border-radius: var(--radius); + box-shadow: var(--shadow); + overflow: hidden; +} + +.card-header { + padding: 1rem; + border-bottom: 1px solid var(--gray); +} + +.card-title { + font-size: 1.25rem; + font-weight: 600; + color: var(--dark); +} + +.card-body { + padding: 1.5rem; +} + +/* Form */ +.form-group { + margin-bottom: 1.25rem; +} + +label { + display: block; + margin-bottom: 0.5rem; + font-weight: 500; + color: var(--dark); + font-size: 0.875rem; +} + +.form-control { + width: 100%; + padding: 0.625rem 0.875rem; + border: 1px solid var(--border); + border-radius: var(--radius); + font-size: 0.875rem; +} + +.form-control:focus { + outline: none; + border-color: var(--primary); + box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1); +} + +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + padding: 0.625rem 1rem; + background-color: var(--primary); + color: white; + border: none; + border-radius: var(--radius); + font-weight: 500; + font-size: 0.875rem; + cursor: pointer; + transition: background-color 0.2s, transform 0.1s; +} + +.btn:hover { + background-color: var(--primary-dark); +} + +.btn:active { + transform: translateY(1px); +} + +.btn i { + margin-right: 0.5rem; +} + +.btn-block { + width: 100%; +} + +.btn-danger { + background-color: var(--danger); +} + +.btn-sm { + padding: 0.375rem 0.75rem; + font-size: 0.75rem; +} + + +.btn-icon i { + margin-right: 0; +} + +/* Table */ +.table-controls { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1rem; +} + +.search-container { + position: relative; + width: 250px; +} + +.search-input { + width: 100%; + padding: 0.5rem 1rem 0.5rem 2.25rem; + border: 1px solid var(--border); + border-radius: var(--radius); + font-size: 0.875rem; +} + +.search-icon { + position: absolute; + left: 0.75rem; + top: 50%; + transform: translateY(-50%); + color: #94a3b8; +} + +table { + width: 100%; + border-collapse: collapse; +} + +th, td { + text-align: left; + padding: 0.75rem 1rem; + border-bottom: 1px solid var(--gray); + font-size: 0.875rem; +} + +th { + font-weight: 600; + color: var(--dark); + background-color: #f8fafc; +} + +tr:last-child td { + border-bottom: none; +} + +tr:hover { + background-color: #f8fafc; +} + +.empty-table { + padding: 3rem 1rem; + text-align: center; + color: #64748b; +} + +.empty-icon { + font-size: 2.5rem; + color: #94a3b8; + margin-bottom: 1rem; +} + +/* Toast Notification */ +.toast-container { + position: fixed; + bottom: 1.5rem; + right: 1.5rem; + z-index: 1010; +} + +.toast.success .toast-icon { + background-color: #dcfce7; + color: #166534; +} + +.toast.error .toast-icon { + background-color: #fee2e2; + color: #991b1b; +} + +/* Confirmations */ +.confirm-delete { + display: none; + background-color: #fee2e2; + border: 1px solid #fecaca; + border-radius: var(--radius); + padding: 0.75rem; + margin-top: 0.5rem; +} + +.confirm-delete.show { + display: block; +} + +.confirm-message { + color: #991b1b; + font-size: 0.875rem; + margin-bottom: 0.75rem; +} + +.confirm-actions { + display: flex; + gap: 0.5rem; +} diff --git a/14_Springboot_Frontend/src/main/java/lk/ijse/css/order.css b/14_Springboot_Frontend/src/main/java/lk/ijse/css/order.css new file mode 100644 index 0000000..7f1f0b8 --- /dev/null +++ b/14_Springboot_Frontend/src/main/java/lk/ijse/css/order.css @@ -0,0 +1,359 @@ +:root { + --primary: #4f46e5; + --primary-light: #6366f1; + --primary-dark: #4338ca; + --secondary: #0ea5e9; + --success: #10b981; + --danger: #ef4444; + --warning: #f59e0b; + --light: #f8fafc; + --dark: #0f172a; +} + +body { + font-family: 'Segoe UI', system-ui, -apple-system, sans-serif; + background-color: #f1f5f9; + color: var(--text); + line-height: 1.5; + padding: 2rem 2rem 0 2rem; +} + + +.app-container { + max-width: 1400px; + margin: 0 auto; +} + +.page-header { + padding: 0 1rem 1rem 1rem; + margin-bottom: 2rem; +} + +.card { + border: none; + border-radius: 1rem; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.05); + transition: all 0.3s ease; + overflow: hidden; + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(10px); + margin-bottom: 1.5rem; +} + +.card:hover { + transform: translateY(-5px); + box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1); +} + +.card-header { + background: transparent; + border-bottom: 1px solid rgba(0, 0, 0, 0.05); + padding: 1.5rem; +} + +.card-body { + padding: 1.5rem; +} + +.card-title { + font-weight: 600; + margin-bottom: 1.25rem; + display: flex; + align-items: center; + color: var(--primary); +} + +.card-title i { + margin-right: 0.75rem; + font-size: 1.25rem; +} + +.form-control, .form-select { + border: 2px solid rgba(0, 0, 0, 0.05); + border-radius: 0.75rem; + padding: 0.75rem 1rem; + font-size: 1rem; + transition: all 0.2s ease; + background-color: rgba(255, 255, 255, 0.8); +} + +.form-control:focus, .form-select:focus { + border-color: var(--primary-light); + box-shadow: 0 0 0 0.25rem rgba(99, 102, 241, 0.15); +} + +.form-control-lg, .form-select-lg { + height: 3.5rem; + font-size: 1rem; +} + +.btn { + padding: 0.75rem 1.5rem; + border-radius: 0.75rem; + font-weight: 500; + letter-spacing: 0.3px; + transition: all 0.3s ease; +} + +.btn-primary { + background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%); + border: none; +} + +.btn-primary:hover { + background: linear-gradient(135deg, var(--primary-dark) 0%, var(--primary-dark) 100%); + transform: translateY(-2px); + box-shadow: 0 5px 15px rgba(79, 70, 229, 0.3); +} + +.btn-success { + background: linear-gradient(135deg, var(--success) 0%, #059669 100%); + border: none; +} + +.btn-success:hover { + background: linear-gradient(135deg, #059669 0%, #047857 100%); + transform: translateY(-2px); + box-shadow: 0 5px 15px rgba(16, 185, 129, 0.3); +} + +.btn-danger { + background: linear-gradient(135deg, var(--danger) 0%, #dc2626 100%); + border: none; +} + +.btn-danger:hover { + background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%); + transform: translateY(-2px); + box-shadow: 0 5px 15px rgba(239, 68, 68, 0.3); +} + +.btn-icon { + display: inline-flex; + align-items: center; + justify-content: center; +} + +.btn-icon i { + margin-right: 0.5rem; +} + +.details-panel { + background: rgba(79, 70, 229, 0.03); + border-radius: 0.75rem; + padding: 1.5rem; + border: 1px solid rgba(79, 70, 229, 0.1); + height: 100%; +} + +.details-panel h6 { + color: var(--primary); + font-weight: 600; + margin-bottom: 1.25rem; + padding-bottom: 0.75rem; + border-bottom: 1px solid rgba(79, 70, 229, 0.1); +} + +.details-panel .detail-item { + display: flex; + justify-content: space-between; + margin-bottom: 1rem; + padding-bottom: 1rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.05); +} + +.details-panel .detail-item:last-child { + margin-bottom: 0; + padding-bottom: 0; + border-bottom: none; +} + +.details-panel .detail-label { + color: #64748b; + font-size: 0.925rem; +} + +.details-panel .detail-value { + font-weight: 500; + text-align: right; +} + +.table { + border-radius: 0.75rem; + overflow: hidden; + margin-bottom: 0; +} + +.table th { + font-weight: 600; + color: #1e293b; + background-color: rgba(241, 245, 249, 0.8); + padding: 1rem; +} + +.table td { + padding: 1rem; + vertical-align: middle; +} + +.badge { + padding: 0.5rem 0.75rem; + font-weight: 500; + border-radius: 0.5rem; +} + +.remove-btn { + color: var(--danger); + background: rgba(239, 68, 68, 0.05); + border: none; + border-radius: 0.5rem; + padding: 0.5rem 0.75rem; + transition: all 0.2s ease; + font-size: 0.875rem; +} + +.remove-btn:hover { + background: rgba(239, 68, 68, 0.1); + color: #b91c1c; +} + +.total-section { + background: linear-gradient(135deg, rgba(79, 70, 229, 0.05) 0%, rgba(14, 165, 233, 0.05) 100%); + border-radius: 0.75rem; + padding: 1.5rem; + margin-top: 1.5rem; + border: 1px solid rgba(79, 70, 229, 0.1); +} + +.total-amount { + font-size: 1.5rem; + font-weight: 700; + color: var(--primary-dark); +} + +#toastContainer { + position: fixed; + top: 20px; + right: 20px; + z-index: 1050; +} + +.toast { + background: white; + border-radius: 0.75rem; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); + margin-bottom: 1rem; + padding: 1rem 1.25rem; + display: flex; + align-items: center; + min-width: 300px; + transform: translateX(120%); + transition: transform 0.3s ease; + border-left: 4px solid transparent; +} + +.toast.show { + transform: translateX(0); +} + +.toast.success { + border-left-color: var(--success); +} + +.toast.error { + border-left-color: var(--danger); +} + +.toast-content { + flex-grow: 1; + margin: 0 0.75rem; +} + +.toast-close { + background: none; + border: none; + color: #94a3b8; + cursor: pointer; + transition: color 0.2s ease; + padding: 0.25rem; +} + +.toast-close:hover { + color: #475569; +} + +.order-id-container { + background: rgba(79, 70, 229, 0.05); + border: 1px solid rgba(79, 70, 229, 0.1); + border-radius: 0.75rem; + padding: 1rem 1.5rem; + margin-bottom: 1.5rem; +} + +.order-id-label { + display: block; + font-size: 0.875rem; + font-weight: 500; + color: #64748b; + margin-bottom: 0.5rem; +} + +.order-id-value { + font-size: 1.25rem; + font-weight: 600; + color: var(--primary); + letter-spacing: 0.5px; +} + +@media (max-width: 992px) { + .app-container { + padding: 1rem; + } + + .page-header { + padding: 1.5rem 0; + } + + .order-id-container { + margin-top: 1rem; + } +} + +/* Loading spinner for selects */ +.select-loading::after { + content: ""; + position: absolute; + right: 10px; + top: 50%; + transform: translateY(-50%); + width: 20px; + height: 20px; + border-radius: 50%; + border: 2px solid rgba(79, 70, 229, 0.2); + border-top-color: var(--primary); + animation: spin 0.8s linear infinite; +} + +@keyframes spin { + to { + transform: translateY(-50%) rotate(360deg); + } +} + +/* Empty cart illustration */ +.empty-cart { + text-align: center; + padding: 2rem; + color: #94a3b8; +} + +.empty-cart i { + font-size: 3rem; + margin-bottom: 1rem; + opacity: 0.5; +} + +.empty-cart p { + font-size: 1.125rem; + margin-bottom: 1.5rem; +} \ No newline at end of file diff --git a/14_Springboot_Frontend/src/main/java/lk/ijse/customer.html b/14_Springboot_Frontend/src/main/java/lk/ijse/customer.html new file mode 100644 index 0000000..106d81a --- /dev/null +++ b/14_Springboot_Frontend/src/main/java/lk/ijse/customer.html @@ -0,0 +1,135 @@ + + + + + + Customer Management + + + + + + + + + + + + + Customer Management + + + + + + + + Add New Customer + + + + + Customer ID + + + + Name + + + + Address + + + + + Save Customer + + + + Update Customer + + + + Clear Form + + + Dashboard + + + + Are you sure you want to delete this customer? This action cannot be undone. + + + Cancel + + + Delete + + + + + + + + + + + Customer List + + + + + + + + + + + + + + ID + Name + Address + Actions + + + + + + + + + + + + No customers found + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/14_Springboot_Frontend/src/main/java/lk/ijse/dashboard.html b/14_Springboot_Frontend/src/main/java/lk/ijse/dashboard.html new file mode 100644 index 0000000..d1388f2 --- /dev/null +++ b/14_Springboot_Frontend/src/main/java/lk/ijse/dashboard.html @@ -0,0 +1,146 @@ + + + + + + Dashboard + + + + + + + Dashboard + Select a module to get started + + + + + + + + + + Customers + Manage customer profiles, view history and track engagement. + + + + + + + + + + + Items + Inventory management, stock levels and product catalog. + + + + + + + + + + + Orders + Process orders, track shipments and manage fulfillment. + + + + + + + + + + + Analytics + Business insights, reports and performance metrics. + + + + + + + + + + + Settings + Configure system preferences, users and permissions. + + + + + + + + + + + + + + + + + Customer Count + Process Customer Count,And Give Numerical Value + + + + + + + + + + Item Count + Process Item Count,And Give Numerical Value + + + + + + + + + + Order Count + Process Order Count,And Give Numerical Value + + + + + + + + + \ No newline at end of file diff --git a/14_Springboot_Frontend/src/main/java/lk/ijse/js/customer.js b/14_Springboot_Frontend/src/main/java/lk/ijse/js/customer.js new file mode 100644 index 0000000..4b67728 --- /dev/null +++ b/14_Springboot_Frontend/src/main/java/lk/ijse/js/customer.js @@ -0,0 +1,284 @@ +$("#saveCustomerBtn").click(function(event) { + event.preventDefault(); + + if (!$("#customerName").val() || !$("#customerAddress").val()) { + showToast('Please fill all the fields', 'error'); + return; + } + + var customerID = $("#customerId").val(); + var customerName = $("#customerName").val(); + var customerAddress = $("#customerAddress").val(); + + var customer = { + "id": customerID, + "name": customerName, + "address": customerAddress + } + + $.ajax({ + method: "POST", + url: "http://localhost:8080/api/v1/customer/save", + contentType: "application/json", + data: JSON.stringify(customer), + success: function(response) { + if (response.code === 201) { + showToast('Customer saved successfully', 'success'); + $("#customerForm")[0].reset(); + loadCustomers(); + generateNextCustomerId(); + } else { + showToast('Failed to save the customer','error'); + } + }, + error: function(xhr, status, error) { + showToast('Error saving customer: ' + error, 'error'); + console.error("AJAX Error: " + status + " - " + error); + } + }); +}); + +$("#updateCustomerBtn").click(function(event) { + event.preventDefault(); + + if (!$("#customerName").val() || !$("#customerAddress").val()) { + showToast('Please fill all the fields', 'error'); + return; + } + + var customerID = $("#customerId").val(); + var customerName = $("#customerName").val(); + var customerAddress = $("#customerAddress").val(); + + var customer = { + "id": customerID, + "name": customerName, + "address": customerAddress + } + $.ajax({ + method: "PUT", + url: "http://localhost:8080/api/v1/customer/update", + contentType: "application/json", + data: JSON.stringify(customer), + success: function(response) { + if (response.code === 201) { + showToast('Customer updated successfully', 'success'); + resetForm(); + loadCustomers(); + } else { + showToast('Failed to update the customer', 'error'); + } + }, + error: function(xhr, status, error) { + showToast('Error updating customer: ' + error, 'error'); + } + }) +}); + +function loadCustomers() { + $.ajax({ + method: "GET", + url: "http://localhost:8080/api/v1/customer/getAll", + success: function(response) { + const customers = response.data; + if (customers && customers.length > 0) { + $("#emptyTable").hide(); + $("#customerTable").show(); + + var tbody = $("#customerTableBody"); + tbody.empty(); + + $.each(customers, function(index, customer) { + var row = $(""); + row.append($("").text(customer.id || "-")); + row.append($("").text(customer.name || "-")); + row.append($("").text(customer.address || "-")); + + var actionsCell = $("").addClass("action-cell"); + + var editBtn = $("") + .addClass("btn btn-sm btn-icon") + .css("background-color", "#fbbf24") + .css("margin-right", "5px") + .html('') + .click(function() { + editCustomer(customer); + }); + + var deleteBtn = $("") + .addClass("btn btn-sm btn-icon btn-danger") + .html('') + .click(function() { + deleteCustomer(customer); + }); + + actionsCell.append(editBtn, deleteBtn); + row.append(actionsCell); + + tbody.append(row); + }); + + updateTotalCustomers(); + } else { + $("#customerTable").hide(); + $("#emptyTable").show(); + } + }, + error: function(xhr, status, error) { + showToast('Error loading customers: ' + error, 'error'); + $("#customerTable").hide(); + $("#emptyTable").show(); + } + }); +} + +$(document).ready(function() { + loadCustomers(); + generateNextCustomerId(); + + $("#resetFormBtn").click(function() { + resetForm(); + }); + + $("#searchInput").on("input", function() { + var searchTerm = $(this).val().toLowerCase(); + $("#customerTableBody tr").filter(function() { + $(this).toggle($(this).text().toLowerCase().indexOf(searchTerm) > -1); + }); + + if ($("#customerTableBody tr:visible").length === 0) { + $("#emptyTable").show(); + $("#customerTable").hide(); + } else { + $("#emptyTable").hide(); + $("#customerTable").show(); + } + updateTotalCustomers(); + }); +}); + +function editCustomer(customer) { + $("#formTitle").text("Edit Customer"); + $("#customerId").val(customer.id).prop("disabled", true); + $("#customerName").val(customer.name); + $("#customerAddress").val(customer.address); + $("#confirmDelete").removeClass("show"); + $("#saveCustomerBtn").hide(); + $("#updateCustomerBtn").show(); + + if (window.innerWidth < 992) { + $("#customerForm")[0].scrollIntoView({ behavior: 'smooth' }); + } +} + +function deleteCustomer(customer) { + $("#formTitle").text("Delete Customer"); + $("#customerId").val(customer.id).prop("disabled", true); + $("#customerName").val(customer.name).prop("disabled", true); + $("#customerAddress").val(customer.address).prop("disabled", true); + $("#saveCustomerBtn").prop("disabled", true); + $("#updateCustomerBtn").hide(); + $("#confirmDelete").addClass("show"); + + $("#confirmDeleteBtn").off("click").on("click", function() { + $.ajax({ + method: "DELETE", + url: "http://localhost:8080/api/v1/customer/delete/" + customer.id, + success: function(response) { + if (response.code === 201) { + showToast("Customer deleted successfully", "success"); + resetForm(); + loadCustomers(); + } else { + showToast("Failed to delete the customer", "error"); + } + }, + error: function(xhr, status, error) { + showToast("Error deleting customer: " + error, "error"); + console.error("Delete error: " + error); + } + }); + }); + + $("#cancelDeleteBtn").off("click").on("click", function() { + resetForm(); + }); + + if (window.innerWidth < 992) { + $("#customerForm")[0].scrollIntoView({ behavior: 'smooth' }); + } +} + +function resetForm() { + $("#customerForm")[0].reset(); + $("#formTitle").text("Add New Customer"); + $("#customerId").prop("disabled", false); + $("#customerName").prop("disabled", false); + $("#customerAddress").prop("disabled", false); + $("#saveCustomerBtn").show().prop("disabled", false); + $("#updateCustomerBtn").hide(); + $("#confirmDelete").removeClass("show"); + generateNextCustomerId(); +} + +function showToast(message, type = 'success') { + const toast = $('').addClass('toast').addClass(type); + + const iconClass = type === 'success' ? 'fa-check-circle' : 'fa-exclamation-circle'; + const toastIcon = $('').addClass('toast-icon').append( + $('').addClass('fas ' + iconClass) + ); + + const toastContent = $('').addClass('toast-content'); + const toastTitle = $('').addClass('toast-title').text( + type === 'success' ? 'Success' : 'Error' + ); + const toastMessage = $('').addClass('toast-message').text(message); + toastContent.append(toastTitle, toastMessage); + + const closeBtn = $('') + .addClass('toast-close') + .html('') + .click(function() { + toast.removeClass('show'); + setTimeout(function() { + toast.remove(); + }, 300); + }); + + toast.append(toastIcon, toastContent, closeBtn); + + $('#toastContainer').append(toast); + + setTimeout(function() { + toast.addClass('show'); + }, 10) + + setTimeout(function() { + toast.removeClass('show'); + setTimeout(function() { + toast.remove(); + }, 300); + }, 5000); +} + +function generateNextCustomerId() { + $.ajax({ + method: "GET", + url: "http://localhost:8080/api/v1/customer/generateNextId", + success: function(response) { + if(response.data) { + $("#customerId").val(response.data).prop("disabled", true); + } + }, + error: function(xhr, status, error) { + showToast('Error generating customer ID: ' + error, 'error'); + console.error("AJAX Error: " + status + " - " + error); + } + }); +} + +function updateTotalCustomers() { + const visibleRows = $("#customerTableBody tr:visible").length; + $("#totalCustomers").text(`Total: ${visibleRows} customers`); +} \ No newline at end of file diff --git a/14_Springboot_Frontend/src/main/java/lk/ijse/js/dashboard.js b/14_Springboot_Frontend/src/main/java/lk/ijse/js/dashboard.js new file mode 100644 index 0000000..016dd81 --- /dev/null +++ b/14_Springboot_Frontend/src/main/java/lk/ijse/js/dashboard.js @@ -0,0 +1,16 @@ +$.ajax({ + method: "GET", + url: "http://localhost:8080/api/v1/customer/getCustomerCount", + contentType: "application/json", + success: function(response) { + if (response.code === 201) { + console.log(response.data); + } else { + console.log('Failed to get the customer count'); + } + }, + error: function(xhr, status, error) { + showToast('Error saving customer: ' + error, 'error'); + console.error("AJAX Error: " + status + " - " + error); + } +}); \ No newline at end of file diff --git a/14_Springboot_Frontend/src/main/java/lk/ijse/js/item.js b/14_Springboot_Frontend/src/main/java/lk/ijse/js/item.js new file mode 100644 index 0000000..0b93eb7 --- /dev/null +++ b/14_Springboot_Frontend/src/main/java/lk/ijse/js/item.js @@ -0,0 +1,231 @@ +$(document).ready(function() { + loadItems(); + getNextItemId(); +}); + +$("#searchInput").on("keyup", function() { + var value = $(this).val().toLowerCase(); + $("#itemTableBody tr").filter(function() { + $(this).toggle($(this).text().toLowerCase().indexOf(value) > -1) + }); + updateTotalItems(); +}); + +$("#resetFormBtn").click(function() { + resetForm(); +}); + +function showToast(message, type) { + const toast = $(` + + + + + + ${type === 'success' ? 'Success' : 'Error'} + ${message} + + + + + + `); + + $("#toastContainer").append(toast); + setTimeout(() => toast.addClass('show'), 100); + + toast.find('.toast-close').click(function() { + toast.removeClass('show'); + setTimeout(() => toast.remove(), 300); + }); + + setTimeout(() => { + toast.removeClass('show'); + setTimeout(() => toast.remove(), 300); + }, 3000); +} + +function getNextItemId() { + $.ajax({ + method: "GET", + url: "http://localhost:8080/api/v1/item/generateNextId", + success: function(response) { + if(response.data) { + $("#itemId").val(response.data); + } + }, + error: function(xhr, status, error) { + showToast("Error getting next ID", "error"); + } + }); +} + +function loadItems() { + $.ajax({ + method: "GET", + url: "http://localhost:8080/api/v1/item/getAll", + success: function(response) { + if(response.data) { + $("#itemTableBody").empty(); + response.data.forEach(function(item) { + $("#itemTableBody").append( + ` + ${item.itemCode} + ${item.name} + ${item.price} + ${item.qty} + + + + + + + + + ` + ); + }); + updateTotalItems() + $("#emptyTable").hide(); + } + }, + error: function(xhr, status, error) { + showToast("Error loading items", "error"); + } + }); +} + +function updateTotalItems() { + const visibleRows = $("#itemTableBody tr:visible").length; + $("#totalItems").text(`Total: ${visibleRows} items`); +} + +$("#saveItemBtn").click(function(event) { + event.preventDefault(); + + if(!$("#itemName").val() || !$("#itemPrice").val() || !$("#itemQty").val()) { + showToast("Please fill all the fields", "error"); + return; + } + + var item = { + "itemCode": $("#itemId").val(), + "name": $("#itemName").val(), + "price": $("#itemPrice").val(), + "qty": $("#itemQty").val() + } + + $.ajax({ + method: "POST", + url: "http://localhost:8080/api/v1/item/save", + contentType: "application/json", + data: JSON.stringify(item), + success: function(response) { + if(response.code === 201) { + showToast("Item saved successfully", "success"); + $("#itemForm")[0].reset(); + loadItems(); + getNextItemId(); + } else { + showToast("Failed to save item", "error"); + } + }, + error: function(xhr, status, error) { + showToast("Error saving item", "error"); + } + }); +}); + +function editItem(item) { + $("#formTitle").text("Edit Item"); + $("#itemId").val(item.itemCode).prop("disabled", true); + $("#itemName").val(item.name); + $("#itemPrice").val(item.price); + $("#itemQty").val(item.qty); + $("#saveItemBtn").hide(); + $("#updateItemBtn").show(); + + if (window.innerWidth < 992) { + $("#itemForm")[0].scrollIntoView({ behavior: 'smooth' }); + } +} + +function deleteItem(item) { + $("#formTitle").text("Delete Item"); + $("#itemId").val(item.itemCode).prop("disabled", true); + $("#itemName").val(item.name); + $("#itemPrice").val(item.price); + $("#itemQty").val(item.qty); + $("#saveItemBtn").prop("disabled", true); + $("#confirmDelete").addClass("show"); +} + +$("#updateItemBtn").click(function(event) { + event.preventDefault(); + + if(!$("#itemName").val() || !$("#itemPrice").val() || !$("#itemQty").val()) { + showToast("Please fill all the fields", "error"); + return; + } + + var item = { + "itemCode": $("#itemId").val(), + "name": $("#itemName").val(), + "price": $("#itemPrice").val(), + "qty": $("#itemQty").val() + } + + $.ajax({ + method: "PUT", + url: "http://localhost:8080/api/v1/item/update", + contentType: "application/json", + data: JSON.stringify(item), + success: function(response) { + if(response.code === 201) { + showToast("Item updated successfully", "success"); + resetForm(); + loadItems(); + } else { + showToast("Failed to update item", "error"); + } + }, + error: function(xhr, status, error) { + showToast("Error updating item", "error"); + } + }); +}); + +$("#confirmDeleteBtn").click(function() { + var itemCode = $("#itemId").val(); + + $.ajax({ + method: "DELETE", + url: "http://localhost:8080/api/v1/item/delete/" + itemCode, + success: function(response) { + if(response.code === 201) { + showToast("Item deleted successfully", "success"); + resetForm(); + loadItems(); + } else { + showToast("Failed to delete item", "error"); + } + }, + error: function(xhr, status, error) { + showToast("Error deleting item", "error"); + } + }); +}); + +$("#cancelDeleteBtn").click(function() { + resetForm(); +}); + +function resetForm() { + $("#formTitle").text("Add New Item"); + $("#itemForm")[0].reset(); + $("#itemId").prop("disabled", false); + $("#saveItemBtn").show().prop("disabled", false); + $("#updateItemBtn").hide(); + $("#confirmDelete").removeClass("show"); + getNextItemId(); +} \ No newline at end of file diff --git a/14_Springboot_Frontend/src/main/java/lk/ijse/js/jquery-3.7.1.min.js b/14_Springboot_Frontend/src/main/java/lk/ijse/js/jquery-3.7.1.min.js new file mode 100644 index 0000000..7f37b5d --- /dev/null +++ b/14_Springboot_Frontend/src/main/java/lk/ijse/js/jquery-3.7.1.min.js @@ -0,0 +1,2 @@ +/*! jQuery v3.7.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(ie,e){"use strict";var oe=[],r=Object.getPrototypeOf,ae=oe.slice,g=oe.flat?function(e){return oe.flat.call(e)}:function(e){return oe.concat.apply([],e)},s=oe.push,se=oe.indexOf,n={},i=n.toString,ue=n.hasOwnProperty,o=ue.toString,a=o.call(Object),le={},v=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},y=function(e){return null!=e&&e===e.window},C=ie.document,u={type:!0,src:!0,nonce:!0,noModule:!0};function m(e,t,n){var r,i,o=(n=n||C).createElement("script");if(o.text=e,t)for(r in u)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[i.call(e)]||"object":typeof e}var t="3.7.1",l=/HTML$/i,ce=function(e,t){return new ce.fn.init(e,t)};function c(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!v(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+ge+")"+ge+"*"),x=new RegExp(ge+"|>"),j=new RegExp(g),A=new RegExp("^"+t+"$"),D={ID:new RegExp("^#("+t+")"),CLASS:new RegExp("^\\.("+t+")"),TAG:new RegExp("^("+t+"|[*])"),ATTR:new RegExp("^"+p),PSEUDO:new RegExp("^"+g),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ge+"*(even|odd|(([+-]|)(\\d*)n|)"+ge+"*(?:([+-]|)"+ge+"*(\\d+)|))"+ge+"*\\)|)","i"),bool:new RegExp("^(?:"+f+")$","i"),needsContext:new RegExp("^"+ge+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ge+"*((?:-\\d)?\\d*)"+ge+"*\\)|)(?=[^-]|$)","i")},N=/^(?:input|select|textarea|button)$/i,q=/^h\d$/i,L=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,H=/[+~]/,O=new RegExp("\\\\[\\da-fA-F]{1,6}"+ge+"?|\\\\([^\\r\\n\\f])","g"),P=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},M=function(){V()},R=J(function(e){return!0===e.disabled&&fe(e,"fieldset")},{dir:"parentNode",next:"legend"});try{k.apply(oe=ae.call(ye.childNodes),ye.childNodes),oe[ye.childNodes.length].nodeType}catch(e){k={apply:function(e,t){me.apply(e,ae.call(t))},call:function(e){me.apply(e,ae.call(arguments,1))}}}function I(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(V(e),e=e||T,C)){if(11!==p&&(u=L.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return k.call(n,a),n}else if(f&&(a=f.getElementById(i))&&I.contains(e,a)&&a.id===i)return k.call(n,a),n}else{if(u[2])return k.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&e.getElementsByClassName)return k.apply(n,e.getElementsByClassName(i)),n}if(!(h[t+" "]||d&&d.test(t))){if(c=t,f=e,1===p&&(x.test(t)||m.test(t))){(f=H.test(t)&&U(e.parentNode)||e)==e&&le.scope||((s=e.getAttribute("id"))?s=ce.escapeSelector(s):e.setAttribute("id",s=S)),o=(l=Y(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+Q(l[o]);c=l.join(",")}try{return k.apply(n,f.querySelectorAll(c)),n}catch(e){h(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return re(t.replace(ve,"$1"),e,n,r)}function W(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function F(e){return e[S]=!0,e}function $(e){var t=T.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function B(t){return function(e){return fe(e,"input")&&e.type===t}}function _(t){return function(e){return(fe(e,"input")||fe(e,"button"))&&e.type===t}}function z(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&R(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function X(a){return F(function(o){return o=+o,F(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function U(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function V(e){var t,n=e?e.ownerDocument||e:ye;return n!=T&&9===n.nodeType&&n.documentElement&&(r=(T=n).documentElement,C=!ce.isXMLDoc(T),i=r.matches||r.webkitMatchesSelector||r.msMatchesSelector,r.msMatchesSelector&&ye!=T&&(t=T.defaultView)&&t.top!==t&&t.addEventListener("unload",M),le.getById=$(function(e){return r.appendChild(e).id=ce.expando,!T.getElementsByName||!T.getElementsByName(ce.expando).length}),le.disconnectedMatch=$(function(e){return i.call(e,"*")}),le.scope=$(function(){return T.querySelectorAll(":scope")}),le.cssHas=$(function(){try{return T.querySelector(":has(*,:jqfake)"),!1}catch(e){return!0}}),le.getById?(b.filter.ID=function(e){var t=e.replace(O,P);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(O,P);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):t.querySelectorAll(e)},b.find.CLASS=function(e,t){if("undefined"!=typeof t.getElementsByClassName&&C)return t.getElementsByClassName(e)},d=[],$(function(e){var t;r.appendChild(e).innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+ge+"*(?:value|"+f+")"),e.querySelectorAll("[id~="+S+"-]").length||d.push("~="),e.querySelectorAll("a#"+S+"+*").length||d.push(".#.+[+~]"),e.querySelectorAll(":checked").length||d.push(":checked"),(t=T.createElement("input")).setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),r.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&d.push(":enabled",":disabled"),(t=T.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||d.push("\\["+ge+"*name"+ge+"*="+ge+"*(?:''|\"\")")}),le.cssHas||d.push(":has"),d=d.length&&new RegExp(d.join("|")),l=function(e,t){if(e===t)return a=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!le.sortDetached&&t.compareDocumentPosition(e)===n?e===T||e.ownerDocument==ye&&I.contains(ye,e)?-1:t===T||t.ownerDocument==ye&&I.contains(ye,t)?1:o?se.call(o,e)-se.call(o,t):0:4&n?-1:1)}),T}for(e in I.matches=function(e,t){return I(e,null,null,t)},I.matchesSelector=function(e,t){if(V(e),C&&!h[t+" "]&&(!d||!d.test(t)))try{var n=i.call(e,t);if(n||le.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){h(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(O,P),e[3]=(e[3]||e[4]||e[5]||"").replace(O,P),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||I.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&I.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return D.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&j.test(n)&&(t=Y(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(O,P).toLowerCase();return"*"===e?function(){return!0}:function(e){return fe(e,t)}},CLASS:function(e){var t=s[e+" "];return t||(t=new RegExp("(^|"+ge+")"+e+"("+ge+"|$)"))&&s(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=I.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function T(e,n,r){return v(n)?ce.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?ce.grep(e,function(e){return e===n!==r}):"string"!=typeof n?ce.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(ce.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||k,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:S.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof ce?t[0]:t,ce.merge(this,ce.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:C,!0)),w.test(r[1])&&ce.isPlainObject(t))for(r in t)v(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=C.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):v(e)?void 0!==n.ready?n.ready(e):e(ce):ce.makeArray(e,this)}).prototype=ce.fn,k=ce(C);var E=/^(?:parents|prev(?:Until|All))/,j={children:!0,contents:!0,next:!0,prev:!0};function A(e,t){while((e=e[t])&&1!==e.nodeType);return e}ce.fn.extend({has:function(e){var t=ce(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,Ce=/^$|^module$|\/(?:java|ecma)script/i;xe=C.createDocumentFragment().appendChild(C.createElement("div")),(be=C.createElement("input")).setAttribute("type","radio"),be.setAttribute("checked","checked"),be.setAttribute("name","t"),xe.appendChild(be),le.checkClone=xe.cloneNode(!0).cloneNode(!0).lastChild.checked,xe.innerHTML="x",le.noCloneChecked=!!xe.cloneNode(!0).lastChild.defaultValue,xe.innerHTML="",le.option=!!xe.lastChild;var ke={thead:[1,"",""],col:[2,"",""],tr:[2,"",""],td:[3,"",""],_default:[0,"",""]};function Se(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&fe(e,t)?ce.merge([e],n):n}function Ee(e,t){for(var n=0,r=e.length;n",""]);var je=/<|?\w+;/;function Ae(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function Re(e,t){return fe(e,"table")&&fe(11!==t.nodeType?t:t.firstChild,"tr")&&ce(e).children("tbody")[0]||e}function Ie(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function We(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Fe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(_.hasData(e)&&(s=_.get(e).events))for(i in _.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),C.head.appendChild(r[0])},abort:function(){i&&i()}}});var Jt,Kt=[],Zt=/(=)\?(?=&|$)|\?\?/;ce.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Kt.pop()||ce.expando+"_"+jt.guid++;return this[e]=!0,e}}),ce.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Zt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Zt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=v(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Zt,"$1"+r):!1!==e.jsonp&&(e.url+=(At.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||ce.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=ie[r],ie[r]=function(){o=arguments},n.always(function(){void 0===i?ce(ie).removeProp(r):ie[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Kt.push(r)),o&&v(i)&&i(o[0]),o=i=void 0}),"script"}),le.createHTMLDocument=((Jt=C.implementation.createHTMLDocument("").body).innerHTML="",2===Jt.childNodes.length),ce.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(le.createHTMLDocument?((r=(t=C.implementation.createHTMLDocument("")).createElement("base")).href=C.location.href,t.head.appendChild(r)):t=C),o=!n&&[],(i=w.exec(e))?[t.createElement(i[1])]:(i=Ae([e],t,o),o&&o.length&&ce(o).remove(),ce.merge([],i.childNodes)));var r,i,o},ce.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(ce.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},ce.expr.pseudos.animated=function(t){return ce.grep(ce.timers,function(e){return t===e.elem}).length},ce.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=ce.css(e,"position"),c=ce(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=ce.css(e,"top"),u=ce.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),v(t)&&(t=t.call(e,n,ce.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},ce.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){ce.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===ce.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===ce.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=ce(e).offset()).top+=ce.css(e,"borderTopWidth",!0),i.left+=ce.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-ce.css(r,"marginTop",!0),left:t.left-i.left-ce.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===ce.css(e,"position"))e=e.offsetParent;return e||J})}}),ce.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;ce.fn[t]=function(e){return M(this,function(e,t,n){var r;if(y(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),ce.each(["top","left"],function(e,n){ce.cssHooks[n]=Ye(le.pixelPosition,function(e,t){if(t)return t=Ge(e,n),_e.test(t)?ce(e).position()[n]+"px":t})}),ce.each({Height:"height",Width:"width"},function(a,s){ce.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){ce.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return M(this,function(e,t,n){var r;return y(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?ce.css(e,t,i):ce.style(e,t,n,i)},s,n?e:void 0,n)}})}),ce.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){ce.fn[t]=function(e){return this.on(t,e)}}),ce.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.on("mouseenter",e).on("mouseleave",t||e)}}),ce.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){ce.fn[n]=function(e,t){return 0 response.text()) + .then(data => { + // Find where to insert the navigation + const navPlaceholder = document.getElementById('nav-placeholder'); + if (navPlaceholder) { + navPlaceholder.innerHTML = data; + } + }) + .catch(error => console.error('Error loading navigation component:', error)); +}); \ No newline at end of file diff --git a/14_Springboot_Frontend/src/main/java/lk/ijse/js/order.js b/14_Springboot_Frontend/src/main/java/lk/ijse/js/order.js new file mode 100644 index 0000000..3f89dde --- /dev/null +++ b/14_Springboot_Frontend/src/main/java/lk/ijse/js/order.js @@ -0,0 +1,486 @@ +let cartItems = []; + +$(document).ready(function() { + initializeApp(); + + if (!$('#toastContainer').length) { + $('body').append(''); + } +}); + +function initializeApp() { + generateNextOrderId(); + + loadCustomers(); + loadItems(); + + initializeEventHandlers(); + + updateCartTable(); +} + +function generateNextOrderId() { + $("#orderIdDisplay").html('Generating...'); + + $.ajax({ + method: "GET", + url: "http://localhost:8080/api/v1/order/generateNextId", + success: function (response) { + if (response.code === 201 && response.data) { + $("#orderId").val(response.data); + $("#orderIdDisplay").text(response.data); + console.log("Next order ID:", response.data); + } else { + showError("Failed to generate order ID"); + $("#orderIdDisplay").text("Error"); + console.error("Error response:", response); + } + }, + error: function (xhr, status, error) { + showError("Failed to generate order ID"); + $("#orderIdDisplay").text("Error"); + console.error("Error details:", {xhr, status, error}); + } + }); +} + +function loadCustomers() { + $("#customerDetailsSelect") + .prop('disabled', true) + .html('Loading customers...'); + + $.ajax({ + method: "GET", + url: "http://localhost:8080/api/v1/customer/getAll", + success: function(response) { + if (response.code === 200 && response.data && response.data.length > 0) { + const customers = response.data; + + $("#customerDetailsSelect") + .empty() + .append('Select a customer...'); + + customers.forEach(customer => { + $("#customerDetailsSelect").append( + `${customer.name} (ID: ${customer.id})` + ); + }); + + window.customersData = customers; + } else { + $("#customerDetailsSelect") + .empty() + .append('No customers available'); + + showError("No customers found in the system"); + } + }, + error: function(xhr, status, error) { + $("#customerDetailsSelect") + .empty() + .append('Error loading customers'); + + showError("Failed to load customers. Please check server connection."); + console.error("Error details:", {xhr, status, error}); + }, + complete: function() { + $("#customerDetailsSelect").prop('disabled', false); + } + }); +} + +function loadItems() { + $("#ItemDetailsSelect") + .prop('disabled', true) + .html('Loading items...'); + + $.ajax({ + method: "GET", + url: "http://localhost:8080/api/v1/item/getAll", + success: function(response) { + if (response.code === 200 && response.data && response.data.length > 0) { + const items = response.data; + + $("#ItemDetailsSelect") + .empty() + .append('Select an item...'); + + items.forEach(item => { + $("#ItemDetailsSelect").append( + `${item.name} (Code: ${item.itemCode})` + ); + }); + + window.itemsData = items; + } else { + $("#ItemDetailsSelect") + .empty() + .append('No items available'); + + showError("No items found in the system"); + } + }, + error: function(xhr, status, error) { + $("#ItemDetailsSelect") + .empty() + .append('Error loading items'); + + showError("Failed to load items. Please check server connection."); + console.error("Error details:", {xhr, status, error}); + }, + complete: function() { + $("#ItemDetailsSelect").prop('disabled', false); + } + }); +} + +function initializeEventHandlers() { + $("#customerDetailsSelect").on('change', function() { + const selectedId = $(this).val(); + + if (!selectedId) { + clearCustomerDetails(); + return; + } + + const selectedCustomer = window.customersData?.find( + c => c.id.toString() === selectedId + ); + + if (selectedCustomer) { + updateCustomerDetails(selectedCustomer); + } else { + showError("Customer data not found"); + clearCustomerDetails(); + } + }); + + $("#ItemDetailsSelect").on('change', function() { + const selectedCode = $(this).val(); + + if (!selectedCode) { + clearItemDetails(); + return; + } + + const selectedItem = window.itemsData?.find( + i => i.itemCode.toString() === selectedCode + ); + + if (selectedItem) { + updateItemDetails(selectedItem); + } else { + showError("Item data not found"); + clearItemDetails(); + } + }); + + $("#addToCartBtn").on('click', function() { + const selectedItemCode = $("#ItemDetailsSelect").val(); + if (!selectedItemCode) { + showError("Please select an item first"); + return; + } + + const selectedItem = window.itemsData?.find( + i => i.itemCode.toString() === selectedItemCode + ); + + if (!selectedItem) { + showError("Selected item not found"); + return; + } + + const existingItem = cartItems.find(item => item.itemCode === selectedItem.itemCode); + + if (existingItem) { + if (existingItem.quantity + 1 > selectedItem.qty) { + showError(`Not enough stock available for ${selectedItem.name}`); + return; + } + existingItem.quantity += 1; + existingItem.total = existingItem.quantity * existingItem.unitPrice; + showSuccess(`Increased ${selectedItem.name} quantity to ${existingItem.quantity}`); + } else { + if (selectedItem.qty < 1) { + showError(`${selectedItem.name} is out of stock`); + return; + } + cartItems.push({ + itemCode: selectedItem.itemCode, + name: selectedItem.name, + quantity: 1, + unitPrice: selectedItem.price, + total: selectedItem.price + }); + showSuccess(`Added ${selectedItem.name} to cart`); + } + + updateCartTable(); + updateTotalAmount(); + }); + + $("#placeOrderButton").on('click', function() { + if (validateOrder()) { + $(this).html('Processing...').prop('disabled', true); + placeOrder(); + } + }); +} + +function validateOrder() { + const selectedCustomerId = $("#customerDetailsSelect").val(); + if (!selectedCustomerId) { + showError("Please select a customer"); + return false; + } + + if (cartItems.length === 0) { + showError("Cart is empty. Please add items to cart"); + return false; + } + + const orderId = $("#orderId").val(); + if (!orderId) { + showError("Invalid order ID"); + return false; + } + + return true; +} + +function updateCustomerDetails(customer) { + $("#customerDetailsName").text(customer.name || 'N/A'); + $("#customerDetailsAddress").text(customer.address || 'N/A'); +} + +function clearCustomerDetails() { + $("#customerDetailsName").text('Select a customer'); + $("#customerDetailsAddress").text('Address will appear here'); +} + +function updateItemDetails(item) { + $("#ItemDetailsName").text(item.name || 'N/A'); + $("#ItemDetailsPrice").text(`$${item.price.toFixed(2)}` || 'N/A'); + + const stockLevel = item.qty || 0; + let stockBadge = ''; + + if (stockLevel > 10) { + stockBadge = `${stockLevel} in stock`; + } else if (stockLevel > 0) { + stockBadge = `Low stock: ${stockLevel}`; + } else { + stockBadge = `Out of stock`; + } + + $("#ItemDetailsStock").html(stockBadge); +} + +function clearItemDetails() { + $("#ItemDetailsName").text('Select an item'); + $("#ItemDetailsPrice").text('Price will appear here'); + $("#ItemDetailsStock").text('Stock will appear here'); +} + +function updateCartTable() { + const tbody = $("#cartTableBody"); + tbody.empty(); + + if (cartItems.length === 0) { + tbody.html(` + + + + + Your cart is empty + Select items to add to your order + + + + `); + return; + } + + cartItems.forEach((item, index) => { + tbody.append(` + + + ${item.itemCode} + + + ${item.name} + + + + + + + ${item.quantity} + + + + + + $${item.unitPrice.toFixed(2)} + + $${item.total.toFixed(2)} + + + + + Remove + + + + `); + }); +} + +function removeFromCart(itemCode) { + const itemToRemove = cartItems.find(item => item.itemCode === itemCode); + if (itemToRemove) { + cartItems = cartItems.filter(item => item.itemCode !== itemCode); + updateCartTable(); + updateTotalAmount(); + showSuccess(`Removed ${itemToRemove.name} from cart`); + } +} + +function updateQuantity(itemCode, change) { + const selectedItem = cartItems.find(item => item.itemCode === itemCode); + if (!selectedItem) return; + + const inventoryItem = window.itemsData?.find(i => i.itemCode.toString() === itemCode); + if (!inventoryItem) return; + + const newQuantity = selectedItem.quantity + change; + + if (newQuantity < 1) { + return; + } + + if (change > 0 && newQuantity > inventoryItem.qty) { + showError(`Not enough stock available for ${selectedItem.name}`); + return; + } + + selectedItem.quantity = newQuantity; + selectedItem.total = selectedItem.quantity * selectedItem.unitPrice; + + updateCartTable(); + updateTotalAmount(); +} + +function updateTotalAmount() { + const total = cartItems.reduce((sum, item) => sum + item.total, 0); + $("#totalAmount").text(`Total: $${total.toFixed(2)}`); + + $("#placeOrderButton").prop('disabled', cartItems.length === 0); +} + +function showToast(message, type = 'success') { + const toast = $('').addClass('toast').addClass(type); + + const iconClass = type === 'success' ? 'bi-check-circle' : 'bi-exclamation-triangle'; + const toastIcon = $('').addClass(`bi ${iconClass} me-2`); + + const toastContent = $('').addClass('toast-content'); + const toastTitle = $('').addClass('fw-semibold mb-1').text( + type === 'success' ? 'Success' : 'Error' + ); + const toastMessage = $('').addClass('text-secondary small').text(message); + toastContent.append(toastTitle, toastMessage); + + const closeBtn = $('') + .addClass('toast-close') + .html('') + .click(function() { + toast.removeClass('show'); + setTimeout(function() { + toast.remove(); + }, 300); + }); + + toast.append(toastIcon, toastContent, closeBtn); + $('#toastContainer').append(toast); + + setTimeout(function() { + toast.addClass('show'); + }, 10); + + setTimeout(function() { + toast.removeClass('show'); + setTimeout(function() { + toast.remove(); + }, 300); + }, 5000); +} + +function showSuccess(message) { + showToast(message, 'success'); +} + +function showError(message) { + showToast(message, 'error'); +} + +function placeOrder() { + const selectedCustomerId = $("#customerDetailsSelect").val(); + const orderId = $("#orderId").val(); + const total = cartItems.reduce((sum, item) => sum + item.total, 0); + + const orderDetails = cartItems.map(item => ({ + itemCode: item.itemCode, + quantity: item.quantity, + unitPrice: item.unitPrice + })); + + const order = { + orderId: orderId, + customerId: selectedCustomerId, + orderDetails: orderDetails, + total: total + }; + + console.log("Sending order to backend:", JSON.stringify(order, null, 2)); + + $.ajax({ + method: "POST", + url: "http://localhost:8080/api/v1/order/save", + contentType: "application/json", + data: JSON.stringify(order), + success: function(response) { + console.log("Order response:", response); + if (response.code === 201) { + + cartItems = []; + updateCartTable(); + updateTotalAmount(); + clearCustomerDetails(); + showSuccess("Your Order "+ orderId + " placed successfully"); + clearItemDetails(); + $("#customerDetailsSelect").val(""); + $("#ItemDetailsSelect").val(""); + + generateNextOrderId(); + } else { + showError("Failed to place order: " + (response.message || "Unknown error")); + console.error("Order save failed:", response); + } + }, + error: function(xhr, status, error) { + showError("Failed to place order"); + console.error("Error details:", { + status: xhr.status, + statusText: xhr.statusText, + responseText: xhr.responseText + }); + }, + complete: function() { + $("#placeOrderButton") + .html(' Place Order') + .prop('disabled', false); + } + }); +} diff --git a/14_Springboot_Frontend/src/main/java/lk/ijse/order.html b/14_Springboot_Frontend/src/main/java/lk/ijse/order.html new file mode 100644 index 0000000..9f1af2d --- /dev/null +++ b/14_Springboot_Frontend/src/main/java/lk/ijse/order.html @@ -0,0 +1,176 @@ + + + + + + Order Management System + + + + + + + + + + + + + + + + + + Create New Order + Add items, select a customer, and submit your order + + + + Order ID + Loading... + + + + + + + + + + + + + Customer Information + + + + + + Select Customer + + Loading customers... + + + + + Customer Details + + Customer Name + Select a customer + + + Address + Address will appear here + + + + + + + + + + + + + + Item Selection + + + + + + Select Item + + Loading items... + + + + + Item Details + + Item Name + Select an item + + + Price + Price will appear here + + + Available Stock + Stock will appear here + + + + + + + Add to Cart + + + + + + + + + + + + Shopping Cart + + + + + + + + Item Code + Name + Quantity + Unit Price + Total + Action + + + + + + + + + Your cart is empty + Select items to add to your order + + + + + + + + + + + Total: $0.00 + + + + Place Order + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/14_Springboot_Frontend/target/classes/lk/ijse/Item.html b/14_Springboot_Frontend/target/classes/lk/ijse/Item.html new file mode 100644 index 0000000..15b1d98 --- /dev/null +++ b/14_Springboot_Frontend/target/classes/lk/ijse/Item.html @@ -0,0 +1,127 @@ + + + + + + Item Management + + + + + + + + + + + + + + Item Management + + + + + + + Add New Item + + + + + Item ID + + + + Name + + + + Price + + + + + Qty + + + + Save Item + + + + Update Item + + + Clear Form + + + + Dashboard + + + + Are you sure you want to delete this item? This action cannot be undone. + + + Cancel + + + Delete + + + + + + + + + + + Item List + + + + + + + + + Total: 0 items + + + + + + + + ID + Name + Price + Qty + Actions + + + + + + + + + + + No items found + + + + + + + + + + + + + + \ No newline at end of file diff --git a/14_Springboot_Frontend/target/classes/lk/ijse/componnent/components.js b/14_Springboot_Frontend/target/classes/lk/ijse/componnent/components.js new file mode 100644 index 0000000..5dd04ba --- /dev/null +++ b/14_Springboot_Frontend/target/classes/lk/ijse/componnent/components.js @@ -0,0 +1,100 @@ +// Define your navigation component HTML +const navComponent = ` + + + + + + + Chama Store + + + + + + + + + Dashboard + + + + + New Order + + + + + Customers + + + + + Item + + + + + + + +`; + +// Function to load components +function loadComponents() { + // Insert navigation + const navPlaceholder = document.getElementById('nav-placeholder'); + if (navPlaceholder) { + navPlaceholder.innerHTML = navComponent; + } + + // Set active link based on current page + const currentPage = window.location.pathname.split('/').pop(); + const navLinks = document.querySelectorAll('.navbar-nav .nav-link'); + + navLinks.forEach(link => { + const href = link.getAttribute('href'); + if (href === currentPage) { + link.classList.add('active'); + } else { + link.classList.remove('active'); + } + }); +} + +// Load components when DOM is ready +document.addEventListener('DOMContentLoaded', loadComponents); \ No newline at end of file diff --git a/14_Springboot_Frontend/target/classes/lk/ijse/css/customer.css b/14_Springboot_Frontend/target/classes/lk/ijse/css/customer.css new file mode 100644 index 0000000..41e9407 --- /dev/null +++ b/14_Springboot_Frontend/target/classes/lk/ijse/css/customer.css @@ -0,0 +1,324 @@ +:root { + --primary: #2563eb; + --primary-dark: #1d4ed8; + --danger: #ef4444; + --success: #10b981; + --dark: #1e293b; + --light: #f8fafc; + --gray: #e2e8f0; + --text: #334155; + --border: #cbd5e1; + --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); + --radius: 8px; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Segoe UI', system-ui, -apple-system, sans-serif; + background-color: #f1f5f9; + color: var(--text); + line-height: 1.5; + padding: 2rem; +} + +.container { + max-width: 1200px; + margin: 0 auto; +} + +header { + margin-bottom: 2rem; +} + +h1 { + color: var(--dark); + font-size: 1.875rem; + margin-bottom: 0.5rem; +} + +.content-wrapper { + display: grid; + grid-template-columns: 350px 1fr; + gap: 1.5rem; +} + +@media (max-width: 992px) { + .content-wrapper { + grid-template-columns: 1fr; + } +} + +.card { + background-color: white; + border-radius: var(--radius); + box-shadow: var(--shadow); + overflow: hidden; +} + +.card-header { + padding: 1rem; + border-bottom: 1px solid var(--gray); +} + +.card-title { + font-size: 1.25rem; + font-weight: 600; + color: var(--dark); +} + +.card-body { + padding: 1.5rem; +} + +/* Form */ +.form-group { + margin-bottom: 1.25rem; +} + +label { + display: block; + margin-bottom: 0.5rem; + font-weight: 500; + color: var(--dark); + font-size: 0.875rem; +} + +.form-control { + width: 100%; + padding: 0.625rem 0.875rem; + border: 1px solid var(--border); + border-radius: var(--radius); + font-size: 0.875rem; +} + +.form-control:focus { + outline: none; + border-color: var(--primary); + box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1); +} + +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + padding: 0.625rem 1rem; + background-color: var(--primary); + color: white; + border: none; + border-radius: var(--radius); + font-weight: 500; + font-size: 0.875rem; + cursor: pointer; + transition: background-color 0.2s, transform 0.1s; +} + +.btn:hover { + background-color: var(--primary-dark); +} + +.btn:active { + transform: translateY(1px); +} + +.btn i { + margin-right: 0.5rem; +} + +.btn-block { + width: 100%; +} + +.btn-danger { + background-color: var(--danger); +} + +.btn-sm { + padding: 0.375rem 0.75rem; + font-size: 0.75rem; +} + +.btn-icon { + width: 2rem; + height: 2rem; + padding: 0; + display: inline-flex; + align-items: center; + justify-content: center; +} + +.btn-icon i { + margin-right: 0; +} + +/* Table */ +.table-controls { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1rem; +} + +.search-container { + position: relative; + width: 250px; +} + +.search-input { + width: 100%; + padding: 0.5rem 1rem 0.5rem 2.25rem; + border: 1px solid var(--border); + border-radius: var(--radius); + font-size: 0.875rem; +} + +.search-icon { + position: absolute; + left: 0.75rem; + top: 50%; + transform: translateY(-50%); + color: #94a3b8; +} + +table { + width: 100%; + border-collapse: collapse; +} + +th, td { + text-align: left; + padding: 0.75rem 1rem; + border-bottom: 1px solid var(--gray); + font-size: 0.875rem; +} + +th { + font-weight: 600; + color: var(--dark); + background-color: #f8fafc; +} + +tr:last-child td { + border-bottom: none; +} + +tr:hover { + background-color: #f8fafc; +} + +.action-cell { + width: 120px; + white-space: nowrap; +} + +.empty-table { + padding: 3rem 1rem; + text-align: center; + color: #64748b; +} + +.empty-icon { + font-size: 2.5rem; + color: #94a3b8; + margin-bottom: 1rem; +} + +/* Toast Notification */ +.toast-container { + position: fixed; + bottom: 1.5rem; + right: 1.5rem; + z-index: 1010; +} + +.toast { + display: flex; + align-items: center; + padding: 0.75rem 1rem; + background-color: white; + border-radius: var(--radius); + box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); + margin-top: 0.75rem; + transform: translateX(150%); + transition: transform 0.3s; + max-width: 350px; +} + +.toast.show { + transform: translateX(0); +} + +.toast.success .toast-icon { + background-color: #dcfce7; + color: #166534; +} + +.toast.error .toast-icon { + background-color: #fee2e2; + color: #991b1b; +} + +.toast-icon { + width: 2rem; + height: 2rem; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin-right: 0.75rem; + flex-shrink: 0; +} + +.toast-content { + flex-grow: 1; +} + +.toast-title { + font-weight: 600; + font-size: 0.875rem; + margin-bottom: 0.25rem; +} + +.toast-message { + font-size: 0.8125rem; + color: #64748b; +} + +.toast-close { + background: none; + border: none; + color: #94a3b8; + cursor: pointer; + padding: 0.5rem; + margin: -0.5rem; + flex-shrink: 0; +} + +/* Confirmations */ +.confirm-delete { + display: none; + background-color: #fee2e2; + border: 1px solid #fecaca; + border-radius: var(--radius); + padding: 0.75rem; + margin-top: 0.5rem; +} + +.confirm-delete.show { + display: block; +} + +.confirm-message { + color: #991b1b; + font-size: 0.875rem; + margin-bottom: 0.75rem; +} + +.confirm-actions { + display: flex; + gap: 0.5rem; +} diff --git a/14_Springboot_Frontend/target/classes/lk/ijse/css/dashboard.css b/14_Springboot_Frontend/target/classes/lk/ijse/css/dashboard.css new file mode 100644 index 0000000..f539a26 --- /dev/null +++ b/14_Springboot_Frontend/target/classes/lk/ijse/css/dashboard.css @@ -0,0 +1,180 @@ +:root { + --primary: #4361ee; + --dark: #2b2d42; + --light: #f8f9fa; + --gray: #e9ecef; + --shadow: 0 4px 12px rgba(0, 0, 0, 0.1); + --transition: all 0.3s ease; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Segoe UI', system-ui, -apple-system, sans-serif; + background-color: var(--gray); + color: var(--dark); + padding: 2rem; + line-height: 1.5; +} + +.container { + max-width: 1200px; + margin: 0 auto; +} + +header { + text-align: center; + margin-bottom: 3rem; +} + +h1 { + font-size: 2.5rem; + margin-bottom: 0.5rem; + color: var(--dark); +} + +.subtitle { + font-size: 1.1rem; + color: #6c757d; + margin-bottom: 1rem; +} + +.cards-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + gap: 2rem; +} + +.card { + background-color: white; + border-radius: 12px; + box-shadow: var(--shadow); + overflow: hidden; + transition: var(--transition); + cursor: pointer; + text-decoration: none; + color: inherit; + height: 100%; + display: flex; + flex-direction: column; +} + +.card:hover { + transform: translateY(-5px); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); +} + +.card:active { + transform: translateY(-2px); +} + +.card-icon { + background-color: var(--primary); + color: white; + height: 120px; + display: flex; + align-items: center; + justify-content: center; +} + +.card-icon i { + font-size: 3rem; +} + +.card-content { + padding: 1.5rem; + flex: 1; +} + +.card-title { + font-size: 1.4rem; + font-weight: 600; + margin-bottom: 0.5rem; +} + +.card-description { + color: #6c757d; + font-size: 0.95rem; +} + +.card-footer { + display: flex; + align-items: center; + padding: 1rem 1.5rem; + background-color: #f8f9fa; + border-top: 1px solid #e9ecef; +} + +.card-footer span { + color: #6c757d; + font-size: 0.9rem; +} + +.card-footer i { + margin-left: auto; + color: var(--primary); +} + +@media (max-width: 768px) { + body { + padding: 1rem; + } + + .cards-grid { + grid-template-columns: 1fr; + gap: 1.5rem; + } + + h1 { + font-size: 2rem; + } +} + +/* Page Content Styling */ +.page { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: white; + z-index: 100; + overflow-y: auto; + padding: 2rem; +} + +.page.active { + display: block; +} + +.page-header { + display: flex; + align-items: center; + margin-bottom: 2rem; +} + +.back-button { + background: none; + border: none; + color: var(--primary); + font-size: 1.2rem; + cursor: pointer; + display: flex; + align-items: center; + margin-right: 1rem; +} + +.page-title { + font-size: 1.8rem; + font-weight: 600; +} + +.page-content { + max-width: 1000px; + margin: 0 auto; +} diff --git a/14_Springboot_Frontend/target/classes/lk/ijse/css/item.css b/14_Springboot_Frontend/target/classes/lk/ijse/css/item.css new file mode 100644 index 0000000..df3be6f --- /dev/null +++ b/14_Springboot_Frontend/target/classes/lk/ijse/css/item.css @@ -0,0 +1,258 @@ +:root { + --primary: #2563eb; + --primary-dark: #1d4ed8; + --danger: #ef4444; + --success: #10b981; + --dark: #1e293b; + --light: #f8fafc; + --gray: #e2e8f0; + --text: #334155; + --border: #cbd5e1; + --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); + --radius: 8px; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Segoe UI', system-ui, -apple-system, sans-serif; + background-color: #f1f5f9; + color: var(--text); + line-height: 1.5; + padding: 2rem; +} + +.container { + max-width: 1200px; + margin: 0 auto; +} + +header { + margin-bottom: 2rem; +} + +h1 { + color: var(--dark); + font-size: 1.875rem; + margin-bottom: 0.5rem; +} + +.content-wrapper { + display: grid; + grid-template-columns: 350px 1fr; + gap: 1.5rem; +} + +@media (max-width: 992px) { + .content-wrapper { + grid-template-columns: 1fr; + } +} + +.card { + background-color: white; + border-radius: var(--radius); + box-shadow: var(--shadow); + overflow: hidden; +} + +.card-header { + padding: 1rem; + border-bottom: 1px solid var(--gray); +} + +.card-title { + font-size: 1.25rem; + font-weight: 600; + color: var(--dark); +} + +.card-body { + padding: 1.5rem; +} + +/* Form */ +.form-group { + margin-bottom: 1.25rem; +} + +label { + display: block; + margin-bottom: 0.5rem; + font-weight: 500; + color: var(--dark); + font-size: 0.875rem; +} + +.form-control { + width: 100%; + padding: 0.625rem 0.875rem; + border: 1px solid var(--border); + border-radius: var(--radius); + font-size: 0.875rem; +} + +.form-control:focus { + outline: none; + border-color: var(--primary); + box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1); +} + +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + padding: 0.625rem 1rem; + background-color: var(--primary); + color: white; + border: none; + border-radius: var(--radius); + font-weight: 500; + font-size: 0.875rem; + cursor: pointer; + transition: background-color 0.2s, transform 0.1s; +} + +.btn:hover { + background-color: var(--primary-dark); +} + +.btn:active { + transform: translateY(1px); +} + +.btn i { + margin-right: 0.5rem; +} + +.btn-block { + width: 100%; +} + +.btn-danger { + background-color: var(--danger); +} + +.btn-sm { + padding: 0.375rem 0.75rem; + font-size: 0.75rem; +} + + +.btn-icon i { + margin-right: 0; +} + +/* Table */ +.table-controls { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1rem; +} + +.search-container { + position: relative; + width: 250px; +} + +.search-input { + width: 100%; + padding: 0.5rem 1rem 0.5rem 2.25rem; + border: 1px solid var(--border); + border-radius: var(--radius); + font-size: 0.875rem; +} + +.search-icon { + position: absolute; + left: 0.75rem; + top: 50%; + transform: translateY(-50%); + color: #94a3b8; +} + +table { + width: 100%; + border-collapse: collapse; +} + +th, td { + text-align: left; + padding: 0.75rem 1rem; + border-bottom: 1px solid var(--gray); + font-size: 0.875rem; +} + +th { + font-weight: 600; + color: var(--dark); + background-color: #f8fafc; +} + +tr:last-child td { + border-bottom: none; +} + +tr:hover { + background-color: #f8fafc; +} + +.empty-table { + padding: 3rem 1rem; + text-align: center; + color: #64748b; +} + +.empty-icon { + font-size: 2.5rem; + color: #94a3b8; + margin-bottom: 1rem; +} + +/* Toast Notification */ +.toast-container { + position: fixed; + bottom: 1.5rem; + right: 1.5rem; + z-index: 1010; +} + +.toast.success .toast-icon { + background-color: #dcfce7; + color: #166534; +} + +.toast.error .toast-icon { + background-color: #fee2e2; + color: #991b1b; +} + +/* Confirmations */ +.confirm-delete { + display: none; + background-color: #fee2e2; + border: 1px solid #fecaca; + border-radius: var(--radius); + padding: 0.75rem; + margin-top: 0.5rem; +} + +.confirm-delete.show { + display: block; +} + +.confirm-message { + color: #991b1b; + font-size: 0.875rem; + margin-bottom: 0.75rem; +} + +.confirm-actions { + display: flex; + gap: 0.5rem; +} diff --git a/14_Springboot_Frontend/target/classes/lk/ijse/css/order.css b/14_Springboot_Frontend/target/classes/lk/ijse/css/order.css new file mode 100644 index 0000000..7f1f0b8 --- /dev/null +++ b/14_Springboot_Frontend/target/classes/lk/ijse/css/order.css @@ -0,0 +1,359 @@ +:root { + --primary: #4f46e5; + --primary-light: #6366f1; + --primary-dark: #4338ca; + --secondary: #0ea5e9; + --success: #10b981; + --danger: #ef4444; + --warning: #f59e0b; + --light: #f8fafc; + --dark: #0f172a; +} + +body { + font-family: 'Segoe UI', system-ui, -apple-system, sans-serif; + background-color: #f1f5f9; + color: var(--text); + line-height: 1.5; + padding: 2rem 2rem 0 2rem; +} + + +.app-container { + max-width: 1400px; + margin: 0 auto; +} + +.page-header { + padding: 0 1rem 1rem 1rem; + margin-bottom: 2rem; +} + +.card { + border: none; + border-radius: 1rem; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.05); + transition: all 0.3s ease; + overflow: hidden; + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(10px); + margin-bottom: 1.5rem; +} + +.card:hover { + transform: translateY(-5px); + box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1); +} + +.card-header { + background: transparent; + border-bottom: 1px solid rgba(0, 0, 0, 0.05); + padding: 1.5rem; +} + +.card-body { + padding: 1.5rem; +} + +.card-title { + font-weight: 600; + margin-bottom: 1.25rem; + display: flex; + align-items: center; + color: var(--primary); +} + +.card-title i { + margin-right: 0.75rem; + font-size: 1.25rem; +} + +.form-control, .form-select { + border: 2px solid rgba(0, 0, 0, 0.05); + border-radius: 0.75rem; + padding: 0.75rem 1rem; + font-size: 1rem; + transition: all 0.2s ease; + background-color: rgba(255, 255, 255, 0.8); +} + +.form-control:focus, .form-select:focus { + border-color: var(--primary-light); + box-shadow: 0 0 0 0.25rem rgba(99, 102, 241, 0.15); +} + +.form-control-lg, .form-select-lg { + height: 3.5rem; + font-size: 1rem; +} + +.btn { + padding: 0.75rem 1.5rem; + border-radius: 0.75rem; + font-weight: 500; + letter-spacing: 0.3px; + transition: all 0.3s ease; +} + +.btn-primary { + background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%); + border: none; +} + +.btn-primary:hover { + background: linear-gradient(135deg, var(--primary-dark) 0%, var(--primary-dark) 100%); + transform: translateY(-2px); + box-shadow: 0 5px 15px rgba(79, 70, 229, 0.3); +} + +.btn-success { + background: linear-gradient(135deg, var(--success) 0%, #059669 100%); + border: none; +} + +.btn-success:hover { + background: linear-gradient(135deg, #059669 0%, #047857 100%); + transform: translateY(-2px); + box-shadow: 0 5px 15px rgba(16, 185, 129, 0.3); +} + +.btn-danger { + background: linear-gradient(135deg, var(--danger) 0%, #dc2626 100%); + border: none; +} + +.btn-danger:hover { + background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%); + transform: translateY(-2px); + box-shadow: 0 5px 15px rgba(239, 68, 68, 0.3); +} + +.btn-icon { + display: inline-flex; + align-items: center; + justify-content: center; +} + +.btn-icon i { + margin-right: 0.5rem; +} + +.details-panel { + background: rgba(79, 70, 229, 0.03); + border-radius: 0.75rem; + padding: 1.5rem; + border: 1px solid rgba(79, 70, 229, 0.1); + height: 100%; +} + +.details-panel h6 { + color: var(--primary); + font-weight: 600; + margin-bottom: 1.25rem; + padding-bottom: 0.75rem; + border-bottom: 1px solid rgba(79, 70, 229, 0.1); +} + +.details-panel .detail-item { + display: flex; + justify-content: space-between; + margin-bottom: 1rem; + padding-bottom: 1rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.05); +} + +.details-panel .detail-item:last-child { + margin-bottom: 0; + padding-bottom: 0; + border-bottom: none; +} + +.details-panel .detail-label { + color: #64748b; + font-size: 0.925rem; +} + +.details-panel .detail-value { + font-weight: 500; + text-align: right; +} + +.table { + border-radius: 0.75rem; + overflow: hidden; + margin-bottom: 0; +} + +.table th { + font-weight: 600; + color: #1e293b; + background-color: rgba(241, 245, 249, 0.8); + padding: 1rem; +} + +.table td { + padding: 1rem; + vertical-align: middle; +} + +.badge { + padding: 0.5rem 0.75rem; + font-weight: 500; + border-radius: 0.5rem; +} + +.remove-btn { + color: var(--danger); + background: rgba(239, 68, 68, 0.05); + border: none; + border-radius: 0.5rem; + padding: 0.5rem 0.75rem; + transition: all 0.2s ease; + font-size: 0.875rem; +} + +.remove-btn:hover { + background: rgba(239, 68, 68, 0.1); + color: #b91c1c; +} + +.total-section { + background: linear-gradient(135deg, rgba(79, 70, 229, 0.05) 0%, rgba(14, 165, 233, 0.05) 100%); + border-radius: 0.75rem; + padding: 1.5rem; + margin-top: 1.5rem; + border: 1px solid rgba(79, 70, 229, 0.1); +} + +.total-amount { + font-size: 1.5rem; + font-weight: 700; + color: var(--primary-dark); +} + +#toastContainer { + position: fixed; + top: 20px; + right: 20px; + z-index: 1050; +} + +.toast { + background: white; + border-radius: 0.75rem; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); + margin-bottom: 1rem; + padding: 1rem 1.25rem; + display: flex; + align-items: center; + min-width: 300px; + transform: translateX(120%); + transition: transform 0.3s ease; + border-left: 4px solid transparent; +} + +.toast.show { + transform: translateX(0); +} + +.toast.success { + border-left-color: var(--success); +} + +.toast.error { + border-left-color: var(--danger); +} + +.toast-content { + flex-grow: 1; + margin: 0 0.75rem; +} + +.toast-close { + background: none; + border: none; + color: #94a3b8; + cursor: pointer; + transition: color 0.2s ease; + padding: 0.25rem; +} + +.toast-close:hover { + color: #475569; +} + +.order-id-container { + background: rgba(79, 70, 229, 0.05); + border: 1px solid rgba(79, 70, 229, 0.1); + border-radius: 0.75rem; + padding: 1rem 1.5rem; + margin-bottom: 1.5rem; +} + +.order-id-label { + display: block; + font-size: 0.875rem; + font-weight: 500; + color: #64748b; + margin-bottom: 0.5rem; +} + +.order-id-value { + font-size: 1.25rem; + font-weight: 600; + color: var(--primary); + letter-spacing: 0.5px; +} + +@media (max-width: 992px) { + .app-container { + padding: 1rem; + } + + .page-header { + padding: 1.5rem 0; + } + + .order-id-container { + margin-top: 1rem; + } +} + +/* Loading spinner for selects */ +.select-loading::after { + content: ""; + position: absolute; + right: 10px; + top: 50%; + transform: translateY(-50%); + width: 20px; + height: 20px; + border-radius: 50%; + border: 2px solid rgba(79, 70, 229, 0.2); + border-top-color: var(--primary); + animation: spin 0.8s linear infinite; +} + +@keyframes spin { + to { + transform: translateY(-50%) rotate(360deg); + } +} + +/* Empty cart illustration */ +.empty-cart { + text-align: center; + padding: 2rem; + color: #94a3b8; +} + +.empty-cart i { + font-size: 3rem; + margin-bottom: 1rem; + opacity: 0.5; +} + +.empty-cart p { + font-size: 1.125rem; + margin-bottom: 1.5rem; +} \ No newline at end of file diff --git a/14_Springboot_Frontend/target/classes/lk/ijse/customer.html b/14_Springboot_Frontend/target/classes/lk/ijse/customer.html new file mode 100644 index 0000000..106d81a --- /dev/null +++ b/14_Springboot_Frontend/target/classes/lk/ijse/customer.html @@ -0,0 +1,135 @@ + + + + + + Customer Management + + + + + + + + + + + + + Customer Management + + + + + + + + Add New Customer + + + + + Customer ID + + + + Name + + + + Address + + + + + Save Customer + + + + Update Customer + + + + Clear Form + + + Dashboard + + + + Are you sure you want to delete this customer? This action cannot be undone. + + + Cancel + + + Delete + + + + + + + + + + + Customer List + + + + + + + + + + + + + + ID + Name + Address + Actions + + + + + + + + + + + + No customers found + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/14_Springboot_Frontend/target/classes/lk/ijse/dashboard.html b/14_Springboot_Frontend/target/classes/lk/ijse/dashboard.html new file mode 100644 index 0000000..d1388f2 --- /dev/null +++ b/14_Springboot_Frontend/target/classes/lk/ijse/dashboard.html @@ -0,0 +1,146 @@ + + + + + + Dashboard + + + + + + + Dashboard + Select a module to get started + + + + + + + + + + Customers + Manage customer profiles, view history and track engagement. + + + + + + + + + + + Items + Inventory management, stock levels and product catalog. + + + + + + + + + + + Orders + Process orders, track shipments and manage fulfillment. + + + + + + + + + + + Analytics + Business insights, reports and performance metrics. + + + + + + + + + + + Settings + Configure system preferences, users and permissions. + + + + + + + + + + + + + + + + + Customer Count + Process Customer Count,And Give Numerical Value + + + + + + + + + + Item Count + Process Item Count,And Give Numerical Value + + + + + + + + + + Order Count + Process Order Count,And Give Numerical Value + + + + + + + + + \ No newline at end of file diff --git a/14_Springboot_Frontend/target/classes/lk/ijse/js/customer.js b/14_Springboot_Frontend/target/classes/lk/ijse/js/customer.js new file mode 100644 index 0000000..4b67728 --- /dev/null +++ b/14_Springboot_Frontend/target/classes/lk/ijse/js/customer.js @@ -0,0 +1,284 @@ +$("#saveCustomerBtn").click(function(event) { + event.preventDefault(); + + if (!$("#customerName").val() || !$("#customerAddress").val()) { + showToast('Please fill all the fields', 'error'); + return; + } + + var customerID = $("#customerId").val(); + var customerName = $("#customerName").val(); + var customerAddress = $("#customerAddress").val(); + + var customer = { + "id": customerID, + "name": customerName, + "address": customerAddress + } + + $.ajax({ + method: "POST", + url: "http://localhost:8080/api/v1/customer/save", + contentType: "application/json", + data: JSON.stringify(customer), + success: function(response) { + if (response.code === 201) { + showToast('Customer saved successfully', 'success'); + $("#customerForm")[0].reset(); + loadCustomers(); + generateNextCustomerId(); + } else { + showToast('Failed to save the customer','error'); + } + }, + error: function(xhr, status, error) { + showToast('Error saving customer: ' + error, 'error'); + console.error("AJAX Error: " + status + " - " + error); + } + }); +}); + +$("#updateCustomerBtn").click(function(event) { + event.preventDefault(); + + if (!$("#customerName").val() || !$("#customerAddress").val()) { + showToast('Please fill all the fields', 'error'); + return; + } + + var customerID = $("#customerId").val(); + var customerName = $("#customerName").val(); + var customerAddress = $("#customerAddress").val(); + + var customer = { + "id": customerID, + "name": customerName, + "address": customerAddress + } + $.ajax({ + method: "PUT", + url: "http://localhost:8080/api/v1/customer/update", + contentType: "application/json", + data: JSON.stringify(customer), + success: function(response) { + if (response.code === 201) { + showToast('Customer updated successfully', 'success'); + resetForm(); + loadCustomers(); + } else { + showToast('Failed to update the customer', 'error'); + } + }, + error: function(xhr, status, error) { + showToast('Error updating customer: ' + error, 'error'); + } + }) +}); + +function loadCustomers() { + $.ajax({ + method: "GET", + url: "http://localhost:8080/api/v1/customer/getAll", + success: function(response) { + const customers = response.data; + if (customers && customers.length > 0) { + $("#emptyTable").hide(); + $("#customerTable").show(); + + var tbody = $("#customerTableBody"); + tbody.empty(); + + $.each(customers, function(index, customer) { + var row = $(""); + row.append($("").text(customer.id || "-")); + row.append($("").text(customer.name || "-")); + row.append($("").text(customer.address || "-")); + + var actionsCell = $("").addClass("action-cell"); + + var editBtn = $("") + .addClass("btn btn-sm btn-icon") + .css("background-color", "#fbbf24") + .css("margin-right", "5px") + .html('') + .click(function() { + editCustomer(customer); + }); + + var deleteBtn = $("") + .addClass("btn btn-sm btn-icon btn-danger") + .html('') + .click(function() { + deleteCustomer(customer); + }); + + actionsCell.append(editBtn, deleteBtn); + row.append(actionsCell); + + tbody.append(row); + }); + + updateTotalCustomers(); + } else { + $("#customerTable").hide(); + $("#emptyTable").show(); + } + }, + error: function(xhr, status, error) { + showToast('Error loading customers: ' + error, 'error'); + $("#customerTable").hide(); + $("#emptyTable").show(); + } + }); +} + +$(document).ready(function() { + loadCustomers(); + generateNextCustomerId(); + + $("#resetFormBtn").click(function() { + resetForm(); + }); + + $("#searchInput").on("input", function() { + var searchTerm = $(this).val().toLowerCase(); + $("#customerTableBody tr").filter(function() { + $(this).toggle($(this).text().toLowerCase().indexOf(searchTerm) > -1); + }); + + if ($("#customerTableBody tr:visible").length === 0) { + $("#emptyTable").show(); + $("#customerTable").hide(); + } else { + $("#emptyTable").hide(); + $("#customerTable").show(); + } + updateTotalCustomers(); + }); +}); + +function editCustomer(customer) { + $("#formTitle").text("Edit Customer"); + $("#customerId").val(customer.id).prop("disabled", true); + $("#customerName").val(customer.name); + $("#customerAddress").val(customer.address); + $("#confirmDelete").removeClass("show"); + $("#saveCustomerBtn").hide(); + $("#updateCustomerBtn").show(); + + if (window.innerWidth < 992) { + $("#customerForm")[0].scrollIntoView({ behavior: 'smooth' }); + } +} + +function deleteCustomer(customer) { + $("#formTitle").text("Delete Customer"); + $("#customerId").val(customer.id).prop("disabled", true); + $("#customerName").val(customer.name).prop("disabled", true); + $("#customerAddress").val(customer.address).prop("disabled", true); + $("#saveCustomerBtn").prop("disabled", true); + $("#updateCustomerBtn").hide(); + $("#confirmDelete").addClass("show"); + + $("#confirmDeleteBtn").off("click").on("click", function() { + $.ajax({ + method: "DELETE", + url: "http://localhost:8080/api/v1/customer/delete/" + customer.id, + success: function(response) { + if (response.code === 201) { + showToast("Customer deleted successfully", "success"); + resetForm(); + loadCustomers(); + } else { + showToast("Failed to delete the customer", "error"); + } + }, + error: function(xhr, status, error) { + showToast("Error deleting customer: " + error, "error"); + console.error("Delete error: " + error); + } + }); + }); + + $("#cancelDeleteBtn").off("click").on("click", function() { + resetForm(); + }); + + if (window.innerWidth < 992) { + $("#customerForm")[0].scrollIntoView({ behavior: 'smooth' }); + } +} + +function resetForm() { + $("#customerForm")[0].reset(); + $("#formTitle").text("Add New Customer"); + $("#customerId").prop("disabled", false); + $("#customerName").prop("disabled", false); + $("#customerAddress").prop("disabled", false); + $("#saveCustomerBtn").show().prop("disabled", false); + $("#updateCustomerBtn").hide(); + $("#confirmDelete").removeClass("show"); + generateNextCustomerId(); +} + +function showToast(message, type = 'success') { + const toast = $('').addClass('toast').addClass(type); + + const iconClass = type === 'success' ? 'fa-check-circle' : 'fa-exclamation-circle'; + const toastIcon = $('').addClass('toast-icon').append( + $('').addClass('fas ' + iconClass) + ); + + const toastContent = $('').addClass('toast-content'); + const toastTitle = $('').addClass('toast-title').text( + type === 'success' ? 'Success' : 'Error' + ); + const toastMessage = $('').addClass('toast-message').text(message); + toastContent.append(toastTitle, toastMessage); + + const closeBtn = $('') + .addClass('toast-close') + .html('') + .click(function() { + toast.removeClass('show'); + setTimeout(function() { + toast.remove(); + }, 300); + }); + + toast.append(toastIcon, toastContent, closeBtn); + + $('#toastContainer').append(toast); + + setTimeout(function() { + toast.addClass('show'); + }, 10) + + setTimeout(function() { + toast.removeClass('show'); + setTimeout(function() { + toast.remove(); + }, 300); + }, 5000); +} + +function generateNextCustomerId() { + $.ajax({ + method: "GET", + url: "http://localhost:8080/api/v1/customer/generateNextId", + success: function(response) { + if(response.data) { + $("#customerId").val(response.data).prop("disabled", true); + } + }, + error: function(xhr, status, error) { + showToast('Error generating customer ID: ' + error, 'error'); + console.error("AJAX Error: " + status + " - " + error); + } + }); +} + +function updateTotalCustomers() { + const visibleRows = $("#customerTableBody tr:visible").length; + $("#totalCustomers").text(`Total: ${visibleRows} customers`); +} \ No newline at end of file diff --git a/14_Springboot_Frontend/target/classes/lk/ijse/js/dashboard.js b/14_Springboot_Frontend/target/classes/lk/ijse/js/dashboard.js new file mode 100644 index 0000000..016dd81 --- /dev/null +++ b/14_Springboot_Frontend/target/classes/lk/ijse/js/dashboard.js @@ -0,0 +1,16 @@ +$.ajax({ + method: "GET", + url: "http://localhost:8080/api/v1/customer/getCustomerCount", + contentType: "application/json", + success: function(response) { + if (response.code === 201) { + console.log(response.data); + } else { + console.log('Failed to get the customer count'); + } + }, + error: function(xhr, status, error) { + showToast('Error saving customer: ' + error, 'error'); + console.error("AJAX Error: " + status + " - " + error); + } +}); \ No newline at end of file diff --git a/14_Springboot_Frontend/target/classes/lk/ijse/js/item.js b/14_Springboot_Frontend/target/classes/lk/ijse/js/item.js new file mode 100644 index 0000000..0b93eb7 --- /dev/null +++ b/14_Springboot_Frontend/target/classes/lk/ijse/js/item.js @@ -0,0 +1,231 @@ +$(document).ready(function() { + loadItems(); + getNextItemId(); +}); + +$("#searchInput").on("keyup", function() { + var value = $(this).val().toLowerCase(); + $("#itemTableBody tr").filter(function() { + $(this).toggle($(this).text().toLowerCase().indexOf(value) > -1) + }); + updateTotalItems(); +}); + +$("#resetFormBtn").click(function() { + resetForm(); +}); + +function showToast(message, type) { + const toast = $(` + + + + + + ${type === 'success' ? 'Success' : 'Error'} + ${message} + + + + + + `); + + $("#toastContainer").append(toast); + setTimeout(() => toast.addClass('show'), 100); + + toast.find('.toast-close').click(function() { + toast.removeClass('show'); + setTimeout(() => toast.remove(), 300); + }); + + setTimeout(() => { + toast.removeClass('show'); + setTimeout(() => toast.remove(), 300); + }, 3000); +} + +function getNextItemId() { + $.ajax({ + method: "GET", + url: "http://localhost:8080/api/v1/item/generateNextId", + success: function(response) { + if(response.data) { + $("#itemId").val(response.data); + } + }, + error: function(xhr, status, error) { + showToast("Error getting next ID", "error"); + } + }); +} + +function loadItems() { + $.ajax({ + method: "GET", + url: "http://localhost:8080/api/v1/item/getAll", + success: function(response) { + if(response.data) { + $("#itemTableBody").empty(); + response.data.forEach(function(item) { + $("#itemTableBody").append( + ` + ${item.itemCode} + ${item.name} + ${item.price} + ${item.qty} + + + + + + + + + ` + ); + }); + updateTotalItems() + $("#emptyTable").hide(); + } + }, + error: function(xhr, status, error) { + showToast("Error loading items", "error"); + } + }); +} + +function updateTotalItems() { + const visibleRows = $("#itemTableBody tr:visible").length; + $("#totalItems").text(`Total: ${visibleRows} items`); +} + +$("#saveItemBtn").click(function(event) { + event.preventDefault(); + + if(!$("#itemName").val() || !$("#itemPrice").val() || !$("#itemQty").val()) { + showToast("Please fill all the fields", "error"); + return; + } + + var item = { + "itemCode": $("#itemId").val(), + "name": $("#itemName").val(), + "price": $("#itemPrice").val(), + "qty": $("#itemQty").val() + } + + $.ajax({ + method: "POST", + url: "http://localhost:8080/api/v1/item/save", + contentType: "application/json", + data: JSON.stringify(item), + success: function(response) { + if(response.code === 201) { + showToast("Item saved successfully", "success"); + $("#itemForm")[0].reset(); + loadItems(); + getNextItemId(); + } else { + showToast("Failed to save item", "error"); + } + }, + error: function(xhr, status, error) { + showToast("Error saving item", "error"); + } + }); +}); + +function editItem(item) { + $("#formTitle").text("Edit Item"); + $("#itemId").val(item.itemCode).prop("disabled", true); + $("#itemName").val(item.name); + $("#itemPrice").val(item.price); + $("#itemQty").val(item.qty); + $("#saveItemBtn").hide(); + $("#updateItemBtn").show(); + + if (window.innerWidth < 992) { + $("#itemForm")[0].scrollIntoView({ behavior: 'smooth' }); + } +} + +function deleteItem(item) { + $("#formTitle").text("Delete Item"); + $("#itemId").val(item.itemCode).prop("disabled", true); + $("#itemName").val(item.name); + $("#itemPrice").val(item.price); + $("#itemQty").val(item.qty); + $("#saveItemBtn").prop("disabled", true); + $("#confirmDelete").addClass("show"); +} + +$("#updateItemBtn").click(function(event) { + event.preventDefault(); + + if(!$("#itemName").val() || !$("#itemPrice").val() || !$("#itemQty").val()) { + showToast("Please fill all the fields", "error"); + return; + } + + var item = { + "itemCode": $("#itemId").val(), + "name": $("#itemName").val(), + "price": $("#itemPrice").val(), + "qty": $("#itemQty").val() + } + + $.ajax({ + method: "PUT", + url: "http://localhost:8080/api/v1/item/update", + contentType: "application/json", + data: JSON.stringify(item), + success: function(response) { + if(response.code === 201) { + showToast("Item updated successfully", "success"); + resetForm(); + loadItems(); + } else { + showToast("Failed to update item", "error"); + } + }, + error: function(xhr, status, error) { + showToast("Error updating item", "error"); + } + }); +}); + +$("#confirmDeleteBtn").click(function() { + var itemCode = $("#itemId").val(); + + $.ajax({ + method: "DELETE", + url: "http://localhost:8080/api/v1/item/delete/" + itemCode, + success: function(response) { + if(response.code === 201) { + showToast("Item deleted successfully", "success"); + resetForm(); + loadItems(); + } else { + showToast("Failed to delete item", "error"); + } + }, + error: function(xhr, status, error) { + showToast("Error deleting item", "error"); + } + }); +}); + +$("#cancelDeleteBtn").click(function() { + resetForm(); +}); + +function resetForm() { + $("#formTitle").text("Add New Item"); + $("#itemForm")[0].reset(); + $("#itemId").prop("disabled", false); + $("#saveItemBtn").show().prop("disabled", false); + $("#updateItemBtn").hide(); + $("#confirmDelete").removeClass("show"); + getNextItemId(); +} \ No newline at end of file diff --git a/14_Springboot_Frontend/target/classes/lk/ijse/js/jquery-3.7.1.min.js b/14_Springboot_Frontend/target/classes/lk/ijse/js/jquery-3.7.1.min.js new file mode 100644 index 0000000..7f37b5d --- /dev/null +++ b/14_Springboot_Frontend/target/classes/lk/ijse/js/jquery-3.7.1.min.js @@ -0,0 +1,2 @@ +/*! jQuery v3.7.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(ie,e){"use strict";var oe=[],r=Object.getPrototypeOf,ae=oe.slice,g=oe.flat?function(e){return oe.flat.call(e)}:function(e){return oe.concat.apply([],e)},s=oe.push,se=oe.indexOf,n={},i=n.toString,ue=n.hasOwnProperty,o=ue.toString,a=o.call(Object),le={},v=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},y=function(e){return null!=e&&e===e.window},C=ie.document,u={type:!0,src:!0,nonce:!0,noModule:!0};function m(e,t,n){var r,i,o=(n=n||C).createElement("script");if(o.text=e,t)for(r in u)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[i.call(e)]||"object":typeof e}var t="3.7.1",l=/HTML$/i,ce=function(e,t){return new ce.fn.init(e,t)};function c(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!v(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+ge+")"+ge+"*"),x=new RegExp(ge+"|>"),j=new RegExp(g),A=new RegExp("^"+t+"$"),D={ID:new RegExp("^#("+t+")"),CLASS:new RegExp("^\\.("+t+")"),TAG:new RegExp("^("+t+"|[*])"),ATTR:new RegExp("^"+p),PSEUDO:new RegExp("^"+g),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ge+"*(even|odd|(([+-]|)(\\d*)n|)"+ge+"*(?:([+-]|)"+ge+"*(\\d+)|))"+ge+"*\\)|)","i"),bool:new RegExp("^(?:"+f+")$","i"),needsContext:new RegExp("^"+ge+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ge+"*((?:-\\d)?\\d*)"+ge+"*\\)|)(?=[^-]|$)","i")},N=/^(?:input|select|textarea|button)$/i,q=/^h\d$/i,L=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,H=/[+~]/,O=new RegExp("\\\\[\\da-fA-F]{1,6}"+ge+"?|\\\\([^\\r\\n\\f])","g"),P=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},M=function(){V()},R=J(function(e){return!0===e.disabled&&fe(e,"fieldset")},{dir:"parentNode",next:"legend"});try{k.apply(oe=ae.call(ye.childNodes),ye.childNodes),oe[ye.childNodes.length].nodeType}catch(e){k={apply:function(e,t){me.apply(e,ae.call(t))},call:function(e){me.apply(e,ae.call(arguments,1))}}}function I(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(V(e),e=e||T,C)){if(11!==p&&(u=L.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return k.call(n,a),n}else if(f&&(a=f.getElementById(i))&&I.contains(e,a)&&a.id===i)return k.call(n,a),n}else{if(u[2])return k.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&e.getElementsByClassName)return k.apply(n,e.getElementsByClassName(i)),n}if(!(h[t+" "]||d&&d.test(t))){if(c=t,f=e,1===p&&(x.test(t)||m.test(t))){(f=H.test(t)&&U(e.parentNode)||e)==e&&le.scope||((s=e.getAttribute("id"))?s=ce.escapeSelector(s):e.setAttribute("id",s=S)),o=(l=Y(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+Q(l[o]);c=l.join(",")}try{return k.apply(n,f.querySelectorAll(c)),n}catch(e){h(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return re(t.replace(ve,"$1"),e,n,r)}function W(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function F(e){return e[S]=!0,e}function $(e){var t=T.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function B(t){return function(e){return fe(e,"input")&&e.type===t}}function _(t){return function(e){return(fe(e,"input")||fe(e,"button"))&&e.type===t}}function z(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&R(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function X(a){return F(function(o){return o=+o,F(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function U(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function V(e){var t,n=e?e.ownerDocument||e:ye;return n!=T&&9===n.nodeType&&n.documentElement&&(r=(T=n).documentElement,C=!ce.isXMLDoc(T),i=r.matches||r.webkitMatchesSelector||r.msMatchesSelector,r.msMatchesSelector&&ye!=T&&(t=T.defaultView)&&t.top!==t&&t.addEventListener("unload",M),le.getById=$(function(e){return r.appendChild(e).id=ce.expando,!T.getElementsByName||!T.getElementsByName(ce.expando).length}),le.disconnectedMatch=$(function(e){return i.call(e,"*")}),le.scope=$(function(){return T.querySelectorAll(":scope")}),le.cssHas=$(function(){try{return T.querySelector(":has(*,:jqfake)"),!1}catch(e){return!0}}),le.getById?(b.filter.ID=function(e){var t=e.replace(O,P);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(O,P);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):t.querySelectorAll(e)},b.find.CLASS=function(e,t){if("undefined"!=typeof t.getElementsByClassName&&C)return t.getElementsByClassName(e)},d=[],$(function(e){var t;r.appendChild(e).innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+ge+"*(?:value|"+f+")"),e.querySelectorAll("[id~="+S+"-]").length||d.push("~="),e.querySelectorAll("a#"+S+"+*").length||d.push(".#.+[+~]"),e.querySelectorAll(":checked").length||d.push(":checked"),(t=T.createElement("input")).setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),r.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&d.push(":enabled",":disabled"),(t=T.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||d.push("\\["+ge+"*name"+ge+"*="+ge+"*(?:''|\"\")")}),le.cssHas||d.push(":has"),d=d.length&&new RegExp(d.join("|")),l=function(e,t){if(e===t)return a=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!le.sortDetached&&t.compareDocumentPosition(e)===n?e===T||e.ownerDocument==ye&&I.contains(ye,e)?-1:t===T||t.ownerDocument==ye&&I.contains(ye,t)?1:o?se.call(o,e)-se.call(o,t):0:4&n?-1:1)}),T}for(e in I.matches=function(e,t){return I(e,null,null,t)},I.matchesSelector=function(e,t){if(V(e),C&&!h[t+" "]&&(!d||!d.test(t)))try{var n=i.call(e,t);if(n||le.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){h(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(O,P),e[3]=(e[3]||e[4]||e[5]||"").replace(O,P),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||I.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&I.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return D.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&j.test(n)&&(t=Y(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(O,P).toLowerCase();return"*"===e?function(){return!0}:function(e){return fe(e,t)}},CLASS:function(e){var t=s[e+" "];return t||(t=new RegExp("(^|"+ge+")"+e+"("+ge+"|$)"))&&s(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=I.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function T(e,n,r){return v(n)?ce.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?ce.grep(e,function(e){return e===n!==r}):"string"!=typeof n?ce.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(ce.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||k,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:S.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof ce?t[0]:t,ce.merge(this,ce.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:C,!0)),w.test(r[1])&&ce.isPlainObject(t))for(r in t)v(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=C.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):v(e)?void 0!==n.ready?n.ready(e):e(ce):ce.makeArray(e,this)}).prototype=ce.fn,k=ce(C);var E=/^(?:parents|prev(?:Until|All))/,j={children:!0,contents:!0,next:!0,prev:!0};function A(e,t){while((e=e[t])&&1!==e.nodeType);return e}ce.fn.extend({has:function(e){var t=ce(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,Ce=/^$|^module$|\/(?:java|ecma)script/i;xe=C.createDocumentFragment().appendChild(C.createElement("div")),(be=C.createElement("input")).setAttribute("type","radio"),be.setAttribute("checked","checked"),be.setAttribute("name","t"),xe.appendChild(be),le.checkClone=xe.cloneNode(!0).cloneNode(!0).lastChild.checked,xe.innerHTML="x",le.noCloneChecked=!!xe.cloneNode(!0).lastChild.defaultValue,xe.innerHTML="",le.option=!!xe.lastChild;var ke={thead:[1,"",""],col:[2,"",""],tr:[2,"",""],td:[3,"",""],_default:[0,"",""]};function Se(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&fe(e,t)?ce.merge([e],n):n}function Ee(e,t){for(var n=0,r=e.length;n",""]);var je=/<|?\w+;/;function Ae(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function Re(e,t){return fe(e,"table")&&fe(11!==t.nodeType?t:t.firstChild,"tr")&&ce(e).children("tbody")[0]||e}function Ie(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function We(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Fe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(_.hasData(e)&&(s=_.get(e).events))for(i in _.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),C.head.appendChild(r[0])},abort:function(){i&&i()}}});var Jt,Kt=[],Zt=/(=)\?(?=&|$)|\?\?/;ce.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Kt.pop()||ce.expando+"_"+jt.guid++;return this[e]=!0,e}}),ce.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Zt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Zt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=v(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Zt,"$1"+r):!1!==e.jsonp&&(e.url+=(At.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||ce.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=ie[r],ie[r]=function(){o=arguments},n.always(function(){void 0===i?ce(ie).removeProp(r):ie[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Kt.push(r)),o&&v(i)&&i(o[0]),o=i=void 0}),"script"}),le.createHTMLDocument=((Jt=C.implementation.createHTMLDocument("").body).innerHTML="",2===Jt.childNodes.length),ce.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(le.createHTMLDocument?((r=(t=C.implementation.createHTMLDocument("")).createElement("base")).href=C.location.href,t.head.appendChild(r)):t=C),o=!n&&[],(i=w.exec(e))?[t.createElement(i[1])]:(i=Ae([e],t,o),o&&o.length&&ce(o).remove(),ce.merge([],i.childNodes)));var r,i,o},ce.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(ce.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},ce.expr.pseudos.animated=function(t){return ce.grep(ce.timers,function(e){return t===e.elem}).length},ce.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=ce.css(e,"position"),c=ce(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=ce.css(e,"top"),u=ce.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),v(t)&&(t=t.call(e,n,ce.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},ce.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){ce.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===ce.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===ce.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=ce(e).offset()).top+=ce.css(e,"borderTopWidth",!0),i.left+=ce.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-ce.css(r,"marginTop",!0),left:t.left-i.left-ce.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===ce.css(e,"position"))e=e.offsetParent;return e||J})}}),ce.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;ce.fn[t]=function(e){return M(this,function(e,t,n){var r;if(y(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),ce.each(["top","left"],function(e,n){ce.cssHooks[n]=Ye(le.pixelPosition,function(e,t){if(t)return t=Ge(e,n),_e.test(t)?ce(e).position()[n]+"px":t})}),ce.each({Height:"height",Width:"width"},function(a,s){ce.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){ce.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return M(this,function(e,t,n){var r;return y(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?ce.css(e,t,i):ce.style(e,t,n,i)},s,n?e:void 0,n)}})}),ce.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){ce.fn[t]=function(e){return this.on(t,e)}}),ce.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.on("mouseenter",e).on("mouseleave",t||e)}}),ce.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){ce.fn[n]=function(e,t){return 0 response.text()) + .then(data => { + // Find where to insert the navigation + const navPlaceholder = document.getElementById('nav-placeholder'); + if (navPlaceholder) { + navPlaceholder.innerHTML = data; + } + }) + .catch(error => console.error('Error loading navigation component:', error)); +}); \ No newline at end of file diff --git a/14_Springboot_Frontend/target/classes/lk/ijse/js/order.js b/14_Springboot_Frontend/target/classes/lk/ijse/js/order.js new file mode 100644 index 0000000..3f89dde --- /dev/null +++ b/14_Springboot_Frontend/target/classes/lk/ijse/js/order.js @@ -0,0 +1,486 @@ +let cartItems = []; + +$(document).ready(function() { + initializeApp(); + + if (!$('#toastContainer').length) { + $('body').append(''); + } +}); + +function initializeApp() { + generateNextOrderId(); + + loadCustomers(); + loadItems(); + + initializeEventHandlers(); + + updateCartTable(); +} + +function generateNextOrderId() { + $("#orderIdDisplay").html('Generating...'); + + $.ajax({ + method: "GET", + url: "http://localhost:8080/api/v1/order/generateNextId", + success: function (response) { + if (response.code === 201 && response.data) { + $("#orderId").val(response.data); + $("#orderIdDisplay").text(response.data); + console.log("Next order ID:", response.data); + } else { + showError("Failed to generate order ID"); + $("#orderIdDisplay").text("Error"); + console.error("Error response:", response); + } + }, + error: function (xhr, status, error) { + showError("Failed to generate order ID"); + $("#orderIdDisplay").text("Error"); + console.error("Error details:", {xhr, status, error}); + } + }); +} + +function loadCustomers() { + $("#customerDetailsSelect") + .prop('disabled', true) + .html('Loading customers...'); + + $.ajax({ + method: "GET", + url: "http://localhost:8080/api/v1/customer/getAll", + success: function(response) { + if (response.code === 200 && response.data && response.data.length > 0) { + const customers = response.data; + + $("#customerDetailsSelect") + .empty() + .append('Select a customer...'); + + customers.forEach(customer => { + $("#customerDetailsSelect").append( + `${customer.name} (ID: ${customer.id})` + ); + }); + + window.customersData = customers; + } else { + $("#customerDetailsSelect") + .empty() + .append('No customers available'); + + showError("No customers found in the system"); + } + }, + error: function(xhr, status, error) { + $("#customerDetailsSelect") + .empty() + .append('Error loading customers'); + + showError("Failed to load customers. Please check server connection."); + console.error("Error details:", {xhr, status, error}); + }, + complete: function() { + $("#customerDetailsSelect").prop('disabled', false); + } + }); +} + +function loadItems() { + $("#ItemDetailsSelect") + .prop('disabled', true) + .html('Loading items...'); + + $.ajax({ + method: "GET", + url: "http://localhost:8080/api/v1/item/getAll", + success: function(response) { + if (response.code === 200 && response.data && response.data.length > 0) { + const items = response.data; + + $("#ItemDetailsSelect") + .empty() + .append('Select an item...'); + + items.forEach(item => { + $("#ItemDetailsSelect").append( + `${item.name} (Code: ${item.itemCode})` + ); + }); + + window.itemsData = items; + } else { + $("#ItemDetailsSelect") + .empty() + .append('No items available'); + + showError("No items found in the system"); + } + }, + error: function(xhr, status, error) { + $("#ItemDetailsSelect") + .empty() + .append('Error loading items'); + + showError("Failed to load items. Please check server connection."); + console.error("Error details:", {xhr, status, error}); + }, + complete: function() { + $("#ItemDetailsSelect").prop('disabled', false); + } + }); +} + +function initializeEventHandlers() { + $("#customerDetailsSelect").on('change', function() { + const selectedId = $(this).val(); + + if (!selectedId) { + clearCustomerDetails(); + return; + } + + const selectedCustomer = window.customersData?.find( + c => c.id.toString() === selectedId + ); + + if (selectedCustomer) { + updateCustomerDetails(selectedCustomer); + } else { + showError("Customer data not found"); + clearCustomerDetails(); + } + }); + + $("#ItemDetailsSelect").on('change', function() { + const selectedCode = $(this).val(); + + if (!selectedCode) { + clearItemDetails(); + return; + } + + const selectedItem = window.itemsData?.find( + i => i.itemCode.toString() === selectedCode + ); + + if (selectedItem) { + updateItemDetails(selectedItem); + } else { + showError("Item data not found"); + clearItemDetails(); + } + }); + + $("#addToCartBtn").on('click', function() { + const selectedItemCode = $("#ItemDetailsSelect").val(); + if (!selectedItemCode) { + showError("Please select an item first"); + return; + } + + const selectedItem = window.itemsData?.find( + i => i.itemCode.toString() === selectedItemCode + ); + + if (!selectedItem) { + showError("Selected item not found"); + return; + } + + const existingItem = cartItems.find(item => item.itemCode === selectedItem.itemCode); + + if (existingItem) { + if (existingItem.quantity + 1 > selectedItem.qty) { + showError(`Not enough stock available for ${selectedItem.name}`); + return; + } + existingItem.quantity += 1; + existingItem.total = existingItem.quantity * existingItem.unitPrice; + showSuccess(`Increased ${selectedItem.name} quantity to ${existingItem.quantity}`); + } else { + if (selectedItem.qty < 1) { + showError(`${selectedItem.name} is out of stock`); + return; + } + cartItems.push({ + itemCode: selectedItem.itemCode, + name: selectedItem.name, + quantity: 1, + unitPrice: selectedItem.price, + total: selectedItem.price + }); + showSuccess(`Added ${selectedItem.name} to cart`); + } + + updateCartTable(); + updateTotalAmount(); + }); + + $("#placeOrderButton").on('click', function() { + if (validateOrder()) { + $(this).html('Processing...').prop('disabled', true); + placeOrder(); + } + }); +} + +function validateOrder() { + const selectedCustomerId = $("#customerDetailsSelect").val(); + if (!selectedCustomerId) { + showError("Please select a customer"); + return false; + } + + if (cartItems.length === 0) { + showError("Cart is empty. Please add items to cart"); + return false; + } + + const orderId = $("#orderId").val(); + if (!orderId) { + showError("Invalid order ID"); + return false; + } + + return true; +} + +function updateCustomerDetails(customer) { + $("#customerDetailsName").text(customer.name || 'N/A'); + $("#customerDetailsAddress").text(customer.address || 'N/A'); +} + +function clearCustomerDetails() { + $("#customerDetailsName").text('Select a customer'); + $("#customerDetailsAddress").text('Address will appear here'); +} + +function updateItemDetails(item) { + $("#ItemDetailsName").text(item.name || 'N/A'); + $("#ItemDetailsPrice").text(`$${item.price.toFixed(2)}` || 'N/A'); + + const stockLevel = item.qty || 0; + let stockBadge = ''; + + if (stockLevel > 10) { + stockBadge = `${stockLevel} in stock`; + } else if (stockLevel > 0) { + stockBadge = `Low stock: ${stockLevel}`; + } else { + stockBadge = `Out of stock`; + } + + $("#ItemDetailsStock").html(stockBadge); +} + +function clearItemDetails() { + $("#ItemDetailsName").text('Select an item'); + $("#ItemDetailsPrice").text('Price will appear here'); + $("#ItemDetailsStock").text('Stock will appear here'); +} + +function updateCartTable() { + const tbody = $("#cartTableBody"); + tbody.empty(); + + if (cartItems.length === 0) { + tbody.html(` + + + + + Your cart is empty + Select items to add to your order + + + + `); + return; + } + + cartItems.forEach((item, index) => { + tbody.append(` + + + ${item.itemCode} + + + ${item.name} + + + + + + + ${item.quantity} + + + + + + $${item.unitPrice.toFixed(2)} + + $${item.total.toFixed(2)} + + + + + Remove + + + + `); + }); +} + +function removeFromCart(itemCode) { + const itemToRemove = cartItems.find(item => item.itemCode === itemCode); + if (itemToRemove) { + cartItems = cartItems.filter(item => item.itemCode !== itemCode); + updateCartTable(); + updateTotalAmount(); + showSuccess(`Removed ${itemToRemove.name} from cart`); + } +} + +function updateQuantity(itemCode, change) { + const selectedItem = cartItems.find(item => item.itemCode === itemCode); + if (!selectedItem) return; + + const inventoryItem = window.itemsData?.find(i => i.itemCode.toString() === itemCode); + if (!inventoryItem) return; + + const newQuantity = selectedItem.quantity + change; + + if (newQuantity < 1) { + return; + } + + if (change > 0 && newQuantity > inventoryItem.qty) { + showError(`Not enough stock available for ${selectedItem.name}`); + return; + } + + selectedItem.quantity = newQuantity; + selectedItem.total = selectedItem.quantity * selectedItem.unitPrice; + + updateCartTable(); + updateTotalAmount(); +} + +function updateTotalAmount() { + const total = cartItems.reduce((sum, item) => sum + item.total, 0); + $("#totalAmount").text(`Total: $${total.toFixed(2)}`); + + $("#placeOrderButton").prop('disabled', cartItems.length === 0); +} + +function showToast(message, type = 'success') { + const toast = $('').addClass('toast').addClass(type); + + const iconClass = type === 'success' ? 'bi-check-circle' : 'bi-exclamation-triangle'; + const toastIcon = $('').addClass(`bi ${iconClass} me-2`); + + const toastContent = $('').addClass('toast-content'); + const toastTitle = $('').addClass('fw-semibold mb-1').text( + type === 'success' ? 'Success' : 'Error' + ); + const toastMessage = $('').addClass('text-secondary small').text(message); + toastContent.append(toastTitle, toastMessage); + + const closeBtn = $('') + .addClass('toast-close') + .html('') + .click(function() { + toast.removeClass('show'); + setTimeout(function() { + toast.remove(); + }, 300); + }); + + toast.append(toastIcon, toastContent, closeBtn); + $('#toastContainer').append(toast); + + setTimeout(function() { + toast.addClass('show'); + }, 10); + + setTimeout(function() { + toast.removeClass('show'); + setTimeout(function() { + toast.remove(); + }, 300); + }, 5000); +} + +function showSuccess(message) { + showToast(message, 'success'); +} + +function showError(message) { + showToast(message, 'error'); +} + +function placeOrder() { + const selectedCustomerId = $("#customerDetailsSelect").val(); + const orderId = $("#orderId").val(); + const total = cartItems.reduce((sum, item) => sum + item.total, 0); + + const orderDetails = cartItems.map(item => ({ + itemCode: item.itemCode, + quantity: item.quantity, + unitPrice: item.unitPrice + })); + + const order = { + orderId: orderId, + customerId: selectedCustomerId, + orderDetails: orderDetails, + total: total + }; + + console.log("Sending order to backend:", JSON.stringify(order, null, 2)); + + $.ajax({ + method: "POST", + url: "http://localhost:8080/api/v1/order/save", + contentType: "application/json", + data: JSON.stringify(order), + success: function(response) { + console.log("Order response:", response); + if (response.code === 201) { + + cartItems = []; + updateCartTable(); + updateTotalAmount(); + clearCustomerDetails(); + showSuccess("Your Order "+ orderId + " placed successfully"); + clearItemDetails(); + $("#customerDetailsSelect").val(""); + $("#ItemDetailsSelect").val(""); + + generateNextOrderId(); + } else { + showError("Failed to place order: " + (response.message || "Unknown error")); + console.error("Order save failed:", response); + } + }, + error: function(xhr, status, error) { + showError("Failed to place order"); + console.error("Error details:", { + status: xhr.status, + statusText: xhr.statusText, + responseText: xhr.responseText + }); + }, + complete: function() { + $("#placeOrderButton") + .html(' Place Order') + .prop('disabled', false); + } + }); +} diff --git a/14_Springboot_Frontend/target/classes/lk/ijse/order.html b/14_Springboot_Frontend/target/classes/lk/ijse/order.html new file mode 100644 index 0000000..9f1af2d --- /dev/null +++ b/14_Springboot_Frontend/target/classes/lk/ijse/order.html @@ -0,0 +1,176 @@ + + + + + + Order Management System + + + + + + + + + + + + + + + + + + Create New Order + Add items, select a customer, and submit your order + + + + Order ID + Loading... + + + + + + + + + + + + + Customer Information + + + + + + Select Customer + + Loading customers... + + + + + Customer Details + + Customer Name + Select a customer + + + Address + Address will appear here + + + + + + + + + + + + + + Item Selection + + + + + + Select Item + + Loading items... + + + + + Item Details + + Item Name + Select an item + + + Price + Price will appear here + + + Available Stock + Stock will appear here + + + + + + + Add to Cart + + + + + + + + + + + + Shopping Cart + + + + + + + + Item Code + Name + Quantity + Unit Price + Total + Action + + + + + + + + + Your cart is empty + Select items to add to your order + + + + + + + + + + + Total: $0.00 + + + + Place Order + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/15_Spring_Security/.gitattributes b/15_Spring_Security/.gitattributes new file mode 100644 index 0000000..3b41682 --- /dev/null +++ b/15_Spring_Security/.gitattributes @@ -0,0 +1,2 @@ +/mvnw text eol=lf +*.cmd text eol=crlf diff --git a/15_Spring_Security/.gitignore b/15_Spring_Security/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/15_Spring_Security/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/15_Spring_Security/.mvn/wrapper/maven-wrapper.properties b/15_Spring_Security/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..d58dfb7 --- /dev/null +++ b/15_Spring_Security/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +wrapperVersion=3.3.2 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip diff --git a/15_Spring_Security/mvnw b/15_Spring_Security/mvnw new file mode 100644 index 0000000..19529dd --- /dev/null +++ b/15_Spring_Security/mvnw @@ -0,0 +1,259 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.2 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/15_Spring_Security/mvnw.cmd b/15_Spring_Security/mvnw.cmd new file mode 100644 index 0000000..249bdf3 --- /dev/null +++ b/15_Spring_Security/mvnw.cmd @@ -0,0 +1,149 @@ +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.2 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' +$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" +if ($env:MAVEN_USER_HOME) { + $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" +} +$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/15_Spring_Security/pom.xml b/15_Spring_Security/pom.xml new file mode 100644 index 0000000..a1743ab --- /dev/null +++ b/15_Spring_Security/pom.xml @@ -0,0 +1,80 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.4.3 + + + lk.ijse + Spring_Security + 0.0.1-SNAPSHOT + Spring_Security + Spring_Security + + + + + + + + + + + + + + + 17 + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.security + spring-security-test + test + + + + com.h2database + h2 + runtime + + + + mysql + mysql-connector-java + 8.0.33 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/15_Spring_Security/src/main/java/lk/ijse/spring_security/SpringSecurityApplicationWork.java b/15_Spring_Security/src/main/java/lk/ijse/spring_security/SpringSecurityApplicationWork.java new file mode 100644 index 0000000..2d4d980 --- /dev/null +++ b/15_Spring_Security/src/main/java/lk/ijse/spring_security/SpringSecurityApplicationWork.java @@ -0,0 +1,13 @@ +package lk.ijse.spring_security; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringSecurityApplicationWork { + + public static void main(String[] args) { + SpringApplication.run(SpringSecurityApplicationWork.class, args); + } + +} diff --git a/15_Spring_Security/src/main/resources/application.properties b/15_Spring_Security/src/main/resources/application.properties new file mode 100644 index 0000000..b912f52 --- /dev/null +++ b/15_Spring_Security/src/main/resources/application.properties @@ -0,0 +1,9 @@ +#spring.datasource.url=jdbc:mysql://localhost:3306/rapotortask +#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +#spring.datasource.username=root +#spring.datasource.password=Ijse@123 +#spring.jpa.hibernate.ddl-auto=update +#spring.jpa.show-sql=true + +spring.security.user.name=Chamath +spring.security.user.password=1234 diff --git a/15_Spring_Security/src/test/java/lk/ijse/spring_security/SpringSecurityApplicationTests.java b/15_Spring_Security/src/test/java/lk/ijse/spring_security/SpringSecurityApplicationTests.java new file mode 100644 index 0000000..3d4eb51 --- /dev/null +++ b/15_Spring_Security/src/test/java/lk/ijse/spring_security/SpringSecurityApplicationTests.java @@ -0,0 +1,13 @@ +package lk.ijse.spring_security; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class SpringSecurityApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/LICENSE b/LICENSE index bd47baa..e863350 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2025 Chamath +Copyright (c) 2025 Chamath Dilshan Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md new file mode 100644 index 0000000..d1c683b --- /dev/null +++ b/README.md @@ -0,0 +1,375 @@ +# 🛍️ Spring Boot E-Commerce Core API + + + +[](https://www.oracle.com/java/) +[](https://spring.io/projects/spring-boot) +[](https://www.mysql.com/) +[](LICENSE) + +[Features](#features) • [Installation](#installation) • [API Reference](#api-reference) • [Documentation](#documentation) • [Contributing](#contributing) + + + +A modern, scalable e-commerce backend API built with Spring Boot, featuring comprehensive order management, customer tracking, and inventory control. + +## 📊 System Architecture + +```mermaid +graph TD + A[Client Applications] -->|REST API| B[API Gateway] + B --> C[Spring Boot Application] + C --> D[Service Layer] + D --> E[Repository Layer] + E --> F[(MySQL Database)] + + style A fill:#f9a825,stroke:#f57f17,stroke-width:2px + style B fill:#29b6f6,stroke:#0288d1,stroke-width:2px + style C fill:#66bb6a,stroke:#43a047,stroke-width:2px + style D fill:#7e57c2,stroke:#5e35b1,stroke-width:2px + style E fill:#ec407a,stroke:#d81b60,stroke-width:2px + style F fill:#5c6bc0,stroke:#3949ab,stroke-width:2px +``` + +## 📈 Performance Metrics + +```mermaid +pie title API Response Time Distribution + "< 100ms" : 45 + "100-300ms" : 30 + "300-500ms" : 15 + "> 500ms" : 10 +``` + +## ✨ Features + + + +| Feature | Description | Status | +|---------|-------------|---------| +| 👥 **Customer Management** | Profile tracking & preferences | ✅ | +| 📦 **Inventory Control** | Real-time stock management | ✅ | +| 🛒 **Order Processing** | Complete order lifecycle | ✅ | +| 🔐 **Security** | JWT Authentication & Authorization | ✅ | +| 📊 **Analytics** | Sales & inventory insights | 🚧 | +| 💳 **Payment Gateway** | Secure payment processing | 🚧 | + + + +[Previous content remains the same until Tech Stack section] + +## 🛠️ Tech Stack + + + +```mermaid +graph LR + A[Java 17] --> B[Spring Boot 3.x] + B --> C[Spring Data JPA] + B --> D[Spring Security] + C --> E[Hibernate] + E --> F[MySQL] + B --> G[Maven] +``` + + + +[Previous installation & setup content remains the same] + +## 📊 API Performance + +```mermaid +gantt + title API Response Times + dateFormat X + axisFormat %s + + section Customer API + GET All :0, 150ms + POST New :0, 200ms + UPDATE :0, 180ms + + section Order API + Create Order :0, 300ms + Get Status :0, 100ms + + section Inventory API + Stock Check :0, 120ms + Update :0, 250ms +``` + +## 🔄 Business Flow + +```mermaid +sequenceDiagram + participant C as Client + participant A as API + participant S as Service + participant D as Database + + C->>A: Place Order + A->>S: Process Order + S->>D: Check Inventory + D-->>S: Inventory Status + S->>D: Update Stock + D-->>S: Confirmation + S-->>A: Order Status + A-->>C: Order Confirmation +``` + +[Previous API Endpoints content remains the same] + +## 📈 System Monitoring + +```mermaid +graph LR + A[API Gateway] -->|Metrics| B[Prometheus] + B -->|Visualization| C[Grafana] + A -->|Logs| D[ELK Stack] + A -->|Traces| E[Jaeger] +``` + +## 🌟 Feature Roadmap + +```mermaid +timeline + title Development Roadmap + 2024 Q1 : Basic E-commerce Features + : Customer Management + : Order Processing + 2024 Q2 : Advanced Features + : Payment Integration + : Analytics Dashboard + 2024 Q3 : Performance Optimization + : Caching Implementation + : Load Balancing + 2024 Q4 : Scale & Security + : Microservices Migration + : Enhanced Security +``` + +[Previous content remains the same until Authors section] + +## 👥 Authors + + + +[](https://github.com/ChamathDilshanC) +[](https://www.linkedin.com/in/chamathdilsahnc/) +[](mailto:dilshancolonne123@gmail.com) + + + +## 📊 Project Statistics + + + + + + + + + + +--- + + + +Made with ❤️ by [Chamath Dilshan](https://github.com/ChamathDilshanC) + +⭐ Star this repository if you find it helpful! + + + +## ✨ Features + +- **Customer Management**: Track and manage customer profiles and preferences +- **Inventory Control**: Real-time stock management and updates +- **Order Processing**: Complete order lifecycle management with transaction support +- **RESTful API**: Modern API design following REST principles +- **Security**: Robust authentication and authorization (customizable) +- **Database**: JPA/Hibernate with transaction management +- **Documentation**: Swagger/OpenAPI integration + +## 🚀 Tech Stack + +- **Java 17** +- **Spring Boot 3.x** +- **Spring Data JPA** +- **MySQL Database** +- **Maven** +- **Hibernate** + +## 📋 Prerequisites + +- JDK 17 or later +- Maven 3.6+ +- MySQL 8.0+ +- Your favorite IDE (IntelliJ IDEA recommended) + +## 🛠️ Installation & Setup + +1. **Clone the repository** + ```bash + git clone https://github.com/yourusername/spring-boot-ecommerce.git + cd spring-boot-ecommerce + ``` + +2. **Configure MySQL** + ```properties + # Update application.properties + spring.datasource.url=jdbc:mysql://localhost:3306/ecommerce_db + spring.datasource.username=your_username + spring.datasource.password=your_password + ``` + +3. **Build the project** + ```bash + mvn clean install + ``` + +4. **Run the application** + ```bash + mvn spring-boot:run + ``` + +## 🌐 API Endpoints + +### Customer Management +``` +GET /api/v1/customer - Get all customers +POST /api/v1/customer - Create new customer +PUT /api/v1/customer - Update customer +DELETE /api/v1/customer/{id} - Delete customer +``` + +### Inventory Management +``` +GET /api/v1/item - Get all items +POST /api/v1/item - Add new item +PUT /api/v1/item - Update item +DELETE /api/v1/item/{code} - Delete item +``` + +### Order Management +``` +POST /api/v1/order/save - Create new order +``` + +## 📦 Sample Request Objects + +### Create Order +```json +{ + "orderId": "ORD001", + "orderDate": "2024-02-15T14:30:00", + "customerId": "C001", + "orderDetails": [ + { + "itemCode": "ITM001", + "quantity": 2, + "unitPrice": 1500.00 + } + ], + "total": 3000.00 +} +``` + +## 🛡️ Security Configuration + +Basic configuration is included but should be customized for production: + +```java +@Configuration +@EnableWebSecurity +public class SecurityConfig { + // Add your security configuration here +} +``` + +## 📊 Database Schema + +### Core Tables +- `customer` - Customer information +- `item` - Product inventory +- `orders` - Order headers +- `order_detail` - Order line items + +## 🔧 Project Structure + +``` +src/ +├── main/ +│ ├── java/ +│ │ └── lk.ijse.spring_boot/ +│ │ ├── controller/ +│ │ ├── dto/ +│ │ ├── entity/ +│ │ ├── repo/ +│ │ ├── service/ +│ │ └── Application.java +│ └── resources/ +│ └── application.properties +└── test/ + └── java/ +``` + +## ⚙️ Configuration + +Key application properties: + +```properties +# Server Configuration +server.port=8080 +server.servlet.context-path=/api + +# Database Configuration +spring.jpa.hibernate.ddl-auto=update +spring.jpa.show-sql=true + +# Swagger/OpenAPI +springdoc.api-docs.path=/api-docs +``` + +## 🧪 Testing + +Run tests using Maven: + +```bash +mvn test +``` + +## 📈 Future Improvements + +- [ ] Add payment gateway integration +- [ ] Implement caching +- [ ] Add event-driven architecture +- [ ] Implement rate limiting +- [ ] Add metrics and monitoring +- [ ] Containerize with Docker + +## 🤝 Contributing + +1. Fork the project +2. Create your feature branch +3. Commit your changes +4. Push to the branch +5. Open a Pull Request + +## 📝 License + +This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details. + +## 👥 Authors + +- **Chamath Dilshan** - *Initial work* - [My Github ❤️](https://github.com/ChamathDilshanC) + +## 🙏 Acknowledgments + +- Spring Boot team for the amazing framework +- The open-source community + +## 📧 Contact + +- Email: dilshancolonne123@gmail.com.com +- LinkedIn: [My Linkedin ❤️](https://www.linkedin.com/in/chamathdilsahnc/) diff --git a/Spring.iml b/Spring.iml deleted file mode 100644 index 4ebfb83..0000000 --- a/Spring.iml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/Z16_Frontend/pom.xml b/Z16_Frontend/pom.xml new file mode 100644 index 0000000..f7a6076 --- /dev/null +++ b/Z16_Frontend/pom.xml @@ -0,0 +1,17 @@ + + + 4.0.0 + + lk.ijse + Z16_Frontend + 1.0-SNAPSHOT + + + 22 + 22 + UTF-8 + + + \ No newline at end of file diff --git a/Z16_Frontend/src/main/java/lk/ijse/JQuery/jquery-3.7.1.min.js b/Z16_Frontend/src/main/java/lk/ijse/JQuery/jquery-3.7.1.min.js new file mode 100644 index 0000000..7f37b5d --- /dev/null +++ b/Z16_Frontend/src/main/java/lk/ijse/JQuery/jquery-3.7.1.min.js @@ -0,0 +1,2 @@ +/*! jQuery v3.7.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(ie,e){"use strict";var oe=[],r=Object.getPrototypeOf,ae=oe.slice,g=oe.flat?function(e){return oe.flat.call(e)}:function(e){return oe.concat.apply([],e)},s=oe.push,se=oe.indexOf,n={},i=n.toString,ue=n.hasOwnProperty,o=ue.toString,a=o.call(Object),le={},v=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},y=function(e){return null!=e&&e===e.window},C=ie.document,u={type:!0,src:!0,nonce:!0,noModule:!0};function m(e,t,n){var r,i,o=(n=n||C).createElement("script");if(o.text=e,t)for(r in u)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[i.call(e)]||"object":typeof e}var t="3.7.1",l=/HTML$/i,ce=function(e,t){return new ce.fn.init(e,t)};function c(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!v(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+ge+")"+ge+"*"),x=new RegExp(ge+"|>"),j=new RegExp(g),A=new RegExp("^"+t+"$"),D={ID:new RegExp("^#("+t+")"),CLASS:new RegExp("^\\.("+t+")"),TAG:new RegExp("^("+t+"|[*])"),ATTR:new RegExp("^"+p),PSEUDO:new RegExp("^"+g),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ge+"*(even|odd|(([+-]|)(\\d*)n|)"+ge+"*(?:([+-]|)"+ge+"*(\\d+)|))"+ge+"*\\)|)","i"),bool:new RegExp("^(?:"+f+")$","i"),needsContext:new RegExp("^"+ge+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ge+"*((?:-\\d)?\\d*)"+ge+"*\\)|)(?=[^-]|$)","i")},N=/^(?:input|select|textarea|button)$/i,q=/^h\d$/i,L=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,H=/[+~]/,O=new RegExp("\\\\[\\da-fA-F]{1,6}"+ge+"?|\\\\([^\\r\\n\\f])","g"),P=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},M=function(){V()},R=J(function(e){return!0===e.disabled&&fe(e,"fieldset")},{dir:"parentNode",next:"legend"});try{k.apply(oe=ae.call(ye.childNodes),ye.childNodes),oe[ye.childNodes.length].nodeType}catch(e){k={apply:function(e,t){me.apply(e,ae.call(t))},call:function(e){me.apply(e,ae.call(arguments,1))}}}function I(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(V(e),e=e||T,C)){if(11!==p&&(u=L.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return k.call(n,a),n}else if(f&&(a=f.getElementById(i))&&I.contains(e,a)&&a.id===i)return k.call(n,a),n}else{if(u[2])return k.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&e.getElementsByClassName)return k.apply(n,e.getElementsByClassName(i)),n}if(!(h[t+" "]||d&&d.test(t))){if(c=t,f=e,1===p&&(x.test(t)||m.test(t))){(f=H.test(t)&&U(e.parentNode)||e)==e&&le.scope||((s=e.getAttribute("id"))?s=ce.escapeSelector(s):e.setAttribute("id",s=S)),o=(l=Y(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+Q(l[o]);c=l.join(",")}try{return k.apply(n,f.querySelectorAll(c)),n}catch(e){h(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return re(t.replace(ve,"$1"),e,n,r)}function W(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function F(e){return e[S]=!0,e}function $(e){var t=T.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function B(t){return function(e){return fe(e,"input")&&e.type===t}}function _(t){return function(e){return(fe(e,"input")||fe(e,"button"))&&e.type===t}}function z(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&R(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function X(a){return F(function(o){return o=+o,F(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function U(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function V(e){var t,n=e?e.ownerDocument||e:ye;return n!=T&&9===n.nodeType&&n.documentElement&&(r=(T=n).documentElement,C=!ce.isXMLDoc(T),i=r.matches||r.webkitMatchesSelector||r.msMatchesSelector,r.msMatchesSelector&&ye!=T&&(t=T.defaultView)&&t.top!==t&&t.addEventListener("unload",M),le.getById=$(function(e){return r.appendChild(e).id=ce.expando,!T.getElementsByName||!T.getElementsByName(ce.expando).length}),le.disconnectedMatch=$(function(e){return i.call(e,"*")}),le.scope=$(function(){return T.querySelectorAll(":scope")}),le.cssHas=$(function(){try{return T.querySelector(":has(*,:jqfake)"),!1}catch(e){return!0}}),le.getById?(b.filter.ID=function(e){var t=e.replace(O,P);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(O,P);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):t.querySelectorAll(e)},b.find.CLASS=function(e,t){if("undefined"!=typeof t.getElementsByClassName&&C)return t.getElementsByClassName(e)},d=[],$(function(e){var t;r.appendChild(e).innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+ge+"*(?:value|"+f+")"),e.querySelectorAll("[id~="+S+"-]").length||d.push("~="),e.querySelectorAll("a#"+S+"+*").length||d.push(".#.+[+~]"),e.querySelectorAll(":checked").length||d.push(":checked"),(t=T.createElement("input")).setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),r.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&d.push(":enabled",":disabled"),(t=T.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||d.push("\\["+ge+"*name"+ge+"*="+ge+"*(?:''|\"\")")}),le.cssHas||d.push(":has"),d=d.length&&new RegExp(d.join("|")),l=function(e,t){if(e===t)return a=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!le.sortDetached&&t.compareDocumentPosition(e)===n?e===T||e.ownerDocument==ye&&I.contains(ye,e)?-1:t===T||t.ownerDocument==ye&&I.contains(ye,t)?1:o?se.call(o,e)-se.call(o,t):0:4&n?-1:1)}),T}for(e in I.matches=function(e,t){return I(e,null,null,t)},I.matchesSelector=function(e,t){if(V(e),C&&!h[t+" "]&&(!d||!d.test(t)))try{var n=i.call(e,t);if(n||le.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){h(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(O,P),e[3]=(e[3]||e[4]||e[5]||"").replace(O,P),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||I.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&I.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return D.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&j.test(n)&&(t=Y(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(O,P).toLowerCase();return"*"===e?function(){return!0}:function(e){return fe(e,t)}},CLASS:function(e){var t=s[e+" "];return t||(t=new RegExp("(^|"+ge+")"+e+"("+ge+"|$)"))&&s(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=I.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function T(e,n,r){return v(n)?ce.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?ce.grep(e,function(e){return e===n!==r}):"string"!=typeof n?ce.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(ce.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||k,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:S.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof ce?t[0]:t,ce.merge(this,ce.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:C,!0)),w.test(r[1])&&ce.isPlainObject(t))for(r in t)v(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=C.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):v(e)?void 0!==n.ready?n.ready(e):e(ce):ce.makeArray(e,this)}).prototype=ce.fn,k=ce(C);var E=/^(?:parents|prev(?:Until|All))/,j={children:!0,contents:!0,next:!0,prev:!0};function A(e,t){while((e=e[t])&&1!==e.nodeType);return e}ce.fn.extend({has:function(e){var t=ce(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,Ce=/^$|^module$|\/(?:java|ecma)script/i;xe=C.createDocumentFragment().appendChild(C.createElement("div")),(be=C.createElement("input")).setAttribute("type","radio"),be.setAttribute("checked","checked"),be.setAttribute("name","t"),xe.appendChild(be),le.checkClone=xe.cloneNode(!0).cloneNode(!0).lastChild.checked,xe.innerHTML="x",le.noCloneChecked=!!xe.cloneNode(!0).lastChild.defaultValue,xe.innerHTML="",le.option=!!xe.lastChild;var ke={thead:[1,"",""],col:[2,"",""],tr:[2,"",""],td:[3,"",""],_default:[0,"",""]};function Se(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&fe(e,t)?ce.merge([e],n):n}function Ee(e,t){for(var n=0,r=e.length;n",""]);var je=/<|?\w+;/;function Ae(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function Re(e,t){return fe(e,"table")&&fe(11!==t.nodeType?t:t.firstChild,"tr")&&ce(e).children("tbody")[0]||e}function Ie(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function We(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Fe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(_.hasData(e)&&(s=_.get(e).events))for(i in _.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),C.head.appendChild(r[0])},abort:function(){i&&i()}}});var Jt,Kt=[],Zt=/(=)\?(?=&|$)|\?\?/;ce.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Kt.pop()||ce.expando+"_"+jt.guid++;return this[e]=!0,e}}),ce.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Zt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Zt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=v(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Zt,"$1"+r):!1!==e.jsonp&&(e.url+=(At.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||ce.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=ie[r],ie[r]=function(){o=arguments},n.always(function(){void 0===i?ce(ie).removeProp(r):ie[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Kt.push(r)),o&&v(i)&&i(o[0]),o=i=void 0}),"script"}),le.createHTMLDocument=((Jt=C.implementation.createHTMLDocument("").body).innerHTML="",2===Jt.childNodes.length),ce.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(le.createHTMLDocument?((r=(t=C.implementation.createHTMLDocument("")).createElement("base")).href=C.location.href,t.head.appendChild(r)):t=C),o=!n&&[],(i=w.exec(e))?[t.createElement(i[1])]:(i=Ae([e],t,o),o&&o.length&&ce(o).remove(),ce.merge([],i.childNodes)));var r,i,o},ce.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(ce.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},ce.expr.pseudos.animated=function(t){return ce.grep(ce.timers,function(e){return t===e.elem}).length},ce.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=ce.css(e,"position"),c=ce(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=ce.css(e,"top"),u=ce.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),v(t)&&(t=t.call(e,n,ce.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},ce.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){ce.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===ce.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===ce.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=ce(e).offset()).top+=ce.css(e,"borderTopWidth",!0),i.left+=ce.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-ce.css(r,"marginTop",!0),left:t.left-i.left-ce.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===ce.css(e,"position"))e=e.offsetParent;return e||J})}}),ce.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;ce.fn[t]=function(e){return M(this,function(e,t,n){var r;if(y(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),ce.each(["top","left"],function(e,n){ce.cssHooks[n]=Ye(le.pixelPosition,function(e,t){if(t)return t=Ge(e,n),_e.test(t)?ce(e).position()[n]+"px":t})}),ce.each({Height:"height",Width:"width"},function(a,s){ce.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){ce.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return M(this,function(e,t,n){var r;return y(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?ce.css(e,t,i):ce.style(e,t,n,i)},s,n?e:void 0,n)}})}),ce.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){ce.fn[t]=function(e){return this.on(t,e)}}),ce.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.on("mouseenter",e).on("mouseleave",t||e)}}),ce.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){ce.fn[n]=function(e,t){return 0').addClass('toast').addClass(type); + + const iconClass = type === 'success' ? 'fa-check-circle' : 'fa-exclamation-circle'; + const toastIcon = $('').addClass('toast-icon').append( + $('').addClass('fas ' + iconClass) + ); + + const toastContent = $('').addClass('toast-content'); + const toastTitle = $('').addClass('toast-title').text( + type === 'success' ? 'Success' : 'Error' + ); + const toastMessage = $('').addClass('toast-message').text(message); + toastContent.append(toastTitle, toastMessage); + + const closeBtn = $('') + .addClass('toast-close') + .html('') + .click(function() { + toast.removeClass('show'); + setTimeout(function() { + toast.remove(); + }, 300); + }); + + toast.append(toastIcon, toastContent, closeBtn); + + $('#toastContainer').append(toast); + + setTimeout(function() { + toast.addClass('show'); + }, 10) + + setTimeout(function() { + toast.removeClass('show'); + setTimeout(function() { + toast.remove(); + }, 300); + }, 5000); +} \ No newline at end of file diff --git a/Z16_Frontend/src/main/java/lk/ijse/Js/register.js b/Z16_Frontend/src/main/java/lk/ijse/Js/register.js new file mode 100644 index 0000000..0f7d01f --- /dev/null +++ b/Z16_Frontend/src/main/java/lk/ijse/Js/register.js @@ -0,0 +1,74 @@ +$("#submit").click(function () { + event.preventDefault(); + + const name = $("#name").val(); + const email = $("#email").val(); + const password = $("#password").val(); + const role = "USER"; + + + $.ajax({ + url: "http://localhost:8080/api/v1/user/register", + method: "POST", + async: true, + contentType: "application/json", + data: JSON.stringify({ + email: email, + password: password, + name: name, + role: role + }), + success: function (data) { + sessionStorage.setItem("token", data.token); + sessionStorage.setItem("email", email); + // set interval + showToast("Register successful", "success"); + setInterval(function () { + window.location.href = "index.html"; + }, 1000); + + }, + error: function (response) { + if (response.status === 401) { + showToast("Invalid credentials. Please try again.", "error"); + } else if (response.status === 500) { + showToast("Internal server error. Please try again later.", "error"); + } else { + showToast("Failed to login", "error"); + } + } + }); +}) + +function showToast(message, type = 'success') { + const toast = $('').addClass('toast').addClass(type); + + const iconClass = type === 'success' ? 'fa-check-circle' : 'fa-exclamation-circle'; + const toastIcon = $('').addClass('toast-icon').append( + $('').addClass('fas ' + iconClass) + ); + + const toastContent = $('').addClass('toast-content'); + const toastTitle = $('').addClass('toast-title').text( + type === 'success' ? 'Success' : 'Error' + ); + const toastMessage = $('').addClass('toast-message').text(message); + toastContent.append(toastTitle, toastMessage); + + const closeBtn = $('') + .addClass('toast-close') + .html('') + .click(function() { + toast.removeClass('show'); + setTimeout(function() { + toast.remove(); + }, 300); + }); + + toast.append(toastIcon, toastContent, closeBtn); + $('body').append(toast); + + setTimeout(function() { + toast.addClass('show'); + }, 100); +} \ No newline at end of file diff --git a/Z16_Frontend/src/main/java/lk/ijse/css/tost.css b/Z16_Frontend/src/main/java/lk/ijse/css/tost.css new file mode 100644 index 0000000..4e2e720 --- /dev/null +++ b/Z16_Frontend/src/main/java/lk/ijse/css/tost.css @@ -0,0 +1,71 @@ + +/* Toast Notification */ +.toast-container { + position: fixed; + bottom: 1.5rem; + right: 1.5rem; + z-index: 1010; +} + +.toast { + display: flex; + align-items: center; + padding: 0.75rem 1rem; + background-color: white; + border-radius: 0.5rem; + box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); + margin-top: 0.75rem; + transform: translateX(150%); + transition: transform 0.3s; + max-width: 350px; +} + +.toast.show { + transform: translateX(0); +} + +.toast.success .toast-icon { + background-color: #dcfce7; + color: #166534; +} + +.toast.error .toast-icon { + background-color: #fee2e2; + color: #991b1b; +} + +.toast-icon { + width: 2rem; + height: 2rem; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin-right: 0.75rem; + flex-shrink: 0; +} + +.toast-content { + flex-grow: 1; +} + +.toast-title { + font-weight: 600; + font-size: 0.875rem; + margin-bottom: 0.25rem; +} + +.toast-message { + font-size: 0.8125rem; + color: #64748b; +} + +.toast-close { + background: none; + border: none; + color: #94a3b8; + cursor: pointer; + padding: 0.5rem; + margin: -0.5rem; + flex-shrink: 0; +} diff --git a/Z16_Frontend/src/main/java/lk/ijse/dashboard.html b/Z16_Frontend/src/main/java/lk/ijse/dashboard.html new file mode 100644 index 0000000..af26839 --- /dev/null +++ b/Z16_Frontend/src/main/java/lk/ijse/dashboard.html @@ -0,0 +1,175 @@ + + + + + + DigiPay -Dashboard + + + + + + + + + digipay + + + Services + Credit + API + Payment + + + + Help + Reports + Download + + + + + + + Simplify The Process + Of Purchasing Or Renewing Subscription + + + + + Subscription + Payment + Portal + + + + + + + + + + + Credit + + **** **** **** 1234 + + + + + + + + + + + + + + Automatic Renewal + Smart System + + + + + + + + + + + + + + + + + + + High Flexibility + + Complete Flexibility In Defining The Length Of The Entire Contract Period And Payment + Terms. + + + + + + + + + + + Cancel The Contract + + The Possibility Of Unilateral Or Bilateral Cancellation Of The Contract + + + + + + + + + + + Access To Report Panel + + Various Highly Services And Reporting Panels For Businesses + + + + + + + + + + + Free For Test + + Free Demo And Free Use For 2 Months Without Any Conditions + + + + + + + + + + + Trial + + Possibility Of Setting A Trial Period For The Contract + + + + + + + + + + + Facilitate Similar Contracts + + The Possibility Of Having Similar Contracts To Deploy Very Rapid To The Project + + + + + \ No newline at end of file diff --git a/Z16_Frontend/src/main/java/lk/ijse/index.html b/Z16_Frontend/src/main/java/lk/ijse/index.html new file mode 100644 index 0000000..0fb31d7 --- /dev/null +++ b/Z16_Frontend/src/main/java/lk/ijse/index.html @@ -0,0 +1,93 @@ + + + + + + Modern Login UI + + + + + + + + + + + + + + + + Welcome Back + Enter your credentials to access your account + + + + + + + + + + + + + + + + + + + + + + + Sign In + + + + + + + Don't have an account? + Register + + + + + + + + + + \ No newline at end of file diff --git a/Z16_Frontend/src/main/java/lk/ijse/register.html b/Z16_Frontend/src/main/java/lk/ijse/register.html new file mode 100644 index 0000000..8806dec --- /dev/null +++ b/Z16_Frontend/src/main/java/lk/ijse/register.html @@ -0,0 +1,118 @@ + + + + + + Modern Sign Up UI + + + + + + + + + + + + + + + + Create Account + Enter your details to register + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + I agree to the Terms of Service and Privacy Policy + + + + + + Sign Up + + + + + + + Already have an account? + Sign In + + + + + + + + + \ No newline at end of file diff --git a/Z16_Frontend/src/main/java/lk/ijse/tailwind.config.js b/Z16_Frontend/src/main/java/lk/ijse/tailwind.config.js new file mode 100644 index 0000000..e69de29 diff --git a/Z16_Frontend/target/classes/lk/ijse/JQuery/jquery-3.7.1.min.js b/Z16_Frontend/target/classes/lk/ijse/JQuery/jquery-3.7.1.min.js new file mode 100644 index 0000000..7f37b5d --- /dev/null +++ b/Z16_Frontend/target/classes/lk/ijse/JQuery/jquery-3.7.1.min.js @@ -0,0 +1,2 @@ +/*! jQuery v3.7.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(ie,e){"use strict";var oe=[],r=Object.getPrototypeOf,ae=oe.slice,g=oe.flat?function(e){return oe.flat.call(e)}:function(e){return oe.concat.apply([],e)},s=oe.push,se=oe.indexOf,n={},i=n.toString,ue=n.hasOwnProperty,o=ue.toString,a=o.call(Object),le={},v=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},y=function(e){return null!=e&&e===e.window},C=ie.document,u={type:!0,src:!0,nonce:!0,noModule:!0};function m(e,t,n){var r,i,o=(n=n||C).createElement("script");if(o.text=e,t)for(r in u)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[i.call(e)]||"object":typeof e}var t="3.7.1",l=/HTML$/i,ce=function(e,t){return new ce.fn.init(e,t)};function c(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!v(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+ge+")"+ge+"*"),x=new RegExp(ge+"|>"),j=new RegExp(g),A=new RegExp("^"+t+"$"),D={ID:new RegExp("^#("+t+")"),CLASS:new RegExp("^\\.("+t+")"),TAG:new RegExp("^("+t+"|[*])"),ATTR:new RegExp("^"+p),PSEUDO:new RegExp("^"+g),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ge+"*(even|odd|(([+-]|)(\\d*)n|)"+ge+"*(?:([+-]|)"+ge+"*(\\d+)|))"+ge+"*\\)|)","i"),bool:new RegExp("^(?:"+f+")$","i"),needsContext:new RegExp("^"+ge+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ge+"*((?:-\\d)?\\d*)"+ge+"*\\)|)(?=[^-]|$)","i")},N=/^(?:input|select|textarea|button)$/i,q=/^h\d$/i,L=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,H=/[+~]/,O=new RegExp("\\\\[\\da-fA-F]{1,6}"+ge+"?|\\\\([^\\r\\n\\f])","g"),P=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},M=function(){V()},R=J(function(e){return!0===e.disabled&&fe(e,"fieldset")},{dir:"parentNode",next:"legend"});try{k.apply(oe=ae.call(ye.childNodes),ye.childNodes),oe[ye.childNodes.length].nodeType}catch(e){k={apply:function(e,t){me.apply(e,ae.call(t))},call:function(e){me.apply(e,ae.call(arguments,1))}}}function I(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(V(e),e=e||T,C)){if(11!==p&&(u=L.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return k.call(n,a),n}else if(f&&(a=f.getElementById(i))&&I.contains(e,a)&&a.id===i)return k.call(n,a),n}else{if(u[2])return k.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&e.getElementsByClassName)return k.apply(n,e.getElementsByClassName(i)),n}if(!(h[t+" "]||d&&d.test(t))){if(c=t,f=e,1===p&&(x.test(t)||m.test(t))){(f=H.test(t)&&U(e.parentNode)||e)==e&&le.scope||((s=e.getAttribute("id"))?s=ce.escapeSelector(s):e.setAttribute("id",s=S)),o=(l=Y(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+Q(l[o]);c=l.join(",")}try{return k.apply(n,f.querySelectorAll(c)),n}catch(e){h(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return re(t.replace(ve,"$1"),e,n,r)}function W(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function F(e){return e[S]=!0,e}function $(e){var t=T.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function B(t){return function(e){return fe(e,"input")&&e.type===t}}function _(t){return function(e){return(fe(e,"input")||fe(e,"button"))&&e.type===t}}function z(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&R(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function X(a){return F(function(o){return o=+o,F(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function U(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function V(e){var t,n=e?e.ownerDocument||e:ye;return n!=T&&9===n.nodeType&&n.documentElement&&(r=(T=n).documentElement,C=!ce.isXMLDoc(T),i=r.matches||r.webkitMatchesSelector||r.msMatchesSelector,r.msMatchesSelector&&ye!=T&&(t=T.defaultView)&&t.top!==t&&t.addEventListener("unload",M),le.getById=$(function(e){return r.appendChild(e).id=ce.expando,!T.getElementsByName||!T.getElementsByName(ce.expando).length}),le.disconnectedMatch=$(function(e){return i.call(e,"*")}),le.scope=$(function(){return T.querySelectorAll(":scope")}),le.cssHas=$(function(){try{return T.querySelector(":has(*,:jqfake)"),!1}catch(e){return!0}}),le.getById?(b.filter.ID=function(e){var t=e.replace(O,P);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(O,P);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):t.querySelectorAll(e)},b.find.CLASS=function(e,t){if("undefined"!=typeof t.getElementsByClassName&&C)return t.getElementsByClassName(e)},d=[],$(function(e){var t;r.appendChild(e).innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+ge+"*(?:value|"+f+")"),e.querySelectorAll("[id~="+S+"-]").length||d.push("~="),e.querySelectorAll("a#"+S+"+*").length||d.push(".#.+[+~]"),e.querySelectorAll(":checked").length||d.push(":checked"),(t=T.createElement("input")).setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),r.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&d.push(":enabled",":disabled"),(t=T.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||d.push("\\["+ge+"*name"+ge+"*="+ge+"*(?:''|\"\")")}),le.cssHas||d.push(":has"),d=d.length&&new RegExp(d.join("|")),l=function(e,t){if(e===t)return a=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!le.sortDetached&&t.compareDocumentPosition(e)===n?e===T||e.ownerDocument==ye&&I.contains(ye,e)?-1:t===T||t.ownerDocument==ye&&I.contains(ye,t)?1:o?se.call(o,e)-se.call(o,t):0:4&n?-1:1)}),T}for(e in I.matches=function(e,t){return I(e,null,null,t)},I.matchesSelector=function(e,t){if(V(e),C&&!h[t+" "]&&(!d||!d.test(t)))try{var n=i.call(e,t);if(n||le.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){h(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(O,P),e[3]=(e[3]||e[4]||e[5]||"").replace(O,P),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||I.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&I.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return D.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&j.test(n)&&(t=Y(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(O,P).toLowerCase();return"*"===e?function(){return!0}:function(e){return fe(e,t)}},CLASS:function(e){var t=s[e+" "];return t||(t=new RegExp("(^|"+ge+")"+e+"("+ge+"|$)"))&&s(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=I.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function T(e,n,r){return v(n)?ce.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?ce.grep(e,function(e){return e===n!==r}):"string"!=typeof n?ce.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(ce.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||k,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:S.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof ce?t[0]:t,ce.merge(this,ce.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:C,!0)),w.test(r[1])&&ce.isPlainObject(t))for(r in t)v(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=C.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):v(e)?void 0!==n.ready?n.ready(e):e(ce):ce.makeArray(e,this)}).prototype=ce.fn,k=ce(C);var E=/^(?:parents|prev(?:Until|All))/,j={children:!0,contents:!0,next:!0,prev:!0};function A(e,t){while((e=e[t])&&1!==e.nodeType);return e}ce.fn.extend({has:function(e){var t=ce(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,Ce=/^$|^module$|\/(?:java|ecma)script/i;xe=C.createDocumentFragment().appendChild(C.createElement("div")),(be=C.createElement("input")).setAttribute("type","radio"),be.setAttribute("checked","checked"),be.setAttribute("name","t"),xe.appendChild(be),le.checkClone=xe.cloneNode(!0).cloneNode(!0).lastChild.checked,xe.innerHTML="x",le.noCloneChecked=!!xe.cloneNode(!0).lastChild.defaultValue,xe.innerHTML="",le.option=!!xe.lastChild;var ke={thead:[1,"",""],col:[2,"",""],tr:[2,"",""],td:[3,"",""],_default:[0,"",""]};function Se(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&fe(e,t)?ce.merge([e],n):n}function Ee(e,t){for(var n=0,r=e.length;n",""]);var je=/<|?\w+;/;function Ae(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function Re(e,t){return fe(e,"table")&&fe(11!==t.nodeType?t:t.firstChild,"tr")&&ce(e).children("tbody")[0]||e}function Ie(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function We(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Fe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(_.hasData(e)&&(s=_.get(e).events))for(i in _.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),C.head.appendChild(r[0])},abort:function(){i&&i()}}});var Jt,Kt=[],Zt=/(=)\?(?=&|$)|\?\?/;ce.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Kt.pop()||ce.expando+"_"+jt.guid++;return this[e]=!0,e}}),ce.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Zt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Zt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=v(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Zt,"$1"+r):!1!==e.jsonp&&(e.url+=(At.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||ce.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=ie[r],ie[r]=function(){o=arguments},n.always(function(){void 0===i?ce(ie).removeProp(r):ie[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Kt.push(r)),o&&v(i)&&i(o[0]),o=i=void 0}),"script"}),le.createHTMLDocument=((Jt=C.implementation.createHTMLDocument("").body).innerHTML="",2===Jt.childNodes.length),ce.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(le.createHTMLDocument?((r=(t=C.implementation.createHTMLDocument("")).createElement("base")).href=C.location.href,t.head.appendChild(r)):t=C),o=!n&&[],(i=w.exec(e))?[t.createElement(i[1])]:(i=Ae([e],t,o),o&&o.length&&ce(o).remove(),ce.merge([],i.childNodes)));var r,i,o},ce.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(ce.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},ce.expr.pseudos.animated=function(t){return ce.grep(ce.timers,function(e){return t===e.elem}).length},ce.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=ce.css(e,"position"),c=ce(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=ce.css(e,"top"),u=ce.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),v(t)&&(t=t.call(e,n,ce.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},ce.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){ce.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===ce.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===ce.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=ce(e).offset()).top+=ce.css(e,"borderTopWidth",!0),i.left+=ce.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-ce.css(r,"marginTop",!0),left:t.left-i.left-ce.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===ce.css(e,"position"))e=e.offsetParent;return e||J})}}),ce.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;ce.fn[t]=function(e){return M(this,function(e,t,n){var r;if(y(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),ce.each(["top","left"],function(e,n){ce.cssHooks[n]=Ye(le.pixelPosition,function(e,t){if(t)return t=Ge(e,n),_e.test(t)?ce(e).position()[n]+"px":t})}),ce.each({Height:"height",Width:"width"},function(a,s){ce.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){ce.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return M(this,function(e,t,n){var r;return y(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?ce.css(e,t,i):ce.style(e,t,n,i)},s,n?e:void 0,n)}})}),ce.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){ce.fn[t]=function(e){return this.on(t,e)}}),ce.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.on("mouseenter",e).on("mouseleave",t||e)}}),ce.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){ce.fn[n]=function(e,t){return 0').addClass('toast').addClass(type); + + const iconClass = type === 'success' ? 'fa-check-circle' : 'fa-exclamation-circle'; + const toastIcon = $('').addClass('toast-icon').append( + $('').addClass('fas ' + iconClass) + ); + + const toastContent = $('').addClass('toast-content'); + const toastTitle = $('').addClass('toast-title').text( + type === 'success' ? 'Success' : 'Error' + ); + const toastMessage = $('').addClass('toast-message').text(message); + toastContent.append(toastTitle, toastMessage); + + const closeBtn = $('') + .addClass('toast-close') + .html('') + .click(function() { + toast.removeClass('show'); + setTimeout(function() { + toast.remove(); + }, 300); + }); + + toast.append(toastIcon, toastContent, closeBtn); + + $('#toastContainer').append(toast); + + setTimeout(function() { + toast.addClass('show'); + }, 10) + + setTimeout(function() { + toast.removeClass('show'); + setTimeout(function() { + toast.remove(); + }, 300); + }, 5000); +} \ No newline at end of file diff --git a/Z16_Frontend/target/classes/lk/ijse/Js/register.js b/Z16_Frontend/target/classes/lk/ijse/Js/register.js new file mode 100644 index 0000000..0f7d01f --- /dev/null +++ b/Z16_Frontend/target/classes/lk/ijse/Js/register.js @@ -0,0 +1,74 @@ +$("#submit").click(function () { + event.preventDefault(); + + const name = $("#name").val(); + const email = $("#email").val(); + const password = $("#password").val(); + const role = "USER"; + + + $.ajax({ + url: "http://localhost:8080/api/v1/user/register", + method: "POST", + async: true, + contentType: "application/json", + data: JSON.stringify({ + email: email, + password: password, + name: name, + role: role + }), + success: function (data) { + sessionStorage.setItem("token", data.token); + sessionStorage.setItem("email", email); + // set interval + showToast("Register successful", "success"); + setInterval(function () { + window.location.href = "index.html"; + }, 1000); + + }, + error: function (response) { + if (response.status === 401) { + showToast("Invalid credentials. Please try again.", "error"); + } else if (response.status === 500) { + showToast("Internal server error. Please try again later.", "error"); + } else { + showToast("Failed to login", "error"); + } + } + }); +}) + +function showToast(message, type = 'success') { + const toast = $('').addClass('toast').addClass(type); + + const iconClass = type === 'success' ? 'fa-check-circle' : 'fa-exclamation-circle'; + const toastIcon = $('').addClass('toast-icon').append( + $('').addClass('fas ' + iconClass) + ); + + const toastContent = $('').addClass('toast-content'); + const toastTitle = $('').addClass('toast-title').text( + type === 'success' ? 'Success' : 'Error' + ); + const toastMessage = $('').addClass('toast-message').text(message); + toastContent.append(toastTitle, toastMessage); + + const closeBtn = $('') + .addClass('toast-close') + .html('') + .click(function() { + toast.removeClass('show'); + setTimeout(function() { + toast.remove(); + }, 300); + }); + + toast.append(toastIcon, toastContent, closeBtn); + $('body').append(toast); + + setTimeout(function() { + toast.addClass('show'); + }, 100); +} \ No newline at end of file diff --git a/Z16_Frontend/target/classes/lk/ijse/css/tost.css b/Z16_Frontend/target/classes/lk/ijse/css/tost.css new file mode 100644 index 0000000..4e2e720 --- /dev/null +++ b/Z16_Frontend/target/classes/lk/ijse/css/tost.css @@ -0,0 +1,71 @@ + +/* Toast Notification */ +.toast-container { + position: fixed; + bottom: 1.5rem; + right: 1.5rem; + z-index: 1010; +} + +.toast { + display: flex; + align-items: center; + padding: 0.75rem 1rem; + background-color: white; + border-radius: 0.5rem; + box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); + margin-top: 0.75rem; + transform: translateX(150%); + transition: transform 0.3s; + max-width: 350px; +} + +.toast.show { + transform: translateX(0); +} + +.toast.success .toast-icon { + background-color: #dcfce7; + color: #166534; +} + +.toast.error .toast-icon { + background-color: #fee2e2; + color: #991b1b; +} + +.toast-icon { + width: 2rem; + height: 2rem; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin-right: 0.75rem; + flex-shrink: 0; +} + +.toast-content { + flex-grow: 1; +} + +.toast-title { + font-weight: 600; + font-size: 0.875rem; + margin-bottom: 0.25rem; +} + +.toast-message { + font-size: 0.8125rem; + color: #64748b; +} + +.toast-close { + background: none; + border: none; + color: #94a3b8; + cursor: pointer; + padding: 0.5rem; + margin: -0.5rem; + flex-shrink: 0; +} diff --git a/Z16_Frontend/target/classes/lk/ijse/dashboard.html b/Z16_Frontend/target/classes/lk/ijse/dashboard.html new file mode 100644 index 0000000..af26839 --- /dev/null +++ b/Z16_Frontend/target/classes/lk/ijse/dashboard.html @@ -0,0 +1,175 @@ + + + + + + DigiPay -Dashboard + + + + + + + + + digipay + + + Services + Credit + API + Payment + + + + Help + Reports + Download + + + + + + + Simplify The Process + Of Purchasing Or Renewing Subscription + + + + + Subscription + Payment + Portal + + + + + + + + + + + Credit + + **** **** **** 1234 + + + + + + + + + + + + + + Automatic Renewal + Smart System + + + + + + + + + + + + + + + + + + + High Flexibility + + Complete Flexibility In Defining The Length Of The Entire Contract Period And Payment + Terms. + + + + + + + + + + + Cancel The Contract + + The Possibility Of Unilateral Or Bilateral Cancellation Of The Contract + + + + + + + + + + + Access To Report Panel + + Various Highly Services And Reporting Panels For Businesses + + + + + + + + + + + Free For Test + + Free Demo And Free Use For 2 Months Without Any Conditions + + + + + + + + + + + Trial + + Possibility Of Setting A Trial Period For The Contract + + + + + + + + + + + Facilitate Similar Contracts + + The Possibility Of Having Similar Contracts To Deploy Very Rapid To The Project + + + + + \ No newline at end of file diff --git a/Z16_Frontend/target/classes/lk/ijse/index.html b/Z16_Frontend/target/classes/lk/ijse/index.html new file mode 100644 index 0000000..0fb31d7 --- /dev/null +++ b/Z16_Frontend/target/classes/lk/ijse/index.html @@ -0,0 +1,93 @@ + + + + + + Modern Login UI + + + + + + + + + + + + + + + + Welcome Back + Enter your credentials to access your account + + + + + + + + + + + + + + + + + + + + + + + Sign In + + + + + + + Don't have an account? + Register + + + + + + + + + + \ No newline at end of file diff --git a/Z16_Frontend/target/classes/lk/ijse/register.html b/Z16_Frontend/target/classes/lk/ijse/register.html new file mode 100644 index 0000000..8806dec --- /dev/null +++ b/Z16_Frontend/target/classes/lk/ijse/register.html @@ -0,0 +1,118 @@ + + + + + + Modern Sign Up UI + + + + + + + + + + + + + + + + Create Account + Enter your details to register + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + I agree to the Terms of Service and Privacy Policy + + + + + + Sign Up + + + + + + + Already have an account? + Sign In + + + + + + + + + \ No newline at end of file diff --git a/Z16_Frontend/target/classes/lk/ijse/tailwind.config.js b/Z16_Frontend/target/classes/lk/ijse/tailwind.config.js new file mode 100644 index 0000000..e69de29 diff --git a/Z16_springwithjwt-master/.gitattributes b/Z16_springwithjwt-master/.gitattributes new file mode 100644 index 0000000..3b41682 --- /dev/null +++ b/Z16_springwithjwt-master/.gitattributes @@ -0,0 +1,2 @@ +/mvnw text eol=lf +*.cmd text eol=crlf diff --git a/Z16_springwithjwt-master/.gitignore b/Z16_springwithjwt-master/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/Z16_springwithjwt-master/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/Z16_springwithjwt-master/.mvn/wrapper/maven-wrapper.properties b/Z16_springwithjwt-master/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..d58dfb7 --- /dev/null +++ b/Z16_springwithjwt-master/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +wrapperVersion=3.3.2 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip diff --git a/Z16_springwithjwt-master/mvnw b/Z16_springwithjwt-master/mvnw new file mode 100644 index 0000000..19529dd --- /dev/null +++ b/Z16_springwithjwt-master/mvnw @@ -0,0 +1,259 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.2 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/Z16_springwithjwt-master/mvnw.cmd b/Z16_springwithjwt-master/mvnw.cmd new file mode 100644 index 0000000..249bdf3 --- /dev/null +++ b/Z16_springwithjwt-master/mvnw.cmd @@ -0,0 +1,149 @@ +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.2 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' +$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" +if ($env:MAVEN_USER_HOME) { + $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" +} +$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/Z16_springwithjwt-master/pom.xml b/Z16_springwithjwt-master/pom.xml new file mode 100644 index 0000000..dc909d3 --- /dev/null +++ b/Z16_springwithjwt-master/pom.xml @@ -0,0 +1,116 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.4.3 + + + org.example + springwithjwt + 0.0.1-SNAPSHOT + springwithjwt + springwithjwt + + + + + + + + + + + + + + + 17 + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + + + + com.mysql + mysql-connector-j + runtime + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.security + spring-security-test + test + + + + + io.jsonwebtoken + jjwt-api + 0.11.5 + + + io.jsonwebtoken + jjwt-impl + 0.11.5 + + + io.jsonwebtoken + jjwt-jackson + 0.11.5 + + + + org.modelmapper + modelmapper + 3.1.1 + + + org.projectlombok + lombok + true + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + 2.3.0 + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt.zip b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt.zip new file mode 100644 index 0000000..cf584f0 Binary files /dev/null and b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt.zip differ diff --git a/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/SpringwithjwtApplication.java b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/SpringwithjwtApplication.java new file mode 100644 index 0000000..401f0a0 --- /dev/null +++ b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/SpringwithjwtApplication.java @@ -0,0 +1,19 @@ +package org.example.springwithjwt; + +import org.modelmapper.ModelMapper; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; + +@SpringBootApplication +public class SpringwithjwtApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringwithjwtApplication.class, args); + } + @Bean + public ModelMapper modelMapper() { + return new ModelMapper(); + } + +} diff --git a/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/config/JwtFilter.java b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/config/JwtFilter.java new file mode 100644 index 0000000..2ac6c3a --- /dev/null +++ b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/config/JwtFilter.java @@ -0,0 +1,77 @@ +package org.example.springwithjwt.config; + + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.example.springwithjwt.service.impl.UserServiceImpl; +import org.example.springwithjwt.util.JwtUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import java.io.IOException; + +/** + * @author udarasan + * @TimeStamp 2023-07-15 15:00 + * @ProjectDetails invoice_service + */ +@Component +public class JwtFilter extends OncePerRequestFilter { + @Autowired + private JwtUtil jwtUtil; + @Autowired + private UserServiceImpl userService; + @Value("${jwt.secret}") + private String secretKey; + + @Override + protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { + String authorization = httpServletRequest.getHeader("Authorization"); + String token = null; + String email = null; + + + if (null != authorization && authorization.startsWith("Bearer ")) { + + token = authorization.substring(7); + email = jwtUtil.getUsernameFromToken(token); + Claims claims=jwtUtil.getUserRoleCodeFromToken(token); + httpServletRequest.setAttribute("email", email); + httpServletRequest.setAttribute("role", claims.get("role")); + } + + if (null != email && SecurityContextHolder.getContext().getAuthentication() == null) { + UserDetails userDetails + = userService.loadUserByUsername(email); + + if (jwtUtil.validateToken(token, userDetails)) { + UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken + = new UsernamePasswordAuthenticationToken(userDetails, + null, userDetails.getAuthorities()); + + usernamePasswordAuthenticationToken.setDetails( + new WebAuthenticationDetailsSource().buildDetails(httpServletRequest) + ); + + SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken); + } + + } + filterChain.doFilter(httpServletRequest, httpServletResponse); + } + + private Claims getClaimsFromJwtToken(String token) { + return Jwts.parser().setSigningKey(secretKey.getBytes()).parseClaimsJws(token).getBody(); + } + +} diff --git a/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/config/WebSecurityConfig.java b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/config/WebSecurityConfig.java new file mode 100644 index 0000000..ea8e888 --- /dev/null +++ b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/config/WebSecurityConfig.java @@ -0,0 +1,68 @@ +package org.example.springwithjwt.config; + +import org.example.springwithjwt.service.impl.UserServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + + +/** + * @author udarasan + * @TimeStamp 2023-07-15 15:00 + * @ProjectDetails invoice_service + */ + +@EnableWebSecurity +@Configuration +@EnableMethodSecurity(prePostEnabled = true) +public class WebSecurityConfig { + @Autowired + private UserServiceImpl userService; + @Autowired + private JwtFilter jwtFilter; + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(userService).passwordEncoder(passwordEncoder()); + } + @Bean + public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) + throws Exception { + return authenticationConfiguration.getAuthenticationManager(); + } + @Bean + protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + return http + .csrf(AbstractHttpConfigurer::disable) + .authorizeHttpRequests(auth -> auth + .requestMatchers( + "/api/v1/auth/authenticate", + "/api/v1/user/register", + "/api/v1/auth/refreshToken", + "/v3/api-docs/**", + "/swagger-ui/**", + "/swagger-ui.html").permitAll() + .anyRequest().authenticated() + ) + .sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class) + .build(); + } + + +} diff --git a/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/controller/AdminController.java b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/controller/AdminController.java new file mode 100644 index 0000000..bd88b42 --- /dev/null +++ b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/controller/AdminController.java @@ -0,0 +1,28 @@ +package org.example.springwithjwt.controller; + +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("api/v1/admin") +public class AdminController { + @GetMapping("/test1") + @PreAuthorize("hasAuthority('ADMIN')") + public String check(){ + return "passed~!1"; + } + + @GetMapping("/test2") + @PreAuthorize("hasAuthority('USER')") + public String checks(){ + return "passed~!2"; + } + @GetMapping("/test3") + @PreAuthorize("hasAuthority('USER')") + public String checkss(){ + return "passed~!2"; + } + +} diff --git a/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/controller/AuthController.java b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/controller/AuthController.java new file mode 100644 index 0000000..c5d8e33 --- /dev/null +++ b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/controller/AuthController.java @@ -0,0 +1,65 @@ +package org.example.springwithjwt.controller; + + +import org.example.springwithjwt.dto.AuthDTO; +import org.example.springwithjwt.dto.ResponseDTO; +import org.example.springwithjwt.dto.UserDTO; +import org.example.springwithjwt.service.impl.UserServiceImpl; +import org.example.springwithjwt.util.JwtUtil; +import org.example.springwithjwt.util.VarList; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("api/v1/auth") +@CrossOrigin +public class AuthController { + + private final JwtUtil jwtUtil; + private final AuthenticationManager authenticationManager; + private final UserServiceImpl userService; + private final ResponseDTO responseDTO; + + //constructor injection + public AuthController(JwtUtil jwtUtil, AuthenticationManager authenticationManager, UserServiceImpl userService, ResponseDTO responseDTO) { + this.jwtUtil = jwtUtil; + this.authenticationManager = authenticationManager; + this.userService = userService; + this.responseDTO = responseDTO; + } + + @PostMapping("/authenticate") + public ResponseEntity authenticate(@RequestBody UserDTO userDTO) { + try { + authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken(userDTO.getEmail(), userDTO.getPassword())); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED) + .body(new ResponseDTO(VarList.Unauthorized, "Invalid Credentials", e.getMessage())); + } + + UserDTO loadedUser = userService.loadUserDetailsByUsername(userDTO.getEmail()); + if (loadedUser == null) { + return ResponseEntity.status(HttpStatus.CONFLICT) + .body(new ResponseDTO(VarList.Conflict, "Authorization Failure! Please Try Again", null)); + } + + String token = jwtUtil.generateToken(loadedUser); + if (token == null || token.isEmpty()) { + return ResponseEntity.status(HttpStatus.CONFLICT) + .body(new ResponseDTO(VarList.Conflict, "Authorization Failure! Please Try Again", null)); + } + + AuthDTO authDTO = new AuthDTO(); + authDTO.setEmail(loadedUser.getEmail()); + authDTO.setToken(token); + + return ResponseEntity.status(HttpStatus.CREATED) + .body(new ResponseDTO(VarList.Created, "Success", authDTO)); + } + +} + diff --git a/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/controller/UserController.java b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/controller/UserController.java new file mode 100644 index 0000000..f94afb1 --- /dev/null +++ b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/controller/UserController.java @@ -0,0 +1,54 @@ +package org.example.springwithjwt.controller; + +import jakarta.validation.Valid; +import org.example.springwithjwt.dto.AuthDTO; +import org.example.springwithjwt.dto.ResponseDTO; +import org.example.springwithjwt.dto.UserDTO; +import org.example.springwithjwt.service.UserService; +import org.example.springwithjwt.util.JwtUtil; +import org.example.springwithjwt.util.VarList; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("api/v1/user") +@CrossOrigin +public class UserController { + private final UserService userService; + private final JwtUtil jwtUtil; + + //constructor injection + public UserController(UserService userService, JwtUtil jwtUtil) { + this.userService = userService; + this.jwtUtil = jwtUtil; + } + @PostMapping(value = "/register") + public ResponseEntity registerUser(@RequestBody @Valid UserDTO userDTO) { + try { + int res = userService.saveUser(userDTO); + switch (res) { + case VarList.Created -> { + String token = jwtUtil.generateToken(userDTO); + AuthDTO authDTO = new AuthDTO(); + authDTO.setEmail(userDTO.getEmail()); + authDTO.setToken(token); + return ResponseEntity.status(HttpStatus.CREATED) + .body(new ResponseDTO(VarList.Created, "Success", authDTO)); + } + case VarList.Not_Acceptable -> { + return ResponseEntity.status(HttpStatus.NOT_ACCEPTABLE) + .body(new ResponseDTO(VarList.Not_Acceptable, "Email Already Used", null)); + } + default -> { + return ResponseEntity.status(HttpStatus.BAD_GATEWAY) + .body(new ResponseDTO(VarList.Bad_Gateway, "Error", null)); + } + } + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ResponseDTO(VarList.Internal_Server_Error, e.getMessage(), null)); + } + } + +} diff --git a/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/dto/AuthDTO.java b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/dto/AuthDTO.java new file mode 100644 index 0000000..fa41445 --- /dev/null +++ b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/dto/AuthDTO.java @@ -0,0 +1,18 @@ +package org.example.springwithjwt.dto; + +import jakarta.validation.constraints.Email; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.stereotype.Component; + + +@AllArgsConstructor +@NoArgsConstructor +@Data +@Component +public class AuthDTO { + @Email + private String email; + private String token; +} \ No newline at end of file diff --git a/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/dto/ResponseDTO.java b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/dto/ResponseDTO.java new file mode 100644 index 0000000..972ad98 --- /dev/null +++ b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/dto/ResponseDTO.java @@ -0,0 +1,17 @@ +package org.example.springwithjwt.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.stereotype.Component; + + +@AllArgsConstructor +@NoArgsConstructor +@Data +@Component +public class ResponseDTO { + private int code; + private String message; + private Object data; +} diff --git a/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/dto/UserDTO.java b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/dto/UserDTO.java new file mode 100644 index 0000000..e8f1112 --- /dev/null +++ b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/dto/UserDTO.java @@ -0,0 +1,16 @@ +package org.example.springwithjwt.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + + +@AllArgsConstructor +@NoArgsConstructor +@Data +public class UserDTO { + private String email; + private String password; + private String name; + private String role; +} diff --git a/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/entity/User.java b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/entity/User.java new file mode 100644 index 0000000..d9047b9 --- /dev/null +++ b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/entity/User.java @@ -0,0 +1,26 @@ +package org.example.springwithjwt.entity; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.UUID; + + +@Entity +@Table(name = "systemuser") +@AllArgsConstructor +@NoArgsConstructor +@Data +public class User implements Serializable { + @Id + @GeneratedValue(strategy = GenerationType.UUID) + private UUID uid; + @Column(unique = true) + private String email; + private String password; + private String name; + private String role; +} \ No newline at end of file diff --git a/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/repo/UserRepository.java b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/repo/UserRepository.java new file mode 100644 index 0000000..a3131ad --- /dev/null +++ b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/repo/UserRepository.java @@ -0,0 +1,15 @@ +package org.example.springwithjwt.repo; + +import org.example.springwithjwt.entity.User; +import org.springframework.data.jpa.repository.JpaRepository; + + +public interface UserRepository extends JpaRepository { + + User findByEmail(String userName); + + boolean existsByEmail(String userName); + + int deleteByEmail(String userName); + +} \ No newline at end of file diff --git a/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/service/UserService.java b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/service/UserService.java new file mode 100644 index 0000000..f0edeec --- /dev/null +++ b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/service/UserService.java @@ -0,0 +1,10 @@ +package org.example.springwithjwt.service; + + +import org.example.springwithjwt.dto.UserDTO; + + +public interface UserService { + int saveUser(UserDTO userDTO); + UserDTO searchUser(String username); +} \ No newline at end of file diff --git a/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/service/impl/UserServiceImpl.java b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..f5f7df7 --- /dev/null +++ b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/service/impl/UserServiceImpl.java @@ -0,0 +1,69 @@ +package org.example.springwithjwt.service.impl; + +import org.example.springwithjwt.dto.UserDTO; +import org.example.springwithjwt.entity.User; +import org.example.springwithjwt.repo.UserRepository; +import org.example.springwithjwt.service.UserService; +import org.example.springwithjwt.util.VarList; +import org.modelmapper.ModelMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.HashSet; +import java.util.Set; + + +@Service +@Transactional +public class UserServiceImpl implements UserDetailsService, UserService { + + @Autowired + private UserRepository userRepository; + + @Autowired + private ModelMapper modelMapper; + + @Override + public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { + User user = userRepository.findByEmail(email); + return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPassword(), getAuthority(user)); + } + + public UserDTO loadUserDetailsByUsername(String username) throws UsernameNotFoundException { + User user = userRepository.findByEmail(username); + return modelMapper.map(user,UserDTO.class); + } + + private Set getAuthority(User user) { + Set authorities = new HashSet<>(); + authorities.add(new SimpleGrantedAuthority(user.getRole())); + return authorities; + } + + @Override + public UserDTO searchUser(String username) { + if (userRepository.existsByEmail(username)) { + User user=userRepository.findByEmail(username); + return modelMapper.map(user,UserDTO.class); + } else { + return null; + } + } + + @Override + public int saveUser(UserDTO userDTO) { + if (userRepository.existsByEmail(userDTO.getEmail())) { + return VarList.Not_Acceptable; + } else { + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + userDTO.setPassword(passwordEncoder.encode(userDTO.getPassword())); + userRepository.save(modelMapper.map(userDTO, User.class)); + return VarList.Created; + } + }} diff --git a/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/util/JwtUtil.java b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/util/JwtUtil.java new file mode 100644 index 0000000..346bb9d --- /dev/null +++ b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/util/JwtUtil.java @@ -0,0 +1,89 @@ +package org.example.springwithjwt.util; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import org.example.springwithjwt.dto.UserDTO; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.PropertySource; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Component; + +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; + + +@Component +@PropertySource(ignoreResourceNotFound = true, value = "classpath:otherprops.properties") +public class JwtUtil implements Serializable { + + private static final long serialVersionUID = 234234523523L; + + public static final long JWT_TOKEN_VALIDITY = 24 * 60 * 60 * 12; + + @Value("${jwt.secret}") + private String secretKey; + + //retrieve username from jwt token + public String getUsernameFromToken(String token) { + return getClaimFromToken(token, Claims::getSubject); + } + + public Claims getUserRoleCodeFromToken(String token) { + return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody(); + } + + //retrieve expiration date from jwt token + public Date getExpirationDateFromToken(String token) { + return getClaimFromToken(token, Claims::getExpiration); + } + + + public T getClaimFromToken(String token, Function claimsResolver) { + final Claims claims = getAllClaimsFromToken(token); + return claimsResolver.apply(claims); + } + + + //for retrieving any information from token we will need the secret key + private Claims getAllClaimsFromToken(String token) { + return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody(); + } + + + //check if the token has expired + private Boolean isTokenExpired(String token) { + final Date expiration = getExpirationDateFromToken(token); + return expiration.before(new Date()); + } + + + //generate token for user + public String generateToken(UserDTO userDTO) { + Map claims = new HashMap<>(); + claims.put("role",userDTO.getRole()); + return doGenerateToken(claims, userDTO.getEmail()); + } + + //while creating the token - + //1. Define claims of the token, like Issuer, Expiration, Subject, and the ID + //2. Sign the JWT using the HS512 algorithm and secret key. + private String doGenerateToken(Map claims, String subject) { + return Jwts.builder() + .setClaims(claims) + .setSubject(subject) + .setIssuedAt(new Date(System.currentTimeMillis())) + .setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY * 1000)) + .signWith(SignatureAlgorithm.HS512, secretKey).compact(); + } + + + //validate token + public Boolean validateToken(String token, UserDetails userDetails) { + final String username = getUsernameFromToken(token); + return (username.equals(userDetails.getUsername()) && !isTokenExpired(token)); + } +} diff --git a/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/util/VarList.java b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/util/VarList.java new file mode 100644 index 0000000..8e5e4a1 --- /dev/null +++ b/Z16_springwithjwt-master/src/main/java/org/example/springwithjwt/util/VarList.java @@ -0,0 +1,58 @@ +package org.example.springwithjwt.util; + +public class VarList { + public static final int Continue = 100; + public static final int Switching_Protocols = 101; + public static final int Early_Hints = 103; + public static final int OK = 200; + public static final int Created = 201; + public static final int Accepted = 202; + public static final int Non_Authoritative_Information = 203; + public static final int No_Content = 204; + public static final int Reset_Content = 205; + public static final int Partial_Content = 206; + public static final int Multiple_Choices = 300; + public static final int Moved_Permanently = 301; + public static final int Found = 302; + public static final int See_Other = 303; + public static final int Not_Modified = 304; + public static final int Temporary_Redirect = 307; + public static final int Permanent_Redirect = 308; + public static final int Bad_Request = 400; + public static final int Unauthorized = 401; + public static final int Payment_Required = 402; + public static final int Forbidden = 403; + public static final int Not_Found = 404; + public static final int Method_Not_Allowed = 405; + public static final int Not_Acceptable = 406; + public static final int Proxy_Authentication_Required = 407; + public static final int Request_Timeout = 408; + public static final int Conflict = 409; + public static final int Gone = 410; + public static final int Length_Required = 411; + public static final int Precondition_Failed = 412; + public static final int Payload_Too_Large = 413; + public static final int URI_Too_Long = 414; + public static final int Unsupported_Media_Type = 415; + public static final int Range_Not_Satisfiable = 416; + public static final int Expectation_Failed = 417; + public static final int I_m_a_teapot = 418; + public static final int Unprocessable_Entity = 422; + public static final int Too_Early = 425; + public static final int Upgrade_Required = 426; + public static final int Precondition_Required = 428; + public static final int Too_Many_Requests = 429; + public static final int Request_Header_Fields_Too_Large = 431; + public static final int Unavailable_For_Legal_Reasons = 451; + public static final int Internal_Server_Error = 500; + public static final int Not_Implemented = 501; + public static final int Bad_Gateway = 502; + public static final int Service_Unavailable = 503; + public static final int Gateway_Timeout = 504; + public static final int HTTP_Version_Not_Supported = 505; + public static final int Variant_Also_Negotiates = 506; + public static final int Insufficient_Storage = 507; + public static final int Loop_Detected = 508; + public static final int Not_Extended = 510; + public static final int Network_Authentication_Required = 511; +} diff --git a/Z16_springwithjwt-master/src/main/resources/application.properties b/Z16_springwithjwt-master/src/main/resources/application.properties new file mode 100644 index 0000000..2d4aaad --- /dev/null +++ b/Z16_springwithjwt-master/src/main/resources/application.properties @@ -0,0 +1,12 @@ +spring.application.name=springwithjwt +spring.datasource.url = jdbc:mysql://localhost:3306/rapotortask?createDatabaseIfNotExist=true&allowPublicKeyRetrieval=true&useSSL=false +spring.datasource.username=root +spring.datasource.password =Ijse@123 +spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL8Dialect +spring.jpa.hibernate.ddl-auto = update +spring.datasource.driver-class-name =com.mysql.cj.jdbc.Driver +spring.jpa.open-in-view=false +spring.jpa.show-sql= true +jwt.secret=2D4A614E645267556B58703273357638792F423F4428472B4B6250655368566DF423F4428472B4B6250655368566D +spring.main.allow-bean-definition-overriding=true +server.port=8080 \ No newline at end of file diff --git a/Z16_springwithjwt-master/src/test/java/org/example/springwithjwt/SpringwithjwtApplicationTests.java b/Z16_springwithjwt-master/src/test/java/org/example/springwithjwt/SpringwithjwtApplicationTests.java new file mode 100644 index 0000000..00011cd --- /dev/null +++ b/Z16_springwithjwt-master/src/test/java/org/example/springwithjwt/SpringwithjwtApplicationTests.java @@ -0,0 +1,13 @@ +package org.example.springwithjwt; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class SpringwithjwtApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/Z17_Springboot_Bean_Validation/.gitattributes b/Z17_Springboot_Bean_Validation/.gitattributes new file mode 100644 index 0000000..3b41682 --- /dev/null +++ b/Z17_Springboot_Bean_Validation/.gitattributes @@ -0,0 +1,2 @@ +/mvnw text eol=lf +*.cmd text eol=crlf diff --git a/Z17_Springboot_Bean_Validation/.gitignore b/Z17_Springboot_Bean_Validation/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/Z17_Springboot_Bean_Validation/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/Z17_Springboot_Bean_Validation/.mvn/wrapper/maven-wrapper.properties b/Z17_Springboot_Bean_Validation/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..d58dfb7 --- /dev/null +++ b/Z17_Springboot_Bean_Validation/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +wrapperVersion=3.3.2 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip diff --git a/Z17_Springboot_Bean_Validation/mvnw b/Z17_Springboot_Bean_Validation/mvnw new file mode 100644 index 0000000..19529dd --- /dev/null +++ b/Z17_Springboot_Bean_Validation/mvnw @@ -0,0 +1,259 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.2 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/Z17_Springboot_Bean_Validation/mvnw.cmd b/Z17_Springboot_Bean_Validation/mvnw.cmd new file mode 100644 index 0000000..249bdf3 --- /dev/null +++ b/Z17_Springboot_Bean_Validation/mvnw.cmd @@ -0,0 +1,149 @@ +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.2 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' +$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" +if ($env:MAVEN_USER_HOME) { + $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" +} +$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/Z17_Springboot_Bean_Validation/pom.xml b/Z17_Springboot_Bean_Validation/pom.xml new file mode 100644 index 0000000..108c4c2 --- /dev/null +++ b/Z17_Springboot_Bean_Validation/pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.4.3 + + + lk.ijse + Z17_Springboot_Bean_Validation + 0.0.1-SNAPSHOT + Z17_Springboot_Bean_Validation + Z17_Springboot_Bean_Validation + + + + + + + + + + + + + + + 21 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.boot + spring-boot-starter-validation + 3.4.1 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/Z17_Springboot_Bean_Validation/src/main/java/lk/ijse/z17_springboot_bean_validation/Advice/GlobalExceptionHandler.java b/Z17_Springboot_Bean_Validation/src/main/java/lk/ijse/z17_springboot_bean_validation/Advice/GlobalExceptionHandler.java new file mode 100644 index 0000000..3a3ea00 --- /dev/null +++ b/Z17_Springboot_Bean_Validation/src/main/java/lk/ijse/z17_springboot_bean_validation/Advice/GlobalExceptionHandler.java @@ -0,0 +1,24 @@ +package lk.ijse.z17_springboot_bean_validation.Advice; + +import lk.ijse.z17_springboot_bean_validation.DTO.ResponseDTO; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import java.util.HashMap; +import java.util.Map; + +@RestControllerAdvice +public class GlobalExceptionHandler { + @ExceptionHandler(MethodArgumentNotValidException.class) + private ResponseEntity handleException(Exception e) { + Map errors = new HashMap<>(); + for (FieldError fieldError : ((MethodArgumentNotValidException) e).getBindingResult().getFieldErrors()) { + errors.put(fieldError.getField(), fieldError.getDefaultMessage()); + } + ResponseDTO responseDTO = new ResponseDTO(401, "Validation Error", errors); + return new ResponseEntity<>(responseDTO, org.springframework.http.HttpStatus.BAD_REQUEST); + } +} diff --git a/Z17_Springboot_Bean_Validation/src/main/java/lk/ijse/z17_springboot_bean_validation/Controller/CustomerController.java b/Z17_Springboot_Bean_Validation/src/main/java/lk/ijse/z17_springboot_bean_validation/Controller/CustomerController.java new file mode 100644 index 0000000..c8d461d --- /dev/null +++ b/Z17_Springboot_Bean_Validation/src/main/java/lk/ijse/z17_springboot_bean_validation/Controller/CustomerController.java @@ -0,0 +1,23 @@ +package lk.ijse.z17_springboot_bean_validation.Controller; + +import jakarta.validation.Valid; +import lk.ijse.z17_springboot_bean_validation.DTO.CustomerDTO; +import lk.ijse.z17_springboot_bean_validation.DTO.ResponseDTO; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("api/v1/customer/") +public class CustomerController { + + @PostMapping("save") + public ResponseEntity saveCustomer(@Valid @RequestBody CustomerDTO customerDTO) { + ResponseDTO responseDTO = new ResponseDTO(200, "Customer Saved Successfully", customerDTO); + return new ResponseEntity<>(responseDTO, HttpStatus.OK); + + } +} diff --git a/Z17_Springboot_Bean_Validation/src/main/java/lk/ijse/z17_springboot_bean_validation/DTO/CustomerDTO.java b/Z17_Springboot_Bean_Validation/src/main/java/lk/ijse/z17_springboot_bean_validation/DTO/CustomerDTO.java new file mode 100644 index 0000000..1834bc0 --- /dev/null +++ b/Z17_Springboot_Bean_Validation/src/main/java/lk/ijse/z17_springboot_bean_validation/DTO/CustomerDTO.java @@ -0,0 +1,53 @@ +package lk.ijse.z17_springboot_bean_validation.DTO; + +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; +import org.springframework.boot.context.properties.bind.Name; + +public class CustomerDTO { + @Name("name") + @Size(min = 3, max = 20, message = "Name should be between 3 and 20 characters") + @NotBlank(message = "Name is mandatory") + @Pattern(regexp = "^[a-zA-Z]*$", message = "Invalid Name") + private String name; + @Email(message = "Invalid Email") + @Pattern(regexp = "^[a-zA-Z0-9+_.-]+@[a-zA-Z0-9.-]+$", message = "Invalid Email") + private String email; + @Pattern(regexp = "^[0-9]*$", message = "Invalid Phone Number") + private String phone; + + public CustomerDTO(String email, String name, String phone) { + this.email = email; + this.name = name; + this.phone = phone; + } + + public CustomerDTO() { + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } +} diff --git a/Z17_Springboot_Bean_Validation/src/main/java/lk/ijse/z17_springboot_bean_validation/DTO/ResponseDTO.java b/Z17_Springboot_Bean_Validation/src/main/java/lk/ijse/z17_springboot_bean_validation/DTO/ResponseDTO.java new file mode 100644 index 0000000..9cdf1f3 --- /dev/null +++ b/Z17_Springboot_Bean_Validation/src/main/java/lk/ijse/z17_springboot_bean_validation/DTO/ResponseDTO.java @@ -0,0 +1,41 @@ +package lk.ijse.z17_springboot_bean_validation.DTO; + +public class ResponseDTO { + private int status; + private String message; + private Object data; + + + public ResponseDTO(int status, String message, Object data) { + this.status = status; + this.message = message; + this.data = data; + } + + public ResponseDTO() { + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public Object getData() { + return data; + } + + public void setData(Object data) { + this.data = data; + } +} diff --git a/Z17_Springboot_Bean_Validation/src/main/java/lk/ijse/z17_springboot_bean_validation/Z17SpringbootBeanValidationApplication.java b/Z17_Springboot_Bean_Validation/src/main/java/lk/ijse/z17_springboot_bean_validation/Z17SpringbootBeanValidationApplication.java new file mode 100644 index 0000000..eea668a --- /dev/null +++ b/Z17_Springboot_Bean_Validation/src/main/java/lk/ijse/z17_springboot_bean_validation/Z17SpringbootBeanValidationApplication.java @@ -0,0 +1,13 @@ +package lk.ijse.z17_springboot_bean_validation; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Z17SpringbootBeanValidationApplication { + + public static void main(String[] args) { + SpringApplication.run(Z17SpringbootBeanValidationApplication.class, args); + } + +} diff --git a/Z17_Springboot_Bean_Validation/src/main/resources/application.properties b/Z17_Springboot_Bean_Validation/src/main/resources/application.properties new file mode 100644 index 0000000..8314ede --- /dev/null +++ b/Z17_Springboot_Bean_Validation/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.application.name=Z17_Springboot_Bean_Validation diff --git a/Z17_Springboot_Bean_Validation/src/test/java/lk/ijse/z17_springboot_bean_validation/Z17SpringbootBeanValidationApplicationTests.java b/Z17_Springboot_Bean_Validation/src/test/java/lk/ijse/z17_springboot_bean_validation/Z17SpringbootBeanValidationApplicationTests.java new file mode 100644 index 0000000..e6f0591 --- /dev/null +++ b/Z17_Springboot_Bean_Validation/src/test/java/lk/ijse/z17_springboot_bean_validation/Z17SpringbootBeanValidationApplicationTests.java @@ -0,0 +1,13 @@ +package lk.ijse.z17_springboot_bean_validation; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class Z17SpringbootBeanValidationApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/Z18_Springboot_Logins.log b/Z18_Springboot_Logins.log new file mode 100644 index 0000000..3753b31 --- /dev/null +++ b/Z18_Springboot_Logins.log @@ -0,0 +1,60 @@ +2025-03-07T11:32:27.580+05:30 INFO 8648 --- [Z18_Springboot_Logins] [main] l.i.z.Z18SpringbootLoginsApplication : Starting Z18SpringbootLoginsApplication using Java 21.0.2 with PID 8648 (C:\Users\dilsh\Desktop\Spring-Framework\Z18_Springboot_Logins\target\classes started by Chamath in C:\Users\dilsh\Desktop\Spring-Framework) +2025-03-07T11:32:27.584+05:30 INFO 8648 --- [Z18_Springboot_Logins] [main] l.i.z.Z18SpringbootLoginsApplication : No active profile set, falling back to 1 default profile: "default" +2025-03-07T11:32:28.928+05:30 INFO 8648 --- [Z18_Springboot_Logins] [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http) +2025-03-07T11:32:28.946+05:30 INFO 8648 --- [Z18_Springboot_Logins] [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2025-03-07T11:32:28.947+05:30 INFO 8648 --- [Z18_Springboot_Logins] [main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.36] +2025-03-07T11:32:29.010+05:30 INFO 8648 --- [Z18_Springboot_Logins] [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2025-03-07T11:32:29.011+05:30 INFO 8648 --- [Z18_Springboot_Logins] [main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1361 ms +2025-03-07T11:32:29.211+05:30 DEBUG 8648 --- [Z18_Springboot_Logins] [main] s.w.s.m.m.a.RequestMappingHandlerMapping : 3 mappings in 'requestMappingHandlerMapping' +2025-03-07T11:32:29.267+05:30 DEBUG 8648 --- [Z18_Springboot_Logins] [main] o.s.w.s.handler.SimpleUrlHandlerMapping : Patterns [/webjars/**, /**] in 'resourceHandlerMapping' +2025-03-07T11:32:29.295+05:30 DEBUG 8648 --- [Z18_Springboot_Logins] [main] s.w.s.m.m.a.RequestMappingHandlerAdapter : ControllerAdvice beans: 0 @ModelAttribute, 0 @InitBinder, 1 RequestBodyAdvice, 1 ResponseBodyAdvice +2025-03-07T11:32:29.338+05:30 DEBUG 8648 --- [Z18_Springboot_Logins] [main] .m.m.a.ExceptionHandlerExceptionResolver : ControllerAdvice beans: 0 @ExceptionHandler, 1 ResponseBodyAdvice +2025-03-07T11:32:29.435+05:30 INFO 8648 --- [Z18_Springboot_Logins] [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/' +2025-03-07T11:32:29.444+05:30 INFO 8648 --- [Z18_Springboot_Logins] [main] l.i.z.Z18SpringbootLoginsApplication : Started Z18SpringbootLoginsApplication in 2.503 seconds (process running for 3.33) +2025-03-07T11:33:04.990+05:30 INFO 8648 --- [Z18_Springboot_Logins] [SpringApplicationShutdownHook] o.s.b.w.e.tomcat.GracefulShutdown : Commencing graceful shutdown. Waiting for active requests to complete +2025-03-07T11:33:04.995+05:30 INFO 8648 --- [Z18_Springboot_Logins] [tomcat-shutdown] o.s.b.w.e.tomcat.GracefulShutdown : Graceful shutdown complete +2025-03-07T11:33:08.837+05:30 INFO 6712 --- [Z18_Springboot_Logins] [main] l.i.z.Z18SpringbootLoginsApplication : Starting Z18SpringbootLoginsApplication using Java 21.0.2 with PID 6712 (C:\Users\dilsh\Desktop\Spring-Framework\Z18_Springboot_Logins\target\classes started by Chamath in C:\Users\dilsh\Desktop\Spring-Framework) +2025-03-07T11:33:08.841+05:30 INFO 6712 --- [Z18_Springboot_Logins] [main] l.i.z.Z18SpringbootLoginsApplication : No active profile set, falling back to 1 default profile: "default" +2025-03-07T11:33:10.097+05:30 INFO 6712 --- [Z18_Springboot_Logins] [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http) +2025-03-07T11:33:10.114+05:30 INFO 6712 --- [Z18_Springboot_Logins] [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2025-03-07T11:33:10.114+05:30 INFO 6712 --- [Z18_Springboot_Logins] [main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.36] +2025-03-07T11:33:10.169+05:30 INFO 6712 --- [Z18_Springboot_Logins] [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2025-03-07T11:33:10.170+05:30 INFO 6712 --- [Z18_Springboot_Logins] [main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1261 ms +2025-03-07T11:33:10.331+05:30 DEBUG 6712 --- [Z18_Springboot_Logins] [main] s.w.s.m.m.a.RequestMappingHandlerMapping : 3 mappings in 'requestMappingHandlerMapping' +2025-03-07T11:33:10.387+05:30 DEBUG 6712 --- [Z18_Springboot_Logins] [main] o.s.w.s.handler.SimpleUrlHandlerMapping : Patterns [/webjars/**, /**] in 'resourceHandlerMapping' +2025-03-07T11:33:10.413+05:30 DEBUG 6712 --- [Z18_Springboot_Logins] [main] s.w.s.m.m.a.RequestMappingHandlerAdapter : ControllerAdvice beans: 0 @ModelAttribute, 0 @InitBinder, 1 RequestBodyAdvice, 1 ResponseBodyAdvice +2025-03-07T11:33:10.451+05:30 DEBUG 6712 --- [Z18_Springboot_Logins] [main] .m.m.a.ExceptionHandlerExceptionResolver : ControllerAdvice beans: 0 @ExceptionHandler, 1 ResponseBodyAdvice +2025-03-07T11:33:10.550+05:30 INFO 6712 --- [Z18_Springboot_Logins] [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/' +2025-03-07T11:33:10.558+05:30 INFO 6712 --- [Z18_Springboot_Logins] [main] l.i.z.Z18SpringbootLoginsApplication : Started Z18SpringbootLoginsApplication in 2.356 seconds (process running for 3.195) +2025-03-07T11:34:26.953+05:30 INFO 6712 --- [Z18_Springboot_Logins] [SpringApplicationShutdownHook] o.s.b.w.e.tomcat.GracefulShutdown : Commencing graceful shutdown. Waiting for active requests to complete +2025-03-07T11:34:26.958+05:30 INFO 6712 --- [Z18_Springboot_Logins] [tomcat-shutdown] o.s.b.w.e.tomcat.GracefulShutdown : Graceful shutdown complete +2025-03-07T11:34:30.045+05:30 INFO 16192 --- [Z18_Springboot_Logins] [main] l.i.z.Z18SpringbootLoginsApplication : Starting Z18SpringbootLoginsApplication using Java 21.0.2 with PID 16192 (C:\Users\dilsh\Desktop\Spring-Framework\Z18_Springboot_Logins\target\classes started by Chamath in C:\Users\dilsh\Desktop\Spring-Framework) +2025-03-07T11:34:30.048+05:30 INFO 16192 --- [Z18_Springboot_Logins] [main] l.i.z.Z18SpringbootLoginsApplication : No active profile set, falling back to 1 default profile: "default" +2025-03-07T11:34:31.310+05:30 INFO 16192 --- [Z18_Springboot_Logins] [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http) +2025-03-07T11:34:31.328+05:30 INFO 16192 --- [Z18_Springboot_Logins] [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2025-03-07T11:34:31.329+05:30 INFO 16192 --- [Z18_Springboot_Logins] [main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.36] +2025-03-07T11:34:31.389+05:30 INFO 16192 --- [Z18_Springboot_Logins] [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2025-03-07T11:34:31.390+05:30 INFO 16192 --- [Z18_Springboot_Logins] [main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1281 ms +2025-03-07T11:34:31.620+05:30 DEBUG 16192 --- [Z18_Springboot_Logins] [main] s.w.s.m.m.a.RequestMappingHandlerMapping : 3 mappings in 'requestMappingHandlerMapping' +2025-03-07T11:34:31.693+05:30 DEBUG 16192 --- [Z18_Springboot_Logins] [main] o.s.w.s.handler.SimpleUrlHandlerMapping : Patterns [/webjars/**, /**] in 'resourceHandlerMapping' +2025-03-07T11:34:31.718+05:30 DEBUG 16192 --- [Z18_Springboot_Logins] [main] s.w.s.m.m.a.RequestMappingHandlerAdapter : ControllerAdvice beans: 0 @ModelAttribute, 0 @InitBinder, 1 RequestBodyAdvice, 1 ResponseBodyAdvice +2025-03-07T11:34:31.756+05:30 DEBUG 16192 --- [Z18_Springboot_Logins] [main] .m.m.a.ExceptionHandlerExceptionResolver : ControllerAdvice beans: 0 @ExceptionHandler, 1 ResponseBodyAdvice +2025-03-07T11:34:31.857+05:30 INFO 16192 --- [Z18_Springboot_Logins] [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/' +2025-03-07T11:34:31.863+05:30 INFO 16192 --- [Z18_Springboot_Logins] [main] l.i.z.Z18SpringbootLoginsApplication : Started Z18SpringbootLoginsApplication in 2.465 seconds (process running for 3.365) +2025-03-07T11:35:51.624+05:30 INFO 16192 --- [Z18_Springboot_Logins] [SpringApplicationShutdownHook] o.s.b.w.e.tomcat.GracefulShutdown : Commencing graceful shutdown. Waiting for active requests to complete +2025-03-07T11:35:51.635+05:30 INFO 16192 --- [Z18_Springboot_Logins] [tomcat-shutdown] o.s.b.w.e.tomcat.GracefulShutdown : Graceful shutdown complete +2025-03-07T11:35:57.909+05:30 INFO 13432 --- [Z18_Springboot_Logins] [main] l.i.z.Z18SpringbootLoginsApplication : Starting Z18SpringbootLoginsApplication using Java 21.0.2 with PID 13432 (C:\Users\dilsh\Desktop\Spring-Framework\Z18_Springboot_Logins\target\classes started by Chamath in C:\Users\dilsh\Desktop\Spring-Framework) +2025-03-07T11:35:57.912+05:30 INFO 13432 --- [Z18_Springboot_Logins] [main] l.i.z.Z18SpringbootLoginsApplication : No active profile set, falling back to 1 default profile: "default" +2025-03-07T11:35:59.159+05:30 INFO 13432 --- [Z18_Springboot_Logins] [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http) +2025-03-07T11:35:59.179+05:30 INFO 13432 --- [Z18_Springboot_Logins] [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2025-03-07T11:35:59.180+05:30 INFO 13432 --- [Z18_Springboot_Logins] [main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.36] +2025-03-07T11:35:59.246+05:30 INFO 13432 --- [Z18_Springboot_Logins] [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2025-03-07T11:35:59.246+05:30 INFO 13432 --- [Z18_Springboot_Logins] [main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1270 ms +2025-03-07T11:35:59.514+05:30 DEBUG 13432 --- [Z18_Springboot_Logins] [main] s.w.s.m.m.a.RequestMappingHandlerMapping : 3 mappings in 'requestMappingHandlerMapping' +2025-03-07T11:35:59.584+05:30 DEBUG 13432 --- [Z18_Springboot_Logins] [main] o.s.w.s.handler.SimpleUrlHandlerMapping : Patterns [/webjars/**, /**] in 'resourceHandlerMapping' +2025-03-07T11:35:59.609+05:30 DEBUG 13432 --- [Z18_Springboot_Logins] [main] s.w.s.m.m.a.RequestMappingHandlerAdapter : ControllerAdvice beans: 0 @ModelAttribute, 0 @InitBinder, 1 RequestBodyAdvice, 1 ResponseBodyAdvice +2025-03-07T11:35:59.656+05:30 DEBUG 13432 --- [Z18_Springboot_Logins] [main] .m.m.a.ExceptionHandlerExceptionResolver : ControllerAdvice beans: 0 @ExceptionHandler, 1 ResponseBodyAdvice +2025-03-07T11:35:59.761+05:30 INFO 13432 --- [Z18_Springboot_Logins] [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/' +2025-03-07T11:35:59.768+05:30 INFO 13432 --- [Z18_Springboot_Logins] [main] l.i.z.Z18SpringbootLoginsApplication : Started Z18SpringbootLoginsApplication in 2.537 seconds (process running for 3.368) +2025-03-07T11:50:02.145+05:30 INFO 13432 --- [Z18_Springboot_Logins] [SpringApplicationShutdownHook] o.s.b.w.e.tomcat.GracefulShutdown : Commencing graceful shutdown. Waiting for active requests to complete +2025-03-07T11:50:02.152+05:30 INFO 13432 --- [Z18_Springboot_Logins] [tomcat-shutdown] o.s.b.w.e.tomcat.GracefulShutdown : Graceful shutdown complete diff --git a/Z18_Springboot_Logins/.gitattributes b/Z18_Springboot_Logins/.gitattributes new file mode 100644 index 0000000..3b41682 --- /dev/null +++ b/Z18_Springboot_Logins/.gitattributes @@ -0,0 +1,2 @@ +/mvnw text eol=lf +*.cmd text eol=crlf diff --git a/Z18_Springboot_Logins/.gitignore b/Z18_Springboot_Logins/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/Z18_Springboot_Logins/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/Z18_Springboot_Logins/.mvn/wrapper/maven-wrapper.properties b/Z18_Springboot_Logins/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..d58dfb7 --- /dev/null +++ b/Z18_Springboot_Logins/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +wrapperVersion=3.3.2 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip diff --git a/Z18_Springboot_Logins/mvnw b/Z18_Springboot_Logins/mvnw new file mode 100644 index 0000000..19529dd --- /dev/null +++ b/Z18_Springboot_Logins/mvnw @@ -0,0 +1,259 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.2 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/Z18_Springboot_Logins/mvnw.cmd b/Z18_Springboot_Logins/mvnw.cmd new file mode 100644 index 0000000..249bdf3 --- /dev/null +++ b/Z18_Springboot_Logins/mvnw.cmd @@ -0,0 +1,149 @@ +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.2 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' +$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" +if ($env:MAVEN_USER_HOME) { + $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" +} +$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/Z18_Springboot_Logins/pom.xml b/Z18_Springboot_Logins/pom.xml new file mode 100644 index 0000000..e262bee --- /dev/null +++ b/Z18_Springboot_Logins/pom.xml @@ -0,0 +1,68 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.4.3 + + + lk.ijse + Z18_Springboot_Logins + 0.0.1-SNAPSHOT + Z18_Springboot_Logins + Z18_Springboot_Logins + + + + + + + + + + + + + + + 21 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.boot + spring-boot-starter-logging + 3.4.3 + + + + ch.qos.logback + logback-classic + runtime + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/Z18_Springboot_Logins/src/main/java/lk/ijse/z18_springboot_logins/Controller/DemoController.java b/Z18_Springboot_Logins/src/main/java/lk/ijse/z18_springboot_logins/Controller/DemoController.java new file mode 100644 index 0000000..ab6a3da --- /dev/null +++ b/Z18_Springboot_Logins/src/main/java/lk/ijse/z18_springboot_logins/Controller/DemoController.java @@ -0,0 +1,23 @@ +package lk.ijse.z18_springboot_logins.Controller; + +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/v1/demo") +public class DemoController { + + private static final org.slf4j.Logger log = LoggerFactory.getLogger(DemoController.class); + + @GetMapping + private void loadDemo(){ + log.trace("This is Trace Log"); + log.debug("This is Debug Log"); + log.info("This is Info Log"); + log.warn("This is Warn Log"); + log.error("This is Error Log"); + } + +} diff --git a/Z18_Springboot_Logins/src/main/java/lk/ijse/z18_springboot_logins/Z18SpringbootLoginsApplication.java b/Z18_Springboot_Logins/src/main/java/lk/ijse/z18_springboot_logins/Z18SpringbootLoginsApplication.java new file mode 100644 index 0000000..009cbc9 --- /dev/null +++ b/Z18_Springboot_Logins/src/main/java/lk/ijse/z18_springboot_logins/Z18SpringbootLoginsApplication.java @@ -0,0 +1,13 @@ +package lk.ijse.z18_springboot_logins; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Z18SpringbootLoginsApplication { + + public static void main(String[] args) { + SpringApplication.run(Z18SpringbootLoginsApplication.class, args); + } + +} diff --git a/Z18_Springboot_Logins/src/main/resources/application.properties b/Z18_Springboot_Logins/src/main/resources/application.properties new file mode 100644 index 0000000..8bceedf --- /dev/null +++ b/Z18_Springboot_Logins/src/main/resources/application.properties @@ -0,0 +1,8 @@ +spring.application.name=Z18_Springboot_Logins + +logging.level.root=INFO +logging.level.org.springframework.web=DEBUG +logging.level.org.hibernate=ERROR + +# Log file configuration +logging.file.name=Z18_Springboot_Logins.log diff --git a/Z18_Springboot_Logins/src/test/java/lk/ijse/z18_springboot_logins/Z18SpringbootLoginsApplicationTests.java b/Z18_Springboot_Logins/src/test/java/lk/ijse/z18_springboot_logins/Z18SpringbootLoginsApplicationTests.java new file mode 100644 index 0000000..2bf51ec --- /dev/null +++ b/Z18_Springboot_Logins/src/test/java/lk/ijse/z18_springboot_logins/Z18SpringbootLoginsApplicationTests.java @@ -0,0 +1,13 @@ +package lk.ijse.z18_springboot_logins; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class Z18SpringbootLoginsApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/desktop.ini b/desktop.ini deleted file mode 100644 index 631af8f..0000000 --- a/desktop.ini +++ /dev/null @@ -1,6 +0,0 @@ -[.ShellClassInfo] -IconResource=C:\WINDOWS\System32\SHELL32.dll,146 -[ViewState] -Mode= -Vid= -FolderType=Generic diff --git a/11_Frontend.iml b/out/Z15_Spring_Sequrity/Z15_Spring_Sequrity.iml similarity index 69% rename from 11_Frontend.iml rename to out/Z15_Spring_Sequrity/Z15_Spring_Sequrity.iml index b66f313..e45ed63 100644 --- a/11_Frontend.iml +++ b/out/Z15_Spring_Sequrity/Z15_Spring_Sequrity.iml @@ -1,8 +1,8 @@ - + - + \ No newline at end of file
Are you sure you want to delete this item? This action cannot be undone.
No items found
Are you sure you want to delete this customer? This action cannot be undone.
No customers found
Select a module to get started
Manage customer profiles, view history and track engagement.
Inventory management, stock levels and product catalog.
Process orders, track shipments and manage fulfillment.
Business insights, reports and performance metrics.
Configure system preferences, users and permissions.
Process Customer Count,And Give Numerical Value
Process Item Count,And Give Numerical Value
Process Order Count,And Give Numerical Value
Your cart is empty
Add items, select a customer, and submit your order
Simplify The Process
Of Purchasing Or Renewing Subscription
Automatic Renewal
Smart System
Complete Flexibility In Defining The Length Of The Entire Contract Period And Payment
Terms.
The Possibility Of Unilateral Or Bilateral Cancellation Of The Contract
Various Highly Services And Reporting Panels For Businesses
Free Demo And Free Use For 2 Months Without Any Conditions
Possibility Of Setting A Trial Period For The Contract
The Possibility Of Having Similar Contracts To Deploy Very Rapid To The Project
Enter your credentials to access your account
+ Don't have an account? + Register +
Enter your details to register
+ Already have an account? + Sign In +