Customizing Printer Frontend

To allow vendors to deliver printers with their own ideas on what a frontend should contain and look like we publish
these original sources. You can modify and compile them. Copy the modified version into the shadow www directory at the
same place and your version will be used instead of the original. That way you can modify anything in the frontend.
Also this is possible you should be aware or one drawback of this concept. With every update from us there is the
possibility that we introduce new features or css rules that are required. So you should not deliver the original
server version to client but a encapsulated version. This encapsulated version installs first you adapted shadow
system data and then runs the original installer from our server. To achieve this add your custom config override script.
For linux this would be

/var/lib/RepetierServer/database/RepetierServer.xml

for other os use the according storage directory. To change download info for updates, shadow directory and name it would
look like this:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<server>
    <update-info-url>http://download.repetier-server.com/files/server/mac/updateinfo.txt</update-info-url>
<branding>
    <shadow-www-directory>path-of-www-shadow</shadow-www-directory>
    <branded-name>Your Server Name</branded-name>
</branding>
</server>

Prepare compilation

The build system uses NodeJS and npm to compile the sources. Make sure they are installed in reachable over your path
variable. Then download and unzip them.

Download the sources for 0.93.0

Download the sources for 0.92.2

Download the sources for 0.92.1

Download the sources for 0.92.0

Download the sources for 0.91.1 and 0.91.2

Download the sources for 0.91.0

Download the sources for 0.90.7

Download the sources for 0.90.6

Download the sources for 0.90.1

Download the sources for 0.86.2

Compile

Version 0.91.0 or newer

Starting with release 0.91.0 we did a big update to touchscreen frontend code and structure. The code was updated from Angular 2 to Angular 7. Also the build system was completely replaced by the current ng builder for angular. This makes many things much easier. To help building the different parts we now rely on gulp and some preset scripts, so all you need to do is call gulp with the wanted action. First install all required packages:

> npm install
> npm install gulp-cli -g
> npm install -g @angular/cli

On some OS you might need to add sudo at the beginning for the last 2 install lines. After that is done you have all required modules and the gulp + angular cli installed, so you can start.

The sources contain an empty directory shadow – this will be your shadow directory that you use to overwrite the servers default content. Files you can add with this library are the css and the touchscreen apps for registration and controlling the printer. Watch our what you want to change. Once you have new files, you need to provide updates to them with any server update or your users may not get fixes or improvements. All following compile commands need to be executed in a terminal inside the RSTouchscreenNG folder.

Compiling new stylesheet only:

> gulp

Compile only the touchscreen sources:

> gulp prod

Compile everything:

>gulp all

Modify Stylesheet

Modifying the stylesheet is quite simple if you only need some colors or want other fonts/sizes. All definitions are stored in projects/style/style with ui.scss as root file creating the final stylesheet. If you look into it, you see there are several breakpoints that get loaded. Each breakpoint has a resolution dependent config and the general blocks/_variables.scss file where the general parameter for all resolutions are defined. Modify them to your needs, compile stylesheet and reload to see how it looks like. If you see no changes you might have not set the shadow directory to your shadow directory you compile into or not restarted the Repetier-Server.

Modify Application

The Applications are split into 5 parts.

  • Repetier-Server Interface Library: projects/binding/src/lib
  • Interface Widgets Library: projects/front-ui/src/lib
  • Pages Library: projects/pages/lib
  • Registration App: projects/register/src/app
  • Regular Interface App: src/app

What you want is a solution that is easy to update to new versions. Therefore the libraries should normally never be changed. The first 2 is quite clear, for the pages you might say you want to change a page so it has some buttons removed or added. That is easy to understand, but while it looks simple to modify them it is not the best solution. A much better solution is to inherit a page you want to modify and only change what you need to have changed. I will show the dashboard as an example. There you most likely will add new items or reorder/remove icons. All files we will create and modify will be in the src/app folder. First we create a new component file mydashboard.component.ts with this content:

import {Component} from '@angular/core';
import {DashboardComponent} from 'pages';

@Component({
    selector: "my-dashboard",
    template: `
<rs-page>
<rs-side>
    <rs-sideicon title="<?php _('Home') ?>" icon="fa fa-home" link="/"></rs-sideicon>
</rs-side><rs-side *rsIfConnected="true">
    <rs-sideicon *rsIfPrinting="true" title="<?php _('Print') ?>" icon="rs rs-print" link="/print-status"></rs-sideicon>
    <rs-sideicon *rsIfPrinting="false" icon="rs rs-move-xy" title="<?php _('Move') ?>" link="/move-tool"></rs-sideicon>
</rs-side><rs-side>
    <rs-sideicon *rsIfConnected="true" icon="rs rs-params" title="<?php _('Status') ?>" link="/params"></rs-sideicon>
</rs-side>
<main>
    <rs-headline *ngIf="printers.active"><i class="fa fa-home"></i> {{printers.printers[printers.active].name}}</rs-headline>
    <rs-headline *ngIf="!(printers.active)"><i class="fa fa-home"></i> <?php _('No Printer Selected') ?></rs-headline>
    <div class="content-h1" rsDrag>
    <div class="margin-leftright" *ngIf="(server$|async).diskUsage?.usage && (server$|async).diskUsage?.available < 1000000000">
      <rs-progress [value]="(server$|async).diskUsage?.usage" [type]="(server$|async).diskUsage?.classname" text="<?php _('Free Disk Space') ?>: {{(server$|async).diskUsage?.available | byte}}"></rs-progress>
    </div>
    <div class="alert error margin-leftright" *ngIf="printer && printer?.recover.state>=2 && printer?.recover.state<=4">
      <?php _('Last print job did not finish. Use the rescue function in the web frontend to continue the aborted job. Starting any new job will void this information and make a rescue impossible!') ?>
    </div>

    <rs-iconlist>
        <rs-icon *ngIf="printers?.active" icon="rs rs-file-gcode" title="<?php _('G-Codes') ?>" link="/gcodes"></rs-icon>
        <rs-icon *ngIf="printers?.active && (printers.printers[printers.active].queue?.length>0)" [counter]="printers.printers[printers.active].queue?.length" icon="rs rs-printqueue" title="<?php _('Print Queue') ?>" link="/print-queue"></rs-icon>
        <rs-icon *rsIfConnected="true" icon="rs rs-move-xy" title="<?php _('Move') ?>" link="/move-tool"></rs-icon>
        <rs-icon *rsIfConnected="true" icon="rs rs-filamentchange" title="<?php _('Change Filament') ?>" link="/changefilament"></rs-icon>
        <rs-icon icon="rs rs-printer" title="<?php _('Printers') ?>" link="/printer-list"></rs-icon>
        <rs-icon *rsIfPrinting="true" icon="rs rs-print" title="<?php _('Print') ?>" link="/print-status"></rs-icon>
        <rs-icon *rsIfConnected="true" icon="rs rs-params" title="<?php _('Status') ?>" link="/params"></rs-icon>
        <rs-icon *ngIf="printers?.active && server.serverFolders?.length" icon="rs rs-usbstick" title="<?php _('Import') ?>" link="/import"></rs-icon>
        <rs-icon *rsIfConnected="true" icon="rs rs-printer-commands" title="<?php _('Console') ?>" link="/console"></rs-icon>
        <rs-icon *ngIf="printer?.config?.quickCommands?.length && printer.online===1" icon="rs rs-printer-commands" title="<?php _('Printer Cmds.') ?>" link="/printer-commands"></rs-icon>
        <rs-icon icon="rs rs-server-commands" title="<?php _('Server Cmds.') ?>" link="/server-commands" *ngIf="(commands$ | async).length"></rs-icon>
        <rs-icon *rsIfConnected="true" icon="rs rs-chart" title="<?php _('Temp. Graph') ?>" link="/temperatures"></rs-icon>
        <rs-icon *ngIf="!wideScreen" icon="fa fa-envelope" title="<?php _('Messages') ?>" link="/messages" [counter]="(messages$|async).length"></rs-icon>
        <rs-icon *ngIf="printer?.config?.webcams?.length>0" icon="rs rs-webcam" title="<?php _('Webcam') ?>" link="/webcam"></rs-icon>
        <rs-icon icon="fa fa-lock" title="<?php _('Lock Screen') ?>" *ngIf="server.settings['frontSetting'] && server.settings['frontSetting'].unlockPin !== ''" link="/unlock"></rs-icon>
        <rs-icon icon="fa fa-gear" title="<?php _('Settings') ?>" link="/settings"></rs-icon>        
        <rs-icon icon="fa fa-refresh" title="<?php _('Restart UI') ?>" (rsClick)="restart()"></rs-icon>
        <rs-icon *ngIf="shutdown" icon="fa fa-power-off" title="<?php _('Shutdown') ?>" (rsClick)="runCommand(shutdown)"></rs-icon>
    </rs-iconlist>
    </div>
</main>
</rs-page>`
})
export class MyDashboardComponent extends DashboardComponent {
}

Please note the subtile differences to the original dashboard.component.ts file:

  • Reduced import statements. We only import the original component and the component directive.
  • selector has a different name. Here we replaced rs- with my.. You can use what you want as long a sit is different.
  • The template part is for now 1:1 but now you are free to modify it as you want.
  • export class has also a different name and now extends the original DashboardComponent. This means all the typescript logic to provide variables are still available and could be modified and added, but by default you have the same as the original, so if we fix something in javascript there is no need to update your code. Only if we add icons you would need to add them in your version as well.

Now that we have the new page, we need to modify the routes, so our new version is used instead. Routes are defined in app-routing.module.ts which gets the following modifications:

...
import {MyDashboardComponent} from"./mydashboard.component"
...
{
    path: '**',
    component: MyDashboardComponent,
    data: {animation: 'dash'}
  }

You see you need to import the component in the top. Then check the list of routes for the old component name DashboardComponent and replace it with your new component name.

The last modification is adding your component to the app module. Edit file app.module.ts to contain

...
import {MyDashboardComponent} from"./mydashboard.component"
...
  declarations: [
    AppComponent,
    MyDashboardComponent  
  ],
...

Here again we add the import and add the component name into the declarations array. Now it is time to compile your version and see if there are any errors:

> gulp prod

This takes quite some while and you will get some warnings “No name was provided for external module ..” that can be ignored. If everything was correct you now have the new app in the shadow directory under modules/front2/app folder.

Own Updater

If you provide own web pages, you also need a own updater, so users will always have a touchscreen that is in sync with the latest version and it’s requirements. Read https://www.repetier-server.com/own-updater-for-repetier-server/ for detailed instructions on creating your own updater.

Upgrading from < 0.91.0

When you upgrade old modifications to the new version you will notice that parts will not compile any more. Main reasons are switch from Angular 2 to Angular 7 and as a consequence switching rxjs from version 4 to 5. For rxjs we have not included the compat module so reduce the size.

For rxjs the changes are normally replacing old import by

import {Observable, SubscriptionLike} from 'rxjs';

and replacing class Subscription with SubscriptionLike. That is all we have done for the complete app.

For the angular upgrade we suggest reading https://update.angular.io/ where you can source and target version and see what has changed. Also remember that the structure has changed.

Last thing is that the apps are not compiled to modules/front2/www any more. They are now in the app and register subdirectory.

Version until 0.90.7

Destination

The compile commands have two different target folders. For development everything is compiled into wwwdev. These
files are not compressed making it much easier to debug it. In case of javascript they also contain map files so browsers
can even say in which source file the error is.

For production everything is compiled into wwwdist folder.

Both already have the exact structure for your shadow directory, so for testing point your local server isntace to use
one of these folders as shadow directory.

Compiling css files:

Compile for development:

> ./node_modules/grunt-cli/bin/grunt sass:dev

Compile for production:

> ./node_modules/grunt-cli/bin/grunt sass:prod

Compiling front application

Application is compile dusing webpack merging the several 1000 js files into just a few javascript libraries. This
decreases download immensely.

Compile for development (will store data in wwww):

> ./node_modules/webpack/bin/webpack.js

or

> ./node_modules/webpack/bin/webpack.js --watch

with –watch webpack will watch for changes in javascript and automatically recompile once you save a file.

Compile for production (will store data in wwwdist):

> NODE_ENV=production ./node_modules/webpack/bin/webpack.js

Understanding the code structure

Stylesheet introduction

All stylesheet files are in wwwsrc/modules/front2/style. The ui.scss file is the main file that includes all
other files. To modify the overall apperiance change “blocks/_variables.scss” to your liking. The other files
contain the css definitions required. Do not change names and only change if you know what you are doing.
The configs folder contains per resolution variables. Normally there is no need to change them but if you want
to tweak some sizes, that is the place for it.

Frontend application

Apart from some node libraries the application uses 2 self written packages. These are located in
wwwsrc/node_modules/@repetier.

binding – Main module for communication with the server. Implements a Redux storage that mimics the server state,
handles all communication and has many actions to change everything you need.

front-ui – Implements all ui elements used in the frontend.

The main application resides in wwwsrc/modules/front2/app

app.modules.ts is the module loader of the app and binds all used modules/components.
dashboard.components.ts is the main screen. Here you would add new screens or remove existing screens.
app.routes.ts declares all used routes of the frontend.
Most of the remaining files are the different screens.