Git Product home page Git Product logo

licket's Introduction

🚧 Still in very alpha stage! 🚧

Licket baby!

European serverπŸ‡ͺπŸ‡Ί US serverπŸ‡ΊπŸ‡Έ

Here it is, brand new sweets to make your life even sweeter than before. Yes you! my brave web developer ;)

What is Licket you ask? Licket is a Java based, Spring Boot driven and Vue.js flavoured stack! While being influenced a lot by Apache Wicket (http://wicket.apache.org, I love you guys...) it brings Java/Javascript web development to a completely new level :)

Step by step HOW-TO or how to get running NOW!

First, grab this repo code and build all by yourself on your local beast or ask build automation to do it for you. Take this dependency with you:

<dependency>
    <groupId>org.licket</groupId>
    <artifactId>licket-spring-autoconfigure</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

Let's start with simple model first:

public class Contact {

    private String name;
    private String description;
    
    // getters/setters ...
}
    

Then a simple Spring service providing some data:

@Service
public class ContactsService {

    public List<Contact> getAllContacts() {
        return newArrayList(
                contact("Chuck Norris", "That's him."),
                contact("Jonh Doe", "Lorem ipsum"),
                contact("Bob Marley", "Je je je")
        );
    }

}

As mentioned in preface, Licket derives many concepts from Apache Wicket like logic less HTML templates. You can define view in very similar way:

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:lick="http://www.w3.org/1999/xhtml">
    <head>
            <title>Contacts Page</title>
    </head>
    <body>
        <h1>Contacts list</h1>

        <div lick:id="contacts-panel">
            <div lick:id="contact">
                Name: <span lick:id="name">here will be name</span>
                Description: <span lick:id="description">and here description</span>
            </div>
        </div>
    </body>
</html>

Then you can model out the components:

public class ContactsAppRoot extends AbstractLicketMultiContainer<Void> {
    
  @Autowired
  private ContactsPanel contactsPanel;

  public ContactsAppRoot(String id) {
      super(id, Void.class, emptyComponentModel(), fromComponentClass(ContactsAppRoot.class));
  }
  
  @Override
  protected void onInitializeContainer() {
    add(contactsPanel);
  }
}

public class ContactsPanel extends AbstractLicketContainer<Contacts> {

    @Autowired
    private ContactsService contactsService;

    public ContactsPanel(String id) {
        super(id, fromComponentContainerClass(ContactsPanel.class));
    }

    @Override
    protected void onInitializeContainer() {
        add(new ContactsList("contact", new LicketComponentModel("contacts"))); 
    }

    private void readContacts() {
        setComponentModel(ofModelObject(fromIterable(contactsService.getAllContacts())));
    }
}

public class ContactsList extends AbstractLicketList<Contact> {

    public ContactsList(String id, LicketComponentModel<String> enclosingComponentPropertyModel) {
        super(id, enclosingComponentPropertyModel, Contact.class);

        add(new LicketLabel("name"));
        add(new LicketLabel("description"));
    }
}

Next,coin your own Spring Boot configuration class and glue all together:

@Configuration
public class LicketConfiguration {

    @LicketRootContainer
    public ContactsAppRoot root() {
        return new ContactsAppRoot("contacts-page");
    }

    @LicketComponent
    public ContactsPanel contactsPanel() {
        return new ContactsPanel("contacts-panel");
    }
    
    @Bean
    public ContactsService contactsService() {
        return new ContactsService();
    }
    
    // other beans ...

}

Feel the magic ✨

licket's People

Contributors

activey avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

licket's Issues

Generate java bindings from typescript .ds files

Just an idea for anyone keen to overtake this project: I think it could be possible to generate java code out of .ds files or anything else from typescript/webpack/whateverelse world to ease adoption of javascript components and other stuff.

Create project page

It would be great to have project page created with Jekyll. Ultimately I'd love to have an option to publish blog posts somehow. Anyone interested in helping me out? ;)

Spring security

Incorporate spring security mechanism. Introduce login page redirection and http interceptors.

WebSockets support

It would be awesome to be able to incorporate WebSockets into Licket framework so it could be possible to pach/reload component models in real time.

Modal rendered twice

Modal resource is generated twice. Getting errors like this:

2017-07-22 14:41:09 [qtp1998882269-18] DEBUG o.l.s.resource.SpringResourceStorage - Resource with name = contacts-page:add-contact-panel:form-modal:actions-section:content-block:add_random and mimetype = text/html is already there, skipping...

Introduce Vue routing library

Use Vue codebase and prepare some mechanism in Licket that would allow a developer to bind components to some routes. U know what I mean ;)

Exception when trying to load vue-resource.js

Hi,

I am trying to run the licket-demo and I get an error when trying to load the resource vue-resource.js.
Could you please advice if I am missing some configuration or library? @activey

Thank you!

java.lang.IllegalArgumentException: InputStream must not be null
        at org.springframework.core.io.InputStreamResource.<init>(InputStreamResource.java:66)
        at org.springframework.core.io.InputStreamResource.<init>(InputStreamResource.java:56)
        at org.licket.spring.web.LicketResourceController.getResource(LicketResourceController.java:53)
        at org.licket.spring.web.LicketResourceController$$FastClassBySpringCGLIB$$160ac7a9.invoke(<generated>)
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:720)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:133)
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:121)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655)
        at org.licket.spring.web.LicketResourceController$$EnhancerBySpringCGLIB$$5544fdf8.getResource(<generated>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:483)
        at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
        at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:845)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1689)
        at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:225)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1676)
        at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1676)
        at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:87)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1676)
        at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1676)
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1676)
        at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:581)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
        at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
        at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
        at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180)
        at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511)
        at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
        at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
        at org.eclipse.jetty.server.Server.handle(Server.java:524)
        at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319)
        at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253)
        at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
        at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)
        at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93)
        at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303)
        at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148)
        at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136)
        at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
        at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589)
        at java.lang.Thread.run(Thread.java:745)

Create algorithm for generating path from one component to another in Vue

When one component in Vue has to interact with another there is no better way to do it than using $refs in Vue component. Situation is simple when you have strict parent-child relation in Vue. In licket you are able to reference different component from different tree parts.

The task is about to create some nifty algorithm, that having two not related component would be able to generate path like this:

this.$parent.$refs['container1'].$refs['xxx'] ... etc

Component visibility

Implement mechanism for setting component visibility with v-show or with v-if (or maybe even allow using different strategies?).

Dimmer component

Implement SemanticUI dimmer component for long running operations.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.