A JavaScript Plone Client
CC Attribution 3.0 Germany:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Bréhault, Eric
Navarro Bosch, Ramon
A key part of the work started at the Barcelona sprint this summer was an extensible Angular 2 based app, which does all its interaction with the Plone backend through the new REST API. It supports both server side and browser side rendering for fast response time, SEO and accessibility.
 Hello everybody. My name is Eric Barrow and I'm going to talk to you about JavaScript from Client, which I've been introduced by Eric in this keynote this morning. Yeah, I know the word here which is kind of boring is JavaScript, right? So I made a small poll on Twitter, I asked, yeah, recording this 3C form in GIS sounds smart, stupid, or seriously? Well, first reaction was, yeah, seriously? How are we doing that? Well, I know a lot of people are complaining about modern GIS is really too complicated, right? It's like changing every time you have every time something new to learn and the process to build even a very simple thing you could do with two lines of jQuery is like crazy and the tooling is crazy as well. Well, that's actually true. I cannot deny that, okay? But I read a blog post like a week ago or something and I was talking about the JavaScript fatigue, right? Because everybody's complaining about JavaScript fatigue every two weeks or so you have a new package error, you have a new framework or so. And so we do experiment with this JavaScript fatigue, but there is also the JavaScript fatigue, right? And the guy was saying basically that's just like when you cook, well, it takes time, you're going to prepare something, but you prefer to do that instead of eating raw meat, right? And it was kind of fun and that's actually quite true. So I can talk about a French recipe. Do you know that it's Blanquette de Vaux? How many of you know about Blanquette de Vaux? A few of them? Yeah, okay. Well, that's something really famous in France and I do cook that from time to time for my family. And actually you need some medium-sized cubes of veal, right? You put lemon on it. And then you need lemon because you're going to boil it for a long time and if you don't put lemon, the meat is going to turn red or brown and with lemon it's going to keep white, okay? And if it's not white, that's not Blanquette, right? So that's really important. And you will need also a few carrots. You will need lorat, rosemary. You will need one onion, but you don't cut it. You just take the entire onion and you pin a clove on it. That's really important detail. And you're going to boil really slowly for one hour and a half, okay? But 20 minutes before it is cooked, you need to take a small amount of the juice and to blend it with flour and cook it with a strong fire in order to make something like a bechamel, right? You know, probably bechamel, but this is going to be the actual Blanquette sauce, right? So when it's all done, you can serve it together and it's really delicious, okay? So that's how you actually do Blanquette de Vaux, right? You can kill a veal and eat the raw meat, okay? Wow. Two approaches. Both are valid, but I do like Blanquette de Vaux, okay? So that's what it's about with JavaScript. We do need the complexity because we are doing complex stuff and at the end we get something with worth it, right? So that's the thing about why we should be accepting that JavaScript is complex, right? But now, regarding Plur itself, developing a CMS in JavaScript, why would we want that, okay? Really? Well, reason number one, right now, the entire web is shaped by JavaScript, right? There is no way you can avoid JavaScript. You need it everywhere. You see it everywhere. But it's not just about the techniques. It's not about the development itself. It's about the whole thing. Even when you're going to recruit someone, when you're going to have some order from your customers, the JavaScript is there. You might find some excellent JavaScript skill out there, but it might be difficult to find a good Python skill. So that's something you cannot avoid and that's part of our system right now. But CMS features are still a must-have. You need that. We cannot ask the users to use, well, Postman to make some JSON requests on the back-end server. Of course not. We do need the CMS features. They are useful even if everything is changing, the browsers are changing, going to have HTTP and so on. It makes no difference. The users are the same kind of people. They need CMS. I know if you heard about Contentful, Contentful is a product. It's not open source at all. And they're offering an Atlas CMS, right? It's an API and you can use it with whichever framework you want. And something bites me. Their headline is like a CMS without the bad bits, right? That's how they advertise themselves. I have the strange and bad feelings that the bad bits here, that's us, right? That's Plon or that might be WordPress or Drupal. That's what they're talking about here. And they're advertising their stuff that way saying, well, you know about the old stuff, the ugly stuff, the dirty stuff, Drupal, WordPress, Plon, whatever. We are different. We are offering something better, something you're going to like. Well, that's not necessarily true. Okay. But the message is not wrong. There are some audience out there which are actually wanting this kind of new tools. And, well, for instance, if you consider WordPress, WordPress is a world-leading CMS ever, right? But do you think we can ever beat WordPress on its own market? We cannot, right? We don't even try. Okay? But that's not important. What we need to think about is the next market, not the today market. And, well, I'm not sure the next market is going to be at the CMS, but it might be. And what I know about it is that when it's going to be the actual thing to do, there will be no difference anymore between WordPress or Plon or Drupal. Whoever is going to provide the right API is going to be the one who is going to get this market, right? Because it won't be anymore about how the backend is done, but how the API behaves and what kind of really to use component, JavaScript component you're going to offer to people. That's what will make a national difference. Why now is someone going to choose, as to choose a CMS, he might consider that PHP simple, something I know, maybe I'm going to prefer that. But tomorrow, that won't be relevant anymore. It will be only about how you can manage your JavaScript development using this CMS. So that's actually really relevant, right? So, what I think is we do know about CMSs, right? We don't just know about how Plon work, how to develop the upstuff or Python. We do know about CMS features. A lot. There's a lot of knowledge in whole community about that. So why not building a GS1, right? Why not? That was reason number one. Reason number two is something you might have experiment with Plon 5. Building front end into back end is painful, right? Ask Andreas Jung. He would tell you something about that, right? You have been playing maybe with bundles, with mockups and so on. And the whole idea to have all this stuff which is offering good and modern practices to build JavaScript stuff, but to put that into back end somehow, to have this connected to the registry and so on, that's painful, right? Why is it? Because that's not the natural way to go. Let's do front end the front end way. That makes sense, right? So let's forget about all this thing having the front end shared between back end and front and let's build everything for the front end way, right? That's actually good architecture. So what are we talking about? While this, NPM install Plon client. Maybe you should have said yarn install Plon client maybe. But yeah, the thing is don't type it, it won't work. It's not already on the NPM repository. It could be, but it's not. The Plon client is going to be the top part of this slide. This is the slide from the Rime on Talk and it's going to be the part on top of the API which provides everything about viewing the website, using the website, managing the content. Everything the user is going to see is going to be Plon client, right? And everything under that, the business model, the data model, the contentful and so on, are going to be managed by the server, right, through the API. So that's about handling the seeming, of course. What seeming CSS and GIS sounds quite okay to be managed in JavaScript in front end technology, right? But that's also that's really form or form lead. That's also templating, viewlets, portlets and all the fancy feature we can offer to the content manager, right? So the person going to manage the content so that could be covered by Mosaic for instance and everything you might imagine regarding configuring the website. So that's a lot, right? That's not that easy. What we are for now is something which is working on top of the API and the good thing about it is that it does work right now on Plon server which have been introduced by Raman, but also on Plon 5 with PlonRace API, okay? The same code, exactly the same one, going to behave the same way. And you might find the repository, you can play with it, it's actually working. It's in GitHub Plon, so it's not in GitHub Pyrenee as mentioned, Raman considering regarding the server because it does actually work with Plon 5, right? So you can use it the way it is and it can be actually a good way to play with it and see how you could use Plon server as well instead of Plon, why not? It actually doesn't make any difference between the two of them because of the API, that's all the point of having a REST API of course. So now, how is it done? It's built with Angular 2, okay? Angular 2 is quite new, it's been released this year, well, lately, I think it was in September, yeah, September. The releasing have been quite painful but now it's a really nice piece of software and something you can have a good feeling about, I think. It's based on components, right? So everything we might have referred to as viewlets or portlets are actually components and they are pure client-side components. So you can see the kind of code you're going to have. This could be your main template, basically you can have a Plon header, a Plon navigation, a Plon toolbar, Plon content, everything going to be a component, an actual component you would use as any HTML element, right? And this comes with a logic and some calls to the backend API, right? So that's quite clean, right? It works with registries, so we'll be able to have registries are there, we have implemented systems which does reproduce the same mechanism. So you can register a view, you can register a component, you can override an existing component with yours, this kind of thing which does work. It's not as rich and flexible as it's the SEA for now, but that's basically the idea. This was not provided by Angular 2, okay? Angular 2 is a framework and the people who are building it are focusing on, well, regular project, of course there are, and CMS is not a regular project. Making a CMS is like a big thing because when you have a CMS, you need to be able to build any website with it, while when you create an application, a JavaScript application, you are just targeting one use case, right? And so we need to provide something which is pluggable, customizable. So it means a lot in terms of architecture. So we are building some key things that we know does work for CMS because we have been doing that for a long, four years, and we are just using the same principle and turning it into Angular 2 mechanism, right? So we do have the registries. We do have something different than JavaScript as well. I know that Python developers are really reluctant to use JavaScript because it's kind of ugly, it's something you don't feel good about. TypeScript is actually really, really interesting language. It's nothing like CoffeeScript, for instance. You might have known what was CoffeeScript, it was basically changing the syntax of JavaScript. It's a superset. It's a superset of JavaScript ES6, all right? And what's really good about it? Okay, it's going to imply compilation, right? Transpillation, exactly. But you need it anyway when you're trying to do anything using the modern approach of JavaScript. You're going to need it for SAS or less, for instance, that's exactly the same for JavaScript. So it's not a big deal. And what you get in exchange of that is you get something really interesting to use. You have types, of course, that's TypeScript, so everything is typing. You can import stuff. So you can import a module. You can import something from an external dependency or something from your inner code. You just do it the exact same way as you do in Python. And you can forget about these crazy things like re-cry.js, which is actually useful and does work, but which is really ugly to write. And you can also forget about what we had, for instance, with Angular 1. All the dependency injection was really verbose. Then you just have a main module in Angular 2 where you're going to have all your injections performed, and then everything is going to be provided to the rest of your application. So all your code base is really clean. You just import such class from such file, such module, and it works exactly how you can expect. So very much like Python does. Of course, you have classes also. You have inheritance. You have decorators, which are really powerful. It makes all the things very readable and maintainable. Really, it's impressive. So what do we have for now? What do we get for now in PlonClient? Well, first thing, we have a basic Plon UI. You have seen the demo, kind of demo from Eric this morning. It was kind of crappy, but we were working on it yesterday, and it left at 6 p.m. and it was really too late. And we have everything fixed a few hours later. And yeah, he had to work on his slides, blah, blah, blah. Anyway, so now what do we have? We have all the elements of the PlonInFace componentized, right? So it's mean navigation, login, breadcrumbs, the fooder, search, toolbar, et cetera. Everything has been componentized. It means that's our elements you can use, but into a template, and it's going to work the way it is, right? We have a theme, so it's a classification of Barcelona. So that's quite straightforward. We took Barcelona to convert it into SAS, and that's how it works. The important thing about the theme, it can be overriding at build time. That's mean the theme is part of the Angular 2 application. So in a component, a typical Angular 2 component, you're going to have in the decorator of the component class, you're going to indicate which is your style. So you're going to be a SAS file, and which is your template. You're going to be a HTML file, right? But that's something that can be overriding when you build your actual project. Webpack is able to use preloaders, and preloaders are aware of any resource you are trying to get when you are building your bundle, and we have implemented a preloader for plant theme. And the thing, it's actually working very much like the portal skin custom thing. You're going to take the precedence on any resource which is named the same way and located at the same location. So if you are, for instance, logging.html somewhere, and you put in your custom folder, logging.html made differently, then automatically, Webpack is going to get that one and use yours instead of the different one, right? So that's how it works. It's not very... It does work. The principle is here is not something we have been testing a lot. For now, we are just working on Barcelona, right? I haven't experimented an actual usage of plant client with a completely different theme. I don't know if it works, actually. But the principle, the principle that you can override thing is easier, okay? We have server-side rendering. Wow. What do we need that? We are building a plant client. It's going to be running on the client side, I mean, any visitor of your website, go on a single-page app, basically, and it's going to get information from the backend and render it dynamically using your components. So that's probably enough. Well, the thing with Angular Universal is it's going to reproduce exactly the same behavior but on the server-side and serve really static pages to your users. It can be useful for first-time rendering, for instance, to improve the performances. It can be also useful for referencing somehow, for Googlebot, et cetera. And it might be useful in any case. So, for instance, if you don't want to offer a non-JavaScript enable website, that's also useful. So that's something which is there. We have a form generator, so that's basically the equivalent of what we had with Z3C form. As Timo explained, it's based on JSON schema. JSON schema is a standard format for schemas, right? And we have extended it because JSON schema is just about the data, right? So it made no difference between, like, a text area and a text input or a rich text. This is all string, right? This is about the data, how it is persisted, okay? So we have extended JSON schema in order to be able to declare everything we need about the widgets, right? About how the form is going to be, not necessarily the data. So it's quite advanced. It's working quite nicely. We had to develop it ourselves, unfortunately, even if it was quite kind of fun. There were some things really interesting in Angular 1, Angular schema form. And I've been using this module for a long time, and it was really, really good. But people there were not migrating to Angular 2 at the time we were, at the time we start plant clients. So I decided to start to our own thing. But I have been in touch with them, as I might be interested in collaborating. So maybe it's going to be the next version, I don't know. But for now, what we have, it's something very rich with all the different widgets you might need. You are able to register new widgets. You might also register new fields. So that's pretty much what you can do with plant. We have tiny MC. We have master slave. So you can have, for instance, a checkbox. And if the checkbox is checked, then you have a part of the form which is automatically displayed or hidden. We have data grid. So you can repeat, a sub-schema can be repeated as many times as you want, and you're going to create a data grid. So that's the kind of feature we have, which are pretty advanced, right? And it's all customizable, right? And this is a separate project than plant client. Plant client is using it as a dependency. It can be used elsewhere, and Roman is going to show you that. We have views. So we provide the basic views, like add, edit, view, search as well, log in and log out our views, and we can register views, right? And those views are actually processed by the client, and we traverse to the, we actually route to the right content in the IPI. The routing is not totally fine. I know I need to improve it, but it's actually work. So you can have any page of your website and add, and you're going to have the add view or edit, and you're going to go to the edit view, just like you have on your actual plant site. And this is something which is not common with AngularJS or any other framework, actually, because most part of people are focused on routing, right? That's how you do a single-page application. We don't. We cannot do that. We are running a CMS, right? We cannot say people there. All the pages are going to be in slash pages, blah, blah. No, we cannot do that. Of course, we don't want that. So here we had to imagine the way to manage that properly. And it goes, I mean, it's totally doable and does work nicely with AngularJS too, okay? But it's something you're not ready to use, basically. It's not part of the regular toolkit. So I'm going to show a demo. So that's Raymond computer, because I had some issue with mine. Yes, here we go. I need to log out, I see, first. So I have no idea if it's going to work, because I was supposed to run the demo of my machine and I just can't connect to the protector. But yeah, I'm quite confident. So that's what we have for now. So you can recognize Barcelona, right? This is the home page we can navigate. So you can see it's not reloading the page. It's just calling the backend to get the content. Yeah, I don't know what's the actual content. But anyway, so that's how you get as a visitor. We can log in. Do you know the login? It's admin, admin? Okay. So now we're logged and we get the toolbar, right? So I can go to, I can add a new folder, for instance. I don't have folders. This is a folder, I guess. Yes. Okay. I'll create a new page. Problems is a little click. No, well, it's not working. No matter, I'm going to go back to home and create something and just edit here. So here's where we get the form generator. So everything here, it's kind of messy, right? Because it's not ordering the stuff properly, but it's actually getting the different field set from the schema of the current content, which is a document, and rendering it with a different widget. So we have tiny MC here. Well, it's actually not a lot of version. This is a broken version. Anyway, so we can go back to view. Yeah, no, we cannot. It's all broken. So I don't even know if I can change the workflow. Maybe I can. Yes, I can. So it works. We can search also. So here you have results. So this is basically what you can do with it for now, right? It's not much, but it does work. Well, some part of it was not working in this demo, but that's something which is fixed. And yeah, it actually implements all those stuff I've been demoing or trying to demo. You can create new contents and new content in new contents. I mean, it does route, it does match the right rendering to the different view you have. It does everything you might need to actually manage content. It does not do anything about configuration, for instance. It does not allow to manage what could be types, for instance, with a mosaic equivalent. This is not done yet, but that's something we're going to do. So here is it for the demo. I don't think I need to show anything else. No, that's it. So go back to my slides. Okay. Yeah, now another demo about something different, but based on the kind of the same thing, the clone manager is something Raymond is going to demo. Well, the main idea is that we've been trying to do the clone client, and it's definitely really a lot of work. And I think that it will be, you see, doing what Eric has shown you, it's been like a lot of months dealing with how we deal with this kind of automatic generation of things that we don't clone in JavaScript. I think that we are going to focus on having more targeted applications that are built on top of the clone client, the REST API. Otherwise, if we try to create all the same that we have in the clone in JavaScript, we may end crazy or something worse. So this is an example of this idea. For instance, last week where I was thinking I should go to the clone conference, I would like to show something that is visible about the clone server, because as you know, as Eric said, how do you make people say, oh, wow, if you show code or terminal, it's really ugly. I was thinking, why don't you use what Eric has been working about this schema form, library, and Angular 2 material, this cool new stuff, and Nucleus on the rock, and Electron to create like a really prototype. So it's a prototype. It's really experimentally just to show the proof of concept, GMI, to work on a clone, on a desktop publication. So I had an afternoon, and yesterday Eric helped me to understand the Angular 2 schema form, and it's really nice, I can show you. So I need to switch from clone backend to clone server backend, and I need to stop the clone client, and I need to start the electron application of clone manager. So this is the, sorry, there is a lot of things here. I don't know if you can, yeah, I can do it full screen. So this is a simple electron application, so you can deliver that as an executable on Windows, Mac, Linux, whatever you want. It's built with Angular 2 and materials too, and it's using the clone client libraries for dealing with the schema. We are trying to create an API library using both ideas, so we have a JavaScript library to consume the rest of the API. So how it works, so we define here, I don't know if you see that, bigger, the kind of server you have, CMFplone, or clone server, you define the log of the server, the ZUDB, the site, the port, you can create new sites, you can define the authentication if it's basic, it also supports you to get the token from an OAuth server, and when you have all these things configured, you can go to browser, and okay, I'm not a designer, so sorry, this is the root of the clone site, where I get the sharing permissions, the local and the generic permissions with the roles of the users, and I get a list of content, so I have like different content here, and I can go to this one, and it shows me the metadata information, and I can go again to Paran, and I can go again to this document with all the sharing information, all the fields. And since yesterday, we are able to create a new document on this place, this is using the schema form, blah, blah, Blonkampf, text, whatever, save, and now I just got a new document inside my folder, it's called Blonkampf, and I can go there and just see it. This application also supports exposing all the registry information that we have, this is the case of the clone server, that it's a really small registry, there is only this option right now, and all the types that we have registered on the clone, so you can browse there. So, it's quite simple, use case to consume the API, building a desktop application to do whatever, so the imagination is the limit here, so we can create applications for the blog site, to create applications for dealing with a document, or a stock management, or whatever you want to focus on a specific solution and deliver binary applications or web applications that fulfill the needs, and I just want to show this idea. Okay, thank you, Roman. So, that's just a basic reuse of some components involved in the client, and it has been set up in a very different way, and it's sort of a different objective, so that's interesting about the flexibility of the whole thing. What we plan for the near future is to have first something like Mosaic, that's something that Roman already worked on, it sounds totally possible to do that quite easily, actually. We're going to reuse the same principle as Mosaic, we're going to save the layout as an HTML template, and we're going to render in this layout the different types we want, the fields or whatever it might be, okay? And this is something which is really quite easy to do with Angular 2. We also want to have a clip, so basically the ability to create a new plan project, so you're going to go plan, create my new plan, and you're going to set up an Angular 2 project for you with all the dependency you might need, and then you can start customizing stuff, creating new theme, creating new components or views or whatever. We also want to support traversal better ways, because right now we are using the default routing from Angular 1, Angular 2, and it's basically really stupid, we just are matching all the routes, so star, star, everything, to a single component which does parse manually the current pass, and then detect what's going to be the URL of the backend equivalent of the current object, except what's going to be the view name, and then render it properly. It's not how we want to do it, because Angular 2 allowed to create your own resolver for the routing, so we plan to have an actual traversing mechanism for Angular 2, and we're going to implement that. We also plan to provide a plan front-end API. For now, the plan client is just like a big project with all the components and all the interface. We're doing the same thing, and we cannot really depend on this and build a site from scratch. We want to extract everything which is about dealing with the backend, rendering the different components, having all the utilities you are made into an API, so you can then create your own project using this API, and your project is going to be really clean, really simple, just focusing on what you want to do exactly. That's something which we need to do, and we also want to provide very simple, reusable examples. We are thinking, for instance, like creating a blog website, where you can post blogs and display the blogs, having categories, kind of stuff, so something really simple, but that would be interesting because it can be reused, so someone which is totally not a plan developer can take it and create a blog and create all these Angular 2 things he knows about and have something working, and it's going to be also really interesting to understand how it works and how you can reuse and how you can understand, plan client, and get involved in the whole thing because for now it's kind of, as Raymond said, probably too big. We are trying to do everything Planned Destroy is actually doing. That's too much, probably too soon, so we want to provide something much cleaner, simpler, right? That's what we plan for the future. So that's it. Any questions? Thank you very much. Second, kind of simple, you were showing 4Ls and didn't have a hash of them. So are you saying that Planned Servers back in support of Station All 5 push back in? Yeah, it's using, yeah, it's not using the old way of routing using the Azure. It could be switched on or off. That's really easy, but basically nobody wants that. Okay, right. Second thing is, you talk about having a CLI, but for people who just want to consume it and make it very like what Raymond was saying about a specific app, the general CLI, and they want to use Angular CLI. Are you going to support that? Yeah, we're actually using Angular CLI, right? So what we want to do is something just like Ionic people are doing right now. You know Ionic maybe? Okay. They do have a clue, so you can really easily create a new Ionic application and then inside that you can use the NG client. Okay, so that's we are not replacing the NG client at all. We just are making the equivalent of Mr. Bob, for instance. You're going to initialize a build out and a titan eggs for you with all the rights that you need to have a Planned Project, what is going to be exactly the same with Planned Client with Angular, right? That's what we need to do. You mentioned TypeScript. I wasn't clear. Is that something that you introduced? Oh no. Or is it part of Angular 2 or where does it come from? Well, it comes from Microsoft. No, I mean in this context. Because Angular 2 is based on TypeScript, right? You can use Angular 2 without TypeScript, but that would be really stupid. All the good thing about it is you do use TypeScript to do Angular 2 and that makes it really wonderful. For instance, just declaring a component is just as beautiful and elegant as declaring a Planned Adapter, for instance. Just a few decorators and yes, I just know that's email, right? It's more a grok approach of the thing, but yes, it's really, really clean. And it makes it all different to me. Really. I mean, I really love Python and I enjoy programming JavaScript. It's always kind of painful to see how ugly it is. This is really different, right? And the good thing about it is it is a super set. So you can still write JavaScript thing. It's going to work. So someone with an actual front-end developer would be okay with that. But a Python developer would be okay with that too. So that's really good. I think it's a very good thing. Okay. If you have two clients connected to your back-end and one client, say, adds a page, will the other client see the new page without doing a reload? Right now, no. But Planned Server will provide a WebSocket. So that's exactly how you're going to work. Absolutely. So right now, WebSocket are here, but the Planned clients are not using it to get information back from the server when it's actually displaying something. So that's quite easy to implement because the whole idea of Planned Server is to have this server because we want that, of course. We do want that. Okay. Well, thank you very much.
 Hello everybody.  My name is Eric Barrow and I'm going to talk to you about JavaScript from Client, which  I've been introduced by Eric in this keynote this morning.  Yeah, I know the word here which is kind of boring is JavaScript, right?  So I made a small poll on Twitter, I asked, yeah, recording this 3C form in GIS sounds  smart, stupid, or seriously?  Well, first reaction was, yeah, seriously?  How are we doing that?  Well, I know a lot of people are complaining about modern GIS is really too complicated,  right?  It's like changing every time you have every time something new to learn and the process  to build even a very simple thing you could do with two lines of jQuery is like crazy  and the tooling is crazy as well.  Well, that's actually true.  I cannot deny that, okay?  But I read a blog post like a week ago or something and I was talking about the JavaScript  fatigue, right?  Because everybody's complaining about JavaScript fatigue every two weeks or so you have a new  package error, you have a new framework or so.  And so we do experiment with this JavaScript fatigue, but there is also the JavaScript  fatigue, right?  And the guy was saying basically that's just like when you cook, well, it takes time, you're  going to prepare something, but you prefer to do that instead of eating raw meat, right?  And it was kind of fun and that's actually quite true.  So I can talk about a French recipe.  Do you know that it's Blanquette de Vaux?  How many of you know about Blanquette de Vaux?  A few of them?  Yeah, okay.  Well, that's something really famous in France and I do cook that from time to time for my  family.  And actually you need some medium-sized cubes of veal, right?  You put lemon on it.  And then you need lemon because you're going to boil it for a long time and if you don't  put lemon, the meat is going to turn red or brown and with lemon it's going to keep white,  okay?  And if it's not white, that's not Blanquette, right?  So that's really important.  And you will need also a few carrots.  You will need lorat, rosemary.  You will need one onion, but you don't cut it.  You just take the entire onion and you pin a clove on it.  That's really important detail.  And you're going to boil really slowly for one hour and a half, okay?  But 20 minutes before it is cooked, you need to take a small amount of the juice and to  blend it with flour and cook it with a strong fire in order to make something like a bechamel,  right?  You know, probably bechamel, but this is going to be the actual Blanquette sauce, right?  So when it's all done, you can serve it together and it's really delicious, okay?  So that's how you actually do Blanquette de Vaux, right?  You can kill a veal and eat the raw meat, okay?  Wow.  Two approaches.  Both are valid, but I do like Blanquette de Vaux, okay?  So that's what it's about with JavaScript.  We do need the complexity because we are doing complex stuff and at the end we get something  with worth it, right?  So that's the thing about why we should be accepting that JavaScript is complex, right?  But now, regarding Plur itself, developing a CMS in JavaScript, why would we want that,  okay?  Really?  Well, reason number one, right now, the entire web is shaped by JavaScript, right?  There is no way you can avoid JavaScript.  You need it everywhere.  You see it everywhere.  But it's not just about the techniques.  It's not about the development itself.  It's about the whole thing.  Even when you're going to recruit someone, when you're going to have some order from  your customers, the JavaScript is there.  You might find some excellent JavaScript skill out there, but it might be difficult to find  a good Python skill.  So that's something you cannot avoid and that's part of our system right now.  But CMS features are still a must-have.  You need that.  We cannot ask the users to use, well, Postman to make some JSON requests on the back-end  server.  Of course not.  We do need the CMS features.  They are useful even if everything is changing, the browsers are changing, going to have HTTP  and so on.  It makes no difference.  The users are the same kind of people.  They need CMS.  I know if you heard about Contentful, Contentful is a product.  It's not open source at all.  And they're offering an Atlas CMS, right?  It's an API and you can use it with whichever framework you want.  And something bites me.  Their headline is like a CMS without the bad bits, right?  That's how they advertise themselves.  I have the strange and bad feelings that the bad bits here, that's us, right?  That's Plon or that might be WordPress or Drupal.  That's what they're talking about here.  And they're advertising their stuff that way saying, well, you know about the old stuff,  the ugly stuff, the dirty stuff, Drupal, WordPress, Plon, whatever.  We are different.  We are offering something better, something you're going to like.  Well, that's not necessarily true.  Okay.  But the message is not wrong.  There are some audience out there which are actually wanting this kind of new tools.  And, well, for instance, if you consider WordPress, WordPress is a world-leading CMS ever, right?  But do you think we can ever beat WordPress on its own market?  We cannot, right?  We don't even try.  Okay?  But that's not important.  What we need to think about is the next market, not the today market.  And, well, I'm not sure the next market is going to be at the CMS, but it might be.  And what I know about it is that when it's going to be the actual thing to do, there  will be no difference anymore between WordPress or Plon or Drupal.  Whoever is going to provide the right API is going to be the one who is going to get  this market, right?  Because it won't be anymore about how the backend is done, but how the API behaves and  what kind of really to use component, JavaScript component you're going to offer to people.  That's what will make a national difference.  Why now is someone going to choose, as to choose a CMS, he might consider that PHP simple,  something I know, maybe I'm going to prefer that.  But tomorrow, that won't be relevant anymore.  It will be only about how you can manage your JavaScript development using this CMS.  So that's actually really relevant, right?  So, what I think is we do know about CMSs, right?  We don't just know about how Plon work, how to develop the upstuff or Python.  We do know about CMS features.  A lot.  There's a lot of knowledge in whole community about that.  So why not building a GS1, right?  Why not?  That was reason number one.  Reason number two is something you might have experiment with Plon 5.  Building front end into back end is painful, right?  Ask Andreas Jung.  He would tell you something about that, right?  You have been playing maybe with bundles, with mockups and so on.  And the whole idea to have all this stuff which is offering good and modern practices  to build JavaScript stuff, but to put that into back end somehow, to have this connected  to the registry and so on, that's painful, right?  Why is it?  Because that's not the natural way to go.  Let's do front end the front end way.  That makes sense, right?  So let's forget about all this thing having the front end shared between back end and  front and let's build everything for the front end way, right?  That's actually good architecture.  So what are we talking about?  While this, NPM install Plon client.  Maybe you should have said yarn install Plon client maybe.  But yeah, the thing is don't type it, it won't work.  It's not already on the NPM repository.  It could be, but it's not.  The Plon client is going to be the top part of this slide.  This is the slide from the Rime on Talk and it's going to be the part on top of the API  which provides everything about viewing the website, using the website, managing the content.  Everything the user is going to see is going to be Plon client, right?  And everything under that, the business model, the data model, the contentful and so on,  are going to be managed by the server, right, through the API.  So that's about handling the seeming, of course.  What seeming CSS and GIS sounds quite okay to be managed in JavaScript in front end technology,  right?  But that's also that's really form or form lead.  That's also templating, viewlets, portlets and all the fancy feature we can offer to  the content manager, right?  So the person going to manage the content so that could be covered by Mosaic for instance  and everything you might imagine regarding configuring the website.  So that's a lot, right?  That's not that easy.  What we are for now is something which is working on top of the API and the good thing  about it is that it does work right now on Plon server which have been introduced by  Raman, but also on Plon 5 with PlonRace API, okay?  The same code, exactly the same one, going to behave the same way.  And you might find the repository, you can play with it, it's actually working.  It's in GitHub Plon, so it's not in GitHub Pyrenee as mentioned, Raman considering regarding  the server because it does actually work with Plon 5, right?  So you can use it the way it is and it can be actually a good way to play with it and  see how you could use Plon server as well instead of Plon, why not?  It actually doesn't make any difference between the two of them because of the API, that's  all the point of having a REST API of course.  So now, how is it done?  It's built with Angular 2, okay?  Angular 2 is quite new, it's been released this year, well, lately, I think it was in  September, yeah, September.  The releasing have been quite painful but now it's a really nice piece of software and  something you can have a good feeling about, I think.  It's based on components, right?  So everything we might have referred to as viewlets or portlets are actually components  and they are pure client-side components.  So you can see the kind of code you're going to have.  This could be your main template, basically you can have a Plon header, a Plon navigation,  a Plon toolbar, Plon content, everything going to be a component, an actual component you  would use as any HTML element, right?  And this comes with a logic and some calls to the backend API, right?  So that's quite clean, right?  It works with registries, so we'll be able to have registries are there, we have implemented  systems which does reproduce the same mechanism.  So you can register a view, you can register a component, you can override an existing  component with yours, this kind of thing which does work.  It's not as rich and flexible as it's the SEA for now, but that's basically the idea.  This was not provided by Angular 2, okay?  Angular 2 is a framework and the people who are building it are focusing on, well, regular  project, of course there are, and CMS is not a regular project.  Making a CMS is like a big thing because when you have a CMS, you need to be able to build  any website with it, while when you create an application, a JavaScript application,  you are just targeting one use case, right?  And so we need to provide something which is pluggable, customizable.  So it means a lot in terms of architecture.  So we are building some key things that we know does work for CMS because we have been  doing that for a long, four years, and we are just using the same principle and turning  it into Angular 2 mechanism, right?  So we do have the registries.  We do have something different than JavaScript as well.  I know that Python developers are really reluctant to use JavaScript because it's kind of ugly,  it's something you don't feel good about.  TypeScript is actually really, really interesting language.  It's nothing like CoffeeScript, for instance.  You might have known what was CoffeeScript, it was basically changing the syntax of JavaScript.  It's a superset.  It's a superset of JavaScript ES6, all right?  And what's really good about it?  Okay, it's going to imply compilation, right?  Transpillation, exactly.  But you need it anyway when you're trying to do anything using the modern approach of  JavaScript.  You're going to need it for SAS or less, for instance, that's exactly the same for JavaScript.  So it's not a big deal.  And what you get in exchange of that is you get something really interesting to use.  You have types, of course, that's TypeScript, so everything is typing.  You can import stuff.  So you can import a module.  You can import something from an external dependency or something from your inner code.  You just do it the exact same way as you do in Python.  And you can forget about these crazy things like re-cry.js, which is actually useful and  does work, but which is really ugly to write.  And you can also forget about what we had, for instance, with Angular 1.  All the dependency injection was really verbose.  Then you just have a main module in Angular 2 where you're going to have all your injections  performed, and then everything is going to be provided to the rest of your application.  So all your code base is really clean.  You just import such class from such file, such module, and it works exactly how you  can expect.  So very much like Python does.  Of course, you have classes also.  You have inheritance.  You have decorators, which are really powerful.  It makes all the things very readable and maintainable.  Really, it's impressive.  So what do we have for now?  What do we get for now in PlonClient?  Well, first thing, we have a basic Plon UI.  You have seen the demo, kind of demo from Eric this morning.  It was kind of crappy, but we were working on it yesterday, and it left at 6 p.m. and  it was really too late.  And we have everything fixed a few hours later.  And yeah, he had to work on his slides, blah, blah, blah.  Anyway, so now what do we have?  We have all the elements of the PlonInFace componentized, right?  So it's mean navigation, login, breadcrumbs, the fooder, search, toolbar, et cetera.  Everything has been componentized.  It means that's our elements you can use, but into a template, and it's going to work  the way it is, right?  We have a theme, so it's a classification of Barcelona.  So that's quite straightforward.  We took Barcelona to convert it into SAS, and that's how it works.  The important thing about the theme, it can be overriding at build time.  That's mean the theme is part of the Angular 2 application.  So in a component, a typical Angular 2 component, you're going to have in the decorator of the  component class, you're going to indicate which is your style.  So you're going to be a SAS file, and which is your template.  You're going to be a HTML file, right?  But that's something that can be overriding when you build your actual project.  Webpack is able to use preloaders, and preloaders are aware of any resource you are trying to  get when you are building your bundle, and we have implemented a preloader for plant  theme.  And the thing, it's actually working very much like the portal skin custom thing.  You're going to take the precedence on any resource which is named the same way and located  at the same location.  So if you are, for instance, logging.html somewhere, and you put in your custom folder,  logging.html made differently, then automatically, Webpack is going to get that one and use yours  instead of the different one, right?  So that's how it works.  It's not very...  It does work.  The principle is here is not something we have been testing a lot.  For now, we are just working on Barcelona, right?  I haven't experimented an actual usage of plant client with a completely different theme.  I don't know if it works, actually.  But the principle, the principle that you can override thing is easier, okay?  We have server-side rendering.  Wow.  What do we need that?  We are building a plant client.  It's going to be running on the client side, I mean, any visitor of your website, go on  a single-page app, basically, and it's going to get information from the backend and render  it dynamically using your components.  So that's probably enough.  Well, the thing with Angular Universal is it's going to reproduce exactly the same behavior  but on the server-side and serve really static pages to your users.  It can be useful for first-time rendering, for instance, to improve the performances.  It can be also useful for referencing somehow, for Googlebot, et cetera.  And it might be useful in any case.  So, for instance, if you don't want to offer a non-JavaScript enable website, that's also  useful.  So that's something which is there.  We have a form generator, so that's basically the equivalent of what we had with Z3C form.  As Timo explained, it's based on JSON schema.  JSON schema is a standard format for schemas, right?  And we have extended it because JSON schema is just about the data, right?  So it made no difference between, like, a text area and a text input or a rich text.  This is all string, right?  This is about the data, how it is persisted, okay?  So we have extended JSON schema in order to be able to declare everything we need about  the widgets, right?  About how the form is going to be, not necessarily the data.  So it's quite advanced.  It's working quite nicely.  We had to develop it ourselves, unfortunately, even if it was quite kind of fun.  There were some things really interesting in Angular 1, Angular schema form.  And I've been using this module for a long time, and it was really, really good.  But people there were not migrating to Angular 2 at the time we were, at the time we start  plant clients.  So I decided to start to our own thing.  But I have been in touch with them, as I might be interested in collaborating.  So maybe it's going to be the next version, I don't know.  But for now, what we have, it's something very rich with all the different widgets you  might need.  You are able to register new widgets.  You might also register new fields.  So that's pretty much what you can do with plant.  We have tiny MC.  We have master slave.  So you can have, for instance, a checkbox.  And if the checkbox is checked, then you have a part of the form which is automatically  displayed or hidden.  We have data grid.  So you can repeat, a sub-schema can be repeated as many times as you want, and you're going  to create a data grid.  So that's the kind of feature we have, which are pretty advanced, right?  And it's all customizable, right?  And this is a separate project than plant client.  Plant client is using it as a dependency.  It can be used elsewhere, and Roman is going to show you that.  We have views.  So we provide the basic views, like add, edit, view, search as well, log in and log out our  views, and we can register views, right?  And those views are actually processed by the client, and we traverse to the, we actually  route to the right content in the IPI.  The routing is not totally fine.  I know I need to improve it, but it's actually work.  So you can have any page of your website and add, and you're going to have the add view  or edit, and you're going to go to the edit view, just like you have on your actual plant  site.  And this is something which is not common with AngularJS or any other framework, actually,  because most part of people are focused on routing, right?  That's how you do a single-page application.  We don't.  We cannot do that.  We are running a CMS, right?  We cannot say people there.  All the pages are going to be in slash pages, blah, blah.  No, we cannot do that.  Of course, we don't want that.  So here we had to imagine the way to manage that properly.  And it goes, I mean, it's totally doable and does work nicely with AngularJS too, okay?  But it's something you're not ready to use, basically.  It's not part of the regular toolkit.  So I'm going to show a demo.  So that's Raymond computer, because I had some issue with mine.  Yes, here we go.  I need to log out, I see, first.  So I have no idea if it's going to work, because I was supposed to run the demo of my machine  and I just can't connect to the protector.  But yeah, I'm quite confident.  So that's what we have for now.  So you can recognize Barcelona, right?  This is the home page we can navigate.  So you can see it's not reloading the page.  It's just calling the backend to get the content.  Yeah, I don't know what's the actual content.  But anyway, so that's how you get as a visitor.  We can log in.  Do you know the login?  It's admin, admin?  Okay.  So now we're logged and we get the toolbar, right?  So I can go to, I can add a new folder, for instance.  I don't have folders.  This is a folder, I guess.  Yes.  Okay.  I'll create a new page.  Problems is a little click.  No, well, it's not working.  No matter, I'm going to go back to home and create something and just edit here.  So here's where we get the form generator.  So everything here, it's kind of messy, right?  Because it's not ordering the stuff properly, but it's actually getting the different field  set from the schema of the current content, which is a document, and rendering it with  a different widget.  So we have tiny MC here.  Well, it's actually not a lot of version.  This is a broken version.  Anyway, so we can go back to view.  Yeah, no, we cannot.  It's all broken.  So I don't even know if I can change the workflow.  Maybe I can.  Yes, I can.  So it works.  We can search also.  So here you have results.  So this is basically what you can do with it for now, right?  It's not much, but it does work.  Well, some part of it was not working in this demo, but that's something which is fixed.  And yeah, it actually implements all those stuff I've been demoing or trying to demo.  You can create new contents and new content in new contents.  I mean, it does route, it does match the right rendering to the different view you have.  It does everything you might need to actually manage content.  It does not do anything about configuration, for instance.  It does not allow to manage what could be types, for instance, with a mosaic equivalent.  This is not done yet, but that's something we're going to do.  So here is it for the demo.  I don't think I need to show anything else.  No, that's it.  So go back to my slides.  Okay.  Yeah, now another demo about something different, but based on the kind of the same thing, the  clone manager is something Raymond is going to demo.  Well, the main idea is that we've been trying to do the clone client, and it's definitely  really a lot of work.  And I think that it will be, you see, doing what Eric has shown you, it's been like a  lot of months dealing with how we deal with this kind of automatic generation of things  that we don't clone in JavaScript.  I think that we are going to focus on having more targeted applications that are built  on top of the clone client, the REST API.  Otherwise, if we try to create all the same that we have in the clone in JavaScript, we  may end crazy or something worse.  So this is an example of this idea.  For instance, last week where I was thinking I should go to the clone conference, I would  like to show something that is visible about the clone server, because as you know, as  Eric said, how do you make people say, oh, wow, if you show code or terminal, it's really  ugly.  I was thinking, why don't you use what Eric has been working about this schema form, library,  and Angular 2 material, this cool new stuff, and Nucleus on the rock, and Electron to create  like a really prototype.  So it's a prototype.  It's really experimentally just to show the proof of concept, GMI, to work on a clone,  on a desktop publication.  So I had an afternoon, and yesterday Eric helped me to understand the Angular 2 schema form,  and it's really nice, I can show you.  So I need to switch from clone backend to clone server backend, and I need to stop the  clone client, and I need to start the electron application of clone manager.  So this is the, sorry, there is a lot of things here.  I don't know if you can, yeah, I can do it full screen.  So this is a simple electron application, so you can deliver that as an executable on  Windows, Mac, Linux, whatever you want.  It's built with Angular 2 and materials too, and it's using the clone client libraries  for dealing with the schema.  We are trying to create an API library using both ideas, so we have a JavaScript library  to consume the rest of the API.  So how it works, so we define here, I don't know if you see that, bigger, the kind of  server you have, CMFplone, or clone server, you define the log of the server, the ZUDB,  the site, the port, you can create new sites, you can define the authentication if it's  basic, it also supports you to get the token from an OAuth server, and when you have all  these things configured, you can go to browser, and okay, I'm not a designer, so sorry, this  is the root of the clone site, where I get the sharing permissions, the local and the  generic permissions with the roles of the users, and I get a list of content, so I have  like different content here, and I can go to this one, and it shows me the metadata  information, and I can go again to Paran, and I can go again to this document with all the  sharing information, all the fields.  And since yesterday, we are able to create a new document on this place, this is using  the schema form, blah, blah, Blonkampf, text, whatever, save, and now I just got a new document  inside my folder, it's called Blonkampf, and I can go there and just see it.  This application also supports exposing all the registry information that we have, this  is the case of the clone server, that it's a really small registry, there is only this  option right now, and all the types that we have registered on the clone, so you can browse  there.  So, it's quite simple, use case to consume the API, building a desktop application to  do whatever, so the imagination is the limit here, so we can create applications for the  blog site, to create applications for dealing with a document, or a stock management, or  whatever you want to focus on a specific solution and deliver binary applications or web applications  that fulfill the needs, and I just want to show this idea.  Okay, thank you, Roman. So, that's just a basic reuse of some components involved in  the client, and it has been set up in a very different way, and it's sort of a different  objective, so that's interesting about the flexibility of the whole thing.  What we plan for the near future is to have first something like Mosaic, that's something  that Roman already worked on, it sounds totally possible to do that quite easily, actually.  We're going to reuse the same principle as Mosaic, we're going to save the layout as  an HTML template, and we're going to render in this layout the different types we want,  the fields or whatever it might be, okay? And this is something which is really quite  easy to do with Angular 2. We also want to have a clip, so basically the ability to create  a new plan project, so you're going to go plan, create my new plan, and you're going  to set up an Angular 2 project for you with all the dependency you might need, and then  you can start customizing stuff, creating new theme, creating new components or views  or whatever. We also want to support traversal better ways, because right now we are using  the default routing from Angular 1, Angular 2, and it's basically really stupid, we just  are matching all the routes, so star, star, everything, to a single component which does  parse manually the current pass, and then detect what's going to be the URL of the backend  equivalent of the current object, except what's going to be the view name, and then render  it properly. It's not how we want to do it, because Angular 2 allowed to create your own  resolver for the routing, so we plan to have an actual traversing mechanism for Angular  2, and we're going to implement that. We also plan to provide a plan front-end API. For  now, the plan client is just like a big project with all the components and all the interface.  We're doing the same thing, and we cannot really depend on this and build a site from  scratch. We want to extract everything which is about dealing with the backend, rendering  the different components, having all the utilities you are made into an API, so you can then  create your own project using this API, and your project is going to be really clean,  really simple, just focusing on what you want to do exactly. That's something which we need  to do, and we also want to provide very simple, reusable examples. We are thinking, for instance,  like creating a blog website, where you can post blogs and display the blogs, having categories,  kind of stuff, so something really simple, but that would be interesting because it can  be reused, so someone which is totally not a plan developer can take it and create a  blog and create all these Angular 2 things he knows about and have something working,  and it's going to be also really interesting to understand how it works and how you can  reuse and how you can understand, plan client, and get involved in the whole thing because  for now it's kind of, as Raymond said, probably too big. We are trying to do everything Planned  Destroy is actually doing. That's too much, probably too soon, so we want to provide something  much cleaner, simpler, right? That's what we plan for the future. So that's it. Any questions?  Thank you very much.  Second, kind of simple, you were showing 4Ls and didn't have a hash of them. So are you  saying that Planned Servers back in support of Station All 5 push back in?  Yeah, it's using, yeah, it's not using the old way of routing using the Azure. It could  be switched on or off. That's really easy, but basically nobody wants that. Okay, right.  Second thing is, you talk about having a CLI, but for people who just want to consume it  and make it very like what Raymond was saying about a specific app, the general CLI, and  they want to use Angular CLI. Are you going to support that?  Yeah, we're actually using Angular CLI, right? So what we want to do is something just like  Ionic people are doing right now. You know Ionic maybe? Okay. They do have a clue, so  you can really easily create a new Ionic application and then inside that you can use the NG client.  Okay, so that's we are not replacing the NG client at all. We just are making the equivalent  of Mr. Bob, for instance. You're going to initialize a build out and a titan eggs for  you with all the rights that you need to have a Planned Project, what is going to be exactly  the same with Planned Client with Angular, right? That's what we need to do.  You mentioned TypeScript. I wasn't clear. Is that something that you introduced?  Oh no. Or is it part of Angular 2 or where does it come from?  Well, it comes from Microsoft. No, I mean in this context.  Because Angular 2 is based on TypeScript, right? You can use Angular 2 without TypeScript,  but that would be really stupid. All the good thing about it is you do use TypeScript to do  Angular 2 and that makes it really wonderful. For instance, just declaring a component is  just as beautiful and elegant as declaring a Planned Adapter, for instance. Just a few  decorators and yes, I just know that's email, right? It's more a grok approach of the thing,  but yes, it's really, really clean. And it makes it all different to me. Really. I mean,  I really love Python and I enjoy programming JavaScript. It's always kind of painful to  see how ugly it is. This is really different, right? And the good thing about it is it is  a super set. So you can still write JavaScript thing. It's going to work. So someone with  an actual front-end developer would be okay with that. But a Python developer would be  okay with that too. So that's really good. I think it's a very good thing. Okay.  If you have two clients connected to your back-end and one client, say, adds a page,  will the other client see the new page without doing a reload?  Right now, no. But Planned Server will provide a WebSocket. So that's exactly how you're  going to work. Absolutely. So right now, WebSocket are here, but the Planned clients are not  using it to get information back from the server when it's actually displaying something.  So that's quite easy to implement because the whole idea of Planned Server is to have this  server because we want that, of course. We do want that. Okay. Well, thank you very much.
Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_0_59.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_60_155.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_156_239.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_240_1007.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_1008_4883.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_4884_5231.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_5232_5279.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_5280_6863.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_6864_7643.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_7644_10871.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_10872_11267.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_11268_11855.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_11856_13115.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_13116_13631.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_13632_17159.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_17160_17807.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_17808_20831.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_20832_23987.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_23988_25559.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_25560_30047.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_30048_35627.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_35628_35735.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_35736_35987.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_35988_36395.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_36396_38567.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_38568_39047.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_39048_39179.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_39180_41555.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_41556_44639.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_44640_44987.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_44988_45215.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_45216_46307.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_46308_46427.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_46428_46487.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_46488_46535.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_46536_46943.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_46944_47123.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_47124_47219.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_47220_47267.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_47268_47327.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_47328_47399.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_47400_47843.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_47844_47987.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_47988_49319.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_49320_49367.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_49368_52463.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_52464_54947.png Day_1__A_JavaScript_Plone_Client__by_Eric_Brehault_Mcrcm0HGN48_54948_61228.png