/* Escape Sequences in Strings
Code Output
\' single quote
\" double quote
\\ backslash
\n newline
\r carriage return
\t tab
\b word boundary
\f form feed */
var firstStr = 'I come first. '
var secondStr = 'I come second.'
/* Concatenating Strings with Plus Operator */
var myStr = firstStr + secondStr;
/* Concatenating Strings with the Plus Equals Operator */
var myStr = firstStr;
myStr += secondStr;
/* Bracket Notation to Find the First Character */
var firstName = "Carlos";
var firstLetter = firstName[0]; // firstLetter is "C"
var firstName[0] = "K"; // not possible! Individual characters of a string literal cannot be changed.
/* Bracket Notation to Find the Last Character in a String */
var firstName = "Carlos";
var lastLetter = firstName[firstName.length - 1]; // lastLetter is "s"
/* Split a string into an array of substrings */
var str = "How are you doing today?";
var res = str.split(" "); // [ 'How', 'are', 'you', 'doing', 'today?' ]
var otherString = "How9are7you2today";
var byDigits = otherString.split(/\d/); // ["How", "are", "you", "today"]
/* Array of strings to single string */
var stringArray = [ 'How', 'are', 'you', 'doing', 'today?' ];
var str = stringArray.join(" "); // "How are you doing today?"
/* Check if a string ends with "universe." */
var str = "Hello world, welcome to the universe.";
var n = str.endsWith("universe.");
/* Lower & Upper Case */
console.log('ALPHABET'.toLowerCase()); // 'alphabet'
console.log('alphabet'.toUpperCase()); // 'ALPHABET'
console.log('test'.charAt(0).toUpperCase() + 'test'.slice(1)); // Test
/* reverse String */
let str = "test";
let reverseStr = str.split("").reverse().join(""); // tset
Year: 2020
[OpenUI5] SAP Fiori elements add-on for OpenUI5 using an OData V4 service
Recently I found this blog post about the new SAP Fiori elements add-on for OpenUI5.
https://blogs.sap.com/2020/12/21/now-available-sap-fiori-elements-add-on-for-openui5/
It includes a little exercise to try it out for yourself. I wrote down all steps I had to make on my Linux Mint 20 installation.
These two links also helped me a lot.
https://github.com/sap-samples/cloud-cap-samples
https://cap.cloud.sap/docs/get-started/
Prerequisites (Node.js, Visual Studio Code, SAP Fiori tools, Git)
curl -sL https://deb.nodesource.com/setup_15.x | sudo -E bash -
sudo apt-get install -y nodejs
node --version
npm -v
Change npm’s default directory to prevent permission errors.
https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally
mkdir ~/.npm-global
npm config set prefix '~/.npm-global'
mkdir ~/.npm-global/lib
#add the following line to your .bashrc or .profile or .zshrc
export PATH=~/.npm-global/bin:$PATH
Step 1: Provide an OData V4 service
git clone https://github.com/sap-samples/cloud-cap-samples remote-odata-service
cd remote-odata-service
npm i
npm i -g @sap/cds-dk
cds watch fiori
Step 2: Generate a SAP Fiori elements List Report Object Page (LROP) app with Fiori tools
1. Open VSC, press Ctrl + P and search for > Fiori: Open Application Generator
2. Choose SAP Fiori elements application
In my case there was no default generator, so first I had to install it.
npm install -g @sap/generator-fiori-elements@latest
This can also be done directly in VSC.
3. Select List Report Object Page
4. Select Connect to an OData Service as Data source and enter as URL http://localhost:4004/browse
5. Choose Books as the Main entity and texts as Navigation entity
6. Complete the mandatory information module name (e.g. bookshop) and Project folder path for storing your app. Of course, you can also fill in the optional information.
Step 3: Make changes in package.json and ui5.yaml required for using OpenUI5
package.json
{
"name": "fiorielements_openui5",
"version": "0.0.1",
"private": true,
"sapux": true,
"description": "A Fiori application.",
"keywords": [
"ui5",
"openui5",
"sapui5"
],
"main": "webapp/index.html",
"scripts": {
"start": "fiori run --open index.html",
"start-local": "fiori run --config ./ui5-local.yaml --open index.html",
"build": "ui5 build -a --clean-dest --include-task=generateManifestBundle generateCachebusterInfo",
"deploy": "fiori add deploy-config"
},
"devDependencies": {
"@sap/ux-specification": "latest",
"@sap/ux-ui5-tooling": "1",
"@ui5/cli": "2.5.0",
"@ui5/fs": "2.0.1",
"@ui5/logger": "2.0.0"
},
"ui5": {
"dependencies": [
"@sap/ux-ui5-tooling",
"@sap/open.fe"
]
},
"dependencies": {
"@sap/open.fe": "1.85.0"
}
}
ui5.yaml
specVersion: '2.2'
metadata:
name: 'fiorielements_openui5'
type: application
framework:
name: OpenUI5
version: "1.85.0"
libraries:
- name: sap.m
- name: sap.ui.core
- name: sap.uxap
- name: themelib_sap_fiori_3
server:
customMiddleware:
- name: fiori-tools-proxy
afterMiddleware: compression
configuration:
ignoreCertError: false # If set to true, certificate errors will be ignored. E.g. self-signed certificates will be accepted
backend:
- path: /browse
url: http://localhost:4004
- name: fiori-tools-appreload
afterMiddleware: compression
configuration:
port: 35729
path: webapp
Step 4: Run the V4 application
cd ~/projects/fiorielements_openui5
npm i
npm start
Now http://localhost:8080/index.html should be opened in your browser.
“Note: Clicking on the Go button in List Report application might request user and password. Please enter user alice, no password.”
Finally I got my list items.
[Empfehlung] Regionale Shops für Lebensmittel und Spezialitäten mit Versand
Öl, Essig, Schnaps und Süßigkeiten: https://hafen-spezerei.de
Räucherfisch: https://inselklause.de/?post_type=product
Lakritze: https://www.sueshi-express.de/
Lokale Delikatessen: https://mutterland.de/
Spicy: https://crafthotsauce.com/
Naturprodukte: https://www.naturprodukte-mv.de/
Italienische Lebensmittel & Weine: https://www.andronaco.info/standorte/hamburg-billbrook/ (kein Versand)
Asiatische Lebensmittel: https://www.vinhloi.de/ (kein Versand)
Vegane/Vegetarische Lebensmittel: https://www.vantastic-foods.com/
Gewürze: https://www.ankerkraut.de oder https://vom-achterhof.de/
Kaffee: https://www.speicherstadt-kaffee.shop oder https://www.mein-eigener-kaffee.de/ oder https://www.roastmarket.de/
Tee: https://www.teekampagne.de/ oder https://teehaus-shila.de/
Erdbeeren und Spargel: https://www.hof-soltau.com/ (kein Versand)
[Nextcloud] Docker update 20.0.1 to 20.0.4 warnings
After pulling the latest Nextcloud image I got some warnings about missing indices, missing primary keys and about converting some column types to big int. The warnings could easily be fixed by running the suggested occ comands. Append “-no-interaction” to suppress the confirmation question (see docs).
docker exec --user www-data nextcloud-app php /var/www/html/occ db:add-missing-indices
docker exec --user www-data nextcloud-app php /var/www/html/occ db:add-missing-primary-keys
docker exec --user www-data nextcloud-app php /var/www/html/occ db:convert-filecache-bigint --no-interaction
[Mint] Software I usually install on my daily driver
Software you get from the default repositories:
sudo apt install \
chromium \
conky-all \
tldr \
tmux \
cantata \
vlc \
kdeconnect \
blueman \
flameshot \
skypeforlinux \
git \
python3-pip \
python-is-python3 \
thefuck \
fortune-mod \
cowsay \
micro \
stacer \
variety \
bashtop \
birdtray \
ssh-tools \
netdiscover \
lynis \
peek \
transgui \
nfs-common \
gsmartcontrol
And some additional repos:
sudo curl -o /usr/share/keyrings/syncthing-archive-keyring.gpg https://syncthing.net/release-key.gpg
echo "deb [signed-by=/usr/share/keyrings/syncthing-archive-keyring.gpg] https://apt.syncthing.net/ syncthing stable" | sudo tee /etc/apt/sources.list.d/syncthing.list
sudo apt-get update
sudo apt-get install syncthing
sudo apt-add-repository ppa:remmina-ppa-team/remmina-next
sudo apt update
sudo apt install remmina remmina-plugin-rdp remmina-plugin-secret
Mainline – Ubuntu Mainline Kernel Installer
sudo apt-add-repository -y ppa:cappelikan/ppa
sudo apt update
sudo apt install mainline
youtube-dl (Check the supported sites here)
sudo curl -L https://yt-dl.org/downloads/latest/youtube-dl -o /usr/local/bin/youtube-dl
sudo chmod a+rx /usr/local/bin/youtube-dl
#Set default download path
micro .config/youtube-dl/config
-o ~/Downloads/%(title)s.%(ext)s
#usage converting to mp3
youtube-dl -x --audio-format mp3 --add-metadata --embed-thumbnail https://youtu.be/dQw4w9WgXcQ
echo "deb http://packages.azlux.fr/debian/ buster main" | sudo tee /etc/apt/sources.list.d/azlux.list
wget -qO - https://azlux.fr/repo.gpg.key | sudo apt-key add -
apt update
apt install broot
Lutris (Following this great guide: https://christitus.com/ultimate-linux-gaming-guide/)
# Install latest Drivers: https://github.com/lutris/docs/blob/master/InstallingDrivers.md
sudo add-apt-repository ppa:kisak/kisak-mesa
sudo dpkg --add-architecture i386
sudo apt update && sudo apt upgrade
sudo apt install libgl1-mesa-dri:i386
sudo apt install mesa-vulkan-drivers mesa-vulkan-drivers:i386
#Add "RADV_PERFTEST=aco" to /etc/environment
# Install Wine https://wiki.winehq.org/Ubuntu
wget -nc https://dl.winehq.org/wine-builds/winehq.key
sudo apt-key add winehq.key
sudo add-apt-repository 'deb https://dl.winehq.org/wine-builds/ubuntu/ focal main'
sudo apt update
sudo apt install --install-recommends winehq-stable
# Lutris
sudo add-apt-repository ppa:lutris-team/lutris
sudo apt update
sudo apt install lutris
sudo apt-add-repository ppa:yktooo/ppa
sudo apt update
sudo apt install indicator-sound-switcher
curl -L https://github.com/dundee/gdu/releases/latest/download/gdu_linux_amd64.tgz | tar xz
chmod +x gdu_linux_amd64
mv gdu_linux_amd64 /usr/bin/gdu
sudo add-apt-repository ppa:atareao/telegram
sudo apt-get update
sudo apt-get install telegram
wget -O- https://updates.signal.org/desktop/apt/keys.asc | gpg --dearmor > signal-desktop-keyring.gpg
cat signal-desktop-keyring.gpg | sudo tee -a /usr/share/keyrings/signal-desktop-keyring.gpg > /dev/null
echo 'deb [arch=amd64 signed-by=/usr/share/keyrings/signal-desktop-keyring.gpg] https://updates.signal.org/desktop/apt/ xenial main' |\
sudo tee -a /etc/apt/sources.list.d/signal.list
sudo apt update && sudo apt install signal-desktop
sudo add-apt-repository ppa:papirus/papirus
sudo apt-get update
sudo apt-get install papirus-icon-theme
sudo add-apt-repository ppa:nextcloud-devs/client
sudo apt update
sudo apt install nextcloud-client
sudo add-apt-repository ppa:xtradeb/apps
sudo apt update
sudo apt install czkawka
And some more software and extensions…
Lolcat https://nocin.eu/shell-neofetch-lolcat/
Cinnamon Extension Transparent panels
Cinnamon Applets QRedshift & Spices Update
Zsh https://nocin.eu/terminal-zsh-oh-my-zsh-powerlevel10k/
Thunderbird with https://addons.thunderbird.net/de/thunderbird/addon/tbsync/ + https://protonmail.com/bridge/ and Thunderbird Conversations (+ configuring birdtray!)
FreeOffice https://www.freeoffice.com/de/download/programme
SAP Gui https://nocin.eu/sap-install-sap-gui-for-java-7-50-on-linux-mint-20/
Steam https://store.steampowered.com/about/
Bashtop https://nocin.eu/software-bashtop-alternative-to-top-and-htop/
Syncthing Tray: https://github.com/Martchus/syncthingtray
FreeOffice: https://www.freeoffice.com/en
Increase GRUB Timeout (#)
sudo micro /etc/default/grub
# if not already set, update
GRUB_TIMEOUT_STYLE=menu
GRUB_TIMEOUT=5
sudo update-grub
Create new shortcut for the “System Monitor”
Copying my dotfiles over. First the .aliases
alias ll='ls -Al --color=auto --block-size=MB --group-directories-first'
alias ls='ls -l --color=auto --block-size=MB --group-directories-first'
alias cp='cp -vRi'
alias rm='rm -vRi'
alias mv='mv -vi'
alias ln='ln -v'
alias mkdir='mkdir -pv' # Creates parent directories if needed
alias chown='chown -v'
alias chmod='chmod -v'
alias rmdir='rmdir -v'
alias ps='ps -f'
#alias tar='tar -xvf' #made some problems
alias df='df -Th'
alias lsd='lsd -Al --group-dirs first'
alias jobs='jobs -lr'
alias sudo='sudo ' #Allows for aliases to work with sudo.
alias pls='sudo $(history -p !!)'
alias wget='wget -qc --show-progress' #Download with WGet with pretty and useful features.
alias grep='grep -sI --color=auto' #Colorful (auto) 'grep' output.
alias psf='ps -faxc -U $UID -o pid,uid,gid,pcpu,pmem,stat,comm' #Less excessive, current-user-focused ps alternative.
alias klog="sudo dmesg -t -L=never -l emerg,alert,crit,err,warn --human --nopager" #Potentially useful option for viewing the kernel log.
alias lsblk='lsblk -o name,label,fstype,size,type,uuid'
alias ping='ping -c 5' # Stop after sending 5 pings
# Docker
alias dpsa='docker ps -a --format "table{{.ID}}\t{{.Names}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}"'
# Find commands I type often so I can alias them
# https://www.jakeworth.com/alias-terminal-commands/
alias typeless='history n 20000 | sed "s/.* //" | sort | uniq -c | sort -g | tail -n 100'
# Micro Editor
alias mic='micro'
alias nano='micro'
# Make mount command output pretty and readable
alias mnt='mount | column -t'
# jump to my download directory
alias dl='cd "$HOME"/Downloads'
# Youtube-dl
alias dlvid='youtube-dl --add-metadata --embed-thumbnail'
alias dlmp3='youtube-dl -x --audio-format mp3 --add-metadata --embed-thumbnail'
alias dlbest='youtube-dl -f bestvideo+bestaudio'
# Git
alias git add .='git aa'
alias git commit -m='git cm'
# mkdir && cd
function mcd() {
mkdir -p $1
cd $1
}
# Archive extraction
# usage: ex <file>
ex ()
{
if [ -f "$1" ] ; then
case $1 in
*.tar.bz2) tar xjf $1 ;;
*.tar.gz) tar xzf $1 ;;
*.bz2) bunzip2 $1 ;;
*.rar) unrar x $1 ;;
*.gz) gunzip $1 ;;
*.tar) tar xf $1 ;;
*.tbz2) tar xjf $1 ;;
*.tgz) tar xzf $1 ;;
*.zip) unzip $1 ;;
*.Z) uncompress $1;;
*.7z) 7z x $1 ;;
*.deb) ar x $1 ;;
*.tar.xz) tar xf $1 ;;
*.tar.zst) unzstd $1 ;;
*) echo "'$1' cannot be extracted via ex()" ;;
esac
else
echo "'$1' is not a valid file"
fi
}
# navigation
up () {
local d=""
local limit="$1"
# Default to limit of 1
if [ -z "$limit" ] || [ "$limit" -le 0 ]; then
limit=1
fi
for ((i=1;i<=limit;i++)); do
d="../$d"
done
# perform cd. Show error if cd fails
if ! cd "$d"; then
echo "Couldn't go up $limit dirs.";
fi
}
Followed by my .zshrc
neofetch | lolcat
# See https://github.com/ohmyzsh/ohmyzsh/wiki/Themes
# ZSH_THEME="robbyrussell"
ZSH_THEME=powerlevel10k/powerlevel10k
# zsh-syntax-highlighting has to be the last plugin!
plugins=(git tmux zsh-autosuggestions zsh-syntax-highlighting)
# Preferred editor for local and remote sessions
if [[ -n $SSH_CONNECTION ]]; then
export EDITOR='micro'
else
export EDITOR='nano'
fi
# To customize prompt, run `p10k configure` or edit ~/.p10k.zsh.
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh
source $ZSH/oh-my-zsh.sh
if [ -f ~/.aliases ]; then
. ~/.aliases
fi
eval $(thefuck --alias FUCK)
[ABAP] Export to memory / Import from memory
Exporting:
DATA: l_p0001 TYPE p0001,
l_return TYPE bapireturn1.
"...
DATA(l_guid) = cl_system_uuid=>create_uuid_c32_static( ).
EXPORT p0001 = l_p0001 TO MEMORY ID l_guid.
SUBMIT z_hr_report WITH p_guid = l_guid AND RETURN.
IMPORT return = l_return FROM MEMORY ID l_guid.
Importing:
REPORT z_hr_report.
PARAMETERS p_guid TYPE sysuuid_c32.
DATA: l_p0001 TYPE p0001,
l_return TYPE bapireturn1.
START-OF-SELECTION.
IMPORT p0001 = l_p0001 FROM MEMORY ID p_guid.
CHECK sy-subrc = 0.
"do stuff...
CALL FUNCTION 'BAPI_EMPLOYEE_ENQUEUE'
EXPORTING
number = l_p0001-pernr
IMPORTING
return = l_return.
IF l_return-type = 'E'.
EXPORT return = l_return TO MEMORY ID p_guid.
RETURN.
ENDIF.
[SAPUI5] Busy Dialog
onInit: function () {
this._oModel = this.getOwnerComponent().getModel();
},
onButtonPress: function (oEvent) {
//get Data
var sPath = oEvent.getSource().getBindingContext().sPath;
var oData = this.getView().getModel().getObject(sPath);
var that = this;
//busy on
this._busyDialog = new sap.m.BusyDialog({});
this._busyDialog.open();
//create
this._oModel.create("/DataSet", oData, {
success: function (oData) {
that._busyDialog.close();
sap.m.MessageToast.show(that.getResourceBundle().getText("ok"));
},
error: function (oError) {
that._busyDialog.close();
sap.m.MessageToast.show(that.getResourceBundle().getText("nok"));
}
});
},
[HR] TMW – Time-Manager-Workplace BAdI
Transaktion: PTMW
BAdI: PT_BLP_USER
Badi Implementierung anlegen und Filter-Ausprägungen hinzufügen. Es muss für jede benötigte Filter-Ausprägung eine eigene BAdI Implementierung und Klasse angelegt werden.
Klasse anlegen und in der Interface Methode die Kundenlogik, wie in der Dokumentation empfohlen, in eine private Methode kapseln.
Bsp.:
METHOD if_ex_pt_blp_user~process_data.
CHECK i_record IS BOUND.
IF i_record->data->category = cl_pt_tmw_tdm_const=>cat_infty
AND i_record->data->type = '2001'.
"hier die erforderliche Logik rein, z.B. weitere Prüfungen
process_it2001( EXPORTING i_record = i_record " Aktueller Satz
i_time_data = i_time_data " Aktuelle Zeitdaten
IMPORTING e_messages = e_messages " Ausgabemeldungen für die Transaktion
e_time_data = e_time_data ). " Neue und geänderte Daten
"An den konkreten Infotypsatz kommt man z.B. folgendermaßen:
DATA(record_data) = CAST cl_pt_td_it2001( i_record->data ).
DATA(p2001) = record_data->if_pt_td_it2001~p2001.
ENDIF.
ENDMETHOD.
[JavaScript] Subtract month from date in format yyyyMMdd
//Input String yyyymmdd
var date_string = '20200101'
//Create date object
var oDate = new Date(date_string.substr(0, 4), date_string.substr(4, 2), date_string.substr(6, 2))
oDate.setMonth(oDate.getMonth() - 1)
var year = oDate.getFullYear().toString()
var month = oDate.getMonth().toString()
var day = oDate.getDay().toString()
//Add leading zero's
if (month.length === 1 ) {
month = '0' + month
}
if (day.length === 1 ) {
day = '0' + day
}
//Return string: 20191201
var sDate = year + month + day
[WordPress] 4 levels of caching
Good overview on: https://www.smarthomebeginner.com/wordpress-on-docker-traefik/#3_WordPress_Caching
Browser Caching: This is what tells the visitors browser to cache the files locally to speed up future site/page visits. We will set this up using Nginx. On Apache, this is accomplished using .htaccess files.
Server Caching: This caches static versions of pages (Page cache). We are going to accomplish this using Nginx FastCGI cache.
Frontend Caching: This means caching WordPress PHP files so they don’t have to be re-compiled for every visit. We are going to set this up using PHP OpCache.
Database Caching: This optimizes database queries by storing them in the RAM for faster delivery. We are going to use Redis for this.