initial commit
This commit is contained in:
Generated
+9
-9
@@ -4150,9 +4150,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001144",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001144.tgz",
|
||||
"integrity": "sha512-4GQTEWNMnVZVOFG3BK0xvGeaDAtiPAbG2N8yuMXuXzx/c2Vd4XoMPO8+E918zeXn5IF0FRVtGShBfkfQea2wHQ==",
|
||||
"version": "1.0.30001146",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001146.tgz",
|
||||
"integrity": "sha512-VAy5RHDfTJhpxnDdp2n40GPPLp3KqNrXz1QqFv4J64HvArKs8nuNMOWkB3ICOaBTU/Aj4rYAo/ytdQDDFF/Pug==",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
@@ -4953,9 +4953,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.3.577",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.577.tgz",
|
||||
"integrity": "sha512-dSb64JQSFif/pD8mpVAgSFkbVi6YHbK6JeEziwNNmXlr/Ne2rZtseFK5SM7JoWSLf6gP0gVvRGi4/2ZRhSX/rA==",
|
||||
"version": "1.3.578",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.578.tgz",
|
||||
"integrity": "sha512-z4gU6dA1CbBJsAErW5swTGAaU2TBzc2mPAonJb00zqW1rOraDo2zfBMDRvaz9cVic+0JEZiYbHWPw/fTaZlG2Q==",
|
||||
"dev": true
|
||||
},
|
||||
"elliptic": {
|
||||
@@ -8669,9 +8669,9 @@
|
||||
"optional": true
|
||||
},
|
||||
"tslib": {
|
||||
"version": "1.13.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
|
||||
"integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==",
|
||||
"version": "1.14.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.0.tgz",
|
||||
"integrity": "sha512-+Zw5lu0D9tvBMjGP8LpvMb0u2WW2QV3y+D8mO6J+cNzCYIN4sVy43Bf9vl92nqFahutN0I8zHa7cc4vihIshnw==",
|
||||
"dev": true
|
||||
},
|
||||
"tty-browserify": {
|
||||
|
||||
+6
-28
@@ -1,28 +1,6 @@
|
||||
package at.windesign.application.data.entity;
|
||||
|
||||
/*
|
||||
$sql = " SELECT serie.seriesID seriesID," .
|
||||
" serie.seriesName seriesName," .
|
||||
" YEAR(serie.firstAired) seriesFirstAired," .
|
||||
" serie.resolution seriesResolution," .
|
||||
" serie.cliffhanger seriesCliffhanger," .
|
||||
" serie.status seriesStatus," .
|
||||
" serie.download seriesDownload," .
|
||||
" season.seasonNumber seasonNumber," .
|
||||
" episode.episodeNumber episodeNumber," .
|
||||
" episode.state episodeState" .
|
||||
" FROM serie" .
|
||||
" LEFT JOIN season ON serie.seriesID = season.seriesID" .
|
||||
" LEFT JOIN episode ON serie.seriesID = episode.seriesID AND season.seasonNumber = episode.seasonNumber" .
|
||||
" WHERE season.seasonNumber != 0 OR" .
|
||||
" serie.seriesID >= 1000000 " .
|
||||
" ORDER BY serie.seriesName," .
|
||||
" serie.firstAired," .
|
||||
" season.seasonNumber," .
|
||||
" episode.episodeNumber;";
|
||||
|
||||
*/
|
||||
public class Series
|
||||
public class Episode
|
||||
{
|
||||
private int seriesID;
|
||||
private String seriesName;
|
||||
@@ -33,9 +11,9 @@ public class Series
|
||||
private String seriesDownload;
|
||||
private int seasonNumber;
|
||||
private int episodeNumber;
|
||||
private String episodeState;
|
||||
private Integer episodeState;
|
||||
|
||||
public Series(int seriesID, String seriesName, int seriesFirstAired, String seriesResolution, boolean seriesCliffhanger, String seriesStatus, String seriesDownload, int seasonNumber, int episodeNumber, String episodeState)
|
||||
public Episode(int seriesID, String seriesName, int seriesFirstAired, String seriesResolution, boolean seriesCliffhanger, String seriesStatus, String seriesDownload, int seasonNumber, int episodeNumber, Integer episodeState)
|
||||
{
|
||||
super();
|
||||
this.seriesID = seriesID;
|
||||
@@ -50,7 +28,7 @@ public class Series
|
||||
this.episodeState = episodeState;
|
||||
}
|
||||
|
||||
public Series()
|
||||
public Episode()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -144,12 +122,12 @@ public class Series
|
||||
this.episodeNumber = episodeNumber;
|
||||
}
|
||||
|
||||
public String getEpisodeState()
|
||||
public Integer getEpisodeState()
|
||||
{
|
||||
return episodeState;
|
||||
}
|
||||
|
||||
public void setEpisodeState(String episodeState)
|
||||
public void setEpisodeState(Integer episodeState)
|
||||
{
|
||||
this.episodeState = episodeState;
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package at.windesign.application.data.entity;
|
||||
|
||||
import com.vaadin.flow.server.StreamResource;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
import java.util.SortedMap;
|
||||
|
||||
public class Serie
|
||||
{
|
||||
private int seriesID;
|
||||
private String seriesName;
|
||||
private int seriesFirstAired;
|
||||
private String seriesResolution;
|
||||
private boolean seriesCliffhanger;
|
||||
private String seriesStatus;
|
||||
private String seriesDownload;
|
||||
SortedMap<Integer, Integer> episodeState;
|
||||
|
||||
public Serie(int seriesID, String seriesName, int seriesFirstAired, String seriesResolution, boolean seriesCliffhanger, String seriesStatus, String seriesDownload, SortedMap<Integer, Integer> episodeState)
|
||||
{
|
||||
super();
|
||||
this.seriesID = seriesID;
|
||||
this.seriesName = seriesName;
|
||||
this.seriesFirstAired = seriesFirstAired;
|
||||
this.seriesResolution = seriesResolution;
|
||||
this.seriesCliffhanger = seriesCliffhanger;
|
||||
this.seriesStatus = seriesStatus;
|
||||
this.seriesDownload = seriesDownload;
|
||||
this.episodeState = episodeState;
|
||||
}
|
||||
|
||||
public Serie()
|
||||
{
|
||||
}
|
||||
|
||||
public int getSeriesID()
|
||||
{
|
||||
return seriesID;
|
||||
}
|
||||
|
||||
public void setSeriesID(int seriesID)
|
||||
{
|
||||
this.seriesID = seriesID;
|
||||
}
|
||||
|
||||
public String getSeriesName()
|
||||
{
|
||||
return seriesName;
|
||||
}
|
||||
|
||||
public void setSeriesName(String seriesName)
|
||||
{
|
||||
this.seriesName = seriesName;
|
||||
}
|
||||
|
||||
public int getSeriesFirstAired()
|
||||
{
|
||||
return seriesFirstAired;
|
||||
}
|
||||
|
||||
public void setSeriesFirstAired(int seriesFirstAired)
|
||||
{
|
||||
this.seriesFirstAired = seriesFirstAired;
|
||||
}
|
||||
|
||||
public String getSeriesResolution()
|
||||
{
|
||||
return seriesResolution;
|
||||
}
|
||||
|
||||
public void setSeriesResolution(String seriesResolution)
|
||||
{
|
||||
this.seriesResolution = seriesResolution;
|
||||
}
|
||||
|
||||
public boolean getSeriesCliffhanger()
|
||||
{
|
||||
return seriesCliffhanger;
|
||||
}
|
||||
|
||||
public void setSeriesCliffhanger(boolean seriesCliffhanger)
|
||||
{
|
||||
this.seriesCliffhanger = seriesCliffhanger;
|
||||
}
|
||||
|
||||
public String getSeriesStatus()
|
||||
{
|
||||
return seriesStatus;
|
||||
}
|
||||
|
||||
public void setSeriesStatus(String seriesStatus)
|
||||
{
|
||||
this.seriesStatus = seriesStatus;
|
||||
}
|
||||
|
||||
public String getSeriesDownload()
|
||||
{
|
||||
return seriesDownload;
|
||||
}
|
||||
|
||||
public void setSeriesDownload(String seriesDownload)
|
||||
{
|
||||
this.seriesDownload = seriesDownload;
|
||||
}
|
||||
|
||||
public SortedMap<Integer, Integer> getEpisodeState()
|
||||
{
|
||||
return episodeState;
|
||||
}
|
||||
|
||||
public void setEpisodeState(SortedMap<Integer, Integer> episodeState)
|
||||
{
|
||||
this.episodeState = episodeState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.valueOf(seriesID);
|
||||
}
|
||||
}
|
||||
+9
-9
@@ -1,6 +1,6 @@
|
||||
package at.windesign.application.data.service;
|
||||
|
||||
import at.windesign.application.data.entity.Series;
|
||||
import at.windesign.application.data.entity.Episode;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -9,12 +9,12 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class SerieService
|
||||
public class EpisodeService
|
||||
{
|
||||
@Autowired
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
public List<Series> findAll()
|
||||
public List<Episode> findAll()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -37,30 +37,30 @@ public class SerieService
|
||||
" serie.firstAired," +
|
||||
" season.seasonNumber," +
|
||||
" episode.episodeNumber;",
|
||||
(rs, rowNum) -> new Series(rs.getInt("seriesID"), rs.getString("seriesName"), rs.getInt("seriesFirstAired"), rs.getString("seriesResolution"), rs.getBoolean("seriesCliffhanger"), rs.getString("seriesStatus"), rs.getString("seriesDownload"), rs.getInt("seasonNumber"), rs.getInt("episodeNumber"), rs.getString("episodeState")));
|
||||
(rs, rowNum) -> new Episode(rs.getInt("seriesID"), rs.getString("seriesName"), rs.getInt("seriesFirstAired"), rs.getString("seriesResolution"), rs.getBoolean("seriesCliffhanger"), rs.getString("seriesStatus"), rs.getString("seriesDownload"), rs.getInt("seasonNumber"), rs.getInt("episodeNumber"), rs.getInt("episodeState")));
|
||||
|
||||
} catch(Exception e)
|
||||
{
|
||||
return new ArrayList<Series>();
|
||||
return new ArrayList<Episode>();
|
||||
}
|
||||
}
|
||||
|
||||
public int saveSerie(Series Series)
|
||||
public int saveEpisode(Episode Episode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int updateSerie(Series Series)
|
||||
private int updateEpisode(Episode Episode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int insertSerie(Series Series)
|
||||
private int insertEpisode(Episode Episode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int deleteSerie(Series Series)
|
||||
public int deleteEpisode(Episode Episode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -1,21 +1,31 @@
|
||||
package at.windesign.application.views.Series;
|
||||
|
||||
import at.windesign.application.data.entity.Series;
|
||||
import at.windesign.application.data.service.SerieService;
|
||||
import at.windesign.application.data.entity.Episode;
|
||||
import at.windesign.application.data.entity.Serie;
|
||||
import at.windesign.application.data.service.EpisodeService;
|
||||
import at.windesign.application.views.main.MainView;
|
||||
import com.vaadin.flow.component.dependency.CssImport;
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
import com.vaadin.flow.component.grid.GridVariant;
|
||||
import com.vaadin.flow.component.html.Div;
|
||||
import com.vaadin.flow.component.html.Image;
|
||||
import com.vaadin.flow.component.notification.Notification;
|
||||
import com.vaadin.flow.component.textfield.TextField;
|
||||
import com.vaadin.flow.router.AfterNavigationEvent;
|
||||
import com.vaadin.flow.router.AfterNavigationObserver;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.server.StreamResource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
@Route(value = "series", layout = MainView.class)
|
||||
@@ -24,61 +34,120 @@ import java.util.List;
|
||||
public class SeriesView extends Div implements AfterNavigationObserver
|
||||
{
|
||||
@Autowired
|
||||
private SerieService serieService;
|
||||
private EpisodeService episodeService;
|
||||
|
||||
private Grid<Series> series;
|
||||
private Grid<Serie> serie;
|
||||
|
||||
private TextField seriesName = new TextField();
|
||||
private TextField seriesFirstAired = new TextField();
|
||||
|
||||
ByteArrayOutputStream imagebuffer = null;
|
||||
StreamResource resource;
|
||||
|
||||
public SeriesView()
|
||||
{
|
||||
resource = new StreamResource("image.png", () -> getImageInputStream());
|
||||
|
||||
setId("series-view");
|
||||
|
||||
series = new Grid<>();
|
||||
series.addThemeVariants(GridVariant.LUMO_NO_BORDER);
|
||||
series.setHeightFull();
|
||||
series.addColumn(Series::getSeriesName).setHeader("Series Name");
|
||||
series.addColumn(Series::getSeriesFirstAired).setHeader("First Aired");
|
||||
series.addColumn(Series::getSeriesResolution).setHeader("Resolution");
|
||||
series.addColumn(Series::getSeriesCliffhanger).setHeader("Cliffhanger");
|
||||
serie = new Grid<>();
|
||||
serie.addThemeVariants(GridVariant.LUMO_NO_BORDER);
|
||||
serie.setHeightFull();
|
||||
serie.addColumn(Serie::getSeriesName).setHeader("Series Name");
|
||||
serie.addColumn(Serie::getSeriesFirstAired).setHeader("First Aired");
|
||||
serie.addColumn(Serie::getSeriesResolution).setHeader("Resolution");
|
||||
serie.addColumn(Serie::getSeriesCliffhanger).setHeader("Cliffhanger");
|
||||
serie.addComponentColumn(i -> new Image(resource, "alt text")).setHeader("Preview");
|
||||
// serie.addComponentColumn(i -> new Image(new StreamResource("image.png", () -> getImageInputStream(Serie::getEpisodeState)), "alt text")).setHeader("Preview");
|
||||
|
||||
|
||||
//when a row is selected or deselected, populate form
|
||||
series.asSingleSelect().addValueChangeListener(event -> populateForm(event.getValue()));
|
||||
serie.asSingleSelect().addValueChangeListener(event -> populateForm(event.getValue()));
|
||||
|
||||
series.addItemDoubleClickListener(
|
||||
serie.addItemDoubleClickListener(
|
||||
event ->
|
||||
{
|
||||
Notification.show("Clicked Item: " + event.getItem());
|
||||
});
|
||||
|
||||
add(series);
|
||||
add(serie);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterNavigation(AfterNavigationEvent event)
|
||||
{
|
||||
List<Series> seriesList = serieService.findAll();
|
||||
List<Series> seriesList1 = new ArrayList<Series>();
|
||||
List<Episode> episodeList = episodeService.findAll();
|
||||
List<Serie> serieList = new ArrayList<>();
|
||||
Episode lastEpisode = null;
|
||||
SortedMap<Integer, Integer> episodeState = new TreeMap<>();
|
||||
int oldID = -1;
|
||||
|
||||
int oldID = -1;
|
||||
|
||||
for(Series s : seriesList)
|
||||
for(Episode e : episodeList)
|
||||
{
|
||||
if(s.getSeriesID() != oldID)
|
||||
if(e.getSeriesID() != oldID)
|
||||
{
|
||||
oldID = s.getSeriesID();
|
||||
seriesList1.add(s);
|
||||
if(oldID != -1)
|
||||
{
|
||||
serieList.add(new Serie(lastEpisode.getSeriesID(), lastEpisode.getSeriesName(), lastEpisode.getSeriesFirstAired(), lastEpisode.getSeriesResolution(), lastEpisode.getSeriesCliffhanger(), lastEpisode.getSeriesStatus(), lastEpisode.getSeriesDownload(), episodeState));
|
||||
episodeState.clear();
|
||||
}
|
||||
|
||||
lastEpisode = e;
|
||||
oldID = e.getSeriesID();
|
||||
}
|
||||
};
|
||||
series.setItems(seriesList1);
|
||||
episodeState.put(e.getSeasonNumber() << 8 + e.getEpisodeNumber(), e.getEpisodeState());
|
||||
}
|
||||
if(oldID != -1)
|
||||
serieList.add(new Serie(lastEpisode.getSeriesID(), lastEpisode.getSeriesName(), lastEpisode.getSeriesFirstAired(), lastEpisode.getSeriesResolution(), lastEpisode.getSeriesCliffhanger(), lastEpisode.getSeriesStatus(), lastEpisode.getSeriesDownload(), episodeState));
|
||||
|
||||
serie.setItems(serieList);
|
||||
}
|
||||
|
||||
private void populateForm(Series value)
|
||||
private void populateForm(Serie value)
|
||||
{
|
||||
if(value == null)
|
||||
{
|
||||
value = new Series();
|
||||
value = new Serie();
|
||||
}
|
||||
}
|
||||
|
||||
// private InputStream getImageInputStream(SortedMap<Integer, Integer> state)
|
||||
private InputStream getImageInputStream()
|
||||
{
|
||||
// int reloads = state.firstKey();
|
||||
int reloads = 1;
|
||||
BufferedImage image = new BufferedImage(400, 400, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D drawable = image.createGraphics();
|
||||
|
||||
// Draw something static
|
||||
drawable.setStroke(new BasicStroke(5));
|
||||
drawable.setColor(Color.WHITE);
|
||||
drawable.fillRect(0, 0, 400, 400);
|
||||
drawable.setColor(Color.BLACK);
|
||||
drawable.drawOval(50, 50, 300, 300);
|
||||
|
||||
// Draw something dynamic
|
||||
drawable.setFont(new Font("Montserrat",
|
||||
Font.PLAIN, 48));
|
||||
drawable.drawString("Reloads=" + reloads, 75, 216);
|
||||
reloads++;
|
||||
drawable.setColor(new Color(0, 165, 235));
|
||||
int x = (int) (200 - 10 + 150 * Math.sin(reloads * 0.3));
|
||||
int y = (int) (200 - 10 + 150 * Math.cos(reloads * 0.3));
|
||||
drawable.fillOval(x, y, 20, 20);
|
||||
|
||||
try
|
||||
{
|
||||
// Write the image to a buffer
|
||||
imagebuffer = new ByteArrayOutputStream();
|
||||
ImageIO.write(image, "png", imagebuffer);
|
||||
|
||||
// Return a stream from the buffer
|
||||
return new ByteArrayInputStream(
|
||||
imagebuffer.toByteArray());
|
||||
} catch(IOException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
package at.windesign.application.views.main;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Optional;
|
||||
|
||||
import at.windesign.application.views.Series.SeriesView;
|
||||
@@ -21,6 +27,9 @@ import com.vaadin.flow.component.tabs.TabsVariant;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.RouterLink;
|
||||
import com.vaadin.flow.server.PWA;
|
||||
import com.vaadin.flow.server.StreamResource;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
/**
|
||||
* The main view is a top-level placeholder for other views.
|
||||
@@ -68,7 +77,9 @@ public class MainView extends AppLayout
|
||||
HorizontalLayout logoLayout = new HorizontalLayout();
|
||||
logoLayout.setId("logo");
|
||||
logoLayout.setAlignItems(FlexComponent.Alignment.CENTER);
|
||||
|
||||
logoLayout.add(new Image("images/logo.png", "multimedia logo"));
|
||||
|
||||
logoLayout.add(new H1("multimedia"));
|
||||
layout.add(logoLayout, menu);
|
||||
return layout;
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
@@ -1,6 +1,6 @@
|
||||
_ _ _ _ _
|
||||
__| | __ _ | |_ __ _ | |__ __ _ ___ ___ _ __ ___ _ _ ___ __ _ | | ___ __ __ __ _ _ __ ___ _ __ | | ___
|
||||
/ _` | / _` || __| / _` || '_ \ / _` |/ __| / _ \ _____ | '_ ` _ \ | | | |/ __| / _` || | _____ / _ \\ \/ / / _` || '_ ` _ \ | '_ \ | | / _ \
|
||||
| (_| || (_| || |_ | (_| || |_) || (_| |\__ \| __/|_____|| | | | | || |_| |\__ \| (_| || ||_____|| __/ > < | (_| || | | | | || |_) || || __/
|
||||
\__,_| \__,_| \__| \__,_||_.__/ \__,_||___/ \___| |_| |_| |_| \__, ||___/ \__, ||_| \___|/_/\_\ \__,_||_| |_| |_|| .__/ |_| \___|
|
||||
|___/ |_| |_|
|
||||
_ _ _ _ _
|
||||
_ __ ___ _ _ | || |_ (_) _ __ ___ ___ __| |(_) __ _
|
||||
| '_ ` _ \ | | | || || __|| || '_ ` _ \ / _ \ / _` || | / _` |
|
||||
| | | | | || |_| || || |_ | || | | | | || __/| (_| || || (_| |
|
||||
|_| |_| |_| \__,_||_| \__||_||_| |_| |_| \___| \__,_||_| \__,_|
|
||||
|
||||
|
||||
Reference in New Issue
Block a user