Let's say I have a domain object Customer. On this object I have an address to an external site.
#PropertyLayout(named = "Link", describedAs = "Clickable link to customer")
public String getLink() {
return "http://www.customer.com";
}
In this case this will be shown as just text on the webpage. How do I create a clickable link in the wicket viewer from this?
There is a third-party extension: https://github.com/kev-m/isis-wicket-url/
This was done by Kevin Meyer, one of our committers.
I've raised https://issues.apache.org/jira/browse/ISIS-1616 to incorporate this into the framework "proper".
Meantime, you can add an action to open the link easily enough
#Action(semantics=SemanticsOf.SAFE)
#MemberOrder(named="link", sequence="1")
public java.net.URL openLink() throws MalformedURLException {
return new java.net.URL(getLink());
}
and just to finish it off, you could add this guard:
public String disableOpenLink() {
if(getLink() == null) { return "no link to open."; }
try {
openLink();
} catch(MalformedURLException ex) {
return "Bad link";
}
return null;
}
I don't think there is out of the box solution in Apache Isis for this.
You will need to roll your own Wicket component for it. For example, annotate this property with custom annotation #ExternalLink and then register a ComponentFactory that creates Wicket ExternalLink component for this property. See https://github.com/isisaddons/isis-wicket-summernote/blob/master/cpt/src/main/java/META-INF/services/org.apache.isis.viewer.wicket.ui.ComponentFactory for example.
Related
How to upload a file in symfony 4.I have done with the symfony document. I don't know where I have missed something. Its throws error while uploading file give me some clues
REFERED LINK:
https://symfony.com/doc/current/controller/upload_file.html
ERROR:
The file "" does not exist
Entity
public function getBrochure()
{
return $this->brochure;
}
public function setBrochure($brochure)
{
$this->brochure = $brochure;
return $this;
}
File upload Listener
class FileUploader
{
private $targetDirectory;
public function __construct($targetDirectory)
{
$this->targetDirectory = $targetDirectory;
}
public function upload(UploadedFile $file)
{
$fileName = md5(uniqid()).'.'.$file->guessExtension();
$file->move($this->getTargetDirectory(), $fileName);
return $fileName;
}
public function getTargetDirectory()
{
return $this->targetDirectory;
}
}
This Symfony tutorial works fine for me so I'll try to explain how and perhaps it will help you or people still looking for an answer, this post getting a bit old.
So first you have to create the FileUploader service in App\Service for better reusability (chapter: Creating an Uploader Service). You can basically copy/paste what they've done here, it works like a charm. Then you need to open your services.yaml in Config folder and explicit your brochure directory:
parameters:
brochures_directory: '%kernel.project_dir%/public/uploads/brochures'
# ...
services:
# ...
App\Service\FileUploader:
arguments:
$targetDirectory: '%brochures_directory%'
Now everything is normally ready to use your FileUploader service.
So if you're in your controller (for example), I guess you want to use it in a form. Thus, you just have to do this (don't forget to use your Service in your Controller):
public function myController(FileUploader $fileUploader)
{
// Create your form and handle it
if ($form isValid() && &form isSubmitted()) {
$file = $myEntity->getBrochure();
$fileName = $this->fileUploader->upload($file);
$myEntity->setBrochure($fileName);
// Form validation and redirection
}
// Render your template
}
One important point I forgot to say. In your FormType, you need to say that the Brochure will be a FileType:
$builder->add('brochure', FileType::class)
But in your entity you have to specify your brochure is stored as a "string":
/**
* #MongoDB\Field(type="string")
*/
protected $brochure;
The reason is your file is getting uploaded and saved in your public/uploads/brochure. But your database is only remembering a string path to reach it.
I hope this will help!
I have Page
getRootRequestMapperAsCompound().add(new NoVersionMapper("/card/${cardId}", CardPage.class));.
On this page there is TinyMCE4 editor. Which try to load images using relative path "images/1.jpg"
I've added resource mapping to allow images successfuly loaded.
mountResource("/card/image/${imageId}", imageResourceReference);
In DEVELOPMENT mode everything work nice, image are loaded in to editor, but in DEPLOYMENT mode, Page has been called twice, first time for /card/1 and second time for /card/image/1.jpg.
How to correctly mount resources for DEPLOYMENT mode?
UPDATE look like found the reason
public int getCompatibilityScore(Request request)
{
return 0; // pages always have priority over resources
}
, but then the question is: "Why it is working nice in development mode"?
Update 2 I haven't find better solution then add my own Resource Mapper with overrided getCompatibilityScore()
public class ImageResourceMapper extends ResourceMapper {
private String[] mountSegments;
public ImageResourceMapper(String path, ResourceReference resourceReference) {
super(path, resourceReference);
mountSegments = getMountSegments(path);
}
public ImageResourceMapper(String path, ResourceReference resourceReference, IPageParametersEncoder encoder) {
super(path, resourceReference, encoder);
mountSegments = getMountSegments(path);
}
#Override
public int getCompatibilityScore(Request request) {
if (urlStartsWith(request.getUrl(), mountSegments)) {
return 10;
}
return 0;
}
}
I want to create a maintenance Page for my cake website by checking a Database Table for a maintenance flag using a sub-function of my AppController "initilize()" method. If the flag is set, i throw my custom MaintenanceException(Currently containing nothing special):
class MaintenanceException extends Exception{
}
To handle it, I implemented a custom App Exception Renderer:
class AppExceptionRenderer extends ExceptionRenderer {
public function maintenance($error)
{
return "MAINTENANCE";
}
}
I am able to see this maintenance Text on my website if I set my DB flag to true, but I could not find any information in cake's error handling documentation (http://book.cakephp.org/3.0/en/development/errors.html) on how I can actually tell the Exception renderer to render view "maintenance" with Template "infopage".
Can I even us that function using the ExceptionRenderer without a custom error controller? And If not, how should a proper ErrorController implementation look like? I already tried this:
class AppExceptionRenderer extends ExceptionRenderer {
protected function _getController(){
return new ErrorController();
}
public function maintenance($error)
{
return $this->_getController()->maintenanceAction();
}
}
together with:
class ErrorController extends Controller {
public function __construct($request = null, $response = null) {
parent::__construct($request, $response);
if (count(Router::extensions()) &&
!isset($this->RequestHandler)
) {
$this->loadComponent('RequestHandler');
}
$eventManager = $this->eventManager();
if (isset($this->Auth)) {
$eventManager->detach($this->Auth);
}
if (isset($this->Security)) {
$eventManager->detach($this->Security);
}
$this->viewPath = 'Error';
}
public function maintenanceAction(){
return $this->render('maintenance','infopage');
}
}
But this only throws NullPointerExceptions and a fatal error. I am really dissapointed by the cake manual as well, because the code examples there are nowhere close to give me an impression of how anything could be done and what functionality I actually have.
Because I had some more time today, I spent an hour digging into the cake Source and found a solution that works well for me (and is propably the way it should be done, altough the cake documentation does not really give a hint):
Step 1: Override the _template(...)-Method of the ExceptionRenderer in your own class. In my case, I copied the Method of the parent and added the following Code at the beginning of the method:
$isMaintenanceException = $exception instanceof MaintenanceException;
if($isMaintenanceException){
$template = 'maintenance';
return $this->template = $template;
}
This tells our Renderer, that the error Template called "maintentance"(which should be located in Folder: /Error) is the Error Page content it should render.
Step 2: The only thing we have to do now (And its is kinda hacky in my opinion, but proposed by the cake documentation in this exact way) is to set the layout param in our template to the name of the base layout we want to render with. So just add the following code on top of your error template:
$this->layout = "infopage";
The error controller I created is actually not even needed with this approach, and I still don't know how the cake error controller actually works. maybe I will dig into this if I have more time, but for the moment.
I've written an Xtext-based plugin for some language. I'm now interested in creating a new independent view (as a separate plugin, though it requires my first plugin), which will interact with the currently-active DSL document - and specifically, interact with the model Xtext parsed (I think it's called the Ecore model?). How do I approach this?
I saw I can get an instance of XtextEditor if I do something like this when initializing my view:
getSite().getPage().addPartListener(new MyListener());
And then, in MyListener, override partActivated and partInputChanged to get an IWorkbenchPartReference, which is a reference to the XtextEditor. But what do I do from here? Is this even the right approach to this problem? Should I instead use some notification functionality from the Xtext side?
Found it out! First, you need an actual document:
IXtextDocument doc = editor.getDocument();
Then, if you want to access the model:
doc.modify(new IUnitOfWork.Void<XtextResource>() { // Can also use just IUnitOfWork
#Override public void process(XtextResource state) throws Exception {
...
}
});
And if you want to get live updates whenever it changes:
doc.addModelListener(new IXtextModelListener() {
#Override public void modelChanged(XtextResource resource) {
for (EObject model : resource.getContent()) {
...
}
}
});
I'm attaching a event receiver to a single list (Web scope). But the ER runs for all lists in the Web. This question says that the feature, the ER is deployed in, have to be Web scope. This is the case.
The Feature is activated programmatically bound to an ER of a list in the TLS.
newProjectWeb.Features.Add(new Guid("57e21870-6285-4e0a-b9a0-067f774492ae"));
Please see my code below. Am I missing an Update or anything?
Thanks for your help in advance.
public void AddEventReceiverToMemberList()
{
try
{
_clsLists.AddEventReceiverToList(Web, ProjectMemberList.LIST_INTERNAL_NAME, typeof(SCMUProjectMemberList), SPEventReceiverType.ItemAdded);
_clsLists.AddEventReceiverToList(Web, ProjectMemberList.LIST_INTERNAL_NAME, typeof(SCMUProjectMemberList), SPEventReceiverType.ItemDeleting);
_clsLists.AddEventReceiverToList(Web, ProjectMemberList.LIST_INTERNAL_NAME, typeof(SCMUProjectMemberList), SPEventReceiverType.ItemUpdated);
Web.Update();
}
catch (Exception)
{
throw;
}
}
public void AddEventReceiverToList(SPWeb web, string listName, Type eventReceiverClass, SPEventReceiverType eventType)
{
SPList list = this.GetListByName(web, listName);
string className = eventReceiverClass.FullName;
string assemblyName = Assembly.GetAssembly(eventReceiverClass).FullName;
list.EventReceivers.Add(eventType, assemblyName, className);
}
If you want to run the event receiver for a single list..
Refer Here
Check the end of the post, Changing the attribute to "ListTemplateId" to "ListURL" in Elements.xml
In the Elements.xml file replace:
<Receivers ListTemplateId="100">
by
<Receivers ListUrl="Lists/Your List Name">