diff --git a/odyseja-ui/src/lib/apiService.ts b/odyseja-ui/src/lib/apiService.ts index 26b0e66..a31958e 100644 --- a/odyseja-ui/src/lib/apiService.ts +++ b/odyseja-ui/src/lib/apiService.ts @@ -78,11 +78,11 @@ export async function del(path: string, succesText: string): Promise { showHappyToast(succesText === undefined ? 'Usunięto pomyślnie' : succesText) } -function showHappyToast(message: string) { +export function showHappyToast(message: string) { showToast(message, 'variant-filled-tertiary') } -function showSadToast(message: string) { +export function showSadToast(message: string) { showToast(message, 'variant-filled-tertiary') } diff --git a/odyseja-ui/src/lib/types.ts b/odyseja-ui/src/lib/types.ts index 99d1aba..2795114 100644 --- a/odyseja-ui/src/lib/types.ts +++ b/odyseja-ui/src/lib/types.ts @@ -1,83 +1,82 @@ - export type Group = { - city: string; - problem: number; - age: number; - stage: number; - part: number; - league: string; + city: string; + problem: number; + age: number; + stage: number; + part: number; + league: string; } export function getGroupTitle(group: Group): string { - let name = `Scena: ${group.stage} • Problem ${group.problem} • Gr. wiekowa ${group.age}`; - if (group.part) { - name = `${name} • Część ${group.part}`; - } + let name = `Scena: ${group.stage} • Problem ${group.problem} • Gr. wiekowa ${group.age}`; + if (group.part) { + name = `${name} • Część ${group.part}`; + } - if (group.league) { - name = `${name} • Liga ${group.league}`; - } - return name; + if (group.league) { + name = `${name} • Liga ${group.league}`; + } + return name; } export function compareGroups(a: Group, b: Group): number { - if (a.problem < b.problem) return -1; - if (a.problem > b.problem) return 1; + if (a.problem < b.problem) return -1; + if (a.problem > b.problem) return 1; - if (a.age < b.age) return -1; - if (a.age > b.age) return 1; + if (a.age < b.age) return -1; + if (a.age > b.age) return 1; - if (a.stage < b.stage) return -1; - if (a.stage > b.stage) return 1; + if (a.stage < b.stage) return -1; + if (a.stage > b.stage) return 1; - if (a.part < b.part) return -1; - if (a.part > b.part) return 1; + if (a.part < b.part) return -1; + if (a.part > b.part) return 1; - if (a.league < b.league) return -1; - if (a.league > b.league) return 1; + if (a.league < b.league) return -1; + if (a.league > b.league) return 1; - return 0; + return 0; } export type Performance = { - id: number; - city: string; - team: string; - problem: number; - age: number; - stage: number; - performance: string; - spontan: string; - part: number; - performanceDay: string; - spontanDay: string; - league: string; + id: number; + city: string; + team: string; + problem: number; + age: number; + stage: number; + performance: string; + spontan: string; + part: number; + performanceDay: string; + spontanDay: string; + league: string; } export function comparePerformances(a: Performance, b: Performance): number { - if (a.id < b.id) return -1; - if (a.id > b.id) return 1; + if (a.id < b.id) return -1; + if (a.id > b.id) return 1; - return 0; + return 0; } export type PerformanceGroup = { - group: Group; - performances: Performance[]; + group: Group; + performances: Performance[]; } export type Timetable = { - timetable: PerformanceGroup[]; + timetable: PerformanceGroup[]; } export type Problems = { - problems: Problem[] + problems: Problem[] } export type Problem = { - id: number, - name: string + id: number, + name: string } export type Cities = { @@ -85,8 +84,8 @@ export type Cities = { } export type City = { - id: number, - name: string + id: number, + name: string } export type Infos = { @@ -95,27 +94,37 @@ export type Infos = { } export type Info = { - id: number, - infoName: string, - infoText: string, - city: number, - category: number, - sortNumber: number, - categoryName: string + id: number, + infoName: string, + infoText: string, + city: number, + category: number, + sortNumber: number, + categoryName: string } export type InfoCategory = { - id: number, - name: string, + id: number, + name: string, } export type Stages = { - stages: Stage[] + stages: Stage[] } export type Stage = { - id: number, - number: number, - city: number, - name: string + id: number, + number: number, + city: number, + name: string +} + +export type Sponsors = { + sponsors: Sponsor[][] } + +export type Sponsor = { + id: number, + rowIndex: number, + columnIndex: number, +} \ No newline at end of file diff --git a/odyseja-ui/src/routes/panel/+layout.svelte b/odyseja-ui/src/routes/panel/+layout.svelte index ad982b5..db3aa58 100644 --- a/odyseja-ui/src/routes/panel/+layout.svelte +++ b/odyseja-ui/src/routes/panel/+layout.svelte @@ -11,7 +11,8 @@ {label: 'Problemy', route: '/panel/problem', icon: 'ic:round-format-list-bulleted'}, {label: 'Informacje', route: '/panel/info', icon: 'ic:outline-info'}, {label: 'Sceny', route: '/panel/stage', icon: 'ic:outline-curtains'}, - {label: 'Miasta', route: '/panel/city', icon: 'ic:outline-curtains'} + {label: 'Miasta', route: '/panel/city', icon: 'ic:outline-curtains'}, + {label: 'Sponsorzy', route: '/panel/sponsor', icon: 'ic:outline-curtains'} ]; export let data: Cities diff --git a/odyseja-ui/src/routes/panel/sponsor/+page.svelte b/odyseja-ui/src/routes/panel/sponsor/+page.svelte new file mode 100644 index 0000000..de8a2d7 --- /dev/null +++ b/odyseja-ui/src/routes/panel/sponsor/+page.svelte @@ -0,0 +1,73 @@ + + +

Sponsorzy

+ +
+ + {#each data.sponsors as row, rowIndex} + + {#each row as sponsor} + + {/each} + + + {/each} +
+ + + + +
+
diff --git a/odyseja-ui/src/routes/panel/sponsor/+page.ts b/odyseja-ui/src/routes/panel/sponsor/+page.ts new file mode 100644 index 0000000..e0f7bfa --- /dev/null +++ b/odyseja-ui/src/routes/panel/sponsor/+page.ts @@ -0,0 +1,8 @@ +import type {PageLoad} from './$types'; +import {fetchSponsors} from "./sponsorService"; + +export const load = (({params}) => { + return fetchSponsors(); +}) satisfies PageLoad; + + diff --git a/odyseja-ui/src/routes/panel/sponsor/sponsorService.ts b/odyseja-ui/src/routes/panel/sponsor/sponsorService.ts new file mode 100644 index 0000000..84ee53e --- /dev/null +++ b/odyseja-ui/src/routes/panel/sponsor/sponsorService.ts @@ -0,0 +1,9 @@ +import {get} from "$lib/apiService"; +import type {Sponsor, Sponsors} from "$lib/types"; + +export async function fetchSponsors(): Promise { + const data = await get('/sponsor'); + const sponsors = data as Sponsor[][]; + sponsors.push([]); + return {sponsors: sponsors} as Sponsors; +} \ No newline at end of file diff --git a/src/main/kotlin/odyseja/odysejapka/domain/Sponsor.kt b/src/main/kotlin/odyseja/odysejapka/domain/Sponsor.kt index b678e03..0b1eb99 100644 --- a/src/main/kotlin/odyseja/odysejapka/domain/Sponsor.kt +++ b/src/main/kotlin/odyseja/odysejapka/domain/Sponsor.kt @@ -2,5 +2,6 @@ package odyseja.odysejapka.domain data class Sponsor( val id: Int, - val name: String + val row: Int, + val column: Int ) \ No newline at end of file diff --git a/src/main/kotlin/odyseja/odysejapka/domain/SponsorEntity.kt b/src/main/kotlin/odyseja/odysejapka/domain/SponsorEntity.kt index 2dd10b8..698ae30 100644 --- a/src/main/kotlin/odyseja/odysejapka/domain/SponsorEntity.kt +++ b/src/main/kotlin/odyseja/odysejapka/domain/SponsorEntity.kt @@ -8,9 +8,17 @@ class SponsorEntity( @GeneratedValue(strategy = GenerationType.AUTO) @Column val id: Int, - @Column - val name: String, @Lob @Column(length = 10000) - val image: ByteArray -) \ No newline at end of file + val image: ByteArray, + @Column + val rowIndex: Int, + @Column + @GeneratedValue(strategy = GenerationType.AUTO) + val columnIndex: Int +) { + + fun toSponsor(): Sponsor { + return Sponsor(id, rowIndex, columnIndex) + } +} \ No newline at end of file diff --git a/src/main/kotlin/odyseja/odysejapka/rest/SponsorController.kt b/src/main/kotlin/odyseja/odysejapka/rest/SponsorController.kt index 8a2076e..0303473 100644 --- a/src/main/kotlin/odyseja/odysejapka/rest/SponsorController.kt +++ b/src/main/kotlin/odyseja/odysejapka/rest/SponsorController.kt @@ -1,6 +1,7 @@ package odyseja.odysejapka.rest import odyseja.odysejapka.domain.Sponsor +import odyseja.odysejapka.domain.SponsorEntity import odyseja.odysejapka.service.SponsorService import org.springframework.http.MediaType import org.springframework.web.bind.annotation.* @@ -12,33 +13,42 @@ import java.io.IOException @RequestMapping("/sponsor") class SponsorController(private val sponsorService: SponsorService) { - @GetMapping( - produces = [MediaType.IMAGE_JPEG_VALUE, MediaType.IMAGE_PNG_VALUE], - value = ["/{imageId}"] - ) - @ResponseBody - @Throws(IOException::class) - fun getImage(@PathVariable imageId: Int): ByteArray? { - return sponsorService.getImage(imageId) - } - - @GetMapping - @ResponseBody - @Throws(IOException::class) - fun getImages(): List { - return sponsorService.getImages() - } - - @PostMapping - fun uploadImage( - @RequestParam("image") file: MultipartFile, @RequestParam("name") name: String - ): String? { - sponsorService.uploadImage(file, name) - return "File uploaded successfully" - } - - @DeleteMapping(value = ["/{imageId}"]) - fun deleteImage(@PathVariable imageId: Int) { - sponsorService.deleteImage(imageId) - } + @GetMapping( + produces = [MediaType.IMAGE_JPEG_VALUE, MediaType.IMAGE_PNG_VALUE], + value = ["/{imageId}"] + ) + @ResponseBody + @Throws(IOException::class) + fun getImage(@PathVariable imageId: Int): ByteArray? { + return sponsorService.getImage(imageId) + } + + @GetMapping + @ResponseBody + @Throws(IOException::class) + fun getImages(): List> { + return sponsorService.getImages() + } + + @PostMapping + fun uploadImage( + @RequestParam("image") file: MultipartFile, + @RequestParam("row") row: Int + ): Sponsor { + val uploadSponsorRequest = UploadSponsorRequest(row) + return sponsorService.uploadImage(file, uploadSponsorRequest) + } + + @DeleteMapping(value = ["/{imageId}"]) + fun deleteImage(@PathVariable imageId: Int) { + sponsorService.deleteImage(imageId) + } + + data class UploadSponsorRequest( + val row: Int + ) { + fun toSponsorEntity(image: ByteArray): SponsorEntity { + return SponsorEntity(0, image, row, 0) + } + } } \ No newline at end of file diff --git a/src/main/kotlin/odyseja/odysejapka/service/SponsorService.kt b/src/main/kotlin/odyseja/odysejapka/service/SponsorService.kt index 1684f53..72b89ba 100644 --- a/src/main/kotlin/odyseja/odysejapka/service/SponsorService.kt +++ b/src/main/kotlin/odyseja/odysejapka/service/SponsorService.kt @@ -1,7 +1,7 @@ package odyseja.odysejapka.service import odyseja.odysejapka.domain.Sponsor -import odyseja.odysejapka.domain.SponsorEntity +import odyseja.odysejapka.rest.SponsorController import org.springframework.stereotype.Service import org.springframework.web.multipart.MultipartFile @@ -25,18 +25,27 @@ class SponsorService( return sponsor.get().image } - fun getImages(): List { - return sponsorRepository.findAll().map { Sponsor(it.id, it.name) } + fun getImages(): List> { + val groupedByRow = sponsorRepository.findAll() + .groupBy { it.rowIndex } + .toSortedMap() + + return groupedByRow.map { entry -> + entry.value.sortedBy { it.columnIndex } + .map { it.toSponsor() } + } } - fun uploadImage(file: MultipartFile, name: String) { + fun uploadImage(file: MultipartFile, uploadSponsorRequest: SponsorController.UploadSponsorRequest): Sponsor { val type = file.originalFilename?.split(".")?.last() if (!acceptedTypes.contains(type)) { throw RuntimeException("Provided invalid file type") } - sponsorRepository.save(SponsorEntity(0, name, file.bytes)) + + val sponsor = sponsorRepository.save(uploadSponsorRequest.toSponsorEntity(file.bytes)) changeService.updateVersion() + return sponsor.toSponsor() } fun deleteImage(imageId: Int) {