Add online video to 'textmedia' element - typo3

In an extension, I would basically like to do what the core does when you click the button "Add media by URL" on an existing textmedia element.
I tried to look in the source code but did not find any convenient API function I could use. Perhaps I could use DataHandler for this?
What the core does is create a textfile (e.g. .youtube) which contains the video id. It then creates a record for this file in sys_file and a file reference (sys_file_reference) between the record in tt_content and the file record in sys_file.
I am using the latest TYPO3 8.

I don't have a complete solution, but I recently had to do something similar:
Create a file from the Video URL and create the corresponding sys_file record:
The class OnlineMediaController::createAction does what you are looking for. Specifically, the function OnlineMediaHelperRegistry::transformUrlToFile will transform the video URL to a file (creating it if necessary).
To use the existing action, you can use the Ajax Route online_media_create.
Or, you can use the existing action to model your own code.
Create a relation between existing records in sys_file and tt_content:
See Creating a file reference (TYPO3 documentation)
Sample code: (Most of the code taken from Creating a file reference)
use TYPO3\CMS\Core\Resource\OnlineMedia\Helpers\OnlineMediaHelperRegistry;
use TYPO3\CMS\Core\Resource\ResourceFactory;
use TYPO3\CMS\Backend\Utility\BackendUtility;
...
protected function addMediaByUrl($url, $uid)
{
$targetFolder = $GLOBALS['BE_USER']->getDefaultUploadFolder();
$file = OnlineMediaHelperRegistry::getInstance()->transformUrlToFile(
$url,
$targetFolder
);
$contentElement = BackendUtility::getRecord('tt_content', $uid);
$newId = 'NEW1234';
$data = array();
$data['sys_file_reference'][$newId] = [
'table_local' => 'sys_file',
'uid_local' => $file->getUid(),
'tablenames' => 'tt_content',
'uid_foreign' => $contentElement['uid'],
'fieldname' => 'assets',
'pid' => $contentElement['pid']
];
$data['tt_content'][$contentElement['uid']] = [
'assets' => $newId
];
// Get an instance of the DataHandler and process the data
/** #var DataHandler $dataHandler */
$dataHandler = GeneralUtility::makeInstance(DataHandler::class);
$dataHandler->start($data, array());
$dataHandler->process_datamap();
// Error or success reporting
if (count($dataHandler->errorLog) === 0) {
// Handle success
} else {
// Handle error
}
}

Maybe you look here for good examples
YoutubeVideo, Vimeo, Video-Files, More Informations you can find at the vhs Docs
Or you could do something like this:
<flux:form id="youtubevideo" label="YouTubeVideo" description="Einbetten eines
YouTube Videos als iframe">
<flux:form.option name="optionsettings">
<flux:form.option.group value="Content" />
<flux:form.option.icon
value="EXT:extension_key/Resources/Public/Icons/Content/YouTubeVideo.svg" />
</flux:form.option>
<flux:field.input name="settings.videoid" label="YouTube Video ID. Entnehmen
Sie die ID aus der YouTube URL. Beispiel: https://www.youtube.com/watch?
v=UX12345678 Die ID ist UX12345678" />
<flux:field.select name="settings.videoformat" label="Video Format"
maxItems="1" multiple="0" default="YouTubeVideo--normal" items="{YouTubeVideo--
normal: 'Normal (4:3)', YouTubeVideo--widescreen: 'Widescreen (16:9)'}"/>
<flux:field.checkbox name="settings.gridPull" label="Bleed Outside (Randlos
glücklich)" default="0" />
</flux:form>
...
<div class="YouTubeVideo {settings.videoformat}">
<iframe width="640" height="480" src="//www.youtube-
nocookie.com/embed/{settings.videoid}?rel=0&showinfo=0" allowfullscreen>
</iframe>
</div>

Finally found the solution:
The key is to set the correct "allowed extensions": add "youtube" or "vimeo".
This will automatically add the missing "Add media by URL" button.
Example using Flux Inline FAL:
<f:section name="Configuration">
<flux:form id="myCustomVideoContentElement">
<flux:field.inline.fal name="settings.records" label="video"
multiple="false" minItems="1" maxItems="1"
allowedExtensions="mp4,mkv,youtube,vimeo"
/>
</flux:form>
</f:section>
(Typo3 9.5)

Related

Vuetify Send data from form with Axios

I am using Vuetify in my VueJs project and I need to send data from my form in which I am uploading a file (CSV) and got some number inputs. I need to do that with Axios.
I've tried to do something but always got a 404.
This is my Vuetify code:
<v-form>
<v-container>
<v-row>
<v-file-input
show-size
counter
multiple
label="Nacitaj CSV"
ref="myfile"
v-model="files"
></v-file-input>
</v-row>
<v-row>
<v-col>
<v-text-field
type="number"
label="zadaj cislo"
/>
</v-col>
<v-col>
<v-text-field
type="number"
label="zadaj cislo"
/>
</v-col>
</v-row>
<v-row>
<v-col :cols="2">
<v-btn
block
color="primary"
#submit="submitFiles"
>
Submit
</v-btn>
</v-col>
</v-row>
</v-container>
</v-form>
methods: {
submitFiles() {
if (this.files) {
let formData = new FormData();
// files
for (let file of this.files) {
formData.append("files", file, file.name);
}
// additional data
formData.append("test", "foo bar");
axios.post("/about", formData);
}
I've tried the script which I found on internet but it wasn't working; also the script was only for the file.
I know this is super old but for the next person arriving at this answer, let's take a look at submitFiles function:
submitFiles() {
if (this.files) {
let formData = new FormData();
// files
for (let file of this.files) {
formData.append("files", file, file.name);
}
// additional data
formData.append("test", "foo bar");
axios.post("/about", formData);
}
the first if is checking if files is not empty. files is part of the model. If there are files it creates a new object to hold the Form data (formData).
Then it will loop the files object and append the files to the object holding the form data and after that it will append a field called test with the value foo bar and make a post request to /about in the domain you're serving your page sending the form data object as the body. If you're getting a 404 it should mean that about doesn't exist.

Getting a dialog on click of Edit Button on admin-on-rest

I am working on an application using admin-on-rest framework. For editing an entry on a Resource we provide XXXEdit, XXXShow, XXXCreate props to it. My requirement is that when I click on an Edit button in List view on any entry I should get a Dialog box with the parameters in XXXEdit instead of going to a new page. I tried doing this by using a Dialog in XXXEdit component
<Edit title={<RoleTitle />} {...props}>
<SimpleForm>
<Dialog
title="Dialog With Actions"
actions={actions}
modal={false}
open={true}
>
<TextInput source="id" />
<TextInput source="name" validate={required} />
.
.//some more fields
</Dialog>
</SimpleForm>
</Edit>
I get errors like The TextInput component wasn't called within a redux-form
If I use a DisabledInput then I get an error cannot read value of undefined
How do I go on with this?
I do not think you can use Simpleform for this. You will need to create a custom Form using Redux-Form. Look at the bottom answer that documents the final answer.
This might help you
How to richly style AOR Edit page
Instead of creating a page. You are creating a component that connects to the Redux state and displays as a dialog box.
I tried to resolve this using HOC and react-router.
I created a button using AOR button and provided a containerElement
containerElement={
<Link
key={record.id}
to={{
...{
pathname: `${basePath}/${encodeURIComponent(record.id)}`
},
...{ state: { modal: true } }
}}
/>
}
I created a route like this where DialogRoleEdit is an AOR edit component wrapped with a dialog HOC below .
<Route
exact
path="/roles/:id"
render={routeProps => {
return !!(
routeProps.location.state && routeProps.location.state.modal
) ? (
<Restricted authClient={authClient} location={routeProps.location}>
<div>
<RoleList resource={"roles"} {...routeProps} />
<DialogRoleEdit resource={"roles"} {...routeProps} />
</div>
</Restricted>
) : (
<Restricted authClient={authClient} location={routeProps.location}>
<RoleEdit resource={"roles"} {...routeProps} />
</Restricted>
);
}}
/>
Finally an HOC
handleClose = () => {
this.props.history.goBack();
};
render() {
const actions = [
<FlatButton label="Cancel" primary={true} onClick={this.handleClose} />
];
return (
<Dialog>
<WrappedComponent/>
</Dialog>
)
}
We need to provide edit prop for this resource in App.js
edit={DialogUserEdit}

Shrine with Rails multiple polymorphic image uploads

I've been struggling for about 5 hours trying to understand why Shrine is blocking my uploads. I either get errors like "Shrine: Invalid file", or "Expected Array but got string" in strong params. If there aren't errors, the images aren't actually saved.
require "image_processing/mini_magick"
class ImageUploader < Shrine
include ImageProcessing::MiniMagick
plugin :activerecord
plugin :backgrounding
plugin :cached_attachment_data
plugin :determine_mime_type
plugin :delete_raw
plugin :direct_upload
plugin :logging, logger: Rails.logger
plugin :processing
plugin :remove_attachment
plugin :store_dimensions
plugin :validation_helpers
plugin :versions
Attacher.validate do
validate_max_size 2.megabytes, message: 'is too large (max is 2 MB)'
validate_mime_type_inclusion ['image/jpg', 'image/jpeg', 'image/png', 'image/gif']
end
def process(io, context)
case context[:phase]
when :store
thumb = resize_to_limit!(io.download, 200, 200)
{ original: io, thumb: thumb }
end
end
end
class Image < ActiveRecord::Base
include ImageUploader[:image]
belongs_to :imageable, polymorphic: true
end
class Product < ApplicationRecord
has_many :images, as: :imageable, dependent: :destroy
accepts_nested_attributes_for :images, allow_destroy: true
...
# Strong Params:
def product_params
params.require(:product).permit(
:name, :brand_id, :category_id, :price, :compare_price, :description,
images_attributes: { image: [] },
product_properties_attributes: [:id, :property_id, :value]
)
...
And my view:
<%= f.fields_for :images do |image_form| %>
<%= image_form.file_field :image, multiple: true %>
<% end %>
According to everything I've read on the docs or from gorails, this should work. Do I need to restructure the images_attributes hash? I also tried using direct_uploads, but struggled to get the presigned_url to work with S3.
Refile makes this really easy, so I'll probably run crying back to that.
Is there something I'm obviously doing wrong?
According to the fields_for documentation, the provided block will be called for each image in the project.images collection. So if your product currently doesn't have any images, the block won't be called (according to the docs).
For nested attributes to work, you need to forward the following parameters when creating the Product:
product[images_attributes][0][image] = <file object or data hash>
product[images_attributes][1][image] = <file object or data hash>
product[images_attributes][2][image] = <file object or data hash>
...
If you look at the "Multiple Files" Shrine guide, it's recommended that you just have a single file field which accepts multiple files:
<input type="file" name="file" multiple>
And then setup direct uploads for this field using Uppy, dynamically generating the image field for each uploaded file populated with the uploaded file data hash:
<input type="hidden" name="product[images_attributes][0][image]" value='{"id":"...","storage":"cache","metadata":{...}}'>
<input type="hidden" name="product[images_attributes][1][image]" value='{"id":"...","storage":"cache","metadata":{...}}'>
....
Alternatively you can just let users attach multiple files, which are all submitted to the app, and then destructure them in the controller:
class ProductsController < ApplicationController
def create
images_attributes = params["files"].map { |file| {image: file} }
Product.create(product_params.merge(images_attributes: images_attributes))
end
end
In that case you have to make sure your HTML form has the enctype="multipart/form-data" attribute set (otherwise only the files' filenames will get submitted, not files themselves).

The requested view was not found in TYPO3

I have my controller in the folder controllers with the name AdController
and my action name is
/**
* action ajaxValue
*
* #param string $argument
* #return void
*/
public function ajaxValueAction($argument = NULL) {
}
and my template file is on location Resources/Private/Templates/Ad/ajaxValue.html
with the name ajaxValue.html
{namespace t=Helhum\TyposcriptRendering\ViewHelpers}
<f:layout name="Default" />
This Template is responsible for creating a table of domain objects.
If you modify this template, do not forget to change the overwrite settings
in /Configuration/ExtensionBuilder/settings.yaml:
Resources:
Private:
Templates:
List.html: keep
Otherwise your changes will be overwritten the next time you save the extension in the extension builder
<f:section name="main">
<f:debug title="Results of customers query">{ads}</f:debug>
<f:flashMessages />
<!-- Category selection box -->
<!-- This is basically called a ajax request which is based on some other file take from the following link http://ajax.helmut-hummel.de/
-->
<div id="dataJson" data-url="{t:uri.ajaxAction(action: 'ajaxValue', format: 'json', controller: 'Ad', pluginName: 'Txcasmarketing') -> f:format.htmlentities()}"></div>
<div class="container">
<div class="btn-group">
<a class="btn btn-primary dropdown-toggle" data-toggle="dropdown" href="#">Select Category<span class="caret"></span></a>
<ul class="dropdown-menu">
<f:for each="{categories}" as="category">
<li>
<a data-catUid="{category.uid}" href="#">{category.name}</a>
</li>
</f:for>
</ul>
</div>
</div>
I am getting the following error
<p><strong>Sorry, the requested view was not found.</strong></p> <p>The technical reason is: <em>No template was found. View could not be resolved for action "ajaxValue" in class "CASmarketing\Casmarketing\Controller\AdController"</em>.</p>
The defaults templates which has been created by extension builder is accessible. the structure of my ex_localconf.php is
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
'CASmarketing.Casmarketing',
'Txcasmarketing', [
'State' => 'list, show, new, create, edit, update, delete',
'Category' => 'list, show, new, create, edit, update, delete',
'Ad' => 'list, ajaxValue, show, new, create, edit, update, delete'
],
// non-cacheable actions
[
'State' => 'create, update, delete',
'Category' => 'create, update, delete',
'Ad' => 'create, update, delete'
]
);
}, $_EXTKEY
);
and my template file is on location Resources/Templates/Ad/ajaxValue.html
with the name ajaxValue.html
and my step.ts file sitting is
plugin.tx_casmarketing_txcasmarketing {
view {
templateRootPaths.0 = EXT:casmarketing/Resources/Private/Templates/
templateRootPaths.1 = {
$plugin.tx_casmarketing_txcasmarketing.view.templateRootPath}
partialRootPaths.0 = EXT:casmarketing/Resources/Private/Partials/
partialRootPaths.1 = {
$plugin.tx_casmarketing_txcasmarketing.view.partialRootPath}
layoutRootPaths.0 = EXT:casmarketing/Resources/Private/Layouts/
layoutRootPaths.1 = {
$plugin.tx_casmarketing_txcasmarketing.view.layoutRootPath}
}
persistence {
storagePid = {
$plugin.tx_casmarketing_txcasmarketing.persistence.storagePid}
#recursive = 1
}
features {
#skipDefaultArguments = 1
}
mvc {
#callDefaultActionIfActionCantBeResolved = 1
}
}
my script file which is basically called the ajax request which is define in the pageLayout.js
$(".dropdown-menu li a").click(function () {
var jsonUrl = $('#dataJson').attr('data-url')
var selectedCatUid = $(this).attr('data-catUid');
$.ajax({
type: 'POST',
url: jsonUrl,
data: {
'tx_casmarketing_txcasmarketing[catId]': selectedCatUid
},
success: function (response) {
alert(response);
},
});
Your template should not be in Resources/Templates/Ad/ajaxValue.html but in Resources/Private/Templates/Ad/AjaxValue.html. Mind the Private sub folder. Also it has to be UpperCase.
Didn't know that it does matter but the filename usually is uppercase. You also should make sure that the typoscript settings are configured to this directory.
Your typoscript should correctly look like this:
plugin.tx_casmarketing_txcasmarketing {
view {
templateRootPaths.0 = EXT:casmarketing/Resources/Private/Templates/
templateRootPaths.1 = {$plugin.tx_casmarketing_txcasmarketing.view.templateRootPath}
partialRootPaths.0 = EXT:casmarketing/Resources/Private/Partials/
partialRootPaths.1 = {$plugin.tx_casmarketing_txcasmarketing.view.partialRootPath}
layoutRootPaths.0 = EXT:casmarketing/Resources/Private/Layouts/
layoutRootPaths.1 = {$plugin.tx_casmarketing_txcasmarketing.view.layoutRootPath}
}
persistence {
storagePid = {$plugin.tx_casmarketing_txcasmarketing.persistence.storagePid}
#recursive = 1
}
features {
#skipDefaultArguments = 1
}
mvc {
#callDefaultActionIfActionCantBeResolved = 1
}
}
If you change this in your setup.txt of the extension this is hardly cached and you have to clear the cache in the install tool. After making sure your typoscript is correctly loaded place your new Views template inside the ext-directory template path first to try it out.
If this does not help please give us the content of your HTML Template.

How to upload file to folder on server in jsp? [duplicate]

This question already has answers here:
How can I upload files to a server using JSP/Servlet?
(14 answers)
Closed 2 years ago.
I am doing project Online Image Gallery, in which I have to upload images. I am doing it with jsp/servlet and IDE is Eclipse.
My Jsp file is as follows
<form action="ActionPage" >
<input type="file" name="myFile">
<br>
<input type="submit">
</form>
Here Actionpage is servlet. On Clicking submit button i want the selected file to be stored inside the folder called "IMAGE" inside the WebContent on server and path on database table.
If any one know the simple solution please share it.
Thanks in advance.
You can read how this is done here
How to upload files to server using JSP/Servlet?
PS: Storing uploaded files inside the applications directory is BAD BAD BAD idea. Think about what would happen if you have your application running for some time, and you want to do a redeploy becase a file is missing some html tag. The upload's directory will be removed by your container!
Try using a folder outside of the application's directory, or use a database.
This is the easiest solution if You are using jsp to develop your website
First of all for taking input from user make a html or jsp page and include tis code in your jsp/html page
First of all download
commons-fileupload-1.2.2.jar
org.apache.commons.io.jar
and add this jar to your library by right-clicking your project then select build path and then add jar files
`<form role="form" action="Upload.jsp" method="post"enctype="multipart/form-data">
<div class="btn btn-success btn-file">
<i class="fa fa-cloud-upload"></i>
Browse
<input type="file" name="file" />
</div>
<button type="submit" value="submit" name='submit'>submit</button>`
</form>
enctype="multipart/form-data"
it is necessary
Now make one jsp named upload.jsp( you can have the target jsp with which we are going to save our image to server of any name but remember to put that name in in above code
<%# page import="java.io.*,java.util.*, javax.servlet.*" %>
<%# page import="javax.servlet.http.*" %>
<%# page import="org.apache.commons.fileupload.*" %>
<%# page import="org.apache.commons.fileupload.disk.*" %>
<%# page import="org.apache.commons.fileupload.servlet.*" %>
<%# page import="org.apache.commons.io.output.*" %>
<%
String userName = (String) session.getAttribute("User");
File file ;
int maxFileSize = 5000000 * 1024;
int maxMemSize = 5000000 * 1024;
ServletContext context = pageContext.getServletContext();
String filePath = context.getInitParameter("file-upload");
// Verify the content type
String contentType = request.getContentType();
if ((contentType.indexOf("multipart/form-data") >= 0)) {
DiskFileItemFactory factory = new DiskFileItemFactory();
// maximum size that will be stored in memory
factory.setSizeThreshold(maxMemSize);
// Location to save data that is larger than maxMemSize.
factory.setRepository(new File("C:\\Users\\"));
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
// maximum file size to be uploaded.
upload.setSizeMax( maxFileSize );
try{
// Parse the request to get file items.
List<FileItem> fileItems = upload.parseRequest(request);
// Process the uploaded file items
Iterator i = fileItems.iterator();
while ( i.hasNext () )
{
FileItem fi = (FileItem)i.next();
if ( !fi.isFormField () )
{
// Get the uploaded file parameters
String fieldName = fi.getFieldName();
String fileName = fi.getName();
boolean isInMemory = fi.isInMemory();
long sizeInBytes = fi.getSize();
// Write the file
if( fileName.lastIndexOf("\\") >= 0 ){
file = new File( filePath +
fileName.substring( fileName.lastIndexOf("\\"))) ;
}else{
file = new File( filePath +
fileName.substring(fileName.lastIndexOf("\\")+1)) ;
}
fi.write( file ) ;
request.setAttribute("Success", "Successfully Uploaded");
RequestDispatcher rd = request.getRequestDispatcher("/UploadFiles.jsp");
rd.forward(request, response);
}
}
}catch(Exception ex) {
System.out.println(ex);
}
}else{
request.setAttribute("Error", "Error!!");
RequestDispatcher rd =request.getRequestDispatcher("/UploadFiles.jsp");
rd.forward(request, response);
}
%>
please don't get confused just copy this code and once you go through this i am sure you will get to know about code
Now the last thin you have to do is to add something to web.xml if you don't have this file then create this...
<context-param>
<description>Location to store uploaded file</description>
<param-name>file-upload</param-name>
<param-value>
C:\\Users\\
</param-value>
</context-param>
just add above code to web.xml you can change the address where your images will be uploaded as desired ( change param-value for this)
In case you face any problem let me know