Exemplar på mina senaste fristående applikationsutvecklingar

Det finns nyare versioner av följande appar. Vänligen kontakta mig för mera detaljer. Flera av de här applikationer får uppdateringar regelbundet.

 


  • App namn:

    Knowledge Database

    Komplexitet:
    Version: 1.0
    idén: En app som hanterar kunskapsartiklar enligt olika struktur som användaren har beskrivit för systemet. Systemet också hjälper med att navigera genom olika struktur och olika gränssnitt.
    Projekttyp: huvudprojekt
    Senaste uppdatering: 30 januari 2023
    Senaste uppdatering anteckning: General search capability added.
    — allows for live data crawl and search, or offline data search.
    — searches table names, table field names, table field values.
    — gives live search feedback, highlights search term in any custom way.

    — allows for interactive data entry.
    See GitHub Repository for this module here
    https://github.com/Bob-Utveckling/MyHTMLBox

    — Logging Module enables interaction with the most recently added/updated records in the database
    See the GitHub Repository for this module here
    https://github.com/Bob-Utveckling/Logging-Module-For-PHP-Applications

    Teknik: PHP, MySQL, JavaScript, jQuery

    Tillgång till appen: Kontakta mig gärna genom mejl

Demo film:

  • App namn:

    Pizzeria Application

    Komplexitet:
    Version: 1.0
    idén: En app som hjälper kunder på en pizzeria att anpassa vad som de vill köpa och hjälper kunder beställa olika pizzor.
    Projekttyp: huvudproject
    Senaste uppdatering: 15 december 2022
    Senaste uppdatering anteckning: Integrated the app with Bambora Payment Processing
    Teknik: Angular 9, PHP, Node.js, MySQL

    Tillgång till appen: Kontakta mig gärna genom mejl
    Demo film:

  • App namn:

    Counseling Application

    Komplexitet:
    idén: En app för att hjälpa en konsult organisera olika filer som hen vill ge tillträde till, beroende på klientens behov
    Version: 1.0
    Projekttyp: pilotprojekt
    Senaste uppdatering: 21 september 2020
    Senaste uppdatering anteckning: upload.php script enables uploading image/video/audio/text and makes connection to online database and registers the update in “resource” table
    Teknik: Angular, Android, Java Spring Boot, PHP, MySQL

    Tillgång till appen: Kontakta mig gärna genom mejl
    Demo film:

  • App namn:

    Work Suggest Application

    Komplexitet:
    idén: En app som gör kommunikation mellan myndigheter eller organisationer och samhällsmedlem enklare.
    Version:
    1.9
    Projekttyp: pilotprojekt
    Senaste uppdatering: 21 januari 2021
    Senaste uppdatering anteckning: Improved the interface for the many-to-many relationship in the system for tasks and persons.
    Teknik: Java Spring Boot, Thymeleaf, MySQL

    Tillgång till appen: Kontakta mig gärna genom mejl
    Demo film:

  • App namn:

    Time-slot Booking

    Komplexitet:
    Version: 1.0
    idén:  En app som hjälper boka tillgängliga tider på olika servicebutiker
    Projekttyp: mindre projekt
    Senaste uppdatering: 27 september 2021
    Senaste uppdatering anteckning: Improved interface
    Teknik: Java Spring Boot

    Tillgång till appen: Kontakta mig gärna genom mejl
    Demo film:

  • App namn:

    Yatzi Board Game

    Komplexitet:
    Version: 3.0
    idén:  En app som ger obegränsat antal spelare att spela brädspelet Yatzi
    Projekttyp:
    huvud projekt
    Senaste uppdatering: 20 oktober 2019
    Senaste uppdatering anteckning: Improved interface
    Teknik: Vue.js, JavaScript, CSS, HTML5

    Tillgång till appen: Kontakta mig gärna genom mejl
    Demo film:

  • App namn:

    Comparison App

    Komplexitet:
    Version: 1.0
    idén: En app som kan installeras som en plug-in på olika hemsidor för att hjälpa kunder jämföra olika produkter med egenskaper som ser lika ut.
    Projekttyp:
    mindre projekt
    Senaste uppdatering: 7 oktober 2021
    Senaste uppdatering anteckning: Improved HTML CSS design in all pages
    Teknik: jQuery, JavaScript, HTML5, CSS

    Tillgång till appen: Kontakta mig gärna genom mejl
    Demo film:

Java Spring Boot in Farsi

ویدئوهای توصیفی جاوا اسپرینگ بوت

فیلم های توصیفی زیر از پروژه ها ی جاوا اسپرینگ بوت استفاده می کنند تا مثال ها را نشان دهند. یکی از اصلی ترین پروژه ها، پروژه ی زیر هست که به صورت فایل زیپ قابل دانلود است و قابل تطبیق با توضیحات است.

Download WorkSuggest Project version 1.9 — Zip file

Video 1 — ویدئوی اول

About Java Spring Boot using an interface

Overview:

– create Controller, include URLs including REST endpoints
using @GetMapping, @PostMapping, @DeleteMapping, @PutMapping
– creat right packages
(common ones are entity, repository, service, controller)
– create an interface
(in this application we have 3 interfaces
one for database interactions,
one for booking, and one for booking service)

interface includes the name and type of methods
you will implement in a class

Video 2 — ویدئوی دوم

Spring CRUD and SQL interactions

Overview:

CrudRepository: Simplification of Create-Read-Update-Delete interactions

<S extends T> save(S entity) – Used to save a single entity at a time.
Iterable<S> saveAll(Iterable<S> entities) – we can save multiple entities at a time.
Optional<T> findById(ID id) – use to get entity basis of id.
boolean existsById(ID id) – used to check whether an entity is already exited in DB for given Id.
Iterable<T> findAll() – find all entity of paricular type.
Iterable<T> findAllById(Iterable<ID> ids) – return all entity of given ids.
long count() – returns the number of entities
void deleteById(ID id) – delete the entity on basis of id
void delete(T entity) – delete the entity which one we are passing.
void delete(Iterable<? extends T> entities) – delete multiple entities which we are passing.
void deleteAll() – delete all entities.

(source: https://www.netsurfingzone.com/jpa/crudrepository-methods-example/ )

@Repository

@Transactional(readOnly = true)
enabling update and insert

@Modifying (see the class TaskStatusRepository.java)

Video 3 — ویدئوی سوم

Database Tables And The Respective Entities In Java Spring Boot

Overview:

We create a database table and define its columns as variables in the entity

Entities represent database tables

These are entities that we have in our Java Spring Boot application.
They will have services and repositoies associated with them.

A set of annotations clarify the class, including Lombok annotations.
The @Entity annotation is important

The @Table(name=”tablename”) is an example of an annotation to give
tablename.

The @Id annotation defines the id field

The @GeneratedValue annotation may be applied to a primary key property

We can define the relationship between tables using
@ManyToOne, @OneToMany, and @ManyToMany annotations.

 

Video 4 — ویدئوی چهارم

One To Many relation description

Overview:

– ٍExample: Task and TaskStatus. One task, many task statuses
– See in the database the foreign key relation
available in TaskStatus table

Example:

– Task.java
@OneToMany(mappedBy = “task”, cascade = CascadeType.ALL)
private Set<TaskStatus> taskStatuses;

– TaskStatus.java
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = “task_id”)
private Task task;

CascadeType
cascade = CascadeType.ALL
https://www.baeldung.com/jpa-cascade-types

FetchType
fetch = FetchType.LAZY
https://www.baeldung.com/hibernate-lazy-eager-loading

Video 5 — ویدئوی پنجم

Many To Many relation description

Overview:

– ٍExample: Task and Person.
One task, many persons
One person, many tasks

– join table is the name of the two tables concatenated with _

– person side is owning side. has @JoinTable annotation

– https://stackoverflow.com/questions/36803306/should-jointable-be-specified-in-both-sides-of-a-manytomany-relationship

– should add on owning side

Video 6 — ویدئوی ششم

Thymeleaf basics

Overview:

– Java EE templating possible with JSP, JSF (used to be in focus)
– Templating is a focus with Java EE, Java Spring Boot
– Thymeleaf: reviewing: https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html
– the generalities in an application:
<html xmlns:th=”http://www.thymeleaf.org”>
<p th:text=”#{home.welcome}”>Welcome to our grocery store!</p>
– fragments, variables, iterations, if statements, html tag values

– have fragments
fragment:
<div th:fragment=”adminDetailBar”…
use it:
<div th:insert=”fragments/general.html :: adminDetailBar” >This was admin bar</div>
<div th:replace=”fragments/header.html :: header-css”/>

th:insert is the simplest: it will simply insert the specified fragment as the body of its host tag.

th:replace actually replaces its host tag with the specified fragment.

th:include is similar to th:insert, but instead of inserting the fragment it only inserts the contents of this fragment.

– if-statements
<div th:if=”${user.isAdmin()} == false”> …

– variables
th:text=”${message}
@{${baseURL} + ‘/admin’}

– iteration
<tr class=”dataRow” th:each=”iter : ${worksuggests}”>
<td th:text=”${iter.worksuggest_id}”>id</td>
<td><a th:href=”@{${baseURL} + ‘/admin/worksuggestlist/’ + ${iter.worksuggest_id} + ‘/remove/’ }”

– switch statements
<div th:switch=”${user.role}”>
<p th:case=”‘admin'”>User is an administrator</p>
<p th:case=”#{roles.manager}”>User is a manager</p>
</div>

– th:value, th:text, … (see section 5.2 Setting value to specific attributes)

<select name=”worksuggestlistid”>
<option value=”” text=”Select the Work Suggestion List for this task” selected=”selected”></option>
<option th:each=”iter : ${worksuggests}”
th:value=”${iter.worksuggest_id}”
th:text=”${iter.title}”></option>
</select>

Video 7 — ویدئوی هفتم

Description for several parts of Spring Boot Security

Overview:

pom.xml file

dependencies

Spring Security is a Spring Framework feature

error handler implements AccessDeniedHandler

UserDetailsService features among others
User, UserDetails

AuthenticationSuccessHandler

WebSecurityConfigurerAdapter

Video 8 — ویدئوی هشتم

Spring Boot Security with basic DataSource

Overview:

Spring Boot makes Java app development easy for the web

A set of jar files — dependencies

test dependecies, application server dependecy (usually minimized in Spring Boot), usual dep.

here: mysql dependency, spring-boot-starter-security, //spring boot starter data jpa

a series of useful classes as autowires

ConfigureAuthentication
configure (WebSecurity web)
configure (HttpSecurity http)
configureGlobal

NoOpPasswordEncoder — various password encoders

now to log-in there will be credential check that comes from db

application.properties has db detail

which tables? authorities, users;

let’s see the database

see users…

log in

example tutorials. keywords: jdbc authentication in Spring Boot

Video 9 — ویدئوی نهم

Spring Boot Session with Redis

Overview:

– Session: keeping user detail while user interacts with our application
– set redis as datasource via application.properties
– download Redis, start its server otherwise Spring Boot can’t connect
– See Redis folder structure
– start redis-server.exe
redis-server.exe –maxheap 1024M
– start redis CLI

http://localhost:3306/
http://localhost:6379/
http://localhost:8080/

JavaInUse example

HttpSession variable as argument in main URL
session.getAttribute

HttpServletRequest
in persistMessage URL
request.getSession.setAttribute

also in URL for destroying the session

demo and the controller
http://localhost:8080/package1_war_exploded/

Video 10 — ویدئوی دهم

using BCrypt in Spring Boot

Overview:

============== SpringSecurityConfig file ============
SpringSecurityConfig has a configure method that takes in auth with the class
AuthenticationManagerBuilder.
It sets the auth’s authenticationProvider to use authProvider

authProvider itself is a bean of type DaoAuthenitcationProvider.

The bean authProvider is of type DaoAuthenticationProvider which is using the passwordEncoder.
It also uses a UserDetailsService

PasswordEncoder is set in the SpringSecurityConfig. It is set to return BCryptPasswordEncoder

PasswordEncoder is autowired in UsersService

User Service:
We can work with User Service which has several User interaction methods.
One of these is “saveUser”. Here in this method we can save our userpasswords with the password encoder
if we include it in our User Service class ile.
saveUser in UsersService uses the passwordEncoder (throught Autowire) to encode and set the password

User Entity:
Users entities has username, password, enabled.

whereever we need to interact with the user such as in UserService’s saveUsers we save with encyrption

for reading the password we just pass in password as is in database
in the user builder in userDetailsServiceImpl

=========== userDetailsServiceImpl ============
builder is spring based. Therefore its password field works with the encrypted password that we pass in

we are returning userDetailsService implementation as an autowire that works in
the SpringSecurityConfig and the DaoAuthenticationProvider.

Video 11 — ویدئوی یازدهم

Spring Boot Angular app description

Overview:

Angular – Interactions: drag and drop

Spring Boot:
Entities: database table structures
Repositories: interactions with the database
Services: contact between (interactions with database) and the user requests (controller)

returning JSON format results

demo of RESTpoints

Submit value to backend using POST

Submitting to backend. The response type is set to <any> so it handle any properties returned in the response.

   this.http.post<any>('http://localhost:8080/getCustomerOrder', { name: 'Angular POST Request Example' }).subscribe(data => {
    console.log("- data id" + data.id);
 

Full example can be found at:

https://jasonwatmore.com/post/2019/11/21/angular-http-post-request-examples

Output variable from one component and receive by other component

This can be done through parent-child component relation. The child component will emit a value using EventEmitter. When adding the child component to a parent component’s template, the child component will have a binding mentioned which maps the emitting to a function in the parent component.

In the child component:

import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';

//... rest of Component

//inside the Component:
@Output()
  pricechange: EventEmitter<number> = new EventEmitter<number>();
  
//where we want to emit a change:
this.pricechange.emit(Number(getIngPrice));

In the parent component’s html template:

<!-- say we have a component with its name.
It will have pricechange which is emitted by the child component
in brackets, mapped to our function in the parent component-->
 <app-logic30-ingredients (pricechange)="changePrice($event)"></app-logic30-ingredients>

The parent component will have the function that receives the emit:

//a function in the component:

changePrice(priceEvent) {
    //alert("changePrice . got " + priceEvent);
    this.thePrice = this.thePrice + priceEvent;
}

Full example at https://ultimatecourses.com/blog/component-events-event-emitter-output-angular-2

Set and get attributes from HTML templates

Set an attribute by using square brackets, name of attribute, and its value:

<ng-container *ngIf="arrIngredients">
    <div id="ingsBox">  
        <div class="ing"
        id="{{'ing'+ing.id}}"
        [attr.name]="ing.name"
        (click)="toggleClick($event)"
        *ngFor="let ing of arrIngredients;">
            {{ing.name}} <br>
            <!-- {{ing.description}} -->
            <hr>
        </div>
    </div>
</ng-container>

Get it in the components via the getAttribute method, i.e.:

  toggleClick(event) { //example function
    alert(event.target.id);
    alert(event.target.getAttribute("name")); //getting it here.
  }

How to call an http method without the observable in Angular 2

Use .toPromise on the http get. You can then use this returned value in a promise if needed, i.e.:

getIngredient1(id2) {
  return this.http.get<ILogic10Ingredient[]>(
    "http://localhost:8080/logic10_base_ingredients/ingredient/"+id2).toPromise();
}

and:

              this.getIngredient1(this.ingAvailForUpdate).then
                (
                  (data2) => {
                    //alert("ing for: " + this.ingAvailForUpdate + ", " + data2[0].name)
                  }
                  ,
                  (err) => alert("err:" + err.message)
                );

The complete example can be found at https://stackoverflow.com/questions/38781162/how-to-call-an-http-method-without-the-observable-in-angular-2

localStorage and sessionStorage

For saving:

// clicks is the variable containing your value to save
localStorage.setItem('clickCounter', clicks);
// If you want to use the sessionStorage
// sessionStorage.setItem('clickCounter', clicks);

For loading:

const clicks = localStorage.getItem('clickCounter');
// If you want to use the sessionStorage
// const clicks = sessionStorage.getItem('clickCounter');

See https://stackoverflow.com/questions/58500879/implement-session-storage-in-an-angular-8-application for more examples

An archive of some useful Node.js techniques along side Angular

The then() method returns a Promise. It takes up to two arguments: callback functions for the success and failure cases of the Promise.

const promise1 = new Promise((resolve, reject) => {
  resolve('Success!');
});

promise1.then((value) => {
  console.log(value);
  // expected output: "Success!"
});

The Promise.all() method takes an iterable of promises as an input, and returns a single Promise that resolves to an array of the results of the input promises. This returned promise will resolve when all of the input’s promises have resolved, or if the input iterable contains no promises. It rejects immediately upon any of the input promises rejecting or non-promises throwing an error, and will reject with this first rejection message / error.

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then((values) => {
  console.log(values);
});
// expected output: Array [3, 42, "foo"]

If you’re using Promises, check out this

you can just fix this by doing the following:

var promises = [];

for(var numb in req.body)
{
    promises.push(checkValue(numb));
}

Promise.all(promises)    
 .then(function(data){ /* do stuff when success */ })
 .catch(function(err){ /* error handling */ });

function checkValue(numb){
 return new Promise(function(resolve, reject){
  // place here your logic
  // return resolve([result object]) in case of success
  // return reject([error object]) in case of error
});

As jfriend00 said above, if you’re going to develop in node.js, then you MUST become comfortable with writing async code.

“chained promises” is probably your best bet:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then

http://html5hive.org/node-js-quickies-working-with-mysql/

https://medium.com/bb-tutorials-and-thoughts/how-to-develop-and-build-angular-app-with-nodejs-e24c40444421

How To Develop and Build Angular App With NodeJS

https://medium.com/bb-tutorials-and-thoughts/packaging-your-angular-app-with-nodejs-backend-for-production-97eb1b0755aa

Packaging Your Angular App With NodeJS Backend For Production

Promises chaining

  • An example for acces to a MySQL call which we require the results for before returning results to user:
exports.getAllSizeIdsForItem = function (getItemId, callback) {
	sqlQuery = "SELECT size_id FROM logic20_rule WHERE item_id='" + getItemId + "'";
	arrSizeIds=[];
	db.runQuery(sqlQuery, function (getResult1) {
		for (m1=0; m1<getResult1.length; m1++) {
			arrSizeIds.push(getResult1[m1].size_id);
			if (m1==getResult1.length-1) {
				callback (arrSizeIds);
			}
		}
	})
}
exports.getSizeDetails = async function(arrSizeIds, res) {
	getSizeDetails_promises = [];
	for (mc1 = 0; mc1<arrSizeIds.length; mc1++) {	
	  await new Promise(next=> {	
		console.log("- " + mc1);
		sqlQuery = "SELECT * FROM logic20_size WHERE id='" + arrSizeIds[mc1] + "'";
		db.runQuery(sqlQuery, function (getResult1) {
			console.log("- logic10 -- category details");
			getSizeDetails_promises.push (getResult1[0]);
			next();
		})
	  })
	}
	Promise.all(getSizeDetails_promises)
		.then(function(data) {	console.log("done, now sending res with details: " + data);
								res.send(data); })
		.catch(function(err) {  console.log("error in Promise.all..." + err);  });
}
	logic20Service.getAllSizeIdsForItem(theItemId, function(getArrSizeIds) {
	    console.log("getArrSizeIds: " + getArrSizeIds);
	    logic20Service.getSizeDetails(getArrSizeIds, res);
	})
function callback () { console.log('all done'); }

var itemsProcessed = 0;

[1, 2, 3].forEach((item, index, array) => {
  asyncFunction(item, () => {
    itemsProcessed++;
    if(itemsProcessed === array.length) {
      callback();
    }
  });
});