File tree 13 files changed +60
-26
lines changed
backend/src/main/kotlin/no/nais/cloud/testnais/sandbox/bachelorurlforkorter
13 files changed +60
-26
lines changed Original file line number Diff line number Diff line change @@ -30,6 +30,7 @@ fun startAppServer(config: Config) {
30
30
path(" api" ) {
31
31
post(" sjekk" , UrlForkorterController ::sjekk, Rolle .Alle )
32
32
post(" forkort" , UrlForkorterController ::forkort, Rolle .Alle )
33
+ post(" slett" , UrlForkorterController ::slett, Rolle .Alle )
33
34
get(" hentalle" , UrlForkorterController ::hentAlleMedMetadata, Rolle .Alle )
34
35
}
35
36
get(" {korturl}" ) { ctx ->
Original file line number Diff line number Diff line change @@ -9,10 +9,6 @@ private val logger = KotlinLogging.logger {}
9
9
10
10
object UrlForkorterController {
11
11
12
- fun test (ctx : Context ) {
13
- ctx.result(" Hello world!" )
14
- }
15
-
16
12
fun redirect (ctx : Context ) {
17
13
val korturl = ctx.pathParam(" korturl" )
18
14
if (! korturl.matches(Regex (" ^[a-z0-9]{6}$" ))) {
@@ -78,4 +74,15 @@ object UrlForkorterController {
78
74
ctx.status(500 )
79
75
}
80
76
}
77
+
78
+ fun slett (ctx : Context ) {
79
+ val id = ctx.queryParam(" id" )
80
+ try {
81
+ ShortUrlDataAccessObject .deleteShortUrlById(Integer .parseInt(id))
82
+ ctx.status(204 )
83
+ } catch (e: Exception ) {
84
+ logger.error(" Feil ved sletting av URL" , e)
85
+ ctx.status(500 )
86
+ }
87
+ }
81
88
}
Original file line number Diff line number Diff line change @@ -2,6 +2,7 @@ package no.nais.cloud.testnais.sandbox.bachelorurlforkorter.common.db
2
2
3
3
import org.jetbrains.exposed.sql.*
4
4
import org.jetbrains.exposed.sql.transactions.transaction
5
+ import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
5
6
6
7
object ShortUrlDataAccessObject {
7
8
fun storeShortUrl (shortUrl : String , longUrl : String , createdBy : String? ) {
@@ -52,4 +53,11 @@ object ShortUrlDataAccessObject {
52
53
}
53
54
}
54
55
}
56
+
57
+ fun deleteShortUrlById (id : Int ): Boolean {
58
+ return transaction {
59
+ ShortUrls .deleteWhere { ShortUrls .id eq id } > 0
60
+ }
61
+ }
62
+
55
63
}
Original file line number Diff line number Diff line change 2
2
< html lang ="en ">
3
3
< head >
4
4
< meta charset ="UTF-8 " />
5
- < link rel ="icon " type ="image/svg+xml " href ="/vite.svg " />
5
+ < link rel ="icon " type ="image/svg+xml " href ="" />
6
6
< meta name ="viewport " content ="width=device-width, initial-scale=1.0 " />
7
7
< title > Url-forkorter</ title >
8
8
</ head >
Load Diff This file was deleted.
Load Diff This file was deleted.
Original file line number Diff line number Diff line change @@ -9,17 +9,9 @@ export default function CreateShortUrl() {
9
9
const [ inputValue , setInputValue ] = useState ( "" ) ;
10
10
const [ result , setResult ] = useState < string | null > ( null ) ;
11
11
12
- async function postShortUrlSearch ( longUrl : string ) {
13
- try {
14
- return await apiRequest < { forkortetUrl : string } > ( `forkort?langurl=${ longUrl } ` , "POST" ) ;
15
- } catch ( error ) {
16
- console . error ( "API error:" , error ) ;
17
- }
18
- }
19
-
20
12
function handleCreateClick ( ) {
21
13
if ( ! isValidUrl ( inputValue ) ) return ;
22
- postShortUrlSearch ( inputValue ) . then ( ( res ) => {
14
+ apiRequest < { forkortetUrl : string } > ( `forkort?langurl= ${ inputValue } ` , "POST" ) . then ( ( res ) => {
23
15
if ( res ) setResult ( res . forkortetUrl ) ;
24
16
} ) . catch ( error => {
25
17
setResult ( null ) ;
@@ -36,7 +28,7 @@ export default function CreateShortUrl() {
36
28
onChange = { setInputValue } >
37
29
</ Input >
38
30
{ result &&
39
- < a href = { url } target = "_blank" > { url } </ a >
31
+ < a href = { url } target = "_blank" > { url } </ a >
40
32
}
41
33
</ >
42
34
)
Original file line number Diff line number Diff line change @@ -7,21 +7,13 @@ export default function SearchShortUrl() {
7
7
const [ inputValue , setInputValue ] = useState ( "" ) ;
8
8
const [ searchResult , setSearchResult ] = useState < string | null > ( null ) ;
9
9
10
- async function postShortUrlSearch ( shortUrl : string ) {
11
- try {
12
- return await apiRequest < { langurl : string } > ( `sjekk?korturl=${ shortUrl } ` , "POST" ) ;
13
- } catch ( error ) {
14
- console . error ( "API error:" , error ) ;
15
- }
16
- }
17
-
18
10
function handleSearchClick ( ) {
19
11
const shortUrl = extractShortUrl ( inputValue )
20
12
if ( shortUrl === null || shortUrl . length !== 6 ) {
21
13
console . log ( "test" )
22
14
return ;
23
15
}
24
- postShortUrlSearch ( shortUrl ) . then ( ( res ) => {
16
+ apiRequest < { langurl : string } > ( `sjekk?korturl= ${ shortUrl } ` , "POST" ) . then ( ( res ) => {
25
17
if ( res ) setSearchResult ( res . langurl ) ;
26
18
else setSearchResult ( null ) ;
27
19
} ) . catch ( error => {
Original file line number Diff line number Diff line change 9
9
TableHeaderCell ,
10
10
TableRow
11
11
} from "./showall.style.ts" ;
12
+ import Icon from "../shared/Icon/Icon.tsx" ;
12
13
13
14
interface UrlData {
14
15
id : number ;
@@ -38,6 +39,14 @@ export default function ShowAllUrls() {
38
39
fetchUrls ( ) . then ( ( ) => setLoading ( false ) ) ;
39
40
} , [ ] ) ;
40
41
42
+ function handleDeleteClick ( id : number ) {
43
+ apiRequest < { forkortetUrl : string } > ( `slett?id=${ id } ` , "POST" )
44
+ . then ( ( ) => setUrls ( ( prevUrls ) => prevUrls . filter ( ( url ) => url . id !== id ) ) )
45
+ . catch ( ( error : Error ) => {
46
+ console . error ( "API error:" , error ) ;
47
+ } ) ;
48
+ }
49
+
41
50
return (
42
51
< TableContainer >
43
52
{ loading && < p > Loading...</ p > }
@@ -53,6 +62,7 @@ export default function ShowAllUrls() {
53
62
< TableHeaderCell > Opprettet</ TableHeaderCell >
54
63
< TableHeaderCell > Av bruker</ TableHeaderCell >
55
64
< TableHeaderCell > Antall besøk</ TableHeaderCell >
65
+ < TableHeaderCell > Slett</ TableHeaderCell >
56
66
</ TableRow >
57
67
</ TableHeader >
58
68
< tbody >
@@ -72,6 +82,7 @@ export default function ShowAllUrls() {
72
82
< TableCell > { new Date ( url . createdAt ) . toLocaleString ( ) } </ TableCell >
73
83
< TableCell > { url . createdBy || "Unknown" } </ TableCell >
74
84
< TableCell > { url . clicks } </ TableCell >
85
+ < TableCell > < Icon icon = "close" onClick = { ( ) => { handleDeleteClick ( url . id ) } } > </ Icon > </ TableCell >
75
86
</ TableRow >
76
87
) ) }
77
88
</ tbody >
Original file line number Diff line number Diff line change
1
+ import { StyledIcon } from "./icon.style.ts" ;
2
+
3
+ interface Props {
4
+ icon : string ;
5
+ onClick ?: ( ) => void ;
6
+ color ?: string ;
7
+ }
8
+
9
+ export default function Icon ( { icon, onClick} : Props ) {
10
+ return (
11
+ < StyledIcon src = { `icons/${ icon } .svg` } onClick = { onClick } />
12
+ )
13
+ }
Original file line number Diff line number Diff line change
1
+ import styled from "styled-components" ;
2
+
3
+ export const StyledIcon = styled . img `
4
+ height: 1.1rem;
5
+ &:hover {
6
+ cursor: pointer;
7
+ }
8
+ `
Original file line number Diff line number Diff line change @@ -19,5 +19,6 @@ export async function apiRequest<T>(
19
19
throw new Error ( `Error ${ response . status } : ${ response . statusText } ` ) ;
20
20
}
21
21
22
+ if ( response . status === 204 ) return null as T ;
22
23
return response . json ( ) ;
23
24
}
You can’t perform that action at this time.
0 commit comments