Deploying loklak search on Heroku & Using config to store and load external URLs

It is really important to have a separate configuration for all the hardcoded URLs having multiple instances across the project. It would help in testing and comparing projects like loklak with a separate configuration for hardcoded URLs. We would also be discussing deployment of Angular based loklak on heroku through this blog post.

Creating shared URL config

The idea here is to export a const Object containing all the collective hardcoded URLs used inside the project. We would try to store similar/collective URLs inside a same key e.g. all the github URLs must go inside key: ‘github’.

export const defaultUrlConfig = {
	fossasia: {
		root: 'https://fossasia.org',
		blog: 'https://blog.fossasia.org'
	},
	loklak: {
		apiServer: 'https://api.loklak.org',
		apiBase: 'loklak.org',
		blog: 'http://blog.loklak.net',
		dev: 'https://dev.loklak.org',
		apps: 'https://apps.loklak.org'
	},
	github: {
		loklak: 'https://github.com/loklak',
		fossasia: 'https://github.com/fossasia'
	},
	phimpme: {
		root: 'https://phimp.me'
	},
	susper: {
		root: 'https://susper.com'
	},
	susiChat: {
		root: 'https://chat.susi.ai'
	},
	pslab: {
		root: 'https://pslab.fossasia.org'
	},
	eventyay: {
		root: 'https://eventyay.com'
	}
};

 

Storing URLs with a key instead of storing it inside a simple Array, makes it easier to add a new URL at required place and easy to modify the existing ones. Now, this configuration can easily be called inside any Component file.

Using config inside the component

Now, the work is really simple. We just need to import the configuration file inside the required Component and store/use directly the respective URLs.

First step would be to import the configuration file as follows:

import { defaultUrlConfig } from ‘../shared/url-config’;

 

Note: Respective path for url-config file for different components might differ.

Now, we would need to store the defaultUrlConfig inside a variable.

public configUrl = defaultUrlConfig;

 

At this point, we have all the configuration URLs which could be extracted from configUrl.

Displaying URLs in HTML

We would use Angular’s interpolation binding syntax to display the URLs from configUrl in HTML. Let’s say we want to display FOSSASIA’s github url in HTML, then we would simply need to do:

{{ configUrl.github.fossasia }}

 

This could be used as an example to to replace all the hardcoded URLs inside the project.

Deploying loklak search on Heroku

Note: I am skipping the initial steps of creating a project on heroku. It is very easy to setup a project on heroku, for initial steps please follow up here.

First step in this direction would be to add a server.js file in root directory and add the following express server code in it:

const express = require(‘express’);
const path = require(‘path’);
const app = express();
app.use(express.static(__dirname + ‘/dist/<name-of-app>’));
app.get(‘/*’, function(req,res) {
res.sendFile(path.join(__dirname+‘/dist/<name-of-app>/index.html’));
});
app.listen(process.env.PORT || 8080);

 

Second step would be to add the following commands inside package.json at respective attributes.

“postinstall”: “ng build –aot -prod”
“start”: “node server.js”

 

Testing

Click on the respective URL link inside the project UI to test the configuration for hardcoded URLs. To check the deployment on heroku, please open the following URLs:

Development branch: loklak-search-dev.herokuapp.com

Master branch: loklak-search.herokuapp.com

Resources

Create new route ‘/settings’ to display project’s configuration

Having a separate route to display all the hardcoded project’s configuration makes it very easy to compare web apps with each other. A similar architecture has been followed in loklak to create a ‘/settings’ route to display configs used inside it. Respective implementation would be discussed in this blog.

Creating Settings Component

First step would be to create a Settings component to render under /settings route.

ng g component settings

 

This command will create new settings component. We have to create settings-routing and settings module inside settings component separately. This route module will be called inside the root app module. The settings-routing module would import Router module as follows:

import { NgModule } from ‘@angular/core’;
import { Routes, RouterModule } from ‘@angular/router’;
import { SettingsComponent } from ‘./settings.component’;
const routes: Routes = [
    {
        path: '',
        component: SettingsComponent
    }
];
@NgModule({
    imports: [RouterModule.forChild(routes)],
    exports: [RouterModule],
    providers: []
})
export class LoklakSettingsRoutingModule { }

 

The settings module would follow the basic module configuration of Angular, and import the settings-routing module as follows:

import { NgModule } from ‘@angular/core’;
import { CommonModule } from ‘@angular/common’;
import { LoklakSettingsRoutingModule }
    from ‘./settings-routing.module’;
import { SettingsComponent } from ‘./settings.component’;
@NgModule({
    imports: [
        CommonModule,
        LoklakSettingsRoutingModule
    ],
    declarations: [
        SettingsComponent
    ]
})
export class SettingsModule { }

 

At this point of time, we are having a basic settings component to render under /settings route.

Loading /settings as child route under root app module

Now, we need to add path of ‘/settings’ route inside root app module as follows:

path: ‘settings’,
loadChildren: ‘./settings/settings.module#SettingsModule’

 

Which means when user is on path /settings, load settings component.

Fetching project configs inside settings component

At this point, we have successfully established /settings route and settings component. Now we need to fetch the project configs inside the settings component to display. We would actually import the config and store it in an array to loop through it in template file using *ngFor to display the items under config array.

Note: We would import newsOrgs containing twitter username of news organizations, and the defaultUrlConfig containing the list of all hardcoded URLs used inside the project. It can be taken as an example to add and display more configurations.

import { Component, OnInit } from ‘@angular/core’;
import { defaultUrlConfig } from ‘../shared/url-config’;
import { newsOrgs } from ‘../shared/news-org’;
@Component({
    selector: ‘app-settings’,
    templateUrl: ‘./settings.component.html’,
    styleUrls: [‘./settings.component.scss’]
})
export class SettingsComponent implements OnInit {
    public urlObject = [];
    public newsConfigOrgs = newsOrgs;
    ngOnInit() {
    let i = 0;
    for (const key in defaultUrlConfig) {
        if (key) {
            const data = [];
            const value = defaultUrlConfig[key];
            const data2 = [];
            for (const key2 in value) {
                if (key2) {
                    const value2 = value[key2];
                    data2.push(key2, value2);
                }
            }
            data.push(key, data2);
            this.urlObject.push(data);
            i++;
            }
        }
    }
}

 

urlObject is an array used to store the list of hardcoded URLs, and newsConfigOrgs is an array containing all the list of news organizations.

Displaying array items in template file

Up to this point, we have successfully stored the data inside the component file of settings component and now we need to display this data in template file. For a sake of an example, we would display news orgs as follows:

<!– News Config –>
<h1><u>News Configuration</u></h1>
<div class=“url-container” *ngFor=“let key of newsConfigOrgs”>
   <h4 class=“news”>{{key}}</h4>
</div>

The above code could be used as an example to display more config stored inside component file. Only the basic implementation has been followed and mentioned inside this blog, complete code can be found here: code.

Creating settings tab in Advanced-Feed

Now we need to provide a link to user to check /settings route. We would actually add another tab as settings inside Advanced-Feed as follows:

<a routerLink=“/settings” target=“_blank” class=“tab”>
   Settings
</a>

Testing /settings route

Search a query on loklak.org, and then click on settings tab which would be similar to:

On clicking settings tab, user should be directed to the /settings route containing non-editable (read-only) configuration.

Resources

How to customize LXQT for Meilix

We had a task of customizing the LXQT (LXQt is the Qt port and the upcoming version of LXDE, the Lightweight Desktop Environment) desktop environment in Meilix for events. For example, we can use a distro at events for presentations so during presentations things like system sounds, notifications and panel can be disturbing elements of presentations so we required LXQT to be pre configured for that so the time required in configuration is not wasted or none of the presentations are disturbed.

The default configuration of LXQT are present in ~/.config/lxqt. Configuration files are in This directory is initialized automatically. The default configuration for new users is found in /etc/xdg/lxqt but we are going to use skel for this so that if there are some changes in future in the LXQT code and they do not match default settings we can always be back to default settings by deleting user side changes. Similar to LXDE. LXQt provides a GUI applications to change its settings as well.

While Openbox is the default window manager we have used in Meilix with  LXQt, you can specify a different window manager to use with LXQt via by editing ~/.config/lxqt/session.conf. To a window manager of choice. Change the following line:

window_manager=openbox

 

We have used the Openbox for Meilix.

To create a configuration for panel we can go to ~/.config/lxqt and edit the panel.conf file if it is not present we can create a file named panel.conf and add/edit the code.

[panel1]
hidable=true 

 

GIF representing auto hide of panel.

In order to configure more things like notification we can edit the ~/.config/lxqt/notification.conf.

We can change things like the placement or the size of notification or the timeout of notification in this file.

For eg:

 [General]
__userfile__=true
placement=top-left
server_decides=1
spacing=6
width=295

 

We can now place all the configurations inside the skel folder so that every new user gets the same configurations we have made.

Resources