44 changed files with 1667 additions and 159 deletions
			
			
		| @ -0,0 +1,27 @@ | |||
| -----BEGIN RSA PRIVATE KEY----- | |||
| MIIEowIBAAKCAQEApNcN8cn0872DhGSdPobrIR9kBfd+qSL/Sqrgk3mywEuuzhN3 | |||
| MOYbaejwdIJacC0OjCMVgm3f2TziefYd2ssvAUjT+M9FCESUSSDHgPVxt22UDZxz | |||
| ZraasA+jdVW0QQtBv8AjyDCXAmMZxcGT1x1htKsKfG2JDxxc1DXub1BaBSkrqcZ1 | |||
| 1u50UK0DBbRcUhd85z9Oivju3IktDaVow09fpwUR/tK1xO8PPsaAUQMKdN1ArGA/ | |||
| O+FFXAirQ7OD8tT4gCmJYrU2h4mAlcjKwpvmXbtHGmZ2tn4nJsaYUxL0vMPHWoTl | |||
| ymOkFbKujBDkTSdKgUdTBy7Bda9ZzAcEBJoGgQIDAQABAoIBAEGVmuO3obEUlu4n | |||
| BfUpwwVzst044nkzBnXT1PR4OCmQMyWk0whulTunRXxlnMwC8UXKc7VoN+b79XPm | |||
| +2vg6XvOWSAmf2XRu1n5I8doYG1FuOFNfRDB2HvyTOvTRJuYeflr3hC5XGvDuC5Z | |||
| XZP6CbTTVKG7BwwvEbQRHSPGyXpBiqd+OOfTpeoobrkGJJAKxvXHO0G7zgB5h/H+ | |||
| 0fjSWvo4QxzOAF74f0qUmWBbvLjWL3yZhVE8mxNcVoV1HlIdXV5anMe9FURci5D4 | |||
| U8ehGky3sbHjcc7wro5IPWJYTrDAmvhI8wMMx7gbHe2HOzyWRX++ifjfP77kw2e3 | |||
| IYnwMAECgYEA05Ehmsipk4rmJeCgmDJomQVsJgMW1zjOJwIljSZ9o55+LHpma6r0 | |||
| O6sdQYgiNwQT0f//iJZkatpDAyC3U6EU9RY7Yoc0R3XK86vryKQlB/Nh1boLldt6 | |||
| 9TGdL5eCzaraiYuLjGvXMGTS8LjB0ftFCGQswl2kcuOFx1YjE4WPoUECgYEAx3Wo | |||
| yenPXHCdD4kIrQ9SxPha2aobh33MjdwSYSiDliaEoBg/voWJExFmMJuvhR46xqmy | |||
| i8E0RuzzBrG4Zhbdo4kcpdF2GtAuxNw8uYvG+SQub8zAmBT7YpXzTmpGQ2TR3i8S | |||
| XzD57s7C1mSkBIwWuVJYcx3Kgm1mQNIOELU31UECgYEAhNc14HhqcaffRp06eRX9 | |||
| s0dCVsPNzalvV/LzHSOz886KrubT9HrNC8Ivhnwx75Vx1IQHMP4tYyJUvVwHgE0+ | |||
| WX1yIDWAz/XYTxP94meekNVy8r30lE3RcK+MYNujV/wVaBPktXDpFwvXnyqDGJPL | |||
| Dq/HouslXLYbw8QEFjfgrYECgYB+oSU6ozThpCEihsY6ULskj+PlwohdubEO8wO8 | |||
| KSN5RRT4Ksz1YQPIVkiBXaXOJoX8MCpJbayJxs73lgbS0Xt+4oKMh3GqzjaTBpuK | |||
| 1MHK1Hyiv+QZ6WA7k6V3SCM5kB1pKItKYeabBStPP2+d725R04SR+PzjVx8O0gzZ | |||
| 8KL0wQKBgC7LRztq8PMDGTHGXVxWXwZ08ZAf2MAsBvYyAU5xudS+pRqlNGDgyxiv | |||
| YQEe9n2DVu7GVsoNnKIapmXV1qx0vTU/CpKV0cpXi6m3XVnbtjBsaYtkYNNZfHVl | |||
| E++gP4qgvALKugnzaGn5oby0PPcFFhnNqRwFb5c3diihwMQhkudG | |||
| -----END RSA PRIVATE KEY----- | |||
| @ -0,0 +1,5 @@ | |||
| #!/bin/bash | |||
| 
 | |||
| yarn prod | |||
| rsync -avz --delete --exclude '/apis/conn.conn' --exclude '.well-known' --exclude '/uploads' -e "ssh -i ./auth/identity.pem -p2222" ./dist/dslak-website/* cdr@2.238.194.8:/www/dslak.it/ | |||
| 
 | |||
| @ -0,0 +1,41 @@ | |||
| <?php | |||
| @include 'conn.conn'; | |||
| $GLOBALS['conn']; | |||
| $conn = @mysqli_connect($DATAhst,$DATAusr,$DATApwd,$DATAdtb)or die("CONNECTION ERROR"); | |||
| 
 | |||
| $content = null; | |||
| $content->status = 200; | |||
| 
 | |||
| $data = json_decode(file_get_contents("php://input")); | |||
| 
 | |||
| if(isset($_GET['act']) && $_GET['act'] == 'login') { | |||
|   if(isset($data->usr) && $data->usr == 'admin' && isset($data->pwd) && $data->pwd == 'JohnHolmes') { | |||
|     http_response_code(200); | |||
|     $content->status = 200; | |||
|     $content->authToken = base64_encode('admin:JohnHolmes'.date("Y-m-d")); | |||
|   } else { | |||
|     http_response_code(401); | |||
|     $content->status = 401; | |||
|     $content->action = 'login'; | |||
|   } | |||
| } else if(isset($_GET['act']) && $_GET['act'] == 'check') { | |||
|   if(isset($data->token) && $data->token == base64_encode('admin:JohnHolmes'.date("Y-m-d"))) { | |||
|     http_response_code(200); | |||
|     $content->status = 200; | |||
|     $content->authToken = base64_encode('admin:JohnHolmes'.date("Y-m-d")); | |||
|   } else { | |||
|     http_response_code(200); | |||
|     $content->status = 401; | |||
|     $content->action = 'check'; | |||
|     $content->token = $data->token; | |||
|   } | |||
| } | |||
| 
 | |||
| header("Access-Control-Allow-Origin: *"); | |||
| header("Content-Type: application/json; charset=UTF-8"); | |||
| header("Access-Control-Allow-Methods: POST"); | |||
| header("Access-Control-Max-Age: 3600"); | |||
| 
 | |||
| echo json_encode($content); | |||
| 
 | |||
| ?> | |||
| @ -0,0 +1,80 @@ | |||
| <?php | |||
| @include 'conn.conn'; | |||
| $GLOBALS['conn']; | |||
| $conn = @mysqli_connect($DATAhst,$DATAusr,$DATApwd,$DATAdtb)or die("CONNECTION ERROR"); | |||
| 
 | |||
| $content = null; | |||
| $data = json_decode(file_get_contents("php://input")); | |||
| 
 | |||
| if(isset($data->token) && $data->token == base64_encode('admin:JohnHolmes'.date("Y-m-d"))) { | |||
| 
 | |||
|   if(isset($_GET['act'])) { | |||
|     if($_GET['act'] == 'save') { | |||
|       if(isset($data->id)) { | |||
|         $q = mysqli_query($conn,"UPDATE `exhibitions` SET title = '".addslashes($data->title)."', content = '".addslashes($data->content)."', | |||
|                                     tags = '".$data->tags."', date_from = '".$data->date_from."', date_to = '".$data->date_to."', | |||
|                                     image = '".$data->image."', works = '".$data->works."', gallery = '".$data->gallery."', | |||
|                                     videos = '".$data->videos."' WHERE id = ".$data->id.""); | |||
|       } else { | |||
|         $q = mysqli_query($conn,"INSERT INTO `exhibitions` | |||
|                                   (`id`, `title`, `content`, `tags`, `date_from`, `date_to`, `image`, `works`, `gallery`, `videos`) | |||
|                                   VALUES (NULL, '".addslashes($data->title)."', '".addslashes($data->content)."', '".$data->tags."', | |||
|                                   '".$data->date_from."', '".$data->date_to."', '".$data->image."', '".$data->works."', | |||
|                                   '".$data->gallery."', '".$data->videos."')"); | |||
|       } | |||
| 
 | |||
|       if($q) { | |||
|         http_response_code(201); | |||
|         $content->status = 201; | |||
|       } else { | |||
|         http_response_code(403); | |||
|         $content->status = "UPDATE `exhibitions` SET title = '".addslashes($data->title)."', content = '".addslashes($data->content)."', | |||
|                                     tags = '".$data->tags."', date_from = '".$data->date_from."', date_to = '".$data->date_to."', | |||
|                                     image = '".$data->image."', works = '".$data->works."', gallery = '".$data->gallery."', | |||
|                                     videos = '".$data->videos."' WHERE id = ".$data->id.""; | |||
|       } | |||
|     } | |||
| 
 | |||
|     if($_GET['act'] == 'delete') { | |||
|       if(isset($data->id)) { | |||
|         $q = mysqli_query($conn,"DELETE FROM `exhibitions` WHERE id = ".$data->id.""); | |||
|         if($q) { | |||
|           http_response_code(201); | |||
|           $content->status = 201; | |||
|         } else { | |||
|           http_response_code(403); | |||
|           $content->status = 403; | |||
|         } | |||
|       } | |||
|     } | |||
| 
 | |||
|     if($q) { | |||
|       $qe = mysqli_query($conn,"SELECT * FROM `exhibitions` ORDER BY id DESC"); | |||
|       if(mysqli_num_rows($qe) > 0) { | |||
|         $content->items = array(); | |||
|         while($re = mysqli_fetch_array($qe)) { | |||
|           $item = null; | |||
|           $item->id = $re['id']; | |||
|           $item->title = $re['title']; | |||
|           $item->date_from = $re['date_from']; | |||
|           $item->date_to = $re['date_to']; | |||
|           $item->tags = $re['tags']; | |||
|           $item->image = $re['image']; | |||
|           array_push($content->items, $item); | |||
|         } | |||
|       } | |||
|     } | |||
|   } | |||
| 
 | |||
| } else { | |||
|   http_response_code(401); | |||
|   $content->status = 401; | |||
| } | |||
| header("Access-Control-Allow-Origin: *"); | |||
| header("Content-Type: application/json; charset=UTF-8"); | |||
| header("Access-Control-Allow-Methods: POST"); | |||
| header("Access-Control-Max-Age: 3600"); | |||
| 
 | |||
| echo json_encode($content); | |||
| 
 | |||
| ?> | |||
| @ -1,95 +1,98 @@ | |||
| <?php | |||
| @include 'conn.conn'; | |||
| $GLOBALS['conn']; | |||
| $conn=@mysqli_connect($DATAhst,$DATAusr,$DATApwd,$DATAdtb)or die("CONNECTION ERROR"); | |||
| $conn = @mysqli_connect($DATAhst,$DATAusr,$DATApwd,$DATAdtb)or die("CONNECTION ERROR"); | |||
| 
 | |||
| $content = null; | |||
| $content->items = array(); | |||
| 
 | |||
| $filter = array("portfolio", "installations", "entertainment", "performances", "workshops"); | |||
| if(isset($_GET['query'])) { | |||
| 
 | |||
| switch($_GET['query']) { | |||
|   case "portfolio": | |||
|   case "installations": | |||
|   case "entertainment": | |||
|   case "performances": | |||
|   case "workshops": | |||
|     if($_GET['query'] == 'portfolio') {$filter = '';} else {$filter = "WHERE type='".$_GET['query']."'";} | |||
|     $qe = mysqli_query($conn,"SELECT * FROM `works` $filter ORDER BY id DESC"); | |||
|     if(mysqli_num_rows($qe) > 0) { | |||
|       $content = null; | |||
|       $content->items = array(); | |||
|       while($re = mysqli_fetch_array($qe)) { | |||
|         $item = null; | |||
|         $item->id = $re['id']; | |||
|         $item->title = $re['title']; | |||
|         $item->type = $re['type']; | |||
|         $item->tags = $re['tags']; | |||
|         $item->image = $re['image']; | |||
|         array_push($content->items, $item); | |||
|   $content->items = array(); | |||
|   switch($_GET['query']) { | |||
|     case "portfolio": | |||
|     case "installations": | |||
|     case "entertainment": | |||
|     case "performances": | |||
|     case "workshops": | |||
|       if($_GET['query'] == 'portfolio') {$filter = '';} else {$filter = "WHERE type='".$_GET['query']."'";} | |||
|       $qe = mysqli_query($conn,"SELECT * FROM `works` $filter ORDER BY id DESC"); | |||
|       if(mysqli_num_rows($qe) > 0) { | |||
|         $content = null; | |||
|         $content->items = array(); | |||
|         while($re = mysqli_fetch_array($qe)) { | |||
|           $item = null; | |||
|           $item->id = $re['id']; | |||
|           $item->title = $re['title']; | |||
|           $item->type = $re['type']; | |||
|           $item->tags = $re['tags']; | |||
|           $item->image = $re['image']; | |||
|           array_push($content->items, $item); | |||
|         } | |||
|       } | |||
|     } | |||
|     break; | |||
|   case "exhibitions": | |||
|     $qe = mysqli_query($conn,"SELECT * FROM `exhibitions` ORDER BY date_from DESC"); | |||
|     if(mysqli_num_rows($qe) > 0) { | |||
|       $content = null; | |||
|       $content->items = array(); | |||
|       while($re = mysqli_fetch_array($qe)) { | |||
|       break; | |||
|     case "exhibitions": | |||
|       $qe = mysqli_query($conn,"SELECT * FROM `exhibitions` ORDER BY date_from DESC"); | |||
|       if(mysqli_num_rows($qe) > 0) { | |||
|         $content = null; | |||
|         $content->items = array(); | |||
|         while($re = mysqli_fetch_array($qe)) { | |||
|           $item = null; | |||
|           $item->id = $re['id']; | |||
|           $item->title = $re['title']; | |||
|           $item->date_from = $re['date_from']; | |||
|           $item->date_to = $re['date_to']; | |||
|           $item->tags = $re['tags']; | |||
|           $item->image = $re['image']; | |||
|           array_push($content->items, $item); | |||
|         } | |||
|       } | |||
|       break; | |||
|     case "detail": | |||
|       $qe = mysqli_query($conn,"SELECT * FROM `".$_GET['type']."` WHERE id=".$_GET['id']); | |||
|       if(mysqli_num_rows($qe)>0) { | |||
|         $content = null; | |||
|         $re = mysqli_fetch_array($qe); | |||
|         $item = null; | |||
|         $item->id = $re['id']; | |||
|         $item->title = $re['title']; | |||
|         $item->date_from = $re['date_from']; | |||
|         $item->date_to = $re['date_to']; | |||
|         $item->content = $re['content']; | |||
|         $item->tags = $re['tags']; | |||
|         $item->image = $re['image']; | |||
|         array_push($content->items, $item); | |||
|       } | |||
|     } | |||
|     break; | |||
|   case "detail": | |||
|     $qe = mysqli_query($conn,"SELECT * FROM `".$_GET['type']."` WHERE id=".$_GET['id']); | |||
|     if(mysqli_num_rows($qe)>0) { | |||
|       $content = null; | |||
|       $re = mysqli_fetch_array($qe); | |||
|       $item = null; | |||
|       $item->id = $re['id']; | |||
|       $item->title = $re['title']; | |||
|       $item->content = $re['content']; | |||
|       $item->tags = $re['tags']; | |||
|       $item->image = $re['image']; | |||
|       if($_GET['type'] == 'exhibitions') { | |||
|         $item->date_from = $re['date_from']; | |||
|         $item->date_to = $re['date_to']; | |||
|         $item->works = array(); | |||
|         $qx = mysqli_query($conn,"SELECT id,title FROM `works` WHERE id IN (".$re['works'].")"); | |||
|         while($re = mysqli_fetch_array($qx)) { | |||
|           $ex = null; | |||
|           $ex->id = $re['id']; | |||
|           $ex->title = $re['title']; | |||
|           array_push($item->works, $ex); | |||
|         } | |||
|       } else if($_GET['type'] == 'works') { | |||
|         $item->type = $re['type']; | |||
|         $item->videos = $re['videos']; | |||
|         $item->gallery = $re['gallery']; | |||
|         $item->exhibitions = array(); | |||
|         $qx = mysqli_query($conn,"SELECT id,title FROM `exhibitions` WHERE id IN (".$re['exhibitions'].")"); | |||
|         while($re = mysqli_fetch_array($qx)) { | |||
|           $ex = null; | |||
|           $ex->id = $re['id']; | |||
|           $ex->title = $re['title']; | |||
|           array_push($item->exhibitions, $ex); | |||
|         if($_GET['type'] == 'exhibitions') { | |||
|           $item->date_from = $re['date_from']; | |||
|           $item->date_to = $re['date_to']; | |||
|           $item->works = array(); | |||
|           $qx = mysqli_query($conn,"SELECT id,title FROM `works` WHERE id IN (".$re['works'].")"); | |||
|           while($re = mysqli_fetch_array($qx)) { | |||
|             $ex = null; | |||
|             $ex->id = $re['id']; | |||
|             $ex->title = $re['title']; | |||
|             array_push($item->works, $ex); | |||
|           } | |||
|         } else if($_GET['type'] == 'works') { | |||
|           $item->type = $re['type']; | |||
|           $item->exhibitions = array(); | |||
|           $qx = mysqli_query($conn,"SELECT id,title FROM `exhibitions` WHERE id IN (".$re['exhibitions'].")"); | |||
|           while($re = mysqli_fetch_array($qx)) { | |||
|             $ex = null; | |||
|             $ex->id = $re['id']; | |||
|             $ex->title = $re['title']; | |||
|             array_push($item->exhibitions, $ex); | |||
|           } | |||
|         } | |||
|         $content->item = $item; | |||
|       } | |||
|       $content->item = $item; | |||
|     } | |||
|     break; | |||
|       break; | |||
|   } | |||
| } | |||
| http_response_code(200); | |||
| 
 | |||
| 
 | |||
| header('Access-Control-Allow-Origin: *'); | |||
| header('Content-Type: application/json'); | |||
| header("Access-Control-Allow-Origin: *"); | |||
| header("Content-Type: application/json; charset=UTF-8"); | |||
| header("Access-Control-Allow-Methods: GET"); | |||
| header("Access-Control-Max-Age: 3600"); | |||
| echo json_encode($content); | |||
| 
 | |||
| ?> | |||
|  | |||
| @ -0,0 +1,24 @@ | |||
| <?php | |||
| 
 | |||
| $content = null; | |||
| $data = json_decode(file_get_contents("php://input")); | |||
| 
 | |||
| if(isset($data->token) && $data->token == base64_encode('admin:JohnHolmes'.date("Y-m-d"))) { | |||
| 
 | |||
|     @unlink('..'.$data->url); | |||
|     http_response_code(200); | |||
|     $content->status = 200; | |||
| 
 | |||
| } else { | |||
|   http_response_code(401); | |||
|   $content->status = 401; | |||
| } | |||
| 
 | |||
| header("Access-Control-Allow-Origin: *"); | |||
| header("Content-Type: application/json; charset=UTF-8"); | |||
| header("Access-Control-Allow-Methods: POST"); | |||
| header("Access-Control-Max-Age: 3600"); | |||
| 
 | |||
| echo json_encode($content); | |||
| 
 | |||
| ?> | |||
| @ -0,0 +1,35 @@ | |||
| <?php | |||
| 
 | |||
| $content = null; | |||
| 
 | |||
| if(isset($_POST['token']) && $_POST['token'] == base64_encode('admin:JohnHolmes'.date("Y-m-d"))) { | |||
| 
 | |||
|   if(is_uploaded_file($_FILES['file']['tmp_name'])) { | |||
|     $file = $_FILES['file']['tmp_name']; | |||
|     $filename = date("YmdHis").".".end((explode(".", $_FILES["file"]["name"]))); | |||
| 
 | |||
|     $path = isset($_POST['path']) ? "/uploads/".$_POST['path'] : "/uploads/"; | |||
|     @move_uploaded_file($file, "..".$path."/".$filename); | |||
| 
 | |||
|     http_response_code(200); | |||
|     $content->status = 200; | |||
|     $content->imageUrl = $path."/".$filename; | |||
| 
 | |||
|   } else { | |||
|     http_response_code(401); | |||
|     $content->status = 401; | |||
|     $content->megssage = 'No file uploaded'; | |||
|   } | |||
| } else { | |||
|   http_response_code(401); | |||
|   $content->status = 401; | |||
| } | |||
| 
 | |||
| header("Access-Control-Allow-Origin: *"); | |||
| header("Content-Type: application/json; charset=UTF-8"); | |||
| header("Access-Control-Allow-Methods: POST"); | |||
| header("Access-Control-Max-Age: 3600"); | |||
| 
 | |||
| echo json_encode($content); | |||
| 
 | |||
| ?> | |||
| @ -0,0 +1,75 @@ | |||
| <?php | |||
| @include 'conn.conn'; | |||
| $GLOBALS['conn']; | |||
| $conn = @mysqli_connect($DATAhst,$DATAusr,$DATApwd,$DATAdtb)or die("CONNECTION ERROR"); | |||
| 
 | |||
| $content = null; | |||
| $data = json_decode(file_get_contents("php://input")); | |||
| 
 | |||
| if(isset($data->token) && $data->token == base64_encode('admin:JohnHolmes'.date("Y-m-d"))) { | |||
| 
 | |||
|   if(isset($_GET['act'])) { | |||
|     if($_GET['act'] == 'save') { | |||
|       if(isset($data->id)) { | |||
|         $q = mysqli_query($conn,"UPDATE `works` SET title = '".addslashes($data->title)."', content = '".addslashes($data->content)."', | |||
|                                     type = '".$data->type."', tags = '".$data->tags."', image = '".$data->image."', | |||
|                                     exhibitions = '".$data->exhibitions."', gallery = '".$data->gallery."', videos = '".$data->videos."' | |||
|                                     WHERE id = ".$data->id.""); | |||
|       } else { | |||
|         $q = mysqli_query($conn,"INSERT INTO `works` (`id`, `title`, `content`, `type`, `tags`, `image`, `exhibitions`, `gallery`, `videos`) | |||
|                                   VALUES (NULL, '".addslashes($data->title)."', '".addslashes($data->content)."', '".$data->type."', | |||
|                                           '".$data->tags."', '".$data->image."', '".$data->exhibitions."', '".$data->gallery."', | |||
|                                           '".$data->videos."')"); | |||
|       } | |||
| 
 | |||
|       if($q) { | |||
|         http_response_code(201); | |||
|         $content->status = 201; | |||
|       } else { | |||
|         http_response_code(403); | |||
|         $content->status = 403; | |||
|       } | |||
|     } | |||
| 
 | |||
|     if($_GET['act'] == 'delete') { | |||
|       if(isset($data->id)) { | |||
|         $q = mysqli_query($conn,"DELETE FROM `works` WHERE id = ".$data->id.""); | |||
|         if($q) { | |||
|           http_response_code(201); | |||
|           $content->status = 201; | |||
|         } else { | |||
|           http_response_code(403); | |||
|           $content->status = 403; | |||
|         } | |||
|       } | |||
|     } | |||
| 
 | |||
|     if($q) { | |||
|       $qe = mysqli_query($conn,"SELECT * FROM `works` ORDER BY id DESC"); | |||
|       if(mysqli_num_rows($qe) > 0) { | |||
|         $content->items = array(); | |||
|         while($re = mysqli_fetch_array($qe)) { | |||
|           $item = null; | |||
|           $item->id = $re['id']; | |||
|           $item->title = $re['title']; | |||
|           $item->type = $re['type']; | |||
|           $item->tags = $re['tags']; | |||
|           $item->image = $re['image']; | |||
|           array_push($content->items, $item); | |||
|         } | |||
|       } | |||
|     } | |||
|   } | |||
| 
 | |||
| } else { | |||
|   http_response_code(401); | |||
|   $content->status = 401; | |||
| } | |||
| header("Access-Control-Allow-Origin: *"); | |||
| header("Content-Type: application/json; charset=UTF-8"); | |||
| header("Access-Control-Allow-Methods: POST"); | |||
| header("Access-Control-Max-Age: 3600"); | |||
| 
 | |||
| echo json_encode($content); | |||
| 
 | |||
| ?> | |||
| @ -0,0 +1,191 @@ | |||
| <div class="component-admin"> | |||
|   <div class="row no-gutters" *ngIf="!authCheck"> | |||
|     <div class="col-12 col-md-6 mx-auto"> | |||
|       <form class="login-form-container" (submit)="login()"> | |||
|         <div class="m-2"> | |||
|           <span class="login-label">Username</span> | |||
|           <input type="text" class="input-text" name="userName" [(ngModel)]="userName"> | |||
|         </div> | |||
|         <div class="m-2"> | |||
|           <span class="login-label">Password</span> | |||
|           <input type="password" class="input-text" name="password" [(ngModel)]="password"> | |||
|         </div> | |||
|         <div class="m-2 pt-4"> | |||
|           <button type="submit" class="button">Sign-in</button> | |||
|         </div> | |||
|       </form> | |||
|     </div> | |||
|   </div> | |||
| 
 | |||
|   <div class="row no-gutters" *ngIf="authCheck"> | |||
|     <div class="col-12 col-md-3 col-lg-2"> | |||
|       <div class="menu"> | |||
|         <span class="section-title">Works</span> | |||
|         <button class="action" [ngClass]="{'active': activeEditor == 'works-add'}" (click)="showEditor('works-add')">Add</button> | |||
|         <button class="action" [ngClass]="{'active': activeEditor == 'works-modify'}" (click)="showEditor('works-modify')">Modify</button> | |||
|         <button class="action" [ngClass]="{'active': activeEditor == 'works-delete'}" (click)="showEditor('works-delete')">Delete</button> | |||
| 
 | |||
|         <span class="section-title">Exhibitions</span> | |||
|         <button class="action" [ngClass]="{'active': activeEditor == 'exhibitions-add'}" (click)="showEditor('exhibitions-add')">Add</button> | |||
|         <button class="action" [ngClass]="{'active': activeEditor == 'exhibitions-modify'}" (click)="showEditor('exhibitions-modify')">Modify</button> | |||
|         <button class="action" [ngClass]="{'active': activeEditor == 'exhibitions-delete'}" (click)="showEditor('exhibitions-delete')">Delete</button> | |||
|       </div> | |||
|     </div> | |||
|     <div class="col px-5 py-4"> | |||
|       <div class="edit-container"> | |||
|         <span class="title">{{sectionTitle}}</span> | |||
|         <form class="form row" *ngIf="activeEditor == 'works-modify' || activeEditor == 'works-delete'"> | |||
|           <div class="col-12"> | |||
|             <select class="input-select" (change)="selectWork($event.target.value)"> | |||
|               <option value="">- Select work from list -</option> | |||
|               <option value="{{work.id}}" *ngFor="let work of works"> | |||
|                 {{work.type}} | {{work.title}} | |||
|               </option> | |||
|             </select> | |||
|           </div> | |||
|         </form> | |||
|         <form class="form row" *ngIf="activeEditor == 'exhibitions-modify' || activeEditor == 'exhibitions-delete'"> | |||
|           <div class="col-12"> | |||
|             <select class="input-select" (change)="selectExhibition($event.target.value)"> | |||
|               <option value="">- Select exhibition from list -</option> | |||
|               <option value="{{exhibition.id}}" *ngFor="let exhibition of exhibitions"> | |||
|                 {{exhibition.date_from | date}} | {{exhibition.title}} | |||
|               </option> | |||
|             </select> | |||
|           </div> | |||
|         </form> | |||
|         <form class="form row" (submit)="saveData()" | |||
|               *ngIf="activeEditor == 'works-add' || (activeEditor == 'works-modify' && activeModify) || | |||
|                     activeEditor == 'exhibitions-add' || (activeEditor == 'exhibitions-modify' && activeModify)"> | |||
|           <div [ngClass]="{'col-8': activeEditor == 'works-add' || activeEditor == 'works-modify', | |||
|                            'col-6': activeEditor == 'exhibitions-add' || activeEditor == 'exhibitions-modify'}"> | |||
|             <span class="label">Title</span> | |||
|             <input type="text" class="input-text" name="title" [(ngModel)]="title"> | |||
|           </div> | |||
|           <div class="col-4" *ngIf="activeEditor == 'works-add' || activeEditor == 'works-modify'"> | |||
|             <span class="label">Type</span> | |||
|             <select class="input-select" name="type" [(ngModel)]="type"> | |||
|               <option [value]="sec.section" *ngFor="let sec of workSections">{{sec.title}}</option> | |||
|             </select> | |||
|           </div> | |||
|           <div class="col-3" *ngIf="activeEditor == 'exhibitions-add' || activeEditor == 'exhibitions-modify'"> | |||
|             <span class="label">Date from</span> | |||
|             <input type="date" class="input-text w-100" name="dateFrom" [(ngModel)]="dateFrom" (change)="dateTo = dateFrom"> | |||
|           </div> | |||
|           <div class="col-3" *ngIf="activeEditor == 'exhibitions-add' || activeEditor == 'exhibitions-modify'"> | |||
|             <span class="label">Date to</span> | |||
|             <input type="date" class="input-text w-100" name="dateTo" [(ngModel)]="dateTo"> | |||
|           </div> | |||
|           <div class="col-12"> | |||
|             <span class="label">Content</span> | |||
|             <angular-editor [placeholder]="'Enter text here...'" [config]="editorConfig" name="content" [(ngModel)]="content"></angular-editor> | |||
|           </div> | |||
|           <div class="col-12"> | |||
|             <span class="label">Tags</span> | |||
|             <input type="text" class="input-text" name="tags" [(ngModel)]="tags"> | |||
|           </div> | |||
|           <div class="col-12"> | |||
|             <span class="label">Gallery</span> | |||
|             <div class="gallery-container"> | |||
| 
 | |||
|               <label class="image-add" for="image-add"> | |||
|                 <input type="file" id="image-add" (change)="onFileChanged($event)"> | |||
|               </label> | |||
| 
 | |||
|               <div class="image-box" [ngClass]="{'main': image.main}" *ngFor="let image of selectedGallery"> | |||
|                 <img class="image" [src]="basePath+image.url"> | |||
|                 <button type="button" class="remove" (click)="galleryRemove(image.url)"><span class="icon-trash-2"></span></button> | |||
|                 <button type="button" class="set-main" (click)="gallerySetMain(image.url)" *ngIf="!image.main"><span class="icon-check"></span></button> | |||
|               </div> | |||
|             </div> | |||
|           </div> | |||
| 
 | |||
|           <div class="col-6" *ngIf="activeEditor == 'works-add' || activeEditor == 'works-modify'"> | |||
|             <span class="label">Exhibitions</span> | |||
|             <select class="input-select" name="exhibitions" (change)="exhibitionAdd($event.target.value)"> | |||
|               <option value=""></option> | |||
|               <option value="{{exhibition.id}}" *ngFor="let exhibition of exhibitions"> | |||
|                 {{exhibition.date_from | date}} | {{exhibition.title}} | |||
|               </option> | |||
|             </select> | |||
| 
 | |||
|             <span class="label font-12 pt-2">Selected exhibitions</span> | |||
|             <span class="selected-exhibition" *ngFor="let se of selectedExhibitions" (click)="exhibitionRemove(se.id)"> | |||
|               {{se.date_from | date}} | {{se.title}} | |||
|             </span> | |||
|           </div> | |||
| 
 | |||
|           <div class="col-6" *ngIf="activeEditor == 'exhibitions-add' || activeEditor == 'exhibitions-modify'"> | |||
|             <span class="label">Works</span> | |||
|             <select class="input-select" name="works" (change)="workAdd($event.target.value)"> | |||
|               <option value=""></option> | |||
|               <option value="{{work.id}}" *ngFor="let work of works"> | |||
|                 {{work.type}} | {{work.title}} | |||
|               </option> | |||
|             </select> | |||
| 
 | |||
|             <span class="label font-12 pt-2">Selected works</span> | |||
|             <span class="selected-work" *ngFor="let sw of selectedWorks" (click)="workRemove(sw.id)"> | |||
|               {{sw.type}} | {{sw.title}} | |||
|             </span> | |||
| 
 | |||
|           </div> | |||
| 
 | |||
|           <div class="col-6"> | |||
|             <span class="label">Video</span> | |||
|             <div class="w-30 d-inline-block pr-2"> | |||
|               <select class="input-select" name="videoType" [(ngModel)]="videoType"> | |||
|                 <option value="youtube">YouTube</option> | |||
|                 <option value="vimeo">Vimeo</option> | |||
|                 <option value="embed">Embed</option> | |||
|               </select> | |||
|             </div> | |||
|             <div class="w-60 d-inline-block pr-2"> | |||
|               <input type="text" class="input-text" name="videoURL" [(ngModel)]="videoURL"> | |||
|             </div> | |||
|             <div class="w-10 d-inline-block"> | |||
|               <span class="button button-transparent icon-plus-square px-0 w-100" (click)="videoAdd()"></span> | |||
|             </div> | |||
| 
 | |||
|             <span class="label font-12 pt-2">Selected Videos</span> | |||
|             <span class="selected-video" *ngFor="let sv of selectedVideos" (click)="videoRemove(sv.url)"> | |||
|               {{sv.type}} | {{sv.url}} | |||
|             </span> | |||
|           </div> | |||
|           <div class="col-12 pt-5"> | |||
|             <button class="button w-100" type="submit">Save</button> | |||
|           </div> | |||
|         </form> | |||
| 
 | |||
| 
 | |||
|         <form class="form row" (submit)="deleteData(modifyId)" | |||
|               *ngIf="(activeEditor == 'works-delete' || activeEditor == 'exhibitions-delete') && modifyId"> | |||
|           <div class="col-12"> | |||
|             <span class="label">Title</span> | |||
|             <div class="preview-box" *ngIf="activeEditor == 'works-delete'">{{type}} | {{title}}</div> | |||
|             <div class="preview-box" *ngIf="activeEditor == 'exhibitions-delete'">{{dateFrom}} | {{title}}</div> | |||
|           </div> | |||
|           <div class="col-12"> | |||
|             <span class="label">Content</span> | |||
|             <div class="preview-box" [innerHTML]="content"></div> | |||
|           </div> | |||
| 
 | |||
|           <div class="col-12"> | |||
|             <span class="label">Gallery</span> | |||
|             <div class="gallery-container"> | |||
|               <div class="image-box" [ngClass]="{'main': image.main}" *ngFor="let image of selectedGallery"> | |||
|                 <img class="image" [src]="basePath+image.url"> | |||
|                 <button type="button" class="remove" (click)="galleryRemove(image.url)"><span class="icon-trash-2"></span></button> | |||
|               </div> | |||
|             </div> | |||
|           </div> | |||
| 
 | |||
|           <div class="col-12 pt-5"> | |||
|             <button class="button w-100" type="submit">Delete</button> | |||
|           </div> | |||
|         </form> | |||
|       </div> | |||
|     </div> | |||
|   </div> | |||
| </div> | |||
| 
 | |||
| @ -0,0 +1,210 @@ | |||
| @import "../../assets/scss/variables"; | |||
| 
 | |||
| .component-admin { | |||
| 
 | |||
|   .login-form-container { | |||
|     text-align: center; | |||
|     padding: 30px 40px; | |||
|     color: $white; | |||
| 
 | |||
|     .login-label { | |||
|       font-size: $font-14; | |||
|       color: $black; | |||
|       padding: 8px; | |||
|     } | |||
| 
 | |||
|     .button { | |||
|       width: 300px; | |||
|     } | |||
|   } | |||
| 
 | |||
|   .edit-container { | |||
|     .title { | |||
|       display: block; | |||
|       font-size: $font-30; | |||
|       font-weight: bolder; | |||
|       text-transform: uppercase; | |||
|       padding: 20px 0; | |||
|     } | |||
|     .form { | |||
|       .label { | |||
|         display: block; | |||
|         font-size: $font-20; | |||
|         text-transform: uppercase; | |||
|         padding: 20px 0 5px 0; | |||
|       } | |||
| 
 | |||
|       .gallery-container { | |||
|         display: flex; | |||
|         background: $white; | |||
|         border-radius: 4px; | |||
|         width: 100%; | |||
|         padding: 5px; | |||
|         min-height: 100px; | |||
| 
 | |||
|         .image-add { | |||
|           appearance: none; | |||
|           display: inline-block; | |||
|           position: relative; | |||
|           border: 2px solid $light-gray; | |||
|           border-radius: 4px; | |||
|           height: 100px; | |||
|           width: 100px; | |||
|           margin: 5px; | |||
|           cursor: pointer; | |||
| 
 | |||
|           &:before { | |||
|             content: '\e90a'; | |||
|             font-family: $font-icon; | |||
|             font-size: $font-30; | |||
|             color: $light-gray; | |||
|             position: absolute; | |||
|             top: 50%; | |||
|             left: 50%; | |||
|             transform: translate(-50%, -50%); | |||
|           } | |||
| 
 | |||
|           input { | |||
|             visibility: hidden; | |||
|           } | |||
|         } | |||
| 
 | |||
|         .image-box { | |||
|           display: inline-block; | |||
|           position: relative; | |||
|           border: 2px solid $light-gray; | |||
|           height: 100px; | |||
|           width: 120px; | |||
|           margin: 5px; | |||
|           border-radius: 4px; | |||
|           overflow: hidden; | |||
| 
 | |||
|           .image { | |||
|             position: absolute; | |||
|             height: 100%; | |||
|             width: 100%; | |||
|             object-fit: cover; | |||
|             z-index: 0; | |||
|           } | |||
| 
 | |||
|           .remove, | |||
|           .set-main { | |||
|             position: absolute; | |||
|             top: 4px; | |||
|             right: 4px; | |||
|             border: 0; | |||
|             border-radius: 2px; | |||
|             color: $black; | |||
|             height: 20px; | |||
|             width: 20px; | |||
|             background: $white-alpha; | |||
|             padding: 0; | |||
|             margin: 0; | |||
|             cursor: pointer; | |||
|             font-size: $font-12; | |||
|             z-index: 10; | |||
|           } | |||
| 
 | |||
|           .remove { | |||
|             color: $red; | |||
|           } | |||
|           .set-main { | |||
|             color: $green; | |||
|             right: 30px; | |||
|           } | |||
| 
 | |||
|           &.main { | |||
|             border: 2px solid $yellow; | |||
|           } | |||
|         } | |||
|       } | |||
| 
 | |||
|       .selected-exhibition, | |||
|       .selected-work, | |||
|       .selected-video { | |||
|         display: block; | |||
|         position: relative; | |||
|         font-size: $font-16; | |||
|         font-weight: bolder; | |||
|         border-radius: 4px; | |||
|         border: 2px solid $white; | |||
|         background: $white-alpha; | |||
|         cursor: pointer; | |||
|         padding: 8px 50px 8px 15px; | |||
|         margin-bottom: 5px; | |||
| 
 | |||
|         &:before { | |||
|           content: '\e903'; | |||
|           position: absolute; | |||
|           top: 8px; | |||
|           right: 10px; | |||
|           font-family: $font-icon; | |||
|           font-size: $font-20; | |||
|           color: $gray; | |||
|         } | |||
|       } | |||
| 
 | |||
|       .preview-box { | |||
|         border-radius: 4px; | |||
|         background: $white-alpha2; | |||
|         padding: 10px; | |||
|         width: 100%; | |||
|       } | |||
|     } | |||
|   } | |||
| 
 | |||
|   .menu { | |||
|     background: $dark-gray; | |||
| 
 | |||
|     .section-title { | |||
|       display: block; | |||
|       width: 100%; | |||
|       padding: 50px 10px 10px; | |||
|       font-size: $font-22; | |||
|       font-weight: bolder; | |||
|       text-transform: uppercase; | |||
|       color: $white; | |||
|       text-align: center; | |||
|       border-bottom: 1px solid $black-alpha; | |||
|     } | |||
| 
 | |||
|     .action { | |||
|       display: block; | |||
|       appearance: none; | |||
|       border: none; | |||
|       border-radius: 0px; | |||
|       width: 100%; | |||
|       padding: 10px; | |||
|       font-size: $font-14; | |||
|       text-transform: uppercase; | |||
|       color: $white; | |||
|       background: $dark-gray; | |||
|       cursor: pointer; | |||
|       border-bottom: 1px solid $black-alpha; | |||
| 
 | |||
|       &.active { | |||
|         background: $yellow; | |||
|         color: $black; | |||
|         border: none; | |||
|       } | |||
|     } | |||
|   } | |||
| } | |||
| 
 | |||
| @media (min-width: map-get($grid-breakpoints, 'md')) { | |||
|   .component-admin { | |||
|     .menu { | |||
|       position: fixed; | |||
|       height: 100vh; | |||
|       width: 25%; | |||
|     } | |||
|   } | |||
| } | |||
| 
 | |||
| @media (min-width: map-get($grid-breakpoints, 'lg')) { | |||
|   .component-admin { | |||
|     .menu { | |||
|       width: 16.66%; | |||
|     } | |||
|   } | |||
| } | |||
| @ -1,20 +1,20 @@ | |||
| import { async, ComponentFixture, TestBed } from '@angular/core/testing'; | |||
| 
 | |||
| import { WorkshopsComponent } from './workshops.component'; | |||
| import { AdminComponent } from './admin.component'; | |||
| 
 | |||
| describe('WorkshopsComponent', () => { | |||
|   let component: WorkshopsComponent; | |||
|   let fixture: ComponentFixture<WorkshopsComponent>; | |||
| describe('AdminComponent', () => { | |||
|   let component: AdminComponent; | |||
|   let fixture: ComponentFixture<AdminComponent>; | |||
| 
 | |||
|   beforeEach(async(() => { | |||
|     TestBed.configureTestingModule({ | |||
|       declarations: [ WorkshopsComponent ] | |||
|       declarations: [ AdminComponent ] | |||
|     }) | |||
|     .compileComponents(); | |||
|   })); | |||
| 
 | |||
|   beforeEach(() => { | |||
|     fixture = TestBed.createComponent(WorkshopsComponent); | |||
|     fixture = TestBed.createComponent(AdminComponent); | |||
|     component = fixture.componentInstance; | |||
|     fixture.detectChanges(); | |||
|   }); | |||
| @ -0,0 +1,437 @@ | |||
| import { Component, OnInit } from '@angular/core' | |||
| import { ApisService } from '../services/apis.service' | |||
| import { AuthService } from '../services/auth.service' | |||
| import { AngularEditorConfig } from '@kolkov/angular-editor' | |||
| import { environment } from '../../environments/environment' | |||
| import { editorConfig } from '../../config/config' | |||
| 
 | |||
| @Component({ | |||
|   selector: 'app-admin', | |||
|   templateUrl: './admin.component.html', | |||
|   styleUrls: ['./admin.component.scss'] | |||
| }) | |||
| export class AdminComponent implements OnInit { | |||
| 
 | |||
|   private restApi = `${environment.API_URL}` | |||
|   public basePath = `${environment.BASE_PATH}` | |||
| 
 | |||
|   public authCheck: boolean = false | |||
|   public userName: string = '' | |||
|   public password: string = '' | |||
|   public activeEditor: string = '' | |||
|   public sectionTitle: string = '' | |||
|   public activeModify: boolean = false | |||
|   public modifyId: number = null | |||
| 
 | |||
|   public exhibitions: any = [] | |||
|   public works: any = [] | |||
|   public selectedExhibitions: any = [] | |||
|   public selectedWorks: any = [] | |||
|   public selectedVideos: any = [] | |||
|   public selectedGallery: any = [] | |||
| 
 | |||
|   // ngModels
 | |||
|   public title: string = '' | |||
|   public type: string = '' | |||
|   public content: string = '' | |||
|   public tags: string = '' | |||
|   public dateFrom: string = '' | |||
|   public dateTo: string = '' | |||
|   public mainImage: string = '' | |||
|   public videoType: string = '' | |||
|   public videoURL: string = '' | |||
| 
 | |||
|   public editorConfig: AngularEditorConfig = editorConfig | |||
|   public workSections: any = [ | |||
|     {title: 'Entertainment', section: 'entertainment'}, | |||
|     {title: 'Installations', section: 'installations'}, | |||
|     {title: 'Performances', section: 'performances'}, | |||
|     {title: 'Workshops', section: 'workshops'} | |||
|   ] | |||
| 
 | |||
|   constructor( | |||
|     private authService: AuthService, | |||
|     private apisService: ApisService | |||
|   ) { } | |||
| 
 | |||
|   ngOnInit(): void { | |||
| 
 | |||
|     const body = { token: window.sessionStorage.getItem('authToken') } | |||
|     this.authService.authCheck(body).toPromise().then((response) => { | |||
|       this.authCheck = response.status && response.status == 200 | |||
| 
 | |||
|       if(this.authCheck) { | |||
|         this.loadData() | |||
|       } | |||
| 
 | |||
|     },(error) => { | |||
|       this.authCheck = false | |||
|       console.error('Auth ERROR INIT', error) | |||
|     }).catch((e) => { | |||
|       this.authCheck = false | |||
|       console.error('Auth CATCH INIT', e) | |||
|     }) | |||
|   } | |||
| 
 | |||
|   login(): void { | |||
|     const body = { usr: this.userName, pwd: this.password } | |||
|     this.authService.login(body).toPromise().then((response) => { | |||
|       this.authCheck = response.status && response.status == 200 | |||
|       if(this.authCheck) { | |||
|         window.sessionStorage.setItem('authToken', response.authToken) | |||
|         this.loadData() | |||
|       } | |||
|     },(error) => { | |||
|       console.error('Auth ERROR', error) | |||
|     }).catch((e) => { | |||
|       console.error('Auth CATCH', e) | |||
|     }) | |||
|   } | |||
| 
 | |||
|   loadData(): void { | |||
|     this.apisService.getPortfolio('exhibitions').toPromise().then((response) => { | |||
|       this.exhibitions = response.items | |||
|     },(error) => { | |||
|       console.error('getPortfolio ERROR', error) | |||
|     }).catch((e) => { | |||
|       console.error('getPortfolio CATCH', e) | |||
|     }) | |||
| 
 | |||
|     this.apisService.getPortfolio('portfolio').toPromise().then((response) => { | |||
|       this.works = response.items | |||
|     },(error) => { | |||
|       console.error('getPortfolio ERROR', error) | |||
|     }).catch((e) => { | |||
|       console.error('getPortfolio CATCH', e) | |||
|     }) | |||
|   } | |||
| 
 | |||
|   showEditor(section): void { | |||
|     switch(section) { | |||
|       case 'works-add': | |||
|         this.sectionTitle = 'Add work' | |||
|         break; | |||
|       case 'works-modify': | |||
|         this.sectionTitle = 'Modify work' | |||
|         break; | |||
|       case 'works-delete': | |||
|         this.sectionTitle = 'Delete work' | |||
|         break; | |||
|       case 'exhibitions-add': | |||
|         this.sectionTitle = 'Add exhibition' | |||
|         break; | |||
|       case 'exhibitions-modify': | |||
|         this.sectionTitle = 'Modify exhibition' | |||
|         break; | |||
|       case 'exhibitions-delete': | |||
|         this.sectionTitle = 'Delete exhibition' | |||
|         break; | |||
|     } | |||
|     this.activeModify = false | |||
|     this.activeEditor = section | |||
|     this.modifyId = null | |||
|     this.resetFields() | |||
|   } | |||
| 
 | |||
|   exhibitionAdd(id): void { | |||
|     this.selectedExhibitions.push( | |||
|       this.exhibitions.filter(item => item.id == id)[0] | |||
|     ) | |||
|     this.exhibitions = this.exhibitions.filter(item => item.id != id) | |||
|   } | |||
| 
 | |||
|   exhibitionRemove(id): void { | |||
|     this.exhibitions.push( | |||
|       this.selectedExhibitions.filter(item => item.id == id)[0] | |||
|     ) | |||
|     this.selectedExhibitions = this.selectedExhibitions.filter(item => item.id != id) | |||
|   } | |||
| 
 | |||
|   workAdd(id): void { | |||
|     this.selectedWorks.push( | |||
|       this.works.filter(item => item.id == id)[0] | |||
|     ) | |||
|     this.works = this.works.filter(item => item.id != id) | |||
|   } | |||
| 
 | |||
|   workRemove(id): void { | |||
|     this.works.push( | |||
|       this.selectedWorks.filter(item => item.id == id)[0] | |||
|     ) | |||
|     this.selectedWorks = this.selectedWorks.filter(item => item.id != id) | |||
|   } | |||
| 
 | |||
|   videoAdd(): void { | |||
|     this.selectedVideos.push({ | |||
|       type: this.videoType, | |||
|       url: this.videoURL.replace(/\"/g, "\\\"") | |||
|     }) | |||
|     this.videoURL = '' | |||
|   } | |||
| 
 | |||
|   videoRemove(url): void { | |||
|     this.selectedVideos = this.selectedVideos.filter(item => item.url != url) | |||
|   } | |||
| 
 | |||
|   onFileChanged(e) { | |||
|     const file = (<HTMLInputElement>e.target).files[0] | |||
|     const uploadData = new FormData() | |||
|     uploadData.append('token', window.sessionStorage.getItem('authToken')) | |||
|     uploadData.append('path', 'assets') | |||
|     uploadData.append('file', file, file.name) | |||
|     this.apisService.uploadImage(uploadData).toPromise().then((response) => { | |||
|       this.selectedGallery.push({ | |||
|         title: response.title || '', | |||
|         url: response.imageUrl | |||
|       }) | |||
|     },(error) => { | |||
|       console.error(error) | |||
|     }).catch((e) => { | |||
|       console.error(e) | |||
|     }) | |||
|   } | |||
| 
 | |||
|   gallerySetMain(url): void { | |||
|     this.selectedGallery.forEach((e) => { | |||
|       if(e.url == url) { | |||
|         e.main = true | |||
|       } else { | |||
|         delete e.main | |||
|       } | |||
|     }) | |||
|   } | |||
| 
 | |||
|   galleryRemove(url): void { | |||
|     const body = { | |||
|       token: window.sessionStorage.getItem('authToken'), | |||
|       url: url | |||
|     } | |||
|     this.apisService.removeImage(body).toPromise().then((response) => { | |||
|       this.selectedGallery = this.selectedGallery.filter(item => item.url != url) | |||
|     },(error) => { | |||
|       console.error(error) | |||
|     }).catch((e) => { | |||
|       console.error(e) | |||
|     }) | |||
|   } | |||
| 
 | |||
|   selectWork(id): void { | |||
|     this.activeModify = true | |||
|     this.modifyId = id | |||
|     this.apisService.getDetails('works', id).toPromise().then((response) => { | |||
|       const detail = response.item | |||
|       this.apisService.getPortfolio('exhibitions').toPromise().then((response) => { | |||
|         this.exhibitions = response.items | |||
|         this.title = detail.title | |||
|         this.content = detail.content | |||
|         this.type = detail.type | |||
|         this.tags = detail.tags | |||
|         this.selectedExhibitions = detail.exhibitions.length ? | |||
|                                     this.exhibitions.filter(item => detail.exhibitions.map(a => a.id).indexOf(item.id) > -1) : [] | |||
|         this.selectedGallery = detail.gallery ? JSON.parse(detail.gallery) : [] | |||
|         this.selectedVideos = detail.videos ? JSON.parse(detail.videos) : [] | |||
| 
 | |||
|       },(error) => { | |||
|         console.error(error) | |||
|       }).catch((e) => { | |||
|         console.error(e) | |||
|       }) | |||
|     },(error) => { | |||
|       console.error(error) | |||
|     }).catch((e) => { | |||
|       console.error(e) | |||
|     }) | |||
|   } | |||
| 
 | |||
|   selectExhibition(id): void { | |||
| 
 | |||
|     this.activeModify = true | |||
|     this.modifyId = id | |||
|     this.apisService.getDetails('exhibitions', id).toPromise().then((response) => { | |||
|       const detail = response.item | |||
|       this.apisService.getPortfolio('portfolio').toPromise().then((response) => { | |||
|         this.works = response.items | |||
|         this.title = detail.title | |||
|         this.content = detail.content | |||
|         this.tags = detail.tags | |||
|         this.dateFrom = detail.date_from | |||
|         this.dateTo = detail.date_to | |||
|         this.selectedWorks = detail.works.length ? | |||
|                                     this.works.filter(item => detail.works.map(a => a.id).indexOf(item.id) > -1) : [] | |||
|         this.selectedGallery = detail.gallery ? JSON.parse(detail.gallery) : [] | |||
|         this.selectedVideos = detail.videos ? JSON.parse(detail.videos) : [] | |||
| 
 | |||
|       },(error) => { | |||
|         console.error(error) | |||
|       }).catch((e) => { | |||
|         console.error(e) | |||
|       }) | |||
|     },(error) => { | |||
|       console.error(error) | |||
|     }).catch((e) => { | |||
|       console.error(e) | |||
|     }) | |||
|   } | |||
| 
 | |||
|   saveData(): void { | |||
|     if(this.activeEditor == 'works-add' || this.activeEditor == 'works-modify') { | |||
|       this.saveWork() | |||
|     } | |||
|     if(this.activeEditor == 'exhibitions-add' || this.activeEditor == 'exhibitions-modify') { | |||
|       this.saveExhibition() | |||
|     } | |||
|   } | |||
| 
 | |||
|   saveWork(): void { | |||
|     let error = false | |||
|     let errorMessages = [] | |||
|     const mainImage = this.selectedGallery.filter(item => item.main) | |||
| 
 | |||
|     if(!this.title){ | |||
|       error = true | |||
|       errorMessages.push('No title') | |||
|     } | |||
|     if(!this.type){ | |||
|       error = true | |||
|       errorMessages.push('No type selected') | |||
|     } | |||
| 
 | |||
|     if(this.selectedGallery.length == 0 || mainImage.length == 0){ | |||
|       error = true | |||
|       errorMessages.push('No main image selected') | |||
|     } | |||
| 
 | |||
|     if(error) { | |||
|       console.log('ERRORS:',errorMessages) | |||
|     } else { | |||
|       const body = { | |||
|         id: this.activeModify ? this.modifyId : null, | |||
|         token: window.sessionStorage.getItem('authToken'), | |||
|         title: this.title, | |||
|         content: this.content, | |||
|         type: this.type, | |||
|         tags: this.tags, | |||
|         image: mainImage[0].url, | |||
|         exhibitions: this.selectedExhibitions.map(a => a.id).join(','), | |||
|         gallery: JSON.stringify(this.selectedGallery), | |||
|         videos: JSON.stringify(this.selectedVideos) | |||
|       } | |||
| 
 | |||
|       this.apisService.saveWork(body).toPromise().then((response) => { | |||
|         this.resetFields() | |||
|         this.works = response.items | |||
|       },(error) => { | |||
|         console.error(error) | |||
|       }).catch((e) => { | |||
|         console.error(e) | |||
|       }) | |||
|     } | |||
|   } | |||
| 
 | |||
|   saveExhibition(): void { | |||
|     let error = false | |||
|     let errorMessages = [] | |||
|     const mainImage = this.selectedGallery.filter(item => item.main) | |||
| 
 | |||
|     if(!this.title){ | |||
|       error = true | |||
|       errorMessages.push('No title') | |||
|     } | |||
|     if(!this.dateFrom){ | |||
|       error = true | |||
|       errorMessages.push('No date from selected') | |||
|     } | |||
|     if(!this.dateTo){ | |||
|       error = true | |||
|       errorMessages.push('No date to selected') | |||
|     } | |||
|     if(this.selectedGallery.length == 0 || mainImage.length == 0){ | |||
|       error = true | |||
|       errorMessages.push('No main image selected') | |||
|     } | |||
| 
 | |||
|     if(error) { | |||
|       console.log('ERRORS:',errorMessages) | |||
|     } else { | |||
|       const body = { | |||
|         id: this.activeModify ? this.modifyId : null, | |||
|         token: window.sessionStorage.getItem('authToken'), | |||
|         title: this.title, | |||
|         content: this.content, | |||
|         date_from: this.dateFrom, | |||
|         date_to: this.dateTo, | |||
|         tags: this.tags, | |||
|         image: mainImage[0].url, | |||
|         works: this.selectedWorks.map(a => a.id).join(','), | |||
|         gallery: JSON.stringify(this.selectedGallery), | |||
|         videos: JSON.stringify(this.selectedVideos) | |||
|       } | |||
| 
 | |||
|       this.apisService.saveExhibition(body).toPromise().then((response) => { | |||
|         this.resetFields() | |||
|         this.exhibitions = response.items | |||
|       },(error) => { | |||
|         console.error(error) | |||
|       }).catch((e) => { | |||
|         console.error(e) | |||
|       }) | |||
|     } | |||
|   } | |||
| 
 | |||
|   deleteData(id): void { | |||
|     if(this.activeEditor == 'works-delete') { | |||
|       this.deleteWork(id) | |||
|     } | |||
|     if(this.activeEditor == 'exhibitions-delete') { | |||
|       this.deleteExhibition(id) | |||
|     } | |||
|   } | |||
| 
 | |||
|   deleteWork(id): void { | |||
| 
 | |||
|     const body = { | |||
|       id: id, | |||
|       token: window.sessionStorage.getItem('authToken') | |||
|     } | |||
| 
 | |||
|     this.apisService.deleteWork(body).toPromise().then((response) => { | |||
|       this.resetFields() | |||
|       this.works = response.items | |||
|     },(error) => { | |||
|       console.error(error) | |||
|     }).catch((e) => { | |||
|       console.error(e) | |||
|     }) | |||
|   } | |||
| 
 | |||
|   deleteExhibition(id): void { | |||
| 
 | |||
|     const body = { | |||
|       id: id, | |||
|       token: window.sessionStorage.getItem('authToken') | |||
|     } | |||
| 
 | |||
|     this.apisService.deleteExhibition(body).toPromise().then((response) => { | |||
|       this.resetFields() | |||
|       this.exhibitions = response.items | |||
|     },(error) => { | |||
|       console.error(error) | |||
|     }).catch((e) => { | |||
|       console.error(e) | |||
|     }) | |||
|   } | |||
| 
 | |||
|   resetFields(): void { | |||
|     this.title = '' | |||
|     this.content = '' | |||
|     this.type = '' | |||
|     this.tags = '' | |||
|     this.dateFrom = '' | |||
|     this.dateTo = '' | |||
|     this.selectedExhibitions = [] | |||
|     this.selectedWorks = [] | |||
|     this.selectedGallery = [] | |||
|     this.selectedVideos = [] | |||
|     this.modifyId = null | |||
|   } | |||
| } | |||
| @ -1,4 +1,5 @@ | |||
| <app-header></app-header> | |||
| <app-header *ngIf="page != '/admin'"></app-header> | |||
| <router-outlet></router-outlet> | |||
| 
 | |||
| <Particles class="particles" [id]="id" [options]="particlesOptions" (particlesLoaded)="particlesLoaded($event)" *ngIf="particlesEnabled"></Particles> | |||
| <Particles class="particles" *ngIf="particlesEnabled && page != '/admin'" | |||
|           [id]="id" [options]="particlesOptions" (particlesLoaded)="particlesLoaded($event)"></Particles> | |||
|  | |||
| @ -0,0 +1,16 @@ | |||
| import { TestBed } from '@angular/core/testing'; | |||
| 
 | |||
| import { AuthService } from './auth.service'; | |||
| 
 | |||
| describe('AuthService', () => { | |||
|   let service: AuthService; | |||
| 
 | |||
|   beforeEach(() => { | |||
|     TestBed.configureTestingModule({}); | |||
|     service = TestBed.inject(AuthService); | |||
|   }); | |||
| 
 | |||
|   it('should be created', () => { | |||
|     expect(service).toBeTruthy(); | |||
|   }); | |||
| }); | |||
| @ -0,0 +1,33 @@ | |||
| import { Injectable } from '@angular/core' | |||
| import { HttpClient, HttpHeaders, HttpParams, HttpRequest } from '@angular/common/http' | |||
| import { Observable, Subject, throwError } from 'rxjs' | |||
| import { catchError } from 'rxjs/operators' | |||
| import { BaseService } from './base-service' | |||
| import { environment } from '../../environments/environment' | |||
| 
 | |||
| @Injectable({ | |||
|   providedIn: 'root' | |||
| }) | |||
| export class AuthService extends BaseService { | |||
| 
 | |||
|   private restApi = `${environment.API_URL}` | |||
| 
 | |||
|   constructor(private http: HttpClient) { | |||
|     super() | |||
|   } | |||
| 
 | |||
|   login(body): Observable<any> { | |||
|     let urlApi = `${this.restApi}auth.php?act=login` | |||
|     return this.http.post<any>(urlApi, JSON.stringify(body)).pipe( | |||
|       catchError(this.handleError) | |||
|     ) | |||
|   } | |||
| 
 | |||
|   authCheck(body): Observable<any> { | |||
|     let urlApi = `${this.restApi}auth.php?act=check` | |||
|     return this.http.post<any>(urlApi, JSON.stringify(body)).pipe( | |||
|       catchError(this.handleError) | |||
|     ) | |||
|   } | |||
| 
 | |||
| } | |||
| @ -1 +0,0 @@ | |||
| <p>workshops works!</p> | |||
| @ -1,15 +0,0 @@ | |||
| import { Component, OnInit } from '@angular/core'; | |||
| 
 | |||
| @Component({ | |||
|   selector: 'app-workshops', | |||
|   templateUrl: './workshops.component.html', | |||
|   styleUrls: ['./workshops.component.scss'] | |||
| }) | |||
| export class WorkshopsComponent implements OnInit { | |||
| 
 | |||
|   constructor() { } | |||
| 
 | |||
|   ngOnInit(): void { | |||
|   } | |||
| 
 | |||
| } | |||
								
									Binary file not shown.
								
							
						
					| Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 28 KiB | 
								
									Binary file not shown.
								
							
						
					
								
									Binary file not shown.
								
							
						
					
								
									
										File diff suppressed because one or more lines are too long
									
								
							
						
					| After Width: | Height: | Size: 432 B | 
| After Width: | Height: | Size: 79 KiB | 
| @ -0,0 +1,90 @@ | |||
| 
 | |||
| 
 | |||
| input, | |||
| select, | |||
| button, | |||
| textarea { | |||
|   border: none; | |||
|   border-radius: 4px; | |||
|   background: $white; | |||
|   appearance: none; | |||
|   font-family: $font-primary; | |||
|   font-size: $font-20; | |||
|   resize: none; | |||
|   &::-ms-clear { | |||
|       display: none; | |||
|   } | |||
|   &:focus {outline:none;} | |||
|   &::-moz-focus-inner {border:0;} | |||
| } | |||
| 
 | |||
| input[type=text], | |||
| input[type=password], | |||
| input[type=file], | |||
| select { | |||
|   color: $black; | |||
|   padding: 10px 20px; | |||
|   width: 100%; | |||
|   text-align: left; | |||
|   box-sizing: border-box; | |||
|   &:focus::placeholder { | |||
|     color: transparent; | |||
|   } | |||
| } | |||
| 
 | |||
| .input-text { | |||
|   padding: 10px 20px !important; | |||
| } | |||
| 
 | |||
| .input-file { | |||
|   padding: 6px 20px !important; | |||
| } | |||
| 
 | |||
| .input-textarea, | |||
| .angular-editor { | |||
|   border-radius: 4px; | |||
|   background: $white; | |||
|   padding: 10px; | |||
|   width: 100%; | |||
| } | |||
| 
 | |||
| .input-select { | |||
|   padding: 9px 20px !important; | |||
|   background-image: url('/assets/images/angle-down.svg'); | |||
|   background-size: 28px; | |||
|   background-position: right 10px top 10px; | |||
|   background-repeat: no-repeat; | |||
| } | |||
| 
 | |||
| .button { | |||
|   position: relative; | |||
|   appearance: none; | |||
|   color: $white; | |||
|   border: none; | |||
|   border-radius: 4px; | |||
|   background: $black; | |||
|   display: inline-block; | |||
|   padding: 10px 20px 10px 20px !important; | |||
|   text-align: center; | |||
|   font-family: $font-20; | |||
|   text-transform: uppercase; | |||
|   font-weight: 500; | |||
|   transition: opacity .3s; | |||
|   white-space: nowrap; | |||
|   outline: none; | |||
|   cursor: pointer; | |||
| 
 | |||
|   &:disabled { | |||
|     opacity: 0.5; | |||
|   } | |||
| 
 | |||
|   &.button-white { | |||
|     background: $white; | |||
|     color: $black !important; | |||
|   } | |||
| 
 | |||
|   &.button-transparent { | |||
|     background: $white-alpha2; | |||
|     color: $black !important; | |||
|   } | |||
| } | |||
| @ -0,0 +1,52 @@ | |||
| import { environment } from '../environments/environment' | |||
| import { AngularEditorConfig } from '@kolkov/angular-editor' | |||
| 
 | |||
| export const editorConfig: AngularEditorConfig = { | |||
|   editable: true, | |||
|   spellcheck: true, | |||
|   height: '300px', | |||
|   translate: 'no', | |||
|   enableToolbar: true, | |||
|   showToolbar: true, | |||
|   placeholder: 'Enter text here...', | |||
|   defaultParagraphSeparator: 'p', | |||
|   defaultFontName: '', | |||
|   defaultFontSize: '', | |||
|   uploadUrl: `${environment.API_URL}upload.php`, | |||
|   uploadWithCredentials: false, | |||
|   sanitize: true, | |||
|   toolbarPosition: 'top', | |||
|   toolbarHiddenButtons: [ | |||
|     [ | |||
|       'undo', | |||
|       'redo', | |||
|       //'bold',
 | |||
|       //'italic',
 | |||
|       //'underline',
 | |||
|       'strikeThrough', | |||
|       'subscript', | |||
|       'superscript', | |||
|       //'justifyLeft',
 | |||
|       //'justifyCenter',
 | |||
|       //'justifyRight',
 | |||
|       //'justifyFull',
 | |||
|       'indent', | |||
|       'outdent', | |||
|       'insertUnorderedList', | |||
|       'insertOrderedList', | |||
|       'heading', | |||
|       'fontName', | |||
|       'fontSize', | |||
|       'textColor', | |||
|       'backgroundColor', | |||
|       'customClasses', | |||
|       //'link',
 | |||
|       'unlink', | |||
|       //'insertImage',
 | |||
|       'insertVideo', | |||
|       'insertHorizontalRule', | |||
|       //'removeFormat',
 | |||
|       //'toggleEditorMode'
 | |||
|     ] | |||
|   ] | |||
| } | |||
| @ -1,5 +1,5 @@ | |||
| export const environment = { | |||
|   production: true, | |||
| 
 | |||
|   API_URL: `https://apis.dslak.it/` | |||
|   API_URL: `https://www.dslak.it/apis/`, | |||
|   BASE_PATH: `https://www.dslak.it` | |||
| } | |||
|  | |||
| @ -1,5 +1,5 @@ | |||
| export const environment = { | |||
|   production: false, | |||
| 
 | |||
|   API_URL: `http://dslakng.local/apis/` | |||
|   API_URL: `http://dslakng.local/apis/`, | |||
|   BASE_PATH: `http://dslakng.local` | |||
| } | |||
|  | |||
					Loading…
					
					
				
		Reference in new issue