Audio and Video nodes for Tiptap based editor working

pull/10/head
Jens Pelzetter 2021-10-19 20:03:34 +02:00
parent 6c18304cd2
commit 773259f89e
12 changed files with 539 additions and 24 deletions

View File

@ -68,7 +68,6 @@ import static org.librecms.CmsConstants.*;
+ "FROM BinaryAsset a "
+ "LEFT JOIN a.permissions p "
+ "WHERE a.objectId = :assetId "
+ "LEFT JOIN a.permissions p "
+ "AND ("
+ " ("
+ " p.grantee IN :roles "

View File

@ -337,7 +337,8 @@ public class Assets {
final ProvidesPropertiesForAssetTypeLiteral literal
= new ProvidesPropertiesForAssetTypeLiteral(
asset.getClass());
asset.getClass()
);
final Instance<AssetPropertiesProvider> instance
= assetPropertiesProviders

View File

@ -0,0 +1,155 @@
/*
* Copyright (C) 2021 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.librecms.contentsection.rs;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.librecms.assets.BinaryAssetDataService;
import org.librecms.assets.AudioAsset;
import org.librecms.contentsection.Asset;
import org.librecms.contentsection.AssetRepository;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentSectionRepository;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Optional;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
@Path("/{content-section}/audiomedia")
public class AudioMedia {
private static final Logger LOGGER = LogManager.getLogger(Images.class);
@Inject
private ContentSectionRepository sectionRepo;
@Inject
private AssetRepository assetRepo;
@Inject
private BinaryAssetDataService dataService;
@GET
@Path("/uuid-{uuid}")
public Response getAudioByUuid(
@PathParam("content-section") final String sectionName,
@PathParam("uuid") final String uuid
) {
final Optional<AudioAsset> video = assetRepo
.findByUuidAndType(uuid, AudioAsset.class);
if (video.isPresent()) {
return loadAudio(video.get());
} else {
return Response
.status(Response.Status.NOT_FOUND)
.entity(
String.format(
"The requested video \"%s\" does not exist.",
uuid
)
)
.build();
}
}
@GET
@Path("/{path:^(?!uuid).+$}")
public Response getAudio(
@PathParam("content-section") final String sectionName,
@PathParam("path") final String path
) {
final Optional<ContentSection> section = sectionRepo
.findByLabel(sectionName);
if (!section.isPresent()) {
return Response
.status(Response.Status.NOT_FOUND)
.entity(String.format("No content section \"%s\" available.",
sectionName))
.build();
}
final Optional<Asset> asset = assetRepo.findByPath(
section.get(), path
);
if (asset.isPresent()) {
if (asset.get() instanceof AudioAsset) {
return loadAudio((AudioAsset) asset.get());
} else {
return Response
.status(Response.Status.NOT_FOUND)
.entity(
String.format(
"The asset found at the requested path \"%s\" "
+ "is not an video.",
path
)
)
.build();
}
} else {
return Response
.status(Response.Status.NOT_FOUND)
.entity(
String.format(
"The requested video \"%s\" does not exist.",
path
)
)
.build();
}
}
private Response loadAudio(final AudioAsset video) {
final String mimeType = video.getMimeType().toString();
return Response
.ok()
.entity(
new StreamingOutput() {
@Override
public void write(final OutputStream outputStream)
throws IOException, WebApplicationException {
dataService.copyDataToOutputStream(
video, outputStream
);
}
})
.header("Content-Type", mimeType)
.build();
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2021 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.librecms.contentsection.rs;
import org.librecms.assets.Bookmark;
import org.librecms.contentsection.Asset;
import java.util.Objects;
import javax.enterprise.context.Dependent;
import javax.json.JsonObjectBuilder;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@Dependent
@ProvidesPropertiesForAssetType(Bookmark.class)
public class BookmarkPropertiesProvider implements AssetPropertiesProvider {
@Override
public void addProperties(
final Asset asset, final JsonObjectBuilder builder
) {
Objects.requireNonNull(asset);
Objects.requireNonNull(builder);
if (!(asset instanceof Bookmark)) {
throw new IllegalArgumentException(
String.format(
"\"%s\" only supports assets of type \"%s\". Check "
+ "the qualifier annotation on \"%s\".",
getClass().getName(),
Bookmark.class.getName(),
getClass().getName()
)
);
}
final Bookmark bookmark = (Bookmark) asset;
builder.add("targetUrl", bookmark.getUrl());
}
}

View File

@ -37,10 +37,12 @@ public class ContentSectionsApplication extends Application{
final Set<Class<?>> classes = new HashSet<>();
classes.add(Assets.class);
classes.add(AudioMedia.class);
classes.add(ContentItems.class);
classes.add(ContentSections.class);
classes.add(Files.class);
classes.add(Images.class);
classes.add(Videos.class);
return classes;
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (C) 2021 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.librecms.contentsection.rs;
import org.librecms.assets.ExternalAudioAsset;
import org.librecms.contentsection.Asset;
import java.util.Objects;
import javax.enterprise.context.Dependent;
import javax.json.JsonObjectBuilder;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@Dependent
@ProvidesPropertiesForAssetType(ExternalAudioAsset.class)
public class ExternalAudioAssetPropertiesProvider extends BookmarkPropertiesProvider {
@Override
public void addProperties(
final Asset asset, final JsonObjectBuilder builder
) {
Objects.requireNonNull(asset);
Objects.requireNonNull(builder);
if (!(asset instanceof ExternalAudioAsset)) {
throw new IllegalArgumentException(
String.format(
"\"%s\" only supports assets of type \"%s\". Check "
+ "the qualifier annotation on \"%s\".",
getClass().getName(),
ExternalAudioAsset.class.getName(),
getClass().getName()
)
);
}
super.addProperties(asset, builder);
}
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (C) 2021 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.librecms.contentsection.rs;
import org.librecms.assets.ExternalVideoAsset;
import org.librecms.contentsection.Asset;
import java.util.Objects;
import javax.enterprise.context.Dependent;
import javax.json.JsonObjectBuilder;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@Dependent
@ProvidesPropertiesForAssetType(ExternalVideoAsset.class)
public class ExternalVideoAssetPropertiesProvider extends BookmarkPropertiesProvider {
@Override
public void addProperties(
final Asset asset, final JsonObjectBuilder builder
) {
Objects.requireNonNull(asset);
Objects.requireNonNull(builder);
if (!(asset instanceof ExternalVideoAsset)) {
throw new IllegalArgumentException(
String.format(
"\"%s\" only supports assets of type \"%s\". Check "
+ "the qualifier annotation on \"%s\".",
getClass().getName(),
ExternalVideoAsset.class.getName(),
getClass().getName()
)
);
}
super.addProperties(asset, builder);
}
}

View File

@ -23,8 +23,6 @@ import org.apache.logging.log4j.Logger;
import org.librecms.assets.BinaryAsset;
import org.librecms.assets.BinaryAssetDataService;
import org.librecms.assets.BinaryAssetRepository;
import org.librecms.contentsection.Asset;
import org.librecms.contentsection.AssetRepository;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentSectionRepository;
@ -51,8 +49,6 @@ public class Files {
private static final Logger LOGGER = LogManager.getLogger(Files.class);
// @Inject
// private AssetRepository assetRepo;
@Inject
private BinaryAssetRepository binaryAssetRepo;
@ -135,7 +131,7 @@ public class Files {
}
})
.header("ContentType", asset.getMimeType())
.header("Content-Type", asset.getMimeType())
.header(
"Content-Disposition",
String.format(

View File

@ -23,11 +23,11 @@ import org.librecms.assets.Image;
import org.librecms.contentsection.Asset;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;
import javax.enterprise.context.Dependent;
import javax.imageio.ImageIO;
import javax.json.JsonObjectBuilder;
@ -35,25 +35,29 @@ import javax.json.JsonObjectBuilder;
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@Dependent
@ProvidesPropertiesForAssetType(Image.class)
public class ImagesPropertiesProvider implements AssetPropertiesProvider {
@Override
public void addProperties(final Asset asset,
final JsonObjectBuilder builder) {
public void addProperties(
final Asset asset, final JsonObjectBuilder builder
) {
Objects.requireNonNull(asset);
Objects.requireNonNull(builder);
if (!(asset instanceof Image)) {
throw new IllegalArgumentException(String
.format("\"%s\" only supports assets of type \"%s\". Check "
+ "the qualifier annotation on \"%s\".",
getClass().getName(),
Image.class.getName(),
getClass().getName()));
throw new IllegalArgumentException(
String.format(
"\"%s\" only supports assets of type \"%s\". Check "
+ "the qualifier annotation on \"%s\".",
getClass().getName(),
Image.class.getName(),
getClass().getName()
)
);
}
final Image image = (Image) asset;
// final byte[] data = image.getData();
// final InputStream inputStream = new ByteArrayInputStream(data);
@ -61,10 +65,10 @@ public class ImagesPropertiesProvider implements AssetPropertiesProvider {
final BufferedImage bufferedImage;
try {
bufferedImage = ImageIO.read(inputStream);
} catch(IOException ex) {
} catch (IOException ex) {
throw new UnexpectedErrorException(ex);
}
builder
.add("name", image.getDisplayName())
.add("filename", image.getFileName())
@ -74,5 +78,5 @@ public class ImagesPropertiesProvider implements AssetPropertiesProvider {
.add("size", image.getDataSize());
// .add("size", data.length);
}
}

View File

@ -0,0 +1,155 @@
/*
* Copyright (C) 2021 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.librecms.contentsection.rs;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.librecms.assets.BinaryAssetDataService;
import org.librecms.assets.VideoAsset;
import org.librecms.contentsection.Asset;
import org.librecms.contentsection.AssetRepository;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentSectionRepository;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Optional;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
@Path("/{content-section}/videos")
public class Videos {
private static final Logger LOGGER = LogManager.getLogger(Images.class);
@Inject
private ContentSectionRepository sectionRepo;
@Inject
private AssetRepository assetRepo;
@Inject
private BinaryAssetDataService dataService;
@GET
@Path("/uuid-{uuid}")
public Response getVideoByUuid(
@PathParam("content-section") final String sectionName,
@PathParam("uuid") final String uuid
) {
final Optional<VideoAsset> video = assetRepo
.findByUuidAndType(uuid, VideoAsset.class);
if (video.isPresent()) {
return loadVideo(video.get());
} else {
return Response
.status(Response.Status.NOT_FOUND)
.entity(
String.format(
"The requested video \"%s\" does not exist.",
uuid
)
)
.build();
}
}
@GET
@Path("/{path:^(?!uuid).+$}")
public Response getVideo(
@PathParam("content-section") final String sectionName,
@PathParam("path") final String path
) {
final Optional<ContentSection> section = sectionRepo
.findByLabel(sectionName);
if (!section.isPresent()) {
return Response
.status(Response.Status.NOT_FOUND)
.entity(String.format("No content section \"%s\" available.",
sectionName))
.build();
}
final Optional<Asset> asset = assetRepo.findByPath(
section.get(), path
);
if (asset.isPresent()) {
if (asset.get() instanceof VideoAsset) {
return loadVideo((VideoAsset) asset.get());
} else {
return Response
.status(Response.Status.NOT_FOUND)
.entity(
String.format(
"The asset found at the requested path \"%s\" "
+ "is not an video.",
path
)
)
.build();
}
} else {
return Response
.status(Response.Status.NOT_FOUND)
.entity(
String.format(
"The requested video \"%s\" does not exist.",
path
)
)
.build();
}
}
private Response loadVideo(final VideoAsset video) {
final String mimeType = video.getMimeType().toString();
return Response
.ok()
.entity(
new StreamingOutput() {
@Override
public void write(final OutputStream outputStream)
throws IOException, WebApplicationException {
dataService.copyDataToOutputStream(
video, outputStream
);
}
})
.header("Content-Type", mimeType)
.build();
}
}

View File

@ -414,7 +414,7 @@ function loadAudioAssets(
selectButton.addEventListener(
"click",
(event) => {
const audioUrl = `/content-sections/info/audio/uuid-${audioAsset["uuid"]}`;
const audioUrl = buildAudioMediaUrl(audioAsset);
node.attrs.audioSrc = audioUrl;
if (audioElem) {
audioElem.src = audioUrl;
@ -443,3 +443,16 @@ function loadAudioAssets(
console.error(error);
});
}
function buildAudioMediaUrl(audioAsset: any) {
switch (audioAsset["type"]) {
case "org.librecms.assets.ExternalAudioAsset":
return audioAsset["properties"]["targetUrl"];
case "org.librecms.assets.AudioAsset":
return `/content-sections/info/audiomedia/uuid-${audioAsset["uuid"]}`;
default:
console.error(`Unknown audio asset type.`);
return "";
}
}

View File

@ -462,7 +462,7 @@ function loadVideos(
selectButton.addEventListener(
"click",
(event) => {
const videoUrl = `/@contentsections/info/videos/uuid-${video["uuid"]}`;
const videoUrl = buildVideoUrl(video);
node.attrs.videoSrc = videoUrl;
if (videoElem) {
videoElem.src = videoUrl;
@ -491,3 +491,15 @@ function loadVideos(
console.error(error);
});
}
function buildVideoUrl(video: any) {
switch (video["type"]) {
case "org.librecms.assets.ExternalVideoAsset":
return video["properties"]["targetUrl"];
case "org.librecms.assets.VideoAsset":
return `/content-sections/info/videos/uuid-${video["uuid"]}`;
default:
console.error(`Unknown video asset type.`);
return "";
}
}