diff --git a/backend/src/main/java/hu/pazmany/Controller.java b/backend/src/main/java/hu/pazmany/Controller.java new file mode 100644 index 0000000000000000000000000000000000000000..a1e1c831738e059eb0a5b2bd692aded92d29b3ff --- /dev/null +++ b/backend/src/main/java/hu/pazmany/Controller.java @@ -0,0 +1,57 @@ +package hu.pazmany; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@CrossOrigin(origins = "http://localhost:3000") +@RestController +public class Controller { + private final NoteStoreService noteStoreService; + private final ResourceLoader resourceLoader; + + @Autowired + public Controller(hu.pazmany.NoteStoreService noteStoreService, ResourceLoader resourceLoader) { + this.noteStoreService = noteStoreService; + this.resourceLoader = resourceLoader; + } + + @PostMapping("/api/login") + public UserLoginDto login(@RequestBody UserLoginDto userLoginDto) { + return noteStoreService.authenticate(userLoginDto.getUsername(), userLoginDto.getPassword()); + } + + @PostMapping("/api/register") + public String register(@RequestBody UserLoginDto userLoginDto) { + return noteStoreService.register(userLoginDto.getFullName(), userLoginDto.getUsername(), userLoginDto.getPassword()); + } + + @PostMapping("/api/details") + public DocumentDto getDetails(@RequestBody DocumentDto documentDto) { + return noteStoreService.getDetails(documentDto.getID(), documentDto.getSubject()); + } + + @PostMapping("/api/setdetails") + public void setDetails(@RequestBody DocumentDto documentDto) { + noteStoreService.setDetails(documentDto); + } + + @PostMapping("/api/addsubject") + public void addSubject(@RequestBody SubjectDto subjectDto) { + noteStoreService.addSubject(subjectDto); + } + + @GetMapping("/download/{filename:.+}") + public ResponseEntity<Resource> downloadFile(@PathVariable String filename) { + Resource resource = resourceLoader.getResource("classpath:/" + filename); + if (!resource.exists()) { + return ResponseEntity.notFound().build(); + } + + return ResponseEntity.ok() + .header("Content-Disposition", "attachment; filename=\"" + resource.getFilename() + "\"") + .body(resource); + } +} \ No newline at end of file diff --git a/backend/src/main/java/hu/pazmany/Document.java b/backend/src/main/java/hu/pazmany/Document.java index 3cd372db0b903a5abcc48d2768a2ccd042cc59a2..6a6e5ed54d875fc2f736d2a0747409dcf374fecb 100644 --- a/backend/src/main/java/hu/pazmany/Document.java +++ b/backend/src/main/java/hu/pazmany/Document.java @@ -38,8 +38,6 @@ public class Document { @Column(name = "filepath", nullable = false) private String filepath; - // Getters and setters - public Long getId() { return id; } @@ -48,7 +46,7 @@ public class Document { this.id = id; } - public hu.pazmany.User getUser() { + public User getUser() { return user; } diff --git a/backend/src/main/java/hu/pazmany/DocumentDto.java b/backend/src/main/java/hu/pazmany/DocumentDto.java new file mode 100644 index 0000000000000000000000000000000000000000..33ca14f40aaf810d1abda8ca78af3f2d79bbbbe3 --- /dev/null +++ b/backend/src/main/java/hu/pazmany/DocumentDto.java @@ -0,0 +1,54 @@ +package hu.pazmany; + +public class DocumentDto { + private Long id; + private String user; + private String subject; + private String title; + private String description; + private String uploaded; + private String filepath; + + public Long getID() { + return id; + } + public void setID(Long id) { + this.id = id; + } + public String getUser() { + return user; + } + public void setUser(String user) { + this.user = user; + } + public String getSubject() { + return subject; + } + public void setSubject(String subject) { + this.subject = subject; + } + public String getTitle() { + return title; + } + public void setTitle(String title) { + this.title = title; + } + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + public String getUploaded() { + return uploaded; + } + public void setUploaded(String uploaded) { + this.uploaded = uploaded; + } + public String getFilepath() { + return filepath; + } + public void setFilepath(String filepath) { + this.filepath = filepath; + } +} diff --git a/backend/src/main/java/hu/pazmany/ExampleController.java b/backend/src/main/java/hu/pazmany/ExampleController.java deleted file mode 100644 index f84dcbd61f71683c47d76021a4836a839f6018d7..0000000000000000000000000000000000000000 --- a/backend/src/main/java/hu/pazmany/ExampleController.java +++ /dev/null @@ -1,26 +0,0 @@ -package hu.pazmany; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; - -@CrossOrigin(origins = "http://localhost:3000") -@RestController -public class ExampleController { - private final UserService userService; - - @Autowired - public ExampleController(UserService userService) { - this.userService = userService; - } - - @PostMapping("/api/login") - public String login(@RequestBody UserLoginDto userLoginDto) { - System.out.println(userLoginDto); - return userService.authenticate(userLoginDto.getUsername(), userLoginDto.getPassword()); - } - - @PostMapping("/api/register") - public void register(@RequestBody UserLoginDto userLoginDto) { - userService.register(userLoginDto.getFullName(), userLoginDto.getUsername(), userLoginDto.getPassword()); - } -} \ No newline at end of file diff --git a/backend/src/main/java/hu/pazmany/NoteStoreService.java b/backend/src/main/java/hu/pazmany/NoteStoreService.java new file mode 100644 index 0000000000000000000000000000000000000000..8c905f1070413d6925d9e8136fb89f64c0c37d6d --- /dev/null +++ b/backend/src/main/java/hu/pazmany/NoteStoreService.java @@ -0,0 +1,79 @@ +package hu.pazmany; + +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; + +@Service +public class NoteStoreService { + private final DocumentRepository documentRepository; + private final UserRepository userRepository; + private final SubjectRepository subjectRepository; + + public NoteStoreService(DocumentRepository documentRepository, UserRepository userRepository, SubjectRepository subjectRepository) { + this.documentRepository = documentRepository; + this.userRepository = userRepository; + this.subjectRepository = subjectRepository; + } + + public UserLoginDto authenticate(String username, String password) { + User user = userRepository.findByUsername(username); + UserLoginDto userLoginDto = new UserLoginDto(); + userLoginDto.setFullName("Fullnamen't"); + userLoginDto.setLoggedIn(false); + if (user != null && user.getPassword().equals(password)) { + userLoginDto.setFullName(user.getFullName()); + userLoginDto.setLoggedIn(!user.isLoggedIn()); + user.setLoggedIn(!user.isLoggedIn()); + userRepository.save(user); + } + return userLoginDto; + } + + public String register(String fullName, String username, String password) { + if (userRepository.findByUsername(username) == null) { + User user = new User(); + user.setFullName(fullName); + user.setUsername(username); + user.setPassword(password); + user.setLoggedIn(false); + userRepository.save(user); + return "Successful registration!"; + } + return "User already exists!"; + } + + public DocumentDto getDetails(long id, String subjectName) { + Document result = documentRepository.findAllBySubject(subjectRepository.findBySubjectId(subjectName)).get((int) id); + + DocumentDto doc = new DocumentDto(); + doc.setID(result.getId()); + doc.setUser(result.getUser().getFullName()); + doc.setSubject(result.getSubject().getName()); + doc.setTitle(result.getTitle()); + doc.setUploaded(result.getUploaded().toString()); + doc.setDescription(result.getDescription()); + doc.setFilepath(result.getFilepath()); + + return doc; + } + + public void setDetails(DocumentDto documentDto) { + Document document = new Document(); + document.setId(documentDto.getID()); + document.setUser(userRepository.findByUsername(documentDto.getUser())); + document.setSubject(subjectRepository.findBySubjectId(documentDto.getSubject())); + document.setTitle(documentDto.getTitle()); + document.setDescription(documentDto.getDescription()); + document.setUploaded(LocalDateTime.now()); + document.setFilepath(documentDto.getFilepath()); + documentRepository.save(document); + } + + public void addSubject(SubjectDto subjectDto) { + Subject subject = new Subject(); + subject.setSubjectId(subjectDto.getSubjectId()); + subject.setName(subjectDto.getName()); + subjectRepository.save(subject); + } +} diff --git a/backend/src/main/java/hu/pazmany/Subject.java b/backend/src/main/java/hu/pazmany/Subject.java index c83cb0bce52a9d7281395a9749f7fe570f00bbc2..cfa4c1c2cabd53997f84505e9de1cd9428c6eea6 100644 --- a/backend/src/main/java/hu/pazmany/Subject.java +++ b/backend/src/main/java/hu/pazmany/Subject.java @@ -15,8 +15,6 @@ public class Subject { @Column(name = "name", nullable = false) private String name; - // Getters and setters - public String getSubjectId() { return subjectId; } diff --git a/backend/src/main/java/hu/pazmany/SubjectDto.java b/backend/src/main/java/hu/pazmany/SubjectDto.java new file mode 100644 index 0000000000000000000000000000000000000000..9ed9464c8f59226cc470969381e53a64bb4a36f9 --- /dev/null +++ b/backend/src/main/java/hu/pazmany/SubjectDto.java @@ -0,0 +1,19 @@ +package hu.pazmany; + +public class SubjectDto { + private String subjectId; + private String name; + + public String getSubjectId() { + return subjectId; + } + public void setSubjectId(String subjectId) { + this.subjectId = subjectId; + } + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } +} diff --git a/backend/src/main/java/hu/pazmany/User.java b/backend/src/main/java/hu/pazmany/User.java index 992c8fa542c49877619f8d428c798a1d2571232a..8b2977fd9f2dda65667d36bca54b05b14d2f6d5d 100644 --- a/backend/src/main/java/hu/pazmany/User.java +++ b/backend/src/main/java/hu/pazmany/User.java @@ -18,7 +18,8 @@ public class User { @Column(name = "fullName") private String fullName; - // Getters and setters + @Column(name = "loggedIn") + private boolean loggedIn; public String getUsername() { return username; @@ -43,4 +44,8 @@ public class User { public void setFullName(String fullName) { this.fullName = fullName; } + + public boolean isLoggedIn() {return loggedIn;} + + public void setLoggedIn(boolean loggedIn) {this.loggedIn = loggedIn;} } diff --git a/backend/src/main/java/hu/pazmany/UserLoginDto.java b/backend/src/main/java/hu/pazmany/UserLoginDto.java index 945d5d564e455020c1f9a7994ae3d914ff6ca0bc..c6e5a273b4414a90960c76fd9b0102ca042fa49d 100644 --- a/backend/src/main/java/hu/pazmany/UserLoginDto.java +++ b/backend/src/main/java/hu/pazmany/UserLoginDto.java @@ -4,6 +4,7 @@ public class UserLoginDto { private String fullName; private String username; private String password; + private boolean loggedIn; public String getFullName() { return fullName; @@ -28,4 +29,8 @@ public class UserLoginDto { public void setPassword(String password) { this.password = password; } + + public boolean isLoggedIn() {return loggedIn;} + + public void setLoggedIn(boolean loggedIn) {this.loggedIn = loggedIn;} } diff --git a/backend/src/main/java/hu/pazmany/UserService.java b/backend/src/main/java/hu/pazmany/UserService.java deleted file mode 100644 index 71adee586ec5f945d0dc8b6e5b796e199456bda5..0000000000000000000000000000000000000000 --- a/backend/src/main/java/hu/pazmany/UserService.java +++ /dev/null @@ -1,31 +0,0 @@ -package hu.pazmany; - -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.stereotype.Service; - -@Service -public class UserService { - private final UserRepository userRepository; - private final BCryptPasswordEncoder passwordEncoder; - - public UserService(UserRepository userRepository, BCryptPasswordEncoder passwordEncoder) { - this.userRepository = userRepository; - this.passwordEncoder = passwordEncoder; - } - - public String authenticate(String username, String password) { - User user = userRepository.findByUsername(username); - if (user != null && passwordEncoder.matches(password, user.getPassword())) { - return user.getFullName(); - } - return "Helytelen felhasználónév vagy jelszó!"; - } - - public void register(String fullName, String username, String password) { - User user = new User(); - user.setFullName(fullName); - user.setUsername(username); - user.setPassword(passwordEncoder.encode(password)); - userRepository.save(user); - } -} diff --git a/backend/src/main/resources/1.eloadas_szoftvertechnologia_2024_v1.0.pdf b/backend/src/main/resources/1.eloadas_szoftvertechnologia_2024_v1.0.pdf new file mode 100644 index 0000000000000000000000000000000000000000..87778fa7278dd23a631b471de0a7265451b49c49 Binary files /dev/null and b/backend/src/main/resources/1.eloadas_szoftvertechnologia_2024_v1.0.pdf differ diff --git a/backend/src/main/resources/3.eloadas_szoftvertechnologia_2024_v1.0.pdf b/backend/src/main/resources/3.eloadas_szoftvertechnologia_2024_v1.0.pdf new file mode 100644 index 0000000000000000000000000000000000000000..db91337e6f21b510b058d1a659294b35092ab17b Binary files /dev/null and b/backend/src/main/resources/3.eloadas_szoftvertechnologia_2024_v1.0.pdf differ diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index a00ab33962dcfdc65359907962b298a5bf22beec..706e4350d65f96cb186c95b581cfc4d418f55f1a 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -13,6 +13,7 @@ spring.h2.console.enabled=true spring.h2.console.path=/h2-console spring.h2.console.settings.trace=false spring.h2.console.settings.web-allow-others=true +spring.jpa.hibernate.ddl-auto=update springdoc.swagger-ui.path=/swagger-ui diff --git a/backend/src/main/resources/data.direktnemsqlakiterjesztes b/backend/src/main/resources/data.direktnemsqlakiterjesztes new file mode 100644 index 0000000000000000000000000000000000000000..f735b1834eba7ba0b9eef4d9a61a8e6d14a3c7fe --- /dev/null +++ b/backend/src/main/resources/data.direktnemsqlakiterjesztes @@ -0,0 +1,38 @@ +-- DROP TABLE documents; +-- DROP TABLE subjects; +-- DROP TABLE users; + +-- CREATE TABLE users ( +-- username VARCHAR(255) PRIMARY KEY, +-- fullName VARCHAR(255), +-- password VARCHAR(255) +-- ); +-- +-- CREATE TABLE subjects ( +-- subjectId VARCHAR(255) PRIMARY KEY, +-- name VARCHAR(255) +-- ); +-- +-- CREATE TABLE documents ( +-- id BIGINT AUTO_INCREMENT PRIMARY KEY, +-- userId VARCHAR(255) NOT NULL, +-- subjectId VARCHAR(255) NOT NULL, +-- title VARCHAR(255) NOT NULL, +-- description VARCHAR(255), +-- uploaded TIMESTAMP, +-- filepath VARCHAR(255) NOT NULL, +-- FOREIGN KEY (userId) REFERENCES users(username), +-- FOREIGN KEY (subjectId) REFERENCES subjects(subjectId) +-- ); + +-- INSERT INTO USERS(username, password, fullName) VALUES ('testUser', 'testPassword', 'Test User'); +-- INSERT INTO SUBJECTS(subjectId, name) VALUES ('testId', 'Test Subject'); +-- INSERT INTO DOCUMENTS(id, userId, subjectId, title, description, uploaded, filepath) VALUES (1, 'testUser', 'testId', 'Test Title', 'Test Description', CURRENT_TIMESTAMP, '/path/to/file'); + +-- INSERT INTO users (username, fullName, password) VALUES ('kazsa', 'Kada Zsolt', 'aaaa'); +-- +-- +-- INSERT INTO subjects (subjectId) VALUES ('Szofttech'); +-- +-- -- Assuming 'uploaded' timestamp is correctly formatted for your DBMS, e.g., '2024-01-01 10:00:00' +-- INSERT INTO documents (userId, subjectId, title, description, uploaded, filepath) VALUES ('kazsa', 'Szofttech', '1. előadás', 'Description of the document', '2024-01-01 10:00:00', 'documents/1.eloadas_szoftvertechnologia_2024_v1.0.pdf'); \ No newline at end of file diff --git a/frontend/jsconfig.json b/frontend/jsconfig.json index 5a1f2d222a302a174e710614c6d76531b7bda926..d62d5478a3ee20b1986da89638b5b2ef1f76f3d8 100644 --- a/frontend/jsconfig.json +++ b/frontend/jsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "paths": { - "@/*": ["./src/*"] + "@/*": ["./src/*", "../documents/*"] } }, "exclude": ["node_modules", "dist"] diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 3a2e2667485ec68bf424a7aa48ca409765ed3fc1..e686221474b0b5dcc515e6f74c572f0e90d73f34 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.0", "dependencies": { "axios": "^1.6.8", + "express": "^4.19.2", "vue": "^3.4.21" }, "devDependencies": { @@ -717,6 +718,23 @@ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.26.tgz", "integrity": "sha512-Fg4zwR0GNnjzodMt3KRy2AWGMKQXByl56+4HjN87soxLNU9P5xcJkstAlIeEF3cU6UYOzmJl1tV0dVPGIljCnQ==" }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -732,6 +750,55 @@ "proxy-from-env": "^1.1.0" } }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -743,11 +810,67 @@ "node": ">= 0.8" } }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -756,6 +879,36 @@ "node": ">=0.4.0" } }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -767,6 +920,25 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/esbuild": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", @@ -805,11 +977,82 @@ "@esbuild/win32-x64": "0.20.2" } }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/follow-redirects": { "version": "1.15.6", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", @@ -842,6 +1085,22 @@ "node": ">= 6" } }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -856,6 +1115,126 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/magic-string": { "version": "0.30.10", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", @@ -864,6 +1243,38 @@ "@jridgewell/sourcemap-codec": "^1.4.15" } }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -883,6 +1294,11 @@ "node": ">= 0.6" } }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -900,6 +1316,46 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -932,11 +1388,59 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/rollup": { "version": "4.17.2", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.17.2.tgz", @@ -972,6 +1476,110 @@ "fsevents": "~2.3.2" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/source-map-js": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", @@ -980,6 +1588,58 @@ "node": ">=0.10.0" } }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/vite": { "version": "5.2.11", "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.11.tgz", diff --git a/frontend/package.json b/frontend/package.json index 72d399235072bb04bcd507f8edb3f3ba7323eef6..6a6032137406f073fdc875428558f08a82e9e8a7 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -10,6 +10,7 @@ }, "dependencies": { "axios": "^1.6.8", + "express": "^4.19.2", "vue": "^3.4.21" }, "devDependencies": { diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 033ae93d2e61006269d1068f192350eb628873e2..197c53382c4ee5be846ced59e6e02399dff646e6 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -1,67 +1,117 @@ <script setup> -import HelloWorld from './components/HelloWorld.vue' -import TheWelcome from './components/TheWelcome.vue' -import PeldaKomponens from "@/components/pelda-komponens.vue"; -import RegisterKomponens from "@/components/register-komponens.vue"; +import HeaderKomponens from '@/components/header-komponens.vue'; import IntroKomponens from "@/components/intro-komponens.vue"; +import BrowseKomponens from "@/components/browse-komponens.vue"; +import axios from "axios"; +import { ref } from 'vue'; + +// handle page switch and other top-level state based logic +const isLoggedIn = ref(false); +const fullName = ref(''); +const username = ref(''); +const password = ref(''); + +function toggleLoggedIn(name, user, pass) { + isLoggedIn.value = !isLoggedIn.value; + if (name) { + fullName.value = name.value; + } else { + fullName.value = ''; + } + + username.value = user; + password.value = pass; +} + +const isLoginFormVisible = ref(false); + +function toggleLoginForm() { + if(isLoggedIn.value) { + toggleLoggedIn(); + isLoginFormVisible.value = false; + } else { + isLoginFormVisible.value = true; + } +} + +// register user +function registerUser(credentials, callback) { + return axios.post('http://localhost:8080/api/register', credentials) + .then(response => { + callback(response.data) + }) + .catch(error => { + console.error(error); + }); +} + +// prepopulating the database + registerUser({fullName: 'Gipsz Jakab', username: 'gipja', password: 'süti'}, function (res) { + //console.log(res) + }).then(() => { + registerUser({fullName: 'Kada Zsolt', username: 'kazso', password: 'keksz'}, function (res) { + //console.log(res) + }) + }).then(() => { + return axios.post('http://localhost:8080/api/addsubject', {subjectId: "szofttech", name: "Szoftver Technológia"}) + }).then(() => { + return axios.post('http://localhost:8080/api/setdetails', { + id: 1, + user: "kazso", + subject: "szofttech", + title: "Szoftvertechnológia: 1. előadás", + description: "A Szoftvertechnológia alapjai című tárgy első előadás diái. Tartalmazza a szoftverkövetelményeket, milyen alap elemei vannak, mit kell tartalmaznia.", + filepath: "1.eloadas_szoftvertechnologia_2024_v1.0.pdf" + }) + } + ).then(() => { + return axios.post('http://localhost:8080/api/setdetails', { + id: 2, + user: "kazso", + subject: "szofttech", + title: "Szoftvertechnológia: 3. előadás", + description: "A Szoftvertechnológia alapjai című tárgy harmadik előadás diái. Tartalmazza a szoftverfolyamatot, milyen modellek léteznek és a szoftverfolyamat szakaszait.", + filepath: "3.eloadas_szoftvertechnologia_2024_v1.0.pdf" + }) + } + ) </script> <template> <header> - <HelloWorld msg="TechnoCool NoteStore" /> + <header-komponens :isLoggedIn="isLoggedIn" :fullName="fullName" :user="username" :pass="password" @toggle-login-form="toggleLoginForm" /> </header> - -<!-- <PeldaKomponens />--> - - - <main> -<!-- <TheWelcome />--> - <h1>A TechnoCool NoteStore jegyzetek, segédanyagok hallgatók közötti egyszerű megosztására alkalmas szolgáltatás.</h1> - </main> -<!-- <main>--> -<!-- <h2>Az oldal eléréséhez jelentkezz be.</h2>--> -<!-- <h3>Nincsen felhasználód? <register-komponens/></h3>--> -<!-- </main>--> - <main> - <intro-komponens/> - </main> + <div v-if="!isLoggedIn"> + <main> + <h1>A TechnoCool NoteStore jegyzetek, segédanyagok hallgatók közötti egyszerű megosztására alkalmas szolgáltatás.</h1> + <div> + <intro-komponens :isLoginFormVisible="isLoginFormVisible" @toggle-logged-in="toggleLoggedIn" /> + </div> + </main> + </div> + <div v-else> + <browse-komponens/> + </div> </template> <style scoped> - -.logo { - display: block; - margin: 0 auto 2rem; -} - @media (min-width: 1024px) { main { - display: block; + display: grid; + grid-template-columns: 1fr 1fr; width: 100%; height: 100%; - color: lightseagreen; + color: var(--light); + padding: 20px; } header { display: block; - position: fixed; - top: 0; - left: 0; - width: 100%; line-height: 1.5; - background-color: #224c49; - } - - .logo { - margin: 0 2rem 0 0; - } - - .wrapper { - display: block; - width: 100%; - height: 20%; + background-color: var(--dark); + margin: 10px 0 20px 0; } main h1 { diff --git a/frontend/src/assets/main.css b/frontend/src/assets/main.css index 36fb845b5232b8594b0d0f0e61a8cff0b73a4128..823d49a8b3170ff9dcbe5b9f5e9b2d6119583b41 100644 --- a/frontend/src/assets/main.css +++ b/frontend/src/assets/main.css @@ -1,10 +1,21 @@ @import './base.css'; +:root { + --lightest: aqua; + --lighter: #768d90; + --lighttext: #b3ced1; + --light: lightseagreen; + --dark: #134946; + --darker: #1f2c2c; + --darkest: #181818; +} + #app { - max-width: 1280px; + /*max-width: 1280px;*/ margin: 0 auto; padding: 2rem; font-weight: normal; + width: 100%; } a, @@ -24,12 +35,51 @@ a, @media (min-width: 1024px) { body { display: flex; - place-items: center; + place-items: flex-start; } #app { - display: grid; - grid-template-columns: 1fr 1fr; + display: block; + /*grid-template-columns: 1fr 1fr;*/ padding: 0 2rem; } } + +.grow { + height: 40px; + width: 130px; + color: var(--light); + border-style: solid; + background-color: var(--darkest); + font-weight: bold; + border-color: var(--dark); +} + +.grow:hover{ + background-color: var(--dark); + color: var(--lightest); + border-color: var(--light); + cursor: pointer; +} + +.grow:active { + border-color: var(--light); + background-color: var(--darkest); + color: var(--light); +} + +.grow:active { + animation-name: growScale; + animation-iteration-count: 1; + animation-timing-function: linear; + animation-duration: 0.1s; +} + +@keyframes growScale { + 0% { + scale: 1; + } + 100%{ + scale: 1.05; + } +} diff --git a/frontend/src/assets/user.svg b/frontend/src/assets/user.svg new file mode 100644 index 0000000000000000000000000000000000000000..6a39d4de2ba53a89ad9890024a98f8c30c07c78a --- /dev/null +++ b/frontend/src/assets/user.svg @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools --> +<svg width="20px" height="20px" viewBox="0" fill="lightseagreen" xmlns="http://www.w3.org/2000/svg"> +<path d="M16 7C16 9.20914 14.2091 11 12 11C9.79086 11 8 9.20914 8 7C8 4.79086 9.79086 3 12 3C14.2091 3 16 4.79086 16 7Z" stroke="lightseagreen" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M12 14C8.13401 14 5 17.134 5 21H19C19 17.134 15.866 14 12 14Z" stroke="lightseagreen" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> +</svg> \ No newline at end of file diff --git a/frontend/src/components/HelloWorld.vue b/frontend/src/components/HelloWorld.vue deleted file mode 100644 index e8431ad62e2b375941d11ef5629f96232d63cd29..0000000000000000000000000000000000000000 --- a/frontend/src/components/HelloWorld.vue +++ /dev/null @@ -1,93 +0,0 @@ -<script setup> -import PeldaKomponens from "@/components/pelda-komponens.vue"; -import LoginKomponens from "@/components/login-komponens.vue"; - -defineProps({ - msg: { - type: String, - required: true - } -}) -</script> - -<template> - <div class="greetings"> -<!-- <h1 class="green">{{ msg }}</h1>--> - <img alt="NoteStore logo" class="logo" src="../assets/book-shelf.svg" width="100" height="100" /> - <h1 class="title">{{msg}}</h1> -<!-- <h3 class="subtitle">--> -<!-- You’ve successfully created a project with--> -<!-- <a href="https://vitejs.dev/" target="_blank" rel="noopener">Vite</a> +--> -<!-- <a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a>.--> -<!-- </h3>--> -<!-- <div class="space"></div>--> - <div class="login"> - <LoginKomponens /> - </div> - </div> -</template> - -<style scoped> - -.login { - position: fixed; - right: 5%; -} - -.title { - color: lightseagreen; -} - -.title:after{ - content: "™"; - vertical-align: super; - font-size: large; -} - -h1 { - font-weight: 500; - font-size: 2.6rem; - position: relative; - top: -10px; -} - -h3 { - font-size: 1.2rem; -} - -.greetings h1, -.greetings h3 { - text-align: center; -} - -.logo { - display: block; - margin: 0 auto 2rem; -} - -@media (min-width: 1024px) { - .greetings h1, - .greetings h3 { - text-align: left; - } - - .greetings { - display: flex; - padding: 1em; - place-items: center flex-start; - flex-wrap: wrap; - } - - .space { - width: 40%; - } - - .logo { - margin: 0 2rem 0 0; - } -} - -.subtitle { - margin-bottom: 16px; -} -</style> diff --git a/frontend/src/components/TheWelcome.vue b/frontend/src/components/TheWelcome.vue deleted file mode 100644 index dab95367d4cb1dfe39b9c898fcd087ee3eda35b6..0000000000000000000000000000000000000000 --- a/frontend/src/components/TheWelcome.vue +++ /dev/null @@ -1,88 +0,0 @@ -<script setup> -import WelcomeItem from './WelcomeItem.vue' -import DocumentationIcon from './icons/IconDocumentation.vue' -import ToolingIcon from './icons/IconTooling.vue' -import EcosystemIcon from './icons/IconEcosystem.vue' -import CommunityIcon from './icons/IconCommunity.vue' -import SupportIcon from './icons/IconSupport.vue' -</script> - -<template> - <WelcomeItem> - <template #icon> - <DocumentationIcon /> - </template> - <template #heading>Documentation</template> - - Vue’s - <a href="https://vuejs.org/" target="_blank" rel="noopener">official documentation</a> - provides you with all information you need to get started. - </WelcomeItem> - - <WelcomeItem> - <template #icon> - <ToolingIcon /> - </template> - <template #heading>Tooling</template> - - This project is served and bundled with - <a href="https://vitejs.dev/guide/features.html" target="_blank" rel="noopener">Vite</a>. The - recommended IDE setup is - <a href="https://code.visualstudio.com/" target="_blank" rel="noopener">VSCode</a> + - <a href="https://github.com/johnsoncodehk/volar" target="_blank" rel="noopener">Volar</a>. If - you need to test your components and web pages, check out - <a href="https://www.cypress.io/" target="_blank" rel="noopener">Cypress</a> and - <a href="https://on.cypress.io/component" target="_blank" rel="noopener" - >Cypress Component Testing</a - >. - - <br /> - - More instructions are available in <code>README.md</code>. - </WelcomeItem> - - <WelcomeItem> - <template #icon> - <EcosystemIcon /> - </template> - <template #heading>Ecosystem</template> - - Get official tools and libraries for your project: - <a href="https://pinia.vuejs.org/" target="_blank" rel="noopener">Pinia</a>, - <a href="https://router.vuejs.org/" target="_blank" rel="noopener">Vue Router</a>, - <a href="https://test-utils.vuejs.org/" target="_blank" rel="noopener">Vue Test Utils</a>, and - <a href="https://github.com/vuejs/devtools" target="_blank" rel="noopener">Vue Dev Tools</a>. If - you need more resources, we suggest paying - <a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">Awesome Vue</a> - a visit. - </WelcomeItem> - - <WelcomeItem> - <template #icon> - <CommunityIcon /> - </template> - <template #heading>Community</template> - - Got stuck? Ask your question on - <a href="https://chat.vuejs.org" target="_blank" rel="noopener">Vue Land</a>, our official - Discord server, or - <a href="https://stackoverflow.com/questions/tagged/vue.js" target="_blank" rel="noopener" - >StackOverflow</a - >. You should also subscribe to - <a href="https://news.vuejs.org" target="_blank" rel="noopener">our mailing list</a> and follow - the official - <a href="https://twitter.com/vuejs" target="_blank" rel="noopener">@vuejs</a> - twitter account for latest news in the Vue world. - </WelcomeItem> - - <WelcomeItem> - <template #icon> - <SupportIcon /> - </template> - <template #heading>Support Vue</template> - - As an independent project, Vue relies on community backing for its sustainability. You can help - us by - <a href="https://vuejs.org/sponsor/" target="_blank" rel="noopener">becoming a sponsor</a>. - </WelcomeItem> -</template> diff --git a/frontend/src/components/browse-komponens.vue b/frontend/src/components/browse-komponens.vue new file mode 100644 index 0000000000000000000000000000000000000000..3c769e3c0f1faafc7a07ab946678fb3c0e18231e --- /dev/null +++ b/frontend/src/components/browse-komponens.vue @@ -0,0 +1,136 @@ +<script setup> + +import {ref} from "vue"; +import axios from "axios"; + +const title = ref("Jegyzet címe") +const userName = ref("Feltöltő neve") +const description = ref("Jegyzet leírása") +let fileName = ref("") + +function getDocumentDetails(id) { + axios.post('http://localhost:8080/api/details', {id: id, subject: "szofttech"}) + .then(response => { + title.value = response.data["title"] + userName.value = response.data["user"] + description.value = response.data["description"] + fileName = response.data["filepath"] + }) + .catch(error => { + console.log(error); + }); +} + +function downloadFile(filename) { + console.log("Filename:", filename); + axios({ + url: `http://localhost:8080/download/${filename}`, + method: 'GET', + responseType: 'blob', + }) + .then((response) => { + const url = window.URL.createObjectURL(new Blob([response.data])); + const link = document.createElement('a'); + link.href = url; + link.setAttribute('download', filename); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + window.URL.revokeObjectURL(url); + }) + .catch(error => console.error('Download error:', error)); +} + +</script> + +<template> + <div class="page-wrapper"> + <main class="browse"> + <ul class="browse-list"> + <li class="module">Modul 1</li> + <li @click=getDocumentDetails(0) class="note">Szofttech ead 1</li> + <li @click=getDocumentDetails(1) class="note">Szofttech ead 3</li> + <li class="module">Modul 2</li> + <li class="note">Másik jegyzet</li> + </ul> + </main> + <main> + <div class="note-page"> + <h2 class="note-header">{{title}}</h2> + <h3 class="note-description"> + {{description}} + </h3> + <div class="footer"> + <h4> + Feltöltötte: <p class="green">{{userName}}</p> + <img alt="user icon" class="user" src="../assets/user.svg" width="18" height="18"/> + </h4> + <span></span> + <button class="grow" @click="downloadFile(fileName)">Letöltés</button> + </div> + </div> + </main> + </div> +</template> + +<style scoped> + +.page-wrapper{ + display: grid; + grid-auto-flow: row; + grid-template-columns: 1fr 2fr; + column-gap: 15px; + padding: 0 10% 0 10%; +} + +.browse-list{ + list-style-type: none; + padding: 0; +} + +li { + padding: 2px; +} + +.note:hover { + cursor: pointer; + color: var(--light); + background-color: #1f2c2c; +} + +.browse { + border: 1px solid var(--lightest); + box-shadow: var(--light) 0 0 5px; + padding: 5px; +} + +.module { + background-color: var(--dark); + color: var(--lighttext); +} + +.note-page { + border: 1px solid var(--lightest); + padding: 25px; + color: var(--lighttext); + box-shadow: var(--light) 0 0 5px; +} + +.note-header { + text-align: center; + margin-bottom: 10px; +} + +.footer { + margin-top: 20px; + display: grid; + grid-template-columns: 2fr 1fr 1fr; + align-items: center; + color: var(--lighter); +} + +.user { + margin-bottom: -2px; +} + +</style> \ No newline at end of file diff --git a/frontend/src/components/header-komponens.vue b/frontend/src/components/header-komponens.vue new file mode 100644 index 0000000000000000000000000000000000000000..72ae4ebe8c3f4ac7b9c41970eb8624d6c8646e33 --- /dev/null +++ b/frontend/src/components/header-komponens.vue @@ -0,0 +1,112 @@ +<script setup> +import axios from "axios"; + +defineProps({ + isLoggedIn: { + type: Boolean, + required: true + }, + fullName: { + type: String, + required: false + }, + user: { + type: String, + required: true + }, + pass: { + type: String, + required: true + } +}) + +function logoutUser(credentials, callback) { + axios.post('http://localhost:8080/api/login', credentials) + .then(response => { + callback(response.data) + }) + .catch(error => { + console.log(error); + }); +} + +function logout(user, pass){ + logoutUser({username: user, password: pass}, function(response) { + //console.log(response) + }) +} +</script> + + +<template> + <div class="greetings"> + <img alt="NoteStore logo" class="logo" src="../assets/book-shelf.svg" width="100" height="100" /> + <h1 class="title">TechnoCool NoteStore</h1> + <div class="login"> + <h3 v-if="(fullName)" class="subtitle">Üdvözöllek, {{ fullName }}!</h3> + <button class="grow" @click="$emit('toggle-login-form'); logout(user, pass)">{{ isLoggedIn ? 'Kijelentkezés' : 'Bejelentkezés' }}</button> + </div> + </div> +</template> + +<style scoped> + +.login { + position: fixed; + right: 5%; +} + +.title { + color: var(--lightest); + text-shadow: 0 0 10px var(--light); +} + +.title:after{ + content: "™"; + vertical-align: super; + font-size: large; +} + +h1 { + font-weight: 500; + font-size: 2.6rem; + position: relative; + top: -10px; +} + +h3 { + font-size: 1.2rem; +} + +.greetings h1, +.greetings h3 { + text-align: center; +} + +.logo { + display: block; + margin: 0 auto 2rem; +} + +@media (min-width: 1024px) { + .greetings h1, + .greetings h3 { + text-align: left; + } + + .greetings { + display: grid; + padding: 1em; + grid-template-columns: 1fr 4fr 2fr; + align-items: center; + } + + .logo { + margin: 0 2rem 0 0; + } + + .subtitle { + color: var(--lightest); + } +} +</style> \ No newline at end of file diff --git a/frontend/src/components/intro-komponens.vue b/frontend/src/components/intro-komponens.vue index 2f683d3595d6c20e22b333cb5458fb6ebbf8a8c9..27ca53b6aafdbaf4898c84a953c43d374f26e7d9 100644 --- a/frontend/src/components/intro-komponens.vue +++ b/frontend/src/components/intro-komponens.vue @@ -2,35 +2,59 @@ import WelcomeItem from './WelcomeItem.vue' import DocumentationIcon from './icons/IconDocumentation.vue' import ToolingIcon from './icons/IconTooling.vue' -import EcosystemIcon from './icons/IconEcosystem.vue' -import CommunityIcon from './icons/IconCommunity.vue' import SupportIcon from './icons/IconSupport.vue' import RegisterKomponens from "@/components/register-komponens.vue"; +import LoginForm from "@/components/loginform-komponens.vue"; +import { ref, defineEmits } from "vue"; + +defineProps({ + isLoginFormVisible: { + type: Boolean, + required: true + } +}) + +let isLoggedIn = ref(false); +let fullName = ref(''); + +const emit = defineEmits(['toggle-logged-in']); + +function handleLogin(success, name, user, pass) { + isLoggedIn.value = success; + if (success) { + fullName.value = name; + emit('toggle-logged-in', fullName, user, pass); + } +} </script> <template> - <WelcomeItem> - <template #icon> - <DocumentationIcon /> - </template> - <template #heading>Jegyzetek</template> - Minden hallgató által készített jegyzet és segédanyag egy helyen. - </WelcomeItem> + <div v-if="!isLoginFormVisible"> + <WelcomeItem> + <template #icon> + <DocumentationIcon /> + </template> + <template #heading>Jegyzetek</template> + Minden hallgató által készített jegyzet és segédanyag egy helyen. + </WelcomeItem> - <WelcomeItem> - <template #icon> - <ToolingIcon /> - </template> - <template #heading>Elérhetőség</template> - Az oldal használata belépés köteles. - Lépj be vagy <RegisterKomponens/>! - </WelcomeItem> + <WelcomeItem> + <template #icon> + <ToolingIcon /> + </template> + <template #heading>Elérhetőség</template> + Az oldal használata belépésköteles. + Lépj be vagy <RegisterKomponens/>! + <div v-if="isLoggedIn">Welcome, {{ fullName }}!</div> + </WelcomeItem> - <WelcomeItem> - <template #icon> - <SupportIcon /> - </template> - <template #heading>TechnoCool Csapata</template> - A projekt a TechnoCool jóvoltából készült a Szoftvertechnológia alapjai tárgy keretein belül. - </WelcomeItem> -</template> + <WelcomeItem> + <template #icon> + <SupportIcon /> + </template> + <template #heading>TechnoCool</template> + A projekt a TechnoCool jóvoltából készült a Szoftvertechnológia alapjai tárgy keretein belül. + </WelcomeItem> + </div> + <LoginForm v-else @login="handleLogin" /> +</template> \ No newline at end of file diff --git a/frontend/src/components/login-komponens.vue b/frontend/src/components/login-komponens.vue deleted file mode 100644 index c19efa892cc218982eda7527d6baa3a78587d746..0000000000000000000000000000000000000000 --- a/frontend/src/components/login-komponens.vue +++ /dev/null @@ -1,106 +0,0 @@ -<script setup> -import {ref} from "vue"; -import axios from 'axios'; - -// const isLoading = ref(true); -// const aFact = ref(''); - -// function getAFact() { -// isLoading.value = true; -// axios.get('https://catfact.ninja/fact').then(result => { -// aFact.value = result.data.fact; -// isLoading.value = false; -// }).catch(error => { -// console.error('cannot get data from api', error); -// }); -// } -// -// getAFact(); - -// const backendStatus = ref('unknown'); -// function checkBackend() { -// axios.get('/api/ok').then(result=>{ -// backendStatus.value = result.data; -// }).catch(error => { -// console.error('cannot get backend OK api endpoint', error); -// backendStatus.value = 'error'; -// }) -// } - -function loginUser(credentials, callback) { - axios.post('http://localhost:8080/api/login', credentials) - .then(response => { - callback(response.data) - }) - .catch(error => { - console.log(error); - }); -} - -const loggedIn = ref(false); -const btnText = ref("Bejelentkezés") -const userName = ref("") -function login(){ - loggedIn.value = !loggedIn.value - - if(loggedIn.value){ - //Itt lesz a kitalált user (Gipsz Jakab, keksz) aki megpróbál bejelentkezni - loginUser({username: 'gipja', password: 'keksz'}, function(response) { - userName.value = response - }) - btnText.value = "Kijelentkezés" - } else { - userName.value = "" - btnText.value = "Bejelentkezés" - } -} - -</script> - -<template> - <h1>{{userName}}</h1> - <button class="grow" @click="login">{{btnText}}</button> -</template> - -<style scoped> -button { - height: 40px; - width: 130px; - color: lightseagreen; - background-color: #181818; - font-weight: bold; - border-color: #181818; -} - -button:hover{ - background-color: #224c49; - color: lightseagreen; - border-color: lightseagreen; -} - -button:active { - border-color: lightseagreen; - background-color: #181818; - color: lightseagreen; -} - -.grow:active { - animation-name: growScale; - animation-iteration-count: 1; - animation-timing-function: linear; - animation-duration: 0.1s; -} - -@keyframes growScale { - 0% { - scale: 1; - } - 100%{ - scale: 1.05; - } -} - -.a-fact { - font-weight: bold; -} -</style> \ No newline at end of file diff --git a/frontend/src/components/loginform-komponens.vue b/frontend/src/components/loginform-komponens.vue new file mode 100644 index 0000000000000000000000000000000000000000..0072592df6dd5e718a847583640a62936222702c --- /dev/null +++ b/frontend/src/components/loginform-komponens.vue @@ -0,0 +1,101 @@ +<script setup> +import { ref, defineEmits } from "vue"; +import axios from 'axios'; + +let credentials = ref({ username: '', password: '' }); +let isFailed = ref(false); +let logged_in = ref(false); + +const emit = defineEmits(['login']); + +async function loginUser() { + try { + const response = await axios.post('http://localhost:8080/api/login', credentials.value); + if (!response.data["loggedIn"]) { + emit('login', false, ""); + isFailed.value = true; + logged_in.value = false; + } else { + emit('login', true, response.data["fullName"], credentials.value.username, credentials.value.password); // Emit login event with success value and full name + isFailed.value = false; + logged_in.value = true; + } + } catch (error) { + console.log(error); + emit('login', false, ""); + isFailed.value = true; + logged_in.value = false; + } +} + +function submitForm() { + loginUser(); +} +</script> + +<template> + <div class="window"> + <h2>Jelentkezz be!</h2> + <form @submit.prevent="submitForm"> + <div> + <label for="username">Felhasználónév:</label> + <input type="text" id="username" v-model="credentials.username" required> + </div> + <div> + <label for="password">Jelszó:</label> + <input type="password" id="password" v-model="credentials.password" required> + </div> + <button type="submit">Bejelentkezés</button> + </form> + <h4 v-if="isFailed">Hiba, próbáld újra!</h4> + </div> +</template> + +<style scoped> + +.window { + border: 1px solid var(--lightest); + box-shadow: 0 0 6px var(--light); + padding: 20px 50px 20px 50px; + width: fit-content; +} + +h4 { + margin-top: 20px; + color: red; +} + +button { + margin-top: 20px; + padding: 10px 20px; + background-color: var(--light); + color: white; + border: none; + border-radius: 5px; + font-size: 1rem; + cursor: pointer; +} + +button:hover { + background-color: var(--dark); + color: var(--lightest) +} + +input[type="text"], +input[type="password"] { + padding: 8px; + border: 1px solid var(--lighttext); + border-radius: 5px; + font-size: 1rem; +} + +label { + display: block; + margin: 8px 0 8px 0; + font-size: 1rem; +} + +form { + margin-top: 20px; +} +</style> \ No newline at end of file diff --git a/frontend/src/components/pelda-komponens.vue b/frontend/src/components/pelda-komponens.vue deleted file mode 100644 index 19d3211c8f212e1eb7683bf3fca196d6caa12cdc..0000000000000000000000000000000000000000 --- a/frontend/src/components/pelda-komponens.vue +++ /dev/null @@ -1,48 +0,0 @@ -<script setup> -import {ref} from "vue"; -import axios from 'axios'; - -const isLoading = ref(true); -const aFact = ref(''); - -function getAFact() { - isLoading.value = true; - axios.get('https://catfact.ninja/fact').then(result => { - aFact.value = result.data.fact; - isLoading.value = false; - }).catch(error => { - console.error('cannot get data from api', error); - }); -} - -getAFact(); - -const backendStatus = ref('unknown'); -function checkBackend() { - axios.get('/api/ok').then(result=>{ - backendStatus.value = result.data; - }).catch(error => { - console.error('cannot get backend OK api endpoint', error); - backendStatus.value = 'error'; - }) -} -</script> - -<template> - <div v-if="isLoading" class="loading">Loading...</div> - <template v-else> -<!-- <button @click="getAFact">Next fact</button>--> -<!-- <div class="a-fact">{{ aFact }}</div>--> - </template> - <button @click="checkBackend">Check Backend</button> - <p>Backend status is: {{backendStatus}}</p> -</template> - -<style scoped> -.loading { - color: lightgray; -} -.a-fact { - font-weight: bold; -} -</style> \ No newline at end of file diff --git a/frontend/src/components/register-komponens.vue b/frontend/src/components/register-komponens.vue index 654db97831601deef77e3b97975de6e8454fcd0d..cae450a1d2dcb9ca83890f3c3114c6e8d782e239 100644 --- a/frontend/src/components/register-komponens.vue +++ b/frontend/src/components/register-komponens.vue @@ -2,18 +2,20 @@ import axios from "axios"; -function registerUser(credentials) { +function registerUser(credentials, callback) { axios.post('http://localhost:8080/api/register', credentials) .then(response => { - console.log("Sikeres regisztráció!") + callback(response.data) }) .catch(error => { - console.error('Sikertelen regisztráció!', error); + console.error(error); }); } function register(){ - registerUser({fullName: 'Gipsz Jakab', username: 'gipja', password: 'keksz'}) + registerUser({fullName: 'Joe', username: 'joe', password: 'Mama'}, function (res) { + //console.log(res) + }) } </script> @@ -24,17 +26,17 @@ function register(){ <style> p { display: inline-block; - color: aqua; + color: var(--lightest); } p:hover { - color: lightseagreen; + color: var(--light); cursor: grab; text-decoration: underline; } p:active { - color: aqua; + color: var(--lightest); } </style> \ No newline at end of file diff --git a/frontend/src/main.js b/frontend/src/main.js index 0ac3a5ff0ceea45d1a9066b2df477773977a338b..79186719317838c69f814d3d80b6085439130f7d 100644 --- a/frontend/src/main.js +++ b/frontend/src/main.js @@ -3,4 +3,4 @@ import './assets/main.css' import { createApp } from 'vue' import App from './App.vue' -createApp(App).mount('#app') +createApp(App).mount('#app') \ No newline at end of file