From 58a6159ff02b4216d1d0e65f5f3ceff27b6f2397 Mon Sep 17 00:00:00 2001 From: "Ramón M. Gómez" Date: Thu, 11 Apr 2019 13:58:48 +0200 Subject: #845: Preparing creation of ogLive based on Kernel 4.18. --- client/boot-tools/boottoolsfunctions.lib | 9 ++++++++- .../boot-tools/includes/etc/initramfs-tools/scripts/VERSION.txt | 2 +- .../boot-tools/includes/usr/bin/boot-tools/listpackages/sw.basic | 3 ++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/client/boot-tools/boottoolsfunctions.lib b/client/boot-tools/boottoolsfunctions.lib index f364f174..7f7bbb38 100755 --- a/client/boot-tools/boottoolsfunctions.lib +++ b/client/boot-tools/boottoolsfunctions.lib @@ -116,13 +116,20 @@ case "${1,,}" in OSARCH="amd64" OSHTTP="http://es.archive.ubuntu.com/ubuntu/" ;; - bionic) # ogLive 1.1.1-rc1 basado en Ubuntu 18.04 y Kernel 4.15. + bionic|bionic-4.15) # ogLive 1.1.1-rc1 basado en Ubuntu 18.04 y Kernel 4.15. OSDISTRIB="ubuntu" OSCODENAME="bionic" OSRELEASE="4.15.0-32-generic" OSARCH="amd64" OSHTTP="http://es.archive.ubuntu.com/ubuntu/" ;; + bionic-4.18) # ogLive 1.1.1-rc3 basado en Ubuntu 18.04 y Kernel 4.18. + OSDISTRIB="ubuntu" + OSCODENAME="bionic" + OSRELEASE="4.18.0-17-generic" + OSARCH="amd64" + OSHTTP="http://es.archive.ubuntu.com/ubuntu/" + ;; host) # ogLive basado en la distribución del servidor. OSDISTRIB=$(lsb_release -is) OSCODENAME=$(lsb_release -cs) diff --git a/client/boot-tools/includes/etc/initramfs-tools/scripts/VERSION.txt b/client/boot-tools/includes/etc/initramfs-tools/scripts/VERSION.txt index 45805bd6..bc92b96f 100644 --- a/client/boot-tools/includes/etc/initramfs-tools/scripts/VERSION.txt +++ b/client/boot-tools/includes/etc/initramfs-tools/scripts/VERSION.txt @@ -1 +1 @@ -OpenGnsys Client 1.1.1-rc2 +OpenGnsys Client 1.1.1-rc3 diff --git a/client/boot-tools/includes/usr/bin/boot-tools/listpackages/sw.basic b/client/boot-tools/includes/usr/bin/boot-tools/listpackages/sw.basic index afd8ff4c..31f2b559 100644 --- a/client/boot-tools/includes/usr/bin/boot-tools/listpackages/sw.basic +++ b/client/boot-tools/includes/usr/bin/boot-tools/listpackages/sw.basic @@ -9,7 +9,8 @@ install console-data install locales install lshw install gawk -install subversion +#install subversion # ogLive anterior a Ubuntu 18.04 +install git # ogLive a partir de Ubuntu 18.04 install python-openssl install python #install php5-cli # ogLive anterior a Ubuntu 16.04 -- cgit v1.2.3-18-g5258 From 2ee6e407882d650915634939ed4d8e587f9b038b Mon Sep 17 00:00:00 2001 From: Irina Gómez Date: Mon, 22 Apr 2019 14:37:49 +0200 Subject: #834 Create image in console: Fixs a error when there are duplicate computers. It only shows monolithic images. --- admin/WebConsole/comandos/CrearImagen.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/admin/WebConsole/comandos/CrearImagen.php b/admin/WebConsole/comandos/CrearImagen.php index 532a589a..1944872a 100644 --- a/admin/WebConsole/comandos/CrearImagen.php +++ b/admin/WebConsole/comandos/CrearImagen.php @@ -122,7 +122,8 @@ function HTMLSELECT_imagenes($cmd,$idrepositorio,$idperfilsoft,$disk,$particion, $cmd->texto="SELECT DISTINCT imagenes.idimagen,imagenes.descripcion,imagenes.nombreca, imagenes.idperfilsoft, repositorios.nombrerepositorio, repositorios.ip FROM imagenes INNER JOIN repositorios USING (idrepositorio) - WHERE repositorios.idrepositorio = (SELECT idrepositorio FROM ordenadores WHERE ordenadores.ip='".$masterip."') + WHERE imagenes.tipo=".$IMAGENES_MONOLITICAS." + AND repositorios.idrepositorio IN (SELECT idrepositorio FROM ordenadores WHERE ordenadores.ip='".$masterip."') OR repositorios.ip='".$masterip."' ORDER BY imagenes.descripcion"; $rs=new Recordset; -- cgit v1.2.3-18-g5258 From febf228ba327c38a04a013d9b0dbb7020fdcce21 Mon Sep 17 00:00:00 2001 From: "Ramón M. Gómez" Date: Mon, 29 Apr 2019 10:48:33 +0200 Subject: #761: OGAGent checks for dobule slash before connecting to REST URL. --- admin/Sources/Clients/ogagent/oglive/Makefile | 21 +++------------------ .../oglive/debian/ogagent-oglive.postinst.debhelper | 5 ----- .../oglive/debian/ogagent-oglive.postrm.debhelper | 12 ------------ .../Clients/ogagent/oglive/scripts/OGAgentTool | 6 ------ .../ogagent/oglive/scripts/OGAgentTool-startup | 10 ---------- .../opengnsys/modules/server/OpenGnSys/__init__.py | 4 +++- 6 files changed, 6 insertions(+), 52 deletions(-) delete mode 100644 admin/Sources/Clients/ogagent/oglive/debian/ogagent-oglive.postinst.debhelper delete mode 100644 admin/Sources/Clients/ogagent/oglive/debian/ogagent-oglive.postrm.debhelper delete mode 100644 admin/Sources/Clients/ogagent/oglive/scripts/OGAgentTool delete mode 100644 admin/Sources/Clients/ogagent/oglive/scripts/OGAgentTool-startup diff --git a/admin/Sources/Clients/ogagent/oglive/Makefile b/admin/Sources/Clients/ogagent/oglive/Makefile index 832e2dc7..84e06107 100644 --- a/admin/Sources/Clients/ogagent/oglive/Makefile +++ b/admin/Sources/Clients/ogagent/oglive/Makefile @@ -30,28 +30,13 @@ install-ogagent: cp -r $(SOURCEDIR)/opengnsys $(LIBDIR)/opengnsys cp -r $(SOURCEDIR)/cfg $(LIBDIR)/cfg + ln -fs $(LIBDIR)/cfg/ogagent.cfg $(CFGDIR) + ln -fs $(LIBDIR)/cfg/ogclient.cfg $(CFGDIR) - # scripts cp scripts/ogagent $(BINDIR) - cp scripts/OGAgentTool-startup $(BINDIR) - cp scripts/OGAgentTool $(BINDIR) - - # Fix permissions chmod 755 $(BINDIR)/ogagent - chmod 755 $(BINDIR)/OGAgentTool-startup - chmod 600 $(LIBDIR)/cfg/ogagent.cfg - - # If for red hat based, copy init.d -ifeq ($(DISTRO),rh) - mkdir -p $(INITDIR) - cp debian/ogagent.init $(INITDIR)/ogagent - chmod +x $(INITDIR)/ogagent - ln -fs /usr/share/OGAgent/cfg/ogagent.cfg $(CFGDIR) - ln -fs /usr/share/OGAgent/cfg/ogclient.cfg $(CFGDIR) -endif - # chmod 0755 $(BINDIR)/ogagent uninstall: rm -rf $(LIBDIR) - # rm -f $(BINDIR)/ogagent + rm -f $(BINDIR)/ogagent rm -rf $(CFGDIR) diff --git a/admin/Sources/Clients/ogagent/oglive/debian/ogagent-oglive.postinst.debhelper b/admin/Sources/Clients/ogagent/oglive/debian/ogagent-oglive.postinst.debhelper deleted file mode 100644 index e75924dc..00000000 --- a/admin/Sources/Clients/ogagent/oglive/debian/ogagent-oglive.postinst.debhelper +++ /dev/null @@ -1,5 +0,0 @@ -# Automatically added by dh_installinit -if [ -x "/etc/init.d/ogagent" ]; then - update-rc.d ogagent defaults >/dev/null || exit $? -fi -# End automatically added section diff --git a/admin/Sources/Clients/ogagent/oglive/debian/ogagent-oglive.postrm.debhelper b/admin/Sources/Clients/ogagent/oglive/debian/ogagent-oglive.postrm.debhelper deleted file mode 100644 index 3167f1f8..00000000 --- a/admin/Sources/Clients/ogagent/oglive/debian/ogagent-oglive.postrm.debhelper +++ /dev/null @@ -1,12 +0,0 @@ -# Automatically added by dh_installinit -if [ "$1" = "purge" ] ; then - update-rc.d ogagent remove >/dev/null -fi - - -# In case this system is running systemd, we make systemd reload the unit files -# to pick up changes. -if [ -d /run/systemd/system ] ; then - systemctl --system daemon-reload >/dev/null || true -fi -# End automatically added section diff --git a/admin/Sources/Clients/ogagent/oglive/scripts/OGAgentTool b/admin/Sources/Clients/ogagent/oglive/scripts/OGAgentTool deleted file mode 100644 index 5b300523..00000000 --- a/admin/Sources/Clients/ogagent/oglive/scripts/OGAgentTool +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -FOLDER=/usr/share/OGAgent - -cd $FOLDER -python OGAgentUser.py $@ diff --git a/admin/Sources/Clients/ogagent/oglive/scripts/OGAgentTool-startup b/admin/Sources/Clients/ogagent/oglive/scripts/OGAgentTool-startup deleted file mode 100644 index bb3a848e..00000000 --- a/admin/Sources/Clients/ogagent/oglive/scripts/OGAgentTool-startup +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -# Simple hack to wait for systray to be present -# Exec tool if not already runned by session manager -ps -ef | grep "$USER" | grep -v grep | grep -v OGAgentTool-startup | grep 'OGAgentTool' -q -# If not already running -if [ $? -eq 1 ]; then - sleep 5 - exec /usr/bin/OGAgentTool -fi \ No newline at end of file diff --git a/admin/Sources/Clients/ogagent/src/opengnsys/modules/server/OpenGnSys/__init__.py b/admin/Sources/Clients/ogagent/src/opengnsys/modules/server/OpenGnSys/__init__.py index 8aed2a8b..e740bbf0 100644 --- a/admin/Sources/Clients/ogagent/src/opengnsys/modules/server/OpenGnSys/__init__.py +++ b/admin/Sources/Clients/ogagent/src/opengnsys/modules/server/OpenGnSys/__init__.py @@ -123,6 +123,8 @@ class OpenGnSysWorker(ServerWorker): # Replacing server IP if its running on ogLive client logger.debug('Activating on ogLive client, new server is {}'.format(os.environ['oglive'])) url = parse.urlsplit(url)._replace(netloc=os.environ['oglive']).geturl() + if not url.endswith(os.path.sep): + url += os.path.sep self.REST = REST(url) # Get network interfaces until they are active or timeout (5 minutes) for t in range(0, 300): @@ -176,7 +178,7 @@ class OpenGnSysWorker(ServerWorker): self.access_token = response['access_token'] self.refresh_token = response['refresh_token'] # Once authenticated with the server, change the API URL for private request - self.REST = REST(url + '/api/private') + self.REST = REST(url + 'api/private') # Set authorization tokens in the REST object, so in each request this token will be used self.REST.set_authorization_headers(self.access_token, self.refresh_token) # Create HTML file (TEMPORARY) -- cgit v1.2.3-18-g5258 From 72eec764f5d49202587895f1f78ce5a2b59ba2a7 Mon Sep 17 00:00:00 2001 From: "jm.bardallo" Date: Mon, 29 Apr 2019 12:22:04 +0200 Subject: Creada pagina del cliente mostrando configuración del disco MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin/WebConsole3/frontend/package.json | 1 + admin/WebConsole3/frontend/src/app/model/client.ts | 16 ++++ .../src/app/pages/client/client.component.html | 103 ++++++++++++--------- .../src/app/pages/client/client.component.ts | 96 ++++++++++++++++++- admin/WebConsole3/frontend/src/assets/i18n/es.json | 2 +- .../frontend/src/environments/environment.ts | 2 +- 6 files changed, 171 insertions(+), 49 deletions(-) diff --git a/admin/WebConsole3/frontend/package.json b/admin/WebConsole3/frontend/package.json index fd197606..15f5d406 100644 --- a/admin/WebConsole3/frontend/package.json +++ b/admin/WebConsole3/frontend/package.json @@ -34,6 +34,7 @@ "angular-loading-page": "^0.6.0", "bootstrap-css-only": "^3.3.7", "chart.js": "^2.7.3", + "chartjs-plugin-datalabels": "^0.6.0", "core-js": "^2.5.4", "font-awesome": "^4.7.0", "ionicons": "^4.5.5", diff --git a/admin/WebConsole3/frontend/src/app/model/client.ts b/admin/WebConsole3/frontend/src/app/model/client.ts index dbc9976e..8977e168 100644 --- a/admin/WebConsole3/frontend/src/app/model/client.ts +++ b/admin/WebConsole3/frontend/src/app/model/client.ts @@ -2,6 +2,20 @@ import { Resource } from 'globunet-angular/core/models/api/resource'; import {Repository} from './repository'; import {HardwareProfile} from './hardware-profile'; import {Netboot} from './netboot'; +import {PartitionInfo} from './image'; + +export class Partition { + cacheContent: string; + filesystem: string; + id: number; + image: any; + numDisk: number; + numPartition: number; + osName: string; + partitionCode: string; + size: number; + usage: number; +} export class Client extends Resource { public name = ''; @@ -15,8 +29,10 @@ export class Client extends Resource { public oglive = null; public netboot: Netboot = null; public organizationalUnit: number; + public partitions?: PartitionInfo[] // Variables temporales para la vista, no vienen del servidor public status?: string; public selected?: boolean; + public disksConfig?: any[]; } diff --git a/admin/WebConsole3/frontend/src/app/pages/client/client.component.html b/admin/WebConsole3/frontend/src/app/pages/client/client.component.html index 0ba00d7d..81c0a3ac 100644 --- a/admin/WebConsole3/frontend/src/app/pages/client/client.component.html +++ b/admin/WebConsole3/frontend/src/app/pages/client/client.component.html @@ -3,7 +3,7 @@ @@ -24,18 +24,18 @@

- +
- +
- - + +
@@ -48,10 +48,6 @@ : {{getSizeInGB(diskConfig.size)}} GB
-
- -
@@ -69,47 +65,62 @@ - - - - {{partition.numPartition}} - {{partition.parttype}} - {{partition.filesystem}} - {{getSizeInGB(partition.size)}} GB - {{partition.usage}}% - {{partition.osName}} - - - - - - - - - - - - - - - - - - - - - - - -
{{file.type}}{{file.name}}{{file.size}}
{{partition.cacheContent.freeSpace}}
- - - -
+ + + + {{partition.numPartition}} + {{partition.parttype}} + {{partition.filesystem}} + {{getSizeInGB(partition.size)}} GB + {{partition.usage}} + % + {{partition.osName}} + + + + + + + + + + + + + + + + + + + + + + + +
{{file.type}}{{file.name}}{{file.size}}
{{partition.cacheContent.freeSpace}}
+ + + +
+
+ + +
diff --git a/admin/WebConsole3/frontend/src/app/pages/client/client.component.ts b/admin/WebConsole3/frontend/src/app/pages/client/client.component.ts index 50346ffd..0611d6dc 100644 --- a/admin/WebConsole3/frontend/src/app/pages/client/client.component.ts +++ b/admin/WebConsole3/frontend/src/app/pages/client/client.component.ts @@ -12,7 +12,8 @@ import {Repository} from '../../model/repository'; import {HardwareProfile} from '../../model/hardware-profile'; import {OgCommonService} from '../../service/og-common.service'; import {ClientFormType} from '../../form-type/client.form-type'; -import {GlobunetFormType} from '../../form-type/globunet.form-type'; +import * as pluginDataLabels from 'chartjs-plugin-datalabels'; +import {ChartOptions} from 'chart.js'; @Component({ selector: 'app-client', @@ -27,6 +28,7 @@ export class ClientComponent implements OnInit { public oglives: any[] = []; private formType: ClientFormType; public form; + public pluginDataLabels; // this tells the tabs component which Pages // should be each tab's root Page @@ -39,6 +41,7 @@ export class ClientComponent implements OnInit { private hardwareProfileService: HardwareProfileService, private ogCommonService: OgCommonService) { this.client = new Client(); + this.client.disksConfig = []; this.formType = new ClientFormType(); this.form = this.formType.getForm(); } @@ -57,6 +60,17 @@ export class ClientComponent implements OnInit { this.clientService.read(id).subscribe( client => { this.client = client; + this.client.disksConfig = this.ogCommonService.getDisksConfigFromPartitions(this.client.partitions); + + const self = this; + this.client.disksConfig.forEach(function(diskConfig) { + const chartData = self.getChartData(diskConfig); + diskConfig.diskChartData = chartData.diskChartData; + diskConfig.diskChartLabels = chartData.diskChartLabels; + diskConfig.diskPieChartColors = chartData.diskPieChartColors; + diskConfig.diskChartOptions = chartData.diskChartOptions; + }); + } ); } @@ -122,6 +136,75 @@ export class ClientComponent implements OnInit { ); } + getChartData(diskConfig) { + const diskChartData = []; + const diskChartLabels = []; + const diskPieChartColors = [{ + backgroundColor: [] + }]; + const self = this; + diskConfig.partitions.forEach(function(partition) { + if (partition.size > 0) { + self.setPartitionPercentOfDisk(diskConfig, partition); + diskChartData.push(partition.percentOfDisk); + diskChartLabels.push([ + (partition.os || partition.filesystem), + partition.percentOfDisk + '%' + ]); + diskPieChartColors[0].backgroundColor.push(self.getPartitionColor(partition)); + } + }); + const diskChartOptions: ChartOptions = { + responsive: true, + legend: { + position: 'bottom' + }, + plugins: { + datalabels: { + formatter: (value, ctx) => { + const label = ctx.chart.data.labels[ctx.dataIndex]; + return label; + }, + }, + } + }; + + return { + diskChartData: diskChartData, + diskChartLabels: diskChartLabels, + diskChartOptions: diskChartOptions, + diskPieChartColors: diskPieChartColors + }; + } + + setPartitionPercentOfDisk(diskConfig, partition) { + partition.percentOfDisk = Math.round(((partition.size * 100) / diskConfig.size) * 100) / 100; + } + + labelFormatter(label, series) { + return '
' + + '
' + + series.percentOfDisk + '%
'; + } + + getPartitionColor(partition) { + let color = 'rgb(252, 90, 90)'; + + // Para la partición de datos se usa un color específico + if (partition.osName === 'DATA') { + color = 'rgb(237,194,64)'; + } else if (partition.filesystem === 'NTFS') { + color = 'rgb(0,192, 239)'; + } else if (partition.filesystem.match('EXT')) { + color = 'rgb(96, 92, 168)'; + } else if (partition.filesystem.match('LINUX-SWAP')) { + color = 'rgb(84, 84, 84)'; + } else if (partition.filesystem.match('CACHE')) { + color = 'rgb(252, 90, 90)'; + } + return color; + } + save() { let request: Observable; if (this.client.id !== 0) { @@ -146,5 +229,16 @@ export class ClientComponent implements OnInit { } + getPartitionUsageClass(usage: number | string | number) { + let result = ''; + if (usage < 60) { + result = 'bg-green'; + } else if (usage >= 60 && usage < 80) { + result = 'bg-yellow'; + } else if (usage >= 80) { + result = 'bg-red'; + } + return result; + } } diff --git a/admin/WebConsole3/frontend/src/assets/i18n/es.json b/admin/WebConsole3/frontend/src/assets/i18n/es.json index dfc609c3..7427ea51 100644 --- a/admin/WebConsole3/frontend/src/assets/i18n/es.json +++ b/admin/WebConsole3/frontend/src/assets/i18n/es.json @@ -110,7 +110,7 @@ "images_info": "Info imágenes", "imageUrl": "Url imagen", "info": "Información", - "initializing": "Opengnsys", + "initializing": "Inicializando", "invalid_login": "Usuario o contraseña no válido", "ip": "Ip", "january": "Enero", diff --git a/admin/WebConsole3/frontend/src/environments/environment.ts b/admin/WebConsole3/frontend/src/environments/environment.ts index fcc0dcba..16b61e25 100644 --- a/admin/WebConsole3/frontend/src/environments/environment.ts +++ b/admin/WebConsole3/frontend/src/environments/environment.ts @@ -1,7 +1,7 @@ // This file can be replaced during build by using the `fileReplacements` array. // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. // The list of file replacements can be found in `angular.json`. -const url = 'https://SERVERIP/opengnsys3'; +const url = 'https://172.16.140.210/opengnsys3'; export const environment = { production: false, BASE_URL: url, -- cgit v1.2.3-18-g5258 From 7e26c8366910912ca23f5cc21f2f3d2c76931dd5 Mon Sep 17 00:00:00 2001 From: "Ramón M. Gómez" Date: Mon, 29 Apr 2019 14:06:27 +0200 Subject: #761: Fix bugs when parsing parameters; stop agent when client is halted. --- admin/WebConsole3/frontend/package.json | 2 -- .../frontend/src/environments/environment.ts | 6 ++--- client/shared/etc/init/default.sh | 26 ++++++++++++---------- client/shared/scripts/poweroff | 8 +++---- client/shared/scripts/reboot | 9 +++----- installer/opengnsys_update.sh | 2 +- 6 files changed, 24 insertions(+), 29 deletions(-) diff --git a/admin/WebConsole3/frontend/package.json b/admin/WebConsole3/frontend/package.json index 15f5d406..a2f353f5 100644 --- a/admin/WebConsole3/frontend/package.json +++ b/admin/WebConsole3/frontend/package.json @@ -59,8 +59,6 @@ "@types/jasminewd2": "~2.0.3", "@types/node": "~8.9.4", "codelyzer": "~4.3.0", - "globunet-angular": "git+https://gitlab.globunet.com/globunet/angular2-shared.git", - "globunet-schematics": "git+https://gitlab.globunet.com/globunet/globunet-angular-schematics.git", "jasmine-core": "~2.99.1", "jasmine-spec-reporter": "~4.2.1", "karma": "~3.0.0", diff --git a/admin/WebConsole3/frontend/src/environments/environment.ts b/admin/WebConsole3/frontend/src/environments/environment.ts index 16b61e25..ef17e26d 100644 --- a/admin/WebConsole3/frontend/src/environments/environment.ts +++ b/admin/WebConsole3/frontend/src/environments/environment.ts @@ -1,7 +1,7 @@ // This file can be replaced during build by using the `fileReplacements` array. // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. // The list of file replacements can be found in `angular.json`. -const url = 'https://172.16.140.210/opengnsys3'; +const url = 'https://SERVERIP/opengnsys3'; export const environment = { production: false, BASE_URL: url, @@ -9,8 +9,8 @@ export const environment = { API_PUBLIC_URL: url + '/api', API_BASE_URL: '/backend/web/app_dev.php/api', OAUTH_DOMAIN: '/backend/web/app_dev.php/oauth/v2/token', - OAUTH_CLIENT_ID: '1_23amzbdp4kskg80444oscko4w0w8wokocs88k0g8w88o4oggs4', - OAUTH_CLIENT_SECRET: '46rttt2trwo4gocgoc4w80k4s8ok48sg8s84kk0cw48csks8o8', + OAUTH_CLIENT_ID: 'CLIENTID', + OAUTH_CLIENT_SECRET: 'CLIENTSECRET', BASE_DIR: 'opengnsys3', clientstatus: ['off', 'initializing', 'oglive', 'busy', 'linux', 'linux_session', 'macos', 'windows', 'windows_session'], windowsboots: ['reboot', 'directo (kexec)'], diff --git a/client/shared/etc/init/default.sh b/client/shared/etc/init/default.sh index efc1e035..2d147c45 100755 --- a/client/shared/etc/init/default.sh +++ b/client/shared/etc/init/default.sh @@ -3,30 +3,31 @@ # Fichero de registro de incidencias (en el servidor; si no, en local). OPENGNSYS=${OPENGNSYS:-/opt/opengnsys} -OGLOGFILE=${OGLOGFILE:-$OPENGNSYS/log/$(ogGetIpAddress).log} +OGLOGFILE=${OGLOGFILE:-$OPENGNSYS/log/$(ogGetIpAdderss).log} if ! touch $OGLOGFILE 2>/dev/null; then OGLOGFILE=/var/log/opengnsys.log fi LOGLEVEL=5 -# TODO - PRUEBA -AGENT_FILE="/var/tmp/ogAdmClient" -touch $AGENT_FILE -chmod a+wxs $AGENT_FILE -chown root:root $AGENT_FILE -# Exportar funciones para comunicacion con el servidor -sendConfigToServer -sendStatusToServer "initializing" - # Matando plymount para inicir browser o shell pkill -9 plymouthd -# Arranque de OpenGnsys Client daemon (socket). +# Cargar idioma. echo "${MSG_LAUNCHCLIENT:-.}" # Indicar fichero de teclado de Qt para el idioma especificado (tipo "es.qmap"). [ -f /usr/local/etc/${LANG%_*}.qmap ] && export QWS_KEYBOARD="TTY:keymap=/usr/local/etc/${LANG%_*}.qmap" -if [ -x "$OPENGNSYS/bin/ogAdmClient" -a "$ogstatus" != "offline" ]; then +VERSION="1.1.1" # TEMPORAL +if [ -f "$OPENGNSYS/images/ogagent-oglive_${VERSION}_all.deb" -a "$ogstatus" != "offline" ]; then + # Instalar, configurar e iniciar agente. + dpkg -i "$OPENGNSYS/images/ogagent-oglive_${VERSION}_all.deb" + sed -i -e "s,remote=.*,remote=https://$(ogGetServerIp)/opengnsys3/backend/web/app_dev.php/," \ + -e "s,client=.*,client=CLIENTID," \ + -e "s,secret=.*,secret=CLIENTSECRET," \ + /usr/share/OGAgent/cfg/ogagent.cfg + ogagent start + sleep 10 +elif [ -x "$OPENGNSYS/bin/ogAdmClient" -a "$ogstatus" != "offline" ]; then # Ejecutar servicio cliente. $OPENGNSYS/bin/ogAdmClient -f $OPENGNSYS/etc/ogAdmClient.cfg -l $OGLOGFILE -d $LOGLEVEL else @@ -42,3 +43,4 @@ if [ "$ogactiveadmin" == "true" ]; then bash fi + diff --git a/client/shared/scripts/poweroff b/client/shared/scripts/poweroff index 7297cad3..563845b3 100755 --- a/client/shared/scripts/poweroff +++ b/client/shared/scripts/poweroff @@ -30,12 +30,10 @@ ethtool -s $DEVICE wol g 2>/dev/null BUSYBOX=$(which busyboxOLD) BUSYBOX=${BUSYBOX:-"busybox"} -# Retardo para dar lugar al registro en cola de acciones. -sleep 5 -# Parar Browser para evitar "cuelgues". -[ "$ogstatus" == "offline" ] || pkill browser +# Parar agente y Browser. +ogagent stop &>/dev/null +pkill -9 browser -sendStatusToServer "off" # Apagar. $BUSYBOX poweroff diff --git a/client/shared/scripts/reboot b/client/shared/scripts/reboot index 5e6305af..30362cc7 100755 --- a/client/shared/scripts/reboot +++ b/client/shared/scripts/reboot @@ -44,12 +44,9 @@ ethtool -s $DEVICE wol g 2>/dev/null BUSYBOX=$(which busyboxOLD) BUSYBOX=${BUSYBOX:-"busybox"} -# Retardo para dar lugar al registro en cola de acciones. -sleep $TIME -# Parar Browser para evitar "cuelgues". -[ "$ogstatus" == "offline" ] || pkill browser - -sendStatusToServer "off" +# Parar agente y Browser. +ogagent stop &>/dev/null +pkill -9 browser # Reiniciar. $BUSYBOX reboot diff --git a/installer/opengnsys_update.sh b/installer/opengnsys_update.sh index ec1b8394..b8d583dd 100755 --- a/installer/opengnsys_update.sh +++ b/installer/opengnsys_update.sh @@ -726,7 +726,7 @@ function updateWeb3() sed -i "s/SERVERIP/$SERVERIP/" src/environments/environment.ts sed -i 's,base href=.*,base href="/opengnsys3/frontend/">,' src/index.html ng build - rsync -irplt dist/opengnsysAngular6 $INSTALL_TARGET/www3/frontend + rsync -irplt dist/opengnsysAngular6/* $INSTALL_TARGET/www3/frontend popd } -- cgit v1.2.3-18-g5258 From 20fc050be9508646e857ac1e086ebc72181587be Mon Sep 17 00:00:00 2001 From: "Ramón M. Gómez" Date: Tue, 30 Apr 2019 10:51:25 +0200 Subject: #761: OGAgent launchs client's default menu on activation process. --- .../opengnsys/modules/server/OpenGnSys/__init__.py | 76 +++++++++++----------- .../ogagent/src/opengnsys/oglive/operations.py | 8 +++ 2 files changed, 45 insertions(+), 39 deletions(-) diff --git a/admin/Sources/Clients/ogagent/src/opengnsys/modules/server/OpenGnSys/__init__.py b/admin/Sources/Clients/ogagent/src/opengnsys/modules/server/OpenGnSys/__init__.py index e740bbf0..035ed9b4 100644 --- a/admin/Sources/Clients/ogagent/src/opengnsys/modules/server/OpenGnSys/__init__.py +++ b/admin/Sources/Clients/ogagent/src/opengnsys/modules/server/OpenGnSys/__init__.py @@ -150,10 +150,10 @@ class OpenGnSysWorker(ServerWorker): pass # Copy file "HostsFile.FirstOctetOfIPAddress" to "HostsFile", if it exists # (used in "exam mode" from the University of Seville) - # hostsFile = os.path.join(operations.get_etc_path(), 'hosts') - # newHostsFile = hostsFile + '.' + self.interface.ip.split('.')[0] - # if os.path.isfile(newHostsFile): - # shutil.copyfile(newHostsFile, hostsFile) + hosts_file = os.path.join(operations.get_etc_path(), 'hosts') + new_file = hosts_file + '.' + self.interface.ip.split('.')[0] + if os.path.isfile(new_file): + shutil.copy2(new_file, hosts_file) # Generate random secret to send on activation self.random = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(self.length)) # Compose login route @@ -172,53 +172,51 @@ class OpenGnSysWorker(ServerWorker): self.REST = REST(self.service.config.get('opengnsys', 'altremote')) response = self.REST.sendMessage(login_route) except: - logger.error('Initialization error') + raise Exception('Initialization error: Cannot connect to the server') finally: - if response['access_token'] is not None: - self.access_token = response['access_token'] - self.refresh_token = response['refresh_token'] - # Once authenticated with the server, change the API URL for private request - self.REST = REST(url + 'api/private') - # Set authorization tokens in the REST object, so in each request this token will be used - self.REST.set_authorization_headers(self.access_token, self.refresh_token) - # Create HTML file (TEMPORARY) - message = """ + if response['access_token'] is None: + raise Exception('Initialization error: Cannot obtain access token') + self.access_token = response['access_token'] + self.refresh_token = response['refresh_token'] + # Once authenticated with the server, change the API URL for private request + self.REST = REST(url + 'api/private') + # Set authorization tokens in the REST object, so in each request this token will be used + self.REST.set_authorization_headers(self.access_token, self.refresh_token) + # Completing ogLive initialization process + os_type = operations.os_type.lower() + if os_type == 'oglive': + # Create HTML file (TEMPORARY) + message = """

Initializing...

- -""" - f = open('/tmp/init.html', 'w') - f.write(message) - f.close() - # Launch browser - subprocess.Popen(['browser', '-qws', '/tmp/init.html']) - self.REST.sendMessage('clients/statuses', {'mac': self.interface.mac, 'ip': self.interface.ip, - 'status': 'initializing'}) - - def cfg(): - """ - Subprocess to send configuration and status - """ - config = operations.get_configuration() - self.REST.sendMessage('clients/configs', {'mac': self.interface.mac, 'ip': self.interface.ip, - 'config': config}) - self.REST.sendMessage('clients/statuses', {'mac': self.interface.mac, 'ip': self.interface.ip, - 'status': 'oglive'}) - - threading.Thread(target=cfg()).start() - else: - logger.error("Initialization error: Can't obtain access token") +""" + f = open('/tmp/init.html', 'w') + f.write(message) + f.close() + # Launching Browser + pid = subprocess.Popen(['browser', '-qws', '/tmp/init.html']) + self.REST.sendMessage('clients/statuses', {'mac': self.interface.mac, 'ip': self.interface.ip, + 'status': 'initializing'}) + # Send configuration message + self.REST.sendMessage('clients/configs', {'mac': self.interface.mac, 'ip': self.interface.ip, + 'config': operations.get_configuration()}) + # Launching new Browser with client's menu + pid.kill() + # menu_url = self.REST.sendMessage('menus?mac' + self.interface.mac + '&ip=' + self.interface.ip) + menu_url = '/opt/opengnsys/log/' + self.interface.ip + '.info.html' # TEMPORARY menu + subprocess.Popen(['browser', '-qws', menu_url]) + # Return status message + self.REST.sendMessage('clients/statuses', {'mac': self.interface.mac, 'ip': self.interface.ip, + 'status': os_type}) def onDeactivation(self): """ Sends OGAgent stopping notification to OpenGnsys server """ logger.debug('onDeactivation') - # self.REST.sendMessage('ogagent/stopped', {'mac': self.interface.mac, 'ip': self.interface.ip, - # 'ostype': operations.os_type, 'osversion': operations.os_version}) self.REST.sendMessage('clients/statuses', {'mac': self.interface.mac, 'ip': self.interface.ip, 'ostype': operations.os_type, 'osversion': operations.os_version, 'status': 'off'}) diff --git a/admin/Sources/Clients/ogagent/src/opengnsys/oglive/operations.py b/admin/Sources/Clients/ogagent/src/opengnsys/oglive/operations.py index 342cfb06..3cdeef09 100644 --- a/admin/Sources/Clients/ogagent/src/opengnsys/oglive/operations.py +++ b/admin/Sources/Clients/ogagent/src/opengnsys/oglive/operations.py @@ -33,6 +33,7 @@ from __future__ import unicode_literals import socket import platform +import os import fcntl import subprocess import struct @@ -174,6 +175,13 @@ def poweroff(): _exec_ogcommand('/opt/opengnsys/scripts/poweroff') +def get_etc_path(): + """ + Returns etc directory path. + """ + return os.sep + 'etc' + + def get_configuration(): """ Returns client's configuration -- cgit v1.2.3-18-g5258 From 2272900dfa23f1c5b7c0926e24ab9c435a3d1b5d Mon Sep 17 00:00:00 2001 From: "jm.bardallo" Date: Thu, 2 May 2019 15:03:30 +0200 Subject: Posibilidad de añadir clientes mediante fichero dhcp Añadido perfil software Añadidos comandos: - Ejecutar script - Crear imagen - Deploy de imagen - Iniciar sesion Añadidos los menus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../frontend/src/app/api/command.service.ts | 52 +-- .../src/app/api/software-component.service.ts | 40 +- .../src/app/api/software-profile.service.ts | 40 +- .../frontend/src/app/api/software-type.service.ts | 40 +- .../frontend/src/app/app-routing.module.ts | 58 ++- admin/WebConsole3/frontend/src/app/app.module.ts | 57 ++- .../frontend/src/app/form-type/menu.form-type.ts | 12 + .../WebConsole3/frontend/src/app/model/command.ts | 22 +- admin/WebConsole3/frontend/src/app/model/image.ts | 44 +- admin/WebConsole3/frontend/src/app/model/menu.ts | 24 +- .../pages/client/dhcp/client-dhcp.component.html | 139 ++++++ .../pages/client/dhcp/client-dhcp.component.scss | 5 + .../app/pages/client/dhcp/client-dhcp.component.ts | 223 ++++++++++ .../create-image-command.component.html | 98 +++++ .../create-image-command.component.scss | 3 + .../create-image-command.component.ts | 188 ++++++++ .../deploy-image-command.component.html | 146 +++++++ .../deploy-image-command.component.scss | 3 + .../deploy-image-command.component.ts | 137 ++++++ .../execute-command/execute-command.component.html | 95 +++++ .../execute-command/execute-command.component.scss | 3 + .../execute-command/execute-command.component.ts | 142 +++++++ .../login-command/login-command.component.html | 81 ++++ .../login-command/login-command.component.scss | 3 + .../login-command/login-command.component.ts | 80 ++++ .../og-commands-options.component.html | 14 +- .../og-execute-command-options.component.html | 11 +- .../og-execute-command-options.component.ts | 3 +- .../og-selected-clients.component.html | 24 +- .../og-selected-clients.component.ts | 11 +- .../hardware-profiles-group.component.html | 47 ++ .../hardware-profiles-group.component.ts | 14 + .../profiles-group/profiles-group.component.html | 47 -- .../profiles-group/profiles-group.component.ts | 14 - .../hardware-profiles-table.component.html | 61 +++ .../hardware-profiles-table.component.ts | 101 +++++ .../profiles-table/profiles-table.component.html | 61 --- .../profiles-table/profiles-table.component.ts | 101 ----- .../app/pages/image/edit/image-edit.component.ts | 176 ++++---- .../src/app/pages/image/image.component.html | 6 +- .../app/pages/menu/edit/menu-edit.component.html | 34 ++ .../app/pages/menu/edit/menu-edit.component.scss | 3 + .../src/app/pages/menu/edit/menu-edit.component.ts | 77 ++++ .../src/app/pages/menu/menu.component.html | 52 ++- .../frontend/src/app/pages/menu/menu.component.ts | 121 +++++- .../ou-clients/ou-client.component.html | 4 +- .../ou-clients/ou-client.component.ts | 17 +- .../software-components-group.component.html | 45 ++ .../software-components-group.component.ts | 10 + .../software-components-table.component.html | 43 ++ .../software-components-table.component.ts | 84 ++++ .../software-components.component.css | 0 .../software-components.component.html | 1 + .../software-components.component.ts | 17 + .../software-profiles-group.component.html | 47 ++ .../software-profiles-group.component.ts | 14 + .../software-profiles-table.component.html | 61 +++ .../software-profiles-table.component.ts | 100 +++++ .../software-profiles.component.css | 0 .../software-profiles.component.html | 3 + .../software-profiles.component.ts | 19 + .../software-types/software-types.component.css | 0 .../software-types/software-types.component.html | 66 +++ .../software-types/software-types.component.ts | 26 ++ .../src/app/pages/software/software.component.css | 0 .../src/app/pages/software/software.component.html | 66 ++- .../src/app/pages/software/software.component.scss | 3 - .../src/app/pages/software/software.component.ts | 84 +++- .../src/app/serializer/image.serializer.ts | 21 +- .../src/app/service/og-commands.service.ts | 471 ++++++++++----------- .../frontend/src/app/service/og-common.service.ts | 3 +- admin/WebConsole3/frontend/src/styles.scss | 4 + 72 files changed, 3180 insertions(+), 742 deletions(-) create mode 100644 admin/WebConsole3/frontend/src/app/form-type/menu.form-type.ts create mode 100644 admin/WebConsole3/frontend/src/app/pages/client/dhcp/client-dhcp.component.html create mode 100644 admin/WebConsole3/frontend/src/app/pages/client/dhcp/client-dhcp.component.scss create mode 100644 admin/WebConsole3/frontend/src/app/pages/client/dhcp/client-dhcp.component.ts create mode 100644 admin/WebConsole3/frontend/src/app/pages/command/create-image-command/create-image-command.component.html create mode 100644 admin/WebConsole3/frontend/src/app/pages/command/create-image-command/create-image-command.component.scss create mode 100644 admin/WebConsole3/frontend/src/app/pages/command/create-image-command/create-image-command.component.ts create mode 100644 admin/WebConsole3/frontend/src/app/pages/command/deploy-image-command/deploy-image-command.component.html create mode 100644 admin/WebConsole3/frontend/src/app/pages/command/deploy-image-command/deploy-image-command.component.scss create mode 100644 admin/WebConsole3/frontend/src/app/pages/command/deploy-image-command/deploy-image-command.component.ts create mode 100644 admin/WebConsole3/frontend/src/app/pages/command/execute-command/execute-command.component.html create mode 100644 admin/WebConsole3/frontend/src/app/pages/command/execute-command/execute-command.component.scss create mode 100644 admin/WebConsole3/frontend/src/app/pages/command/execute-command/execute-command.component.ts create mode 100644 admin/WebConsole3/frontend/src/app/pages/command/login-command/login-command.component.html create mode 100644 admin/WebConsole3/frontend/src/app/pages/command/login-command/login-command.component.scss create mode 100644 admin/WebConsole3/frontend/src/app/pages/command/login-command/login-command.component.ts create mode 100644 admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-group/hardware-profiles-group.component.html create mode 100644 admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-group/hardware-profiles-group.component.ts delete mode 100644 admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-group/profiles-group.component.html delete mode 100644 admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-group/profiles-group.component.ts create mode 100644 admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-table/hardware-profiles-table.component.html create mode 100644 admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-table/hardware-profiles-table.component.ts delete mode 100644 admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-table/profiles-table.component.html delete mode 100644 admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-table/profiles-table.component.ts create mode 100644 admin/WebConsole3/frontend/src/app/pages/menu/edit/menu-edit.component.html create mode 100644 admin/WebConsole3/frontend/src/app/pages/menu/edit/menu-edit.component.scss create mode 100644 admin/WebConsole3/frontend/src/app/pages/menu/edit/menu-edit.component.ts create mode 100644 admin/WebConsole3/frontend/src/app/pages/software/software-components/software-components-group/software-components-group.component.html create mode 100644 admin/WebConsole3/frontend/src/app/pages/software/software-components/software-components-group/software-components-group.component.ts create mode 100644 admin/WebConsole3/frontend/src/app/pages/software/software-components/software-components-table/software-components-table.component.html create mode 100644 admin/WebConsole3/frontend/src/app/pages/software/software-components/software-components-table/software-components-table.component.ts create mode 100644 admin/WebConsole3/frontend/src/app/pages/software/software-components/software-components.component.css create mode 100644 admin/WebConsole3/frontend/src/app/pages/software/software-components/software-components.component.html create mode 100644 admin/WebConsole3/frontend/src/app/pages/software/software-components/software-components.component.ts create mode 100644 admin/WebConsole3/frontend/src/app/pages/software/software-profiles/software-profiles-group/software-profiles-group.component.html create mode 100644 admin/WebConsole3/frontend/src/app/pages/software/software-profiles/software-profiles-group/software-profiles-group.component.ts create mode 100644 admin/WebConsole3/frontend/src/app/pages/software/software-profiles/software-profiles-table/software-profiles-table.component.html create mode 100644 admin/WebConsole3/frontend/src/app/pages/software/software-profiles/software-profiles-table/software-profiles-table.component.ts create mode 100644 admin/WebConsole3/frontend/src/app/pages/software/software-profiles/software-profiles.component.css create mode 100644 admin/WebConsole3/frontend/src/app/pages/software/software-profiles/software-profiles.component.html create mode 100644 admin/WebConsole3/frontend/src/app/pages/software/software-profiles/software-profiles.component.ts create mode 100644 admin/WebConsole3/frontend/src/app/pages/software/software-types/software-types.component.css create mode 100644 admin/WebConsole3/frontend/src/app/pages/software/software-types/software-types.component.html create mode 100644 admin/WebConsole3/frontend/src/app/pages/software/software-types/software-types.component.ts create mode 100644 admin/WebConsole3/frontend/src/app/pages/software/software.component.css delete mode 100644 admin/WebConsole3/frontend/src/app/pages/software/software.component.scss diff --git a/admin/WebConsole3/frontend/src/app/api/command.service.ts b/admin/WebConsole3/frontend/src/app/api/command.service.ts index fe77bda3..28b18520 100644 --- a/admin/WebConsole3/frontend/src/app/api/command.service.ts +++ b/admin/WebConsole3/frontend/src/app/api/command.service.ts @@ -1,26 +1,26 @@ -import { Injectable } from '@angular/core'; -import { HttpClient} from '@angular/common/http'; - -import { environment } from '../../environments/environment'; -import { Command } from '../model/command'; -import { CommandSerializer } from '../serializer/command.serializer'; - -import {ResourceService} from 'globunet-angular/core/providers/api/resource.service'; -import {Observable} from 'rxjs'; - - -@Injectable({ - providedIn: 'root' -}) -export class CommandService extends ResourceService { - - constructor(http: HttpClient) { - super(http, environment.API_URL, 'commands', new CommandSerializer()); - } - - execute(params): Observable { - const url = this.url + 'executes.json'; - return this.httpClient.post(url, params); - } - -} +import {Injectable} from '@angular/core'; +import {HttpClient} from '@angular/common/http'; + +import {environment} from '../../environments/environment'; +import {Command} from '../model/command'; +import {CommandSerializer} from '../serializer/command.serializer'; + +import {ResourceService} from 'globunet-angular/core/providers/api/resource.service'; +import {Observable} from 'rxjs'; + + +@Injectable({ + providedIn: 'root' +}) +export class CommandService extends ResourceService { + + constructor(http: HttpClient) { + super(http, environment.API_URL, 'commands', new CommandSerializer()); + } + + execute(params): Observable { + const url = this.url + '/commands/executes.json'; + return this.httpClient.post(url, params); + } + +} diff --git a/admin/WebConsole3/frontend/src/app/api/software-component.service.ts b/admin/WebConsole3/frontend/src/app/api/software-component.service.ts index 6b794109..b154d41a 100644 --- a/admin/WebConsole3/frontend/src/app/api/software-component.service.ts +++ b/admin/WebConsole3/frontend/src/app/api/software-component.service.ts @@ -1,20 +1,20 @@ -import { Injectable } from '@angular/core'; -import { HttpClient} from '@angular/common/http'; - -import { environment } from '../../environments/environment'; -import { SoftwareComponent } from "../model/software-component"; -import { SoftwareComponentSerializer } from "../serializer/software-component.serializer"; - -import {ResourceService} from "globunet-angular/core/providers/api/resource.service"; - - -@Injectable({ - providedIn: 'root' -}) -export class SoftwareComponentService extends ResourceService { - - constructor(http: HttpClient){ - super(http, environment.API_URL,"softwareComponents", new SoftwareComponentSerializer()); - } - -} +import { Injectable } from '@angular/core'; +import { HttpClient} from '@angular/common/http'; + +import { environment } from '../../environments/environment'; +import { SoftwareComponent } from "../model/software-component"; +import { SoftwareComponentSerializer } from "../serializer/software-component.serializer"; + +import {ResourceService} from "globunet-angular/core/providers/api/resource.service"; + + +@Injectable({ + providedIn: 'root' +}) +export class SoftwareComponentService extends ResourceService { + + constructor(http: HttpClient){ + super(http, environment.API_URL,"softwarecomponents", new SoftwareComponentSerializer()); + } + +} diff --git a/admin/WebConsole3/frontend/src/app/api/software-profile.service.ts b/admin/WebConsole3/frontend/src/app/api/software-profile.service.ts index 442d97a7..92b09e23 100644 --- a/admin/WebConsole3/frontend/src/app/api/software-profile.service.ts +++ b/admin/WebConsole3/frontend/src/app/api/software-profile.service.ts @@ -1,20 +1,20 @@ -import { Injectable } from '@angular/core'; -import { HttpClient} from '@angular/common/http'; - -import { environment } from '../../environments/environment'; -import { SoftwareProfile } from "../model/software-profile"; -import { SoftwareProfileSerializer } from "../serializer/software-profile.serializer"; - -import {ResourceService} from "globunet-angular/core/providers/api/resource.service"; - - -@Injectable({ - providedIn: 'root' -}) -export class SoftwareProfileService extends ResourceService { - - constructor(http: HttpClient){ - super(http, environment.API_URL,"softwareProfiles", new SoftwareProfileSerializer()); - } - -} +import { Injectable } from '@angular/core'; +import { HttpClient} from '@angular/common/http'; + +import { environment } from '../../environments/environment'; +import { SoftwareProfile } from "../model/software-profile"; +import { SoftwareProfileSerializer } from "../serializer/software-profile.serializer"; + +import {ResourceService} from "globunet-angular/core/providers/api/resource.service"; + + +@Injectable({ + providedIn: 'root' +}) +export class SoftwareProfileService extends ResourceService { + + constructor(http: HttpClient){ + super(http, environment.API_URL,"softwareprofiles", new SoftwareProfileSerializer()); + } + +} diff --git a/admin/WebConsole3/frontend/src/app/api/software-type.service.ts b/admin/WebConsole3/frontend/src/app/api/software-type.service.ts index aa2e457e..ccc6eb8f 100644 --- a/admin/WebConsole3/frontend/src/app/api/software-type.service.ts +++ b/admin/WebConsole3/frontend/src/app/api/software-type.service.ts @@ -1,20 +1,20 @@ -import { Injectable } from '@angular/core'; -import { HttpClient} from '@angular/common/http'; - -import { environment } from '../../environments/environment'; -import { SoftwareType } from "../model/software-type"; -import { SoftwareTypeSerializer } from "../serializer/software-type.serializer"; - -import {ResourceService} from "globunet-angular/core/providers/api/resource.service"; - - -@Injectable({ - providedIn: 'root' -}) -export class SoftwareTypeService extends ResourceService { - - constructor(http: HttpClient){ - super(http, environment.API_URL,"softwareTypes", new SoftwareTypeSerializer()); - } - -} +import { Injectable } from '@angular/core'; +import { HttpClient} from '@angular/common/http'; + +import { environment } from '../../environments/environment'; +import { SoftwareType } from "../model/software-type"; +import { SoftwareTypeSerializer } from "../serializer/software-type.serializer"; + +import {ResourceService} from "globunet-angular/core/providers/api/resource.service"; + + +@Injectable({ + providedIn: 'root' +}) +export class SoftwareTypeService extends ResourceService { + + constructor(http: HttpClient){ + super(http, environment.API_URL,"softwaretypes", new SoftwareTypeSerializer()); + } + +} diff --git a/admin/WebConsole3/frontend/src/app/app-routing.module.ts b/admin/WebConsole3/frontend/src/app/app-routing.module.ts index 7e5c4c63..80d357fa 100644 --- a/admin/WebConsole3/frontend/src/app/app-routing.module.ts +++ b/admin/WebConsole3/frontend/src/app/app-routing.module.ts @@ -17,6 +17,16 @@ import {ImageEditComponent} from './pages/image/edit/image-edit.component'; import {ProfileComponent} from './pages/profile/profile.component'; import {OrganizationalUnitEditComponent} from './pages/organizational-unit/edit/organizational-unit-edit.component'; import {ClientComponent} from './pages/client/client.component'; +import {ClientDhcpComponent} from './pages/client/dhcp/client-dhcp.component'; +import {DeployImageCommandComponent} from './pages/command/deploy-image-command/deploy-image-command.component'; +import {MenuComponent} from './pages/menu/menu.component'; +import {MenuEditComponent} from './pages/menu/edit/menu-edit.component'; +import {SoftwareProfileComponent} from './pages/software-profile/software-profile.component'; +import {SoftwareComponentComponent} from './pages/software-component/software-component.component'; +import {SoftwareComponent} from './pages/software/software.component'; +import {LoginCommandComponent} from './pages/command/login-command/login-command.component'; +import {ExecuteCommandComponent} from './pages/command/execute-command/execute-command.component'; +import {CreateImageCommandComponent} from './pages/command/create-image-command/create-image-command.component'; const routes: Routes = [ @@ -59,14 +69,18 @@ const routes: Routes = [ }, { path: 'clients/dhcp', - component: ClientComponent + component: ClientDhcpComponent }, { path: 'images', component: ImageComponent }, { - path: 'images/create', + path: 'images/create/monolithic', + component: ImageEditComponent + }, + { + path: 'images/create/basic', component: ImageEditComponent }, { @@ -93,10 +107,50 @@ const routes: Routes = [ path: 'hardware/profile/:id', component: HardwareProfileComponent }, + { + path: 'software', + component: SoftwareComponent, + }, + { + path: 'software/profile/create', + component: SoftwareProfileComponent + }, + { + path: 'software/component/create', + component: SoftwareComponentComponent + }, + { + path: 'software/profile/:id', + component: SoftwareProfileComponent + }, + { + path: 'menus', + component: MenuComponent + }, + { + path: 'menus/create', + component: MenuEditComponent + }, { path: 'commands', component: CommandComponent }, + { + path: 'commands/deploy_image', + component: DeployImageCommandComponent + }, + { + path: 'commands/login', + component: LoginCommandComponent + }, + { + path: 'commands/execute', + component: ExecuteCommandComponent + }, + { + path: 'commands/create_image', + component: CreateImageCommandComponent + }, { path: 'commands/:id', component: EditCommandComponent diff --git a/admin/WebConsole3/frontend/src/app/app.module.ts b/admin/WebConsole3/frontend/src/app/app.module.ts index 3dd55fe6..5f861c65 100644 --- a/admin/WebConsole3/frontend/src/app/app.module.ts +++ b/admin/WebConsole3/frontend/src/app/app.module.ts @@ -26,8 +26,8 @@ import { HardwareComponent } from './pages/hardware/hardware.component'; import { HardwareComponentsComponent } from './pages/hardware/hardware-components/hardware-components.component'; import { HardwareProfilesComponent } from './pages/hardware/hardware-profiles/hardware-profiles.component'; import { HardwareTypesComponent } from './pages/hardware/hardware-types/hardware-types.component'; -import {ProfilesTableComponent} from './pages/hardware/hardware-profiles/profiles-table/profiles-table.component'; -import {ProfilesGroupComponent} from './pages/hardware/hardware-profiles/profiles-group/profiles-group.component'; +import {HardwareProfilesTableComponent} from './pages/hardware/hardware-profiles/profiles-table/hardware-profiles-table.component'; +import {HardwareProfilesGroupComponent} from './pages/hardware/hardware-profiles/profiles-group/hardware-profiles-group.component'; import {HardwareComponentsTableComponent} from './pages/hardware/hardware-components/hardware-components-table/hardware-components-table.component'; import {HardwareComponentsGroupComponent} from './pages/hardware/hardware-components/hardware-components-group/hardware-components-group.component'; import {HardwareProfileComponent} from './pages/hardware-profile/hardware-profile.component'; @@ -58,6 +58,23 @@ import {OrganizationalUnitEditComponent} from './pages/organizational-unit/edit/ import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; import {ClientComponent} from './pages/client/client.component'; import {ChartsModule} from 'ng2-charts'; +import {ClientDhcpComponent} from './pages/client/dhcp/client-dhcp.component'; +import {DeployImageCommandComponent} from './pages/command/deploy-image-command/deploy-image-command.component'; +import {MenuComponent} from './pages/menu/menu.component'; +import {MenuEditComponent} from './pages/menu/edit/menu-edit.component'; +import {SoftwareComponentComponent} from './pages/software-component/software-component.component'; +import {SoftwareComponent} from './pages/software/software.component'; +import {SoftwareComponentsComponent} from './pages/software/software-components/software-components.component'; +import {SoftwareProfilesComponent} from './pages/software/software-profiles/software-profiles.component'; +import {SoftwareProfileComponent} from './pages/software-profile/software-profile.component'; +import {SoftwareTypesComponent} from './pages/software/software-types/software-types.component'; +import {SoftwareProfilesTableComponent} from './pages/software/software-profiles/software-profiles-table/software-profiles-table.component'; +import {SoftwareProfilesGroupComponent} from './pages/software/software-profiles/software-profiles-group/software-profiles-group.component'; +import {SoftwareComponentsTableComponent} from './pages/software/software-components/software-components-table/software-components-table.component'; +import {SoftwareComponentsGroupComponent} from './pages/software/software-components/software-components-group/software-components-group.component'; +import {LoginCommandComponent} from './pages/command/login-command/login-command.component'; +import {ExecuteCommandComponent} from './pages/command/execute-command/execute-command.component'; +import {CreateImageCommandComponent} from './pages/command/create-image-command/create-image-command.component'; @@ -67,6 +84,8 @@ import {ChartsModule} from 'ng2-charts'; LoginComponent, ImageComponent, ImageEditComponent, + MenuComponent, + MenuEditComponent, DashboardComponent, RepositoryComponent, OrganizationalUnitComponent, @@ -79,14 +98,29 @@ import {ChartsModule} from 'ng2-charts'; HardwareProfilesComponent, HardwareProfileComponent, HardwareTypesComponent, - ProfilesTableComponent, - ProfilesGroupComponent, + HardwareProfilesTableComponent, + HardwareProfilesGroupComponent, HardwareComponentsTableComponent, HardwareComponentsGroupComponent, + SoftwareComponentComponent, + SoftwareComponent, + SoftwareComponentsComponent, + SoftwareProfilesComponent, + SoftwareProfileComponent, + SoftwareTypesComponent, + SoftwareProfilesTableComponent, + SoftwareProfilesGroupComponent, + SoftwareComponentsTableComponent, + SoftwareComponentsGroupComponent, OuGroupComponent, OuClientComponent, ClientComponent, + ClientDhcpComponent, CommandComponent, + DeployImageCommandComponent, + LoginCommandComponent, + ExecuteCommandComponent, + CreateImageCommandComponent, EditCommandComponent, IcheckDirective, FixedToolboxBarDirective, @@ -110,17 +144,28 @@ import {ChartsModule} from 'ng2-charts'; LoginComponent, ImageComponent, ImageEditComponent, + MenuComponent, + MenuEditComponent, OrganizationalUnitComponent, OrganizationalUnitEditComponent, Ng2TableActionComponent, - ProfilesTableComponent, - ProfilesGroupComponent, + HardwareProfilesTableComponent, + HardwareProfilesGroupComponent, HardwareComponentsTableComponent, HardwareComponentsGroupComponent, + SoftwareProfilesTableComponent, + SoftwareProfilesGroupComponent, + SoftwareComponentsTableComponent, + SoftwareComponentsGroupComponent, OuGroupComponent, OuClientComponent, ClientComponent, + ClientDhcpComponent, CommandComponent, + DeployImageCommandComponent, + LoginCommandComponent, + ExecuteCommandComponent, + CreateImageCommandComponent, EditCommandComponent, OgOuGeneralOptionsComponent, TraceComponent, diff --git a/admin/WebConsole3/frontend/src/app/form-type/menu.form-type.ts b/admin/WebConsole3/frontend/src/app/form-type/menu.form-type.ts new file mode 100644 index 00000000..94a8d97b --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/form-type/menu.form-type.ts @@ -0,0 +1,12 @@ +import {GlobunetFormType} from './globunet.form-type'; +import {Menu} from '../model/menu'; + + +export class MenuFormType extends GlobunetFormType { + getForm() { + const form: any[] = GlobunetFormType.getForm(new Menu()); + this.setFieldType(form, 'description', 'textarea'); + this.setFieldType(form, 'resolution', 'select'); + return form; + } +} diff --git a/admin/WebConsole3/frontend/src/app/model/command.ts b/admin/WebConsole3/frontend/src/app/model/command.ts index 2f3639ba..2c5697aa 100644 --- a/admin/WebConsole3/frontend/src/app/model/command.ts +++ b/admin/WebConsole3/frontend/src/app/model/command.ts @@ -1,8 +1,14 @@ -import { Resource } from 'globunet-angular/core/models/api/resource'; - -export class Command extends Resource { - public title = ''; - public script = ''; - public parameters = false; - -} +import { Resource } from 'globunet-angular/core/models/api/resource'; + +export class Excecution { + script = ''; + clients = ''; + type = ''; +} + +export class Command extends Resource { + public title = ''; + public script = ''; + public parameters = false; + +} diff --git a/admin/WebConsole3/frontend/src/app/model/image.ts b/admin/WebConsole3/frontend/src/app/model/image.ts index 2a85299f..2d52cf63 100644 --- a/admin/WebConsole3/frontend/src/app/model/image.ts +++ b/admin/WebConsole3/frontend/src/app/model/image.ts @@ -1,20 +1,24 @@ -import { Resource } from 'globunet-angular/core/models/api/resource'; -import {Repository} from './repository'; - -export class PartitionInfo { - numDisk: number; - numPartition: number; - partitionCode: string; - filesystem: string; - osName: string; -} - -export class Image extends Resource { - public canonicalName: string = ''; - public repository: Repository = new Repository(); - public description: string = ''; - public comments: string = ''; - public revision: string; - public createdAt: Date; - public partitionInfo: PartitionInfo; -} +import { Resource } from 'globunet-angular/core/models/api/resource'; +import {Repository} from './repository'; +import {Client} from './client'; +import {SoftwareProfile} from './software-profile'; + +export class PartitionInfo { + numDisk: number; + numPartition: number; + partitionCode: string; + filesystem: string; + osName: string; +} + +export class Image extends Resource { + public canonicalName = ''; + public repository: Repository = new Repository(); + public description = ''; + public comments = ''; + public revision: string; + public createdAt: Date; + public softwareProfile: SoftwareProfile; + public partitionInfo: PartitionInfo; + public client?: Client; +} diff --git a/admin/WebConsole3/frontend/src/app/model/menu.ts b/admin/WebConsole3/frontend/src/app/model/menu.ts index e8928976..1d19bd44 100644 --- a/admin/WebConsole3/frontend/src/app/model/menu.ts +++ b/admin/WebConsole3/frontend/src/app/model/menu.ts @@ -1,12 +1,12 @@ -import { Resource } from 'globunet-angular/core/models/api/resource'; - -export class Menu extends Resource { - public title: string; - public resolution: string; - public description: string; - public comments: string; - public publicColumns: number; - public publicUrl: string; - public privateColumns: number; - public privateUrl: string; -} +import { Resource } from 'globunet-angular/core/models/api/resource'; + +export class Menu extends Resource { + public title = ''; + public resolution = ''; + public description = ''; + public comments = ''; + public publicUrl = '' + public privateUrl = ''; + public publicColumns: number; + public privateColumns: number; +} diff --git a/admin/WebConsole3/frontend/src/app/pages/client/dhcp/client-dhcp.component.html b/admin/WebConsole3/frontend/src/app/pages/client/dhcp/client-dhcp.component.html new file mode 100644 index 00000000..c21f5c8d --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/client/dhcp/client-dhcp.component.html @@ -0,0 +1,139 @@ +
+

+

+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+

+
+ + +
+
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+

+
+
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ +
+
+
+ + + + + + + + + + + + + + + + + +
+ + +
+ + {{client.name}}{{client.ip}}{{client.mac}}
+
+
+
+ +
+
+
+
diff --git a/admin/WebConsole3/frontend/src/app/pages/client/dhcp/client-dhcp.component.scss b/admin/WebConsole3/frontend/src/app/pages/client/dhcp/client-dhcp.component.scss new file mode 100644 index 00000000..0bbea7e4 --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/client/dhcp/client-dhcp.component.scss @@ -0,0 +1,5 @@ +::ng-deep app-client { + ::ng-deep .box-title { + width: 100%; + } +} diff --git a/admin/WebConsole3/frontend/src/app/pages/client/dhcp/client-dhcp.component.ts b/admin/WebConsole3/frontend/src/app/pages/client/dhcp/client-dhcp.component.ts new file mode 100644 index 00000000..70394ba4 --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/client/dhcp/client-dhcp.component.ts @@ -0,0 +1,223 @@ +import {Component, OnInit} from '@angular/core'; + +import {ClientService} from 'src/app/api/client.service'; +import {ActivatedRoute, ParamMap, Router} from '@angular/router'; +import {forkJoin, Observable} from 'rxjs'; +import {NetbootService} from '../../../api/netboot.service'; +import {ToasterService} from '../../../service/toaster.service'; +import {RepositoryService} from '../../../api/repository.service'; +import {HardwareProfileService} from '../../../api/hardware-profile.service'; +import {Repository} from '../../../model/repository'; +import {HardwareProfile} from '../../../model/hardware-profile'; +import {OgCommonService} from '../../../service/og-common.service'; +import {ClientFormType} from '../../../form-type/client.form-type'; +import {TranslateService} from '@ngx-translate/core'; + +@Component({ + selector: 'app-client-dhcp', + templateUrl: './client-dhcp.component.html', + styleUrls: ['./client-dhcp.component.scss'] +}) +export class ClientDhcpComponent implements OnInit { + public netboots: any = []; + public repositories: Repository[] = []; + public hardwareProfiles: HardwareProfile[] = []; + public oglives: any[] = []; + private formType: ClientFormType; + public form; + public constants = {}; + private dhcpFile: string; + public commonProperties: any; + public dhcpText: string; + public clients: any[]; + public selectAll: boolean; + + // this tells the tabs component which Pages + // should be each tab's root Page + constructor(private router: Router, + private activatedRouter: ActivatedRoute, + private clientService: ClientService, + private netbootService: NetbootService, + private translate: TranslateService, + private toaster: ToasterService, + private repositoryService: RepositoryService, + private hardwareProfileService: HardwareProfileService, + private ogCommonService: OgCommonService) { + + this.commonProperties = {}; + this.clients = []; + + } + + ngOnInit() { + this.ogCommonService.loadEngineConfig().subscribe( + data => { + this.constants = data.constants; + } + ); + this.dhcpFile = '/etc/dhcp/dhcpd.conf'; + this.loadNetboots(); + // Los repositorios vienen cargados ya desde config.router + this.repositoryService.list().subscribe( + (repositories) => { + this.repositories = repositories; + this.commonProperties.repository = this.repositories[0].id; + if (!this.hardwareProfiles) { + this.hardwareProfileService.list().subscribe( + (response) => { + this.hardwareProfiles = response; + this.commonProperties.hardwareProfile = this.hardwareProfiles[0].id; + }, + (error) => { + alert(error); + } + ); + } else { + this.hardwareProfiles = this.hardwareProfiles; + } + }, + (error) => { + this.toaster.pop({type: 'error', title: 'error', body: error}); + } + ); + + } + + loadNetboots() { + this.netbootService.list().subscribe( + (result) => { + this.netboots = result; + this.commonProperties.netboot = this.netboots[0]; + }, + (error) => { + this.toaster.pop({type: 'error', title: 'error', body: error}); + } + ); + } + + + downloadFromServer() { + this.dhcpText = 'ddns-update-style none;\n' + + 'option domain-name "example.org";\n' + + 'log-facility local7;\n' + + 'not-authoritative;\n' + + '\n' + + 'subnet 172.16.140.0 netmask 255.255.255.0 {\n' + + ' option domain-name-servers 172.16.3.1;\n' + + ' option routers 172.16.140.254;\n' + + ' option broadcast-address 172.16.140.255;\n' + + ' default-lease-time 600;\n' + + ' max-lease-time 7200;\n' + + ' next-server 172.16.140.210;\n' + + ' filename "grldr";\n' + + ' use-host-decl-names on;\n' + + '\n' + + '# host HOSTNAME1 {\n' + + '# hardware ethernet HOSTMAC1;\n' + + '# fixed-address HOSTIP1;\n' + + '# }\n' + + '\n' + + ' host pc-pruebas {\n' + + ' hardware ethernet 00:1B:21:1F:EE:9D;\n' + + ' fixed-address 172.16.140.213;\n' + + ' }\n' + + ' host pc-virtualbox {\n' + + ' hardware ethernet 20:CF:30:BF:9A:39;\n' + + ' fixed-address 172.16.140.214;\n' + + ' }\n' + + '\n' + + '\n' + + '}\n'; + /* + ServerDchpResource.getDhcp().then( + function(response) { + this.dhcpText = response.text; + this.toaster.pop({type: 'success', title: 'success', body: this.translate.instant('successfully_loaded')}); + }, + function(error) { + this.toaster.pop({type: 'error', title: 'error', body: error}); + } + ); + /**/ + } + + proccessDhcp() { + if (typeof this.dhcpText !== 'undefined' && this.dhcpText !== '') { + const lines = this.dhcpText.split('\n'); + this.clients = []; + for (let i = 0; i < lines.length; i++) { + // Comprobar si la línea actual contiene la palabra "host" sin ninguna # delante que sería comentario + if (/^host/.test(lines[i].trim())) { + // Unimos las siguientes líneas hasta encontrar "}" + let line = ''; + while(lines[i].indexOf("}") === -1 && i < lines.length){ + line += lines[i]; + i++; + } + // procesar la linea + // host pc53-151 { hardware ethernet 00:1E:33:61:49:B8; fixed-address 172.16.53.151; } + let parts = line.split('{'); + const hostname = parts[0].trim().split(' ')[1]; + + // Las siguientes partes pueden estar en la linea actual o las siguientes + parts = parts[1].trim().split(";"); + const mac = parts[0].trim().split('ethernet')[1]; + // lo mismo puede ocurrir con fixed-address puede estar en lineas diferentes + parts = parts[1].trim().split('fixed-address'); + const ip = parts[1]; + this.clients.push( + { + name: hostname, + ip: ip, + mac: mac, + $$selected: true + } + ); + } + } + } else { + this.toaster.pop({type: 'error', title: 'error', body: this.translate.instant('nothing_to_proccess')}); + } + } + + selectedUnselectAll() { + for (let c = 0; c < this.clients.length; c++) { + this.clients[c].$$selected = this.selectAll; + } + } + + save() { + const promises = []; + let ou = ''; + this.activatedRouter.queryParams.subscribe( + query => { + ou = query.ou; + } + ); + for (let c = 0; c < this.clients.length; c++) { + if (this.clients[c].$$selected === true) { + const client = Object.assign({}, this.clients[c]); + + // Si se indicó un padre en la url, se añade dicha propiedad + client.organizationalUnit = ou; + client.idproautoexec = 0; + client.netdriver = this.commonProperties.netdriver; + client.netiface = this.commonProperties.netiface; + // Propiedades comunes + // client.repository = this.commonProperties.repository; + // client.hardwareProfile = this.commonProperties.hardwareProfile; + promises.push(this.clientService.create(client)); + } + } + forkJoin(promises).subscribe( + (response) => { + this.toaster.pop({type: 'success', title: 'success', body: 'Successfully saved'}); + this.router.navigate(['/app/ous']); + }, + (error) => { + this.toaster.pop({type: 'error', title: 'error', body: error}); + } + ); + } + +} diff --git a/admin/WebConsole3/frontend/src/app/pages/command/create-image-command/create-image-command.component.html b/admin/WebConsole3/frontend/src/app/pages/command/create-image-command/create-image-command.component.html new file mode 100644 index 00000000..9534718c --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/command/create-image-command/create-image-command.component.html @@ -0,0 +1,98 @@ +
+

+

+ +
+
+
+
+
+ +
+
+
+
+
+

+ +
+ +
+
+
+
+
+
+
+
+
+ +
+
+ + +
+
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + {{partition.numDisk}} + + {{partition.numPartition}} + + {{partition.filesystem}} + + {{partition.osName}} +
+
+
+
+
+
+
+
diff --git a/admin/WebConsole3/frontend/src/app/pages/command/create-image-command/create-image-command.component.scss b/admin/WebConsole3/frontend/src/app/pages/command/create-image-command/create-image-command.component.scss new file mode 100644 index 00000000..08b1082b --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/command/create-image-command/create-image-command.component.scss @@ -0,0 +1,3 @@ +app-execute-command { + +} diff --git a/admin/WebConsole3/frontend/src/app/pages/command/create-image-command/create-image-command.component.ts b/admin/WebConsole3/frontend/src/app/pages/command/create-image-command/create-image-command.component.ts new file mode 100644 index 00000000..8f018e33 --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/command/create-image-command/create-image-command.component.ts @@ -0,0 +1,188 @@ +import {Component, OnInit} from '@angular/core'; + +import {ToasterService} from '../../../service/toaster.service'; +import {ActivatedRoute, Router} from '@angular/router'; +import {TranslateService} from '@ngx-translate/core'; +import {OgCommonService} from '../../../service/og-common.service'; +import {OgSweetAlertService} from '../../../service/og-sweet-alert.service'; +import {AuthModule} from 'globunet-angular/core'; +import {User} from '../../../model/user'; +import {OGCommandsService} from '../../../service/og-commands.service'; +import {CommandService} from '../../../api/command.service'; +import {Image} from '../../../model/image'; +import {Command, Excecution} from '../../../model/command'; +import {Client, Partition} from '../../../model/client'; +import {Repository} from '../../../model/repository'; +import {RepositoryService} from '../../../api/repository.service'; +import {ImageService} from '../../../api/image.service'; +import {forkJoin} from 'rxjs'; + +@Component({ + selector: 'app-create-image-command', + templateUrl: './create-image-command.component.html', + styleUrls: [ './create-image-command.component.scss' ] +}) +export class CreateImageCommandComponent implements OnInit { + private readonly user: User; + private constants: any; + public repositories: Repository[]; + public execution = new Excecution(); + public commands: Command[] = []; + public client: Client; + public images = []; + public command = {canonicalName: '', image: new Image()}; + public selectedPartition: number; + + + // this tells the tabs component which Pages + // should be each tab's root Page + constructor(public ogCommandsService: OGCommandsService, + private authModule: AuthModule, + private router: Router, + private activatedRoute: ActivatedRoute, + private ogCommonService: OgCommonService, + private commandService: CommandService, + private imageService: ImageService, + private repositoryService: RepositoryService, + private ogSweetAlert: OgSweetAlertService, + private toaster: ToasterService, + private translate: TranslateService) { + this.user = this.authModule.getLoggedUser(); + } + + + + ngOnInit() { + if (this.user && this.ogCommonService.selectedClients) { + const clientId = Object.keys(this.ogCommonService.selectedClients)[0]; + this.client = this.ogCommonService.selectedClients[clientId]; + this.execution.clients = clientId; + this.ogCommonService.loadEngineConfig().subscribe( + data => { + this.constants = data.constants; + } + ); + this.loadRepositories(); + this.loadImages(); + } else { + // TODO - dar error? + this.ogSweetAlert.error(this.translate.instant('opengnsys_error'), this.translate.instant('not_clients_selected')); + this.router.navigate(['app.ous']); + } + } + + + sendCommand() { + if (!this.selectedPartition) { + this.toaster.pop({type: 'error', title: 'error', body: this.translate.instant('you_must_select_partition')}); + } else { + const disk = this.client.partitions[this.selectedPartition].numDisk; + const partition = this.client.partitions[this.selectedPartition].numPartition; + // Al crear la imagen, le asociamos un perfil software + // @ts-ignore + this.execution.script = this.constants.commands.SOFTWARE_INVENTORY + ' ' + disk + ' ' + partition + '\n'; + this.execution.script += this.constants.commands.CREATE_IMAGE + ' ' + disk + ' ' + partition + ' ' + this.command.canonicalName + ' REPO '; + // @ts-ignore + this.execution.script = this.execution.script.replace(/\"/g, '\\"').replace(/\$/g, '\\\$'); + + let image: Image = this.command.image; + let newImage = false; + + let result = true; + // Crear la imagen si no existe + if (!image) { + newImage = true; + // Comprobar que exista el repositorio, sino no podemos crear la nueva imagen + if (!this.repositories) { + result = false; + this.toaster.pop({type: 'error', title: 'error', body: this.translate.instant('no_repository_exist')}); + } else { + // Usar el repositorio por defecto + const repository = this.repositories[0]; + image = new Image(); + image.canonicalName = this.command.canonicalName; + image.description = this.translate.instant('image_created_automatically'); + image.repository = repository; + } + } + + // Asignar a la imagen los atributos del sistema operativo elegido + image.client = this.client; + + // Si no hubo ningun error se guardan todas las pgms + if (result === true) { + const promises = []; + if (newImage === true) { + promises.push(this.imageService.create(image)); + } else { + const imageCopy = Object.assign({}, image); + delete imageCopy.id; + delete imageCopy.softwareProfile; + promises.push(this.imageService.update(imageCopy)); + } + this.execution.type = 'CREATE_IMAGE'; + promises.push(this.commandService.execute(this.execution)); + forkJoin(promises).subscribe( + (response) => { + this.toaster.pop({type: 'success', title: 'success', body: this.translate.instant('successfully_executed')}); + this.router.navigate(['app.ous']); + }, + (error) => { + this.toaster.pop({type: 'error', title: 'error', body: error}); + } + ); + } + } + } + + setCanonicalName() { + if (this.command.image !== null) { + this.command.canonicalName = this.command.image.canonicalName; + } else { + this.command.canonicalName = ''; + } + } + + private loadImages() { + this.imageService.list().subscribe( + (response) => { + this.images = response; + }, + (error) => { + this.toaster.pop({type: 'error', title: 'error', body: error}); + } + ); + } + private loadRepositories() { + this.repositoryService.list().subscribe( + (response) => { + this.repositories = response; + }, + (error) => { + this.toaster.pop({type: 'error', title: 'error', body: error}); + } + ); + } + + isClonable(partition) { + let clonable = false; + let index = 0; + const code = partition.partitionCode; + + if (partition.numPartition !== 0) { + // Buscar el codigo entre las constantes + while (index < this.constants.partitiontable.length && !clonable) { + // para cada tabla de particiones, buscamos el codigo de la particion + const elements = this.constants.partitiontable[index].partitions.filter(function(part) { + return (part.id === partition.partitionCode.padStart(2, '0')); + } + ); + clonable = (elements.length > 0 && elements[0].clonable === true); + index++; + } + } + + return clonable; + } + +} diff --git a/admin/WebConsole3/frontend/src/app/pages/command/deploy-image-command/deploy-image-command.component.html b/admin/WebConsole3/frontend/src/app/pages/command/deploy-image-command/deploy-image-command.component.html new file mode 100644 index 00000000..7dc55c29 --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/command/deploy-image-command/deploy-image-command.component.html @@ -0,0 +1,146 @@ +
+

+ +
+
+

+ +
+
+
+
+
+ +
+
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+
+ + +
+
+
+ + + +
+
+ + +
+
+ + +
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+ + +
+
+ + +
+
+
+ +
+ + +
+
diff --git a/admin/WebConsole3/frontend/src/app/pages/command/deploy-image-command/deploy-image-command.component.scss b/admin/WebConsole3/frontend/src/app/pages/command/deploy-image-command/deploy-image-command.component.scss new file mode 100644 index 00000000..ccb34440 --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/command/deploy-image-command/deploy-image-command.component.scss @@ -0,0 +1,3 @@ +command { + +} diff --git a/admin/WebConsole3/frontend/src/app/pages/command/deploy-image-command/deploy-image-command.component.ts b/admin/WebConsole3/frontend/src/app/pages/command/deploy-image-command/deploy-image-command.component.ts new file mode 100644 index 00000000..b8312964 --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/command/deploy-image-command/deploy-image-command.component.ts @@ -0,0 +1,137 @@ +import {Component, OnInit} from '@angular/core'; + +import {ToasterService} from '../../../service/toaster.service'; +import {ActivatedRoute, Router} from '@angular/router'; +import {TranslateService} from '@ngx-translate/core'; +import {OgCommonService} from '../../../service/og-common.service'; +import {OgSweetAlertService} from '../../../service/og-sweet-alert.service'; +import {AuthModule} from 'globunet-angular/core'; +import {User} from '../../../model/user'; +import {ImageService} from '../../../api/image.service'; +import {OGCommandsService} from '../../../service/og-commands.service'; + +@Component({ + selector: 'app-deploy-image-command', + templateUrl: './deploy-image-command.component.html', + styleUrls: [ './deploy-image-command.component.scss' ] +}) +export class DeployImageCommandComponent implements OnInit { + torrent = { + mode: 'peer', + seedTime: '60' + }; + multicast = { + port: '9000', + address: '239.194.16.140', + mode: 'full-duplex', + speed: 90, + maxClients: 50, + maxWaitTime: 60 + }; + disk = 1; + partition = 1; + + images = []; + deployMethods = []; + deployMethod = 'MULTICAST'; + private deployImage: string; + private user: User; + private constants: any; + public image: any; + public editInstructions = false; + + + // this tells the tabs component which Pages + // should be each tab's root Page + constructor(public ogCommandsService: OGCommandsService, + private authModule: AuthModule, + private router: Router, + private activatedRoute: ActivatedRoute, + private ogCommonService: OgCommonService, + private imageService: ImageService, + private ogSweetAlert: OgSweetAlertService, + private toaster: ToasterService, + private translate: TranslateService) { + this.user = this.authModule.getLoggedUser(); + } + + + ngOnInit() { + this.deployImage = 'true'; + this.updateDeployOptions(); + if (this.user) { + // Comprobar la selección de clientes + if (this.ogCommonService.getSelectionSize() > 0) { + this.imageService.list().subscribe( + (response) => { + this.images = response; + }, + (error) => { + this.images = []; + + } + ); + + } else { + // TODO - dar error? + this.toaster.pop({type: 'error', body: this.translate.instant('not_clients_selected'), title: this.translate.instant('opengnsys_error')}); + this.router.navigate(['app.ous']); + } + } + } + + updateDeployOptions() { + this.ogCommonService.loadEngineConfig().subscribe( + data => { + this.constants = data.constants; + if (this.deployImage === 'true') { + this.deployMethods = this.constants.deployMethods.deployImage; + } else { + // Si es updateCache, se quitan las opciones de deploy direct + this.deployMethods = this.constants.deployMethods.updateCache; + } + } + ); + + } + + /**/ + generateOgInstruction() { + let script = ''; + const disk = this.disk; + const partition = this.partition; + // Capturar ip del repositorio de la imagen elegida + let ip = '172.16.140.210'; + let imgName = this.image.canonicalName; + let target = ' ' + disk + ' ' + partition; + let log = 'ogEcho log session "[0] $MSG_SCRIPTS_TASK_START '; + + // Modo deploy + if (this.deployImage === 'true') { + script = 'deployImage '; + } else { + script = 'updateCache '; + ip = 'REPO'; + imgName += '.img'; + target = ''; + } + script += ip + ' /' + imgName + target + ' ' + this.deployMethod; + log += script + '"\n'; + script = log + script; + + // Modo + let params = ''; + if (this.deployMethod === 'MULTICAST' || this.deployMethod === 'MULTICAST-DIRECT') { + params = this.multicast.port + ':' + this.multicast.mode + ':' + this.multicast.address + ':' + this.multicast.speed + 'M:' + this.multicast.maxClients + ':' + this.multicast.maxWaitTime; + } else if (this.deployMethod === 'TORRENT') { + params = this.torrent.mode + ':' + this.torrent.seedTime; + } + script += ' ' + params; + + this.ogCommandsService.ogInstructions = script; + } + + setCanonicalName() { + //this.command.canonicalName = this.command.image.canonicalName; + } +} diff --git a/admin/WebConsole3/frontend/src/app/pages/command/execute-command/execute-command.component.html b/admin/WebConsole3/frontend/src/app/pages/command/execute-command/execute-command.component.html new file mode 100644 index 00000000..37d7f8e2 --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/command/execute-command/execute-command.component.html @@ -0,0 +1,95 @@ +
+

+

+ +
+
+

+ +
+
+
+
+ +
+
+
+ +
+
+
+
+
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+ +

+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
diff --git a/admin/WebConsole3/frontend/src/app/pages/command/execute-command/execute-command.component.scss b/admin/WebConsole3/frontend/src/app/pages/command/execute-command/execute-command.component.scss new file mode 100644 index 00000000..08b1082b --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/command/execute-command/execute-command.component.scss @@ -0,0 +1,3 @@ +app-execute-command { + +} diff --git a/admin/WebConsole3/frontend/src/app/pages/command/execute-command/execute-command.component.ts b/admin/WebConsole3/frontend/src/app/pages/command/execute-command/execute-command.component.ts new file mode 100644 index 00000000..9560258a --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/command/execute-command/execute-command.component.ts @@ -0,0 +1,142 @@ +import {Component, OnInit} from '@angular/core'; + +import {ToasterService} from '../../../service/toaster.service'; +import {ActivatedRoute, Router} from '@angular/router'; +import {TranslateService} from '@ngx-translate/core'; +import {OgCommonService} from '../../../service/og-common.service'; +import {OgSweetAlertService} from '../../../service/og-sweet-alert.service'; +import {AuthModule} from 'globunet-angular/core'; +import {User} from '../../../model/user'; +import {OGCommandsService} from '../../../service/og-commands.service'; +import {CommandService} from '../../../api/command.service'; +import {CommandFormType} from '../../../form-type/command.form-type'; +import {Command} from '../../../model/command'; + +@Component({ + selector: 'app-execute-command', + templateUrl: './execute-command.component.html', + styleUrls: [ './execute-command.component.scss' ] +}) +export class ExecuteCommandComponent implements OnInit { + execution = {script: '', clients: ''}; + selectedCommand = { + inputs: [], + script: '' + }; + newCommand = 'true'; + private user: User; + private selectedClients = []; + private form = []; + private formType: CommandFormType; + public commands: Command[] = []; + editInstructions = false; + + + // this tells the tabs component which Pages + // should be each tab's root Page + constructor(public ogCommandsService: OGCommandsService, + private authModule: AuthModule, + private router: Router, + private activatedRoute: ActivatedRoute, + private ogCommonService: OgCommonService, + private commandService: CommandService, + private ogSweetAlert: OgSweetAlertService, + private toaster: ToasterService, + private translate: TranslateService) { + this.user = this.authModule.getLoggedUser(); + } + + + + + + + ngOnInit(): void { + this.selectedClients = this.ogCommonService.selectedClients; + if (this.user && this.selectedClients) { + this.loadFormOptions(); + this.loadCommands(); + } else { + // TODO - dar error? + this.ogSweetAlert.error(this.translate.instant('opengnsys_error'), this.translate.instant('not_clients_selected')); + this.router.navigate(['/app/ous']); + } + } + + sendCommand() { + let result = true; + + if (!this.execution.script) { + result = false; + this.toaster.pop({type: 'error', title: 'error', body: this.translate.instant('command_not_valid')}); + } else if (!this.execution.clients) { + result = false; + this.toaster.pop({type: 'error', title: 'error', body: this.translate.instant('not_clients_selected')}); + } + // Si no hubo ningun error + if (result === true) { + this.execution.script = this.execution.script.replace(/\"/g, '\\"').replace(/\$/g, '\\\$'); + // Resetar las instrucciones del script opengnsys almacenadas. + this.ogCommandsService.ogInstructions = ''; + this.commandService.execute(this.execution).subscribe( + (response) => { + this.toaster.pop({type: 'success', title: 'success', body: 'Successfully saved'}); + this.router.navigate(['/app/ous']); + }, + function(error) { + this.toaster.pop({type: 'error', title: 'error', body: error}); + } + ); + } + } + + loadFormOptions() { + this.formType = new CommandFormType(); + this.form = this.formType.getForm(); + } + + loadCommands() { + this.commandService.list().subscribe( + (result) => { + this.commands = result; + } + ); + } + + + executeSelectedCommand() { + // Ejecuta el contenido de ogInstructions + this.ogCommandsService.execute('RUN_SCRIPT'); + } + + updateSelectedCommand() { + this.getParamsNumber(this.selectedCommand); + this.ogCommandsService.ogInstructions = this.selectedCommand.script; + } + + + updateScript(i, value) { + this.selectedCommand.inputs[i] = value.target.value; + let script = this.selectedCommand.script; + for (let index = 0; index < this.selectedCommand.inputs.length; index++) { + script = script.replace('@' + (index + 1), this.selectedCommand.inputs[index]); + } + this.ogCommandsService.ogInstructions = script; + + } + + getParamsNumber(command) { + const params = []; + if (command.parameters === true) { + const allparams = command.script.match(/@[1-9]+/g)||[]; + for (let index = 0; index < allparams.length; index++) { + if (params.indexOf(allparams[index]) === -1) { + params.push(allparams[index]); + } + } + this.selectedCommand.inputs = params; + } + return params.length; + } + +} diff --git a/admin/WebConsole3/frontend/src/app/pages/command/login-command/login-command.component.html b/admin/WebConsole3/frontend/src/app/pages/command/login-command/login-command.component.html new file mode 100644 index 00000000..e8bcdbc5 --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/command/login-command/login-command.component.html @@ -0,0 +1,81 @@ +
+

+

+ +
+
+
+
+
+ +
+
+
+
+
+

+ +
+ +
+
+
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ {{client.name}} +
+ + + + +
+ + + {{partition.numDisk}} + + {{partition.numPartition}} + + {{partition.filesystem}} + + {{partition.osName}} +
+
+
+
+
+
+
+
diff --git a/admin/WebConsole3/frontend/src/app/pages/command/login-command/login-command.component.scss b/admin/WebConsole3/frontend/src/app/pages/command/login-command/login-command.component.scss new file mode 100644 index 00000000..ccb34440 --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/command/login-command/login-command.component.scss @@ -0,0 +1,3 @@ +command { + +} diff --git a/admin/WebConsole3/frontend/src/app/pages/command/login-command/login-command.component.ts b/admin/WebConsole3/frontend/src/app/pages/command/login-command/login-command.component.ts new file mode 100644 index 00000000..af234984 --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/command/login-command/login-command.component.ts @@ -0,0 +1,80 @@ +import {Component, OnInit} from '@angular/core'; + +import {ToasterService} from '../../../service/toaster.service'; +import {ActivatedRoute, Router} from '@angular/router'; +import {TranslateService} from '@ngx-translate/core'; +import {OgCommonService} from '../../../service/og-common.service'; +import {OgSweetAlertService} from '../../../service/og-sweet-alert.service'; +import {AuthModule} from 'globunet-angular/core'; +import {User} from '../../../model/user'; +import {ImageService} from '../../../api/image.service'; +import {OGCommandsService} from '../../../service/og-commands.service'; +import {Client} from '../../../model/client'; +import {CommandService} from '../../../api/command.service'; + +@Component({ + selector: 'app-login-command', + templateUrl: './login-command.component.html', + styleUrls: [ './login-command.component.scss' ] +}) +export class LoginCommandComponent implements OnInit { + execution = {clients: '', script: '', type: ''}; + command = {}; + user: User; + selectedClients: Client[]; + selectedPartition: any; + client: Client; + + // this tells the tabs component which Pages + // should be each tab's root Page + constructor(public ogCommandsService: OGCommandsService, + private authModule: AuthModule, + private router: Router, + private activatedRoute: ActivatedRoute, + private ogCommonService: OgCommonService, + private commandService: CommandService, + private ogSweetAlert: OgSweetAlertService, + private toaster: ToasterService, + private translate: TranslateService) { + this.user = this.authModule.getLoggedUser(); + } + + + + ngOnInit() { + this.selectedClients = this.ogCommonService.selectedClients; + if (this.user && this.selectedClients) { + this.execution.clients = Object.keys(this.selectedClients).join(','); + } + } + + + sendCommand() { + if (!this.selectedPartition) { + this.toaster.pop({type: 'error', title: 'error', body: this.translate.instant('you_must_select_partition')}); + } else { + const disk = this.selectedPartition.numDisk; + const partition = this.selectedPartition.numPartition; + + this.execution.script = 'bootOs ' + disk + ' ' + partition + ' &'; + this.execution.script = this.execution.script.replace(/\"/g, '\\"').replace(/\$/g, '\\\$'); + this.execution.type = 'RUN_SCRIPT'; + + this.commandService.execute(this.execution).subscribe( + (response) => { + this.toaster.pop({type: 'success', title: 'success', body: this.translate.instant('successfully_executed')}); + this.router.navigate(['app.ous']); + }, + (error) => { + this.toaster.pop({type: 'error', title: 'error', body: error}); + } + ); + } + } + + + canLogin(partition) { + return partition.osName !== '' && partition.osName !== 'DATA'; + } + +} diff --git a/admin/WebConsole3/frontend/src/app/pages/common/og-options/og-commands-options/og-commands-options.component.html b/admin/WebConsole3/frontend/src/app/pages/common/og-options/og-commands-options/og-commands-options.component.html index 7f114997..c008d3a1 100644 --- a/admin/WebConsole3/frontend/src/app/pages/common/og-options/og-commands-options/og-commands-options.component.html +++ b/admin/WebConsole3/frontend/src/app/pages/common/og-options/og-commands-options/og-commands-options.component.html @@ -6,14 +6,14 @@ - + - - - - - - + + + + + + diff --git a/admin/WebConsole3/frontend/src/app/pages/common/og-options/og-execute-command-options/og-execute-command-options.component.html b/admin/WebConsole3/frontend/src/app/pages/common/og-options/og-execute-command-options/og-execute-command-options.component.html index efaabd65..2bc015f9 100644 --- a/admin/WebConsole3/frontend/src/app/pages/common/og-options/og-execute-command-options/og-execute-command-options.component.html +++ b/admin/WebConsole3/frontend/src/app/pages/common/og-options/og-execute-command-options/og-execute-command-options.component.html @@ -1,3 +1,8 @@ -

- og-execute-command-options works! -

+
+ + +
diff --git a/admin/WebConsole3/frontend/src/app/pages/common/og-options/og-execute-command-options/og-execute-command-options.component.ts b/admin/WebConsole3/frontend/src/app/pages/common/og-options/og-execute-command-options/og-execute-command-options.component.ts index 55da5e36..86ccbf53 100644 --- a/admin/WebConsole3/frontend/src/app/pages/common/og-options/og-execute-command-options/og-execute-command-options.component.ts +++ b/admin/WebConsole3/frontend/src/app/pages/common/og-options/og-execute-command-options/og-execute-command-options.component.ts @@ -1,4 +1,5 @@ import { Component, OnInit } from '@angular/core'; +import {OGCommandsService} from '../../../../service/og-commands.service'; @Component({ selector: 'app-og-execute-command-options', @@ -7,7 +8,7 @@ import { Component, OnInit } from '@angular/core'; }) export class OgExecuteCommandOptionsComponent implements OnInit { - constructor() { } + constructor(public ogCommandsService: OGCommandsService) { } ngOnInit() { } diff --git a/admin/WebConsole3/frontend/src/app/pages/common/og-options/og-selected-clients/og-selected-clients.component.html b/admin/WebConsole3/frontend/src/app/pages/common/og-options/og-selected-clients/og-selected-clients.component.html index e87b931a..ebb52d60 100644 --- a/admin/WebConsole3/frontend/src/app/pages/common/og-options/og-selected-clients/og-selected-clients.component.html +++ b/admin/WebConsole3/frontend/src/app/pages/common/og-options/og-selected-clients/og-selected-clients.component.html @@ -1,3 +1,21 @@ -

- og-selected-clients works! -

+
+
+
+ + + + + + + +
+ {{client.name}} + {{client.ip}} + {{client.mac}} +
+ +
+
+
diff --git a/admin/WebConsole3/frontend/src/app/pages/common/og-options/og-selected-clients/og-selected-clients.component.ts b/admin/WebConsole3/frontend/src/app/pages/common/og-options/og-selected-clients/og-selected-clients.component.ts index 9c6f1c4e..a6c7a606 100644 --- a/admin/WebConsole3/frontend/src/app/pages/common/og-options/og-selected-clients/og-selected-clients.component.ts +++ b/admin/WebConsole3/frontend/src/app/pages/common/og-options/og-selected-clients/og-selected-clients.component.ts @@ -1,4 +1,6 @@ import { Component, OnInit } from '@angular/core'; +import {OgCommonService} from '../../../../service/og-common.service'; +import {Client} from '../../../../model/client'; @Component({ selector: 'app-og-selected-clients', @@ -6,10 +8,17 @@ import { Component, OnInit } from '@angular/core'; styleUrls: ['./og-selected-clients.component.css'] }) export class OgSelectedClientsComponent implements OnInit { + public selectedClients: Client[]; - constructor() { } + constructor(public ogCommonService: OgCommonService) { + this.selectedClients = []; + } ngOnInit() { + this.selectedClients = this.ogCommonService.selectedClients; } + getClientInfo(c: Client) { + console.log(c); + } } diff --git a/admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-group/hardware-profiles-group.component.html b/admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-group/hardware-profiles-group.component.html new file mode 100644 index 00000000..d7a73e89 --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-group/hardware-profiles-group.component.html @@ -0,0 +1,47 @@ + + + +

+
+
+ + + + +
  • + +
  • +
  • + +
  • +
  • +
  • + +
  • + + +
    +
    +
    +
    + + + + + +
    +

    + +
    + + + + + + +
    diff --git a/admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-group/hardware-profiles-group.component.ts b/admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-group/hardware-profiles-group.component.ts new file mode 100644 index 00000000..884bb680 --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-group/hardware-profiles-group.component.ts @@ -0,0 +1,14 @@ +import {ComponentMetadata} from 'codelyzer/angular/metadata'; +import {Component, Input} from '@angular/core'; + +@Component({ + selector: 'app-profiles-group', + templateUrl: 'hardware-profiles-group.component.html' +}) +export class HardwareProfilesGroupComponent { + @Input() content; + + constructor() { + console.log(this.content); + } +} diff --git a/admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-group/profiles-group.component.html b/admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-group/profiles-group.component.html deleted file mode 100644 index 365ceebe..00000000 --- a/admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-group/profiles-group.component.html +++ /dev/null @@ -1,47 +0,0 @@ - - - -

    -
    -
    - - - - -
  • - -
  • -
  • - -
  • -
  • -
  • - -
  • - - -
    -
    -
    -
    - - - - - -
    -

    - -
    - - - - - - -
    diff --git a/admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-group/profiles-group.component.ts b/admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-group/profiles-group.component.ts deleted file mode 100644 index f9dbd868..00000000 --- a/admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-group/profiles-group.component.ts +++ /dev/null @@ -1,14 +0,0 @@ -import {ComponentMetadata} from 'codelyzer/angular/metadata'; -import {Component, Input} from '@angular/core'; - -@Component({ - selector: 'app-profiles-group', - templateUrl: 'profiles-group.component.html' -}) -export class ProfilesGroupComponent { - @Input() content; - - constructor() { - console.log(this.content); - } -} diff --git a/admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-table/hardware-profiles-table.component.html b/admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-table/hardware-profiles-table.component.html new file mode 100644 index 00000000..70bd2fd1 --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-table/hardware-profiles-table.component.html @@ -0,0 +1,61 @@ + + + + + + + + + + + + + +
    + + + + + {{profile.description}} + + + + + + + {{profile.windowsboot}} + + + +
    + + +
    +
    + + + + +
    diff --git a/admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-table/hardware-profiles-table.component.ts b/admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-table/hardware-profiles-table.component.ts new file mode 100644 index 00000000..76db2008 --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-table/hardware-profiles-table.component.ts @@ -0,0 +1,101 @@ +import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; +import {HardwareProfile} from '../../../../model/hardware-profile'; +import {HardwareProfileService} from '../../../../api/hardware-profile.service'; +import {ToasterService} from '../../../../service/toaster.service'; +import {TranslateService} from '@ngx-translate/core'; +import {OgSweetAlertService} from '../../../../service/og-sweet-alert.service'; +import {Router} from '@angular/router'; +import {environment} from '../../../../../environments/environment'; +import {PartitionInfo} from '../../../../model/image'; +import {Ng2TableActionComponent} from '../../../common/table-action/ng2-table-action.component'; + +@Component({ + selector: 'app-profiles-table', + templateUrl: 'hardware-profiles-table.component.html' +}) +export class HardwareProfilesTableComponent implements OnInit { + @Input() profiles; + windowsboots: any; + tableOptions: any; + + public constructor(private router: Router, private hardwareProfileService: HardwareProfileService, private ogSweetAlert: OgSweetAlertService, private toaster: ToasterService, private translate: TranslateService) { + + } + ngOnInit(): void { + this.windowsboots = environment.windowsboots; + this.tableOptions = { + override: false, + buttons: [ + { + action: 'edit' + }, + { + label: 'configure', + handler: (profile) => this.goToEditProfile(profile), + classes: 'btn-default' + }, + { + action: 'delete' + } + ] + }; + } + + editHardwareProfile(hardwareProfile) { + hardwareProfile.$$editing = true; + hardwareProfile.$$tmpName = hardwareProfile.name; + hardwareProfile.$$tmpDescription = hardwareProfile.description; + hardwareProfile.$$tmpWindowsboot = hardwareProfile.windowsboot; + } + + saveHardwareProfile(hardwareProfile) { + hardwareProfile.$$editing = false; + hardwareProfile.name = hardwareProfile.$$tmpName; + hardwareProfile.description = hardwareProfile.$$tmpDescription; + hardwareProfile.windowsboot = hardwareProfile.$$tmpWindowsboot; + const hpCopy = Object.assign({}, hardwareProfile); + // TODO - Llamar al servidor para guardar el cambio + this.hardwareProfileService.update(hpCopy).subscribe( + (response) => { + this.toaster.pop({type: 'success', title: 'success', body: this.translate.instant('successfully_saved')}); + }, + (error) => { + this.toaster.pop({type: 'error', title: 'error', body: error}); + } + ); + } + + deleteHardwareProfile(hardwareProfile) { + const self = this; + + this.ogSweetAlert.question(this.translate.instant('sure_to_delete') + '?', this.translate.instant('action_cannot_be_undone'), + function(result) { + if (result.value === true) { + self.hardwareProfileService.delete(hardwareProfile.id).subscribe( + (response) => { + self.toaster.pop({type: 'success', title: self.translate.instant('success'), body: self.translate.instant('successfully_deleted')}); + const index = self.profiles.indexOf(hardwareProfile); + if (index !== -1) { + self.profiles.splice(index, 1); + } + }, + (error) => { + self.toaster.pop({type: 'error', title: self.translate.instant('error'), body: error}); + } + ); + } + } + ); + } + + goToEditProfile(profile: HardwareProfile) { + this.router.navigate(['/app/hardware/profile', profile.id]).then( + success => { + console.log(success); + }, + error => { + console.log(error); + } + ); + } +} diff --git a/admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-table/profiles-table.component.html b/admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-table/profiles-table.component.html deleted file mode 100644 index 45f17240..00000000 --- a/admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-table/profiles-table.component.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - -
    - - - - - {{profile.description}} - - - - - - - {{profile.windowsboot}} - - - -
    - - -
    -
    - - - - -
    diff --git a/admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-table/profiles-table.component.ts b/admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-table/profiles-table.component.ts deleted file mode 100644 index c1a155ff..00000000 --- a/admin/WebConsole3/frontend/src/app/pages/hardware/hardware-profiles/profiles-table/profiles-table.component.ts +++ /dev/null @@ -1,101 +0,0 @@ -import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; -import {HardwareProfile} from '../../../../model/hardware-profile'; -import {HardwareProfileService} from '../../../../api/hardware-profile.service'; -import {ToasterService} from '../../../../service/toaster.service'; -import {TranslateService} from '@ngx-translate/core'; -import {OgSweetAlertService} from '../../../../service/og-sweet-alert.service'; -import {Router} from '@angular/router'; -import {environment} from '../../../../../environments/environment'; -import {PartitionInfo} from '../../../../model/image'; -import {Ng2TableActionComponent} from '../../../common/table-action/ng2-table-action.component'; - -@Component({ - selector: 'app-profiles-table', - templateUrl: 'profiles-table.component.html' -}) -export class ProfilesTableComponent implements OnInit { - @Input() profiles; - windowsboots: any; - tableOptions: any; - - public constructor(private router: Router, private hardwareProfileService: HardwareProfileService, private ogSweetAlert: OgSweetAlertService, private toaster: ToasterService, private translate: TranslateService) { - - } - ngOnInit(): void { - this.windowsboots = environment.windowsboots; - this.tableOptions = { - override: false, - buttons: [ - { - action: 'edit' - }, - { - label: 'configure', - handler: (profile) => this.goToEditProfile(profile), - classes: 'btn-default' - }, - { - action: 'delete' - } - ] - }; - } - - editHardwareProfile(hardwareProfile) { - hardwareProfile.$$editing = true; - hardwareProfile.$$tmpName = hardwareProfile.name; - hardwareProfile.$$tmpDescription = hardwareProfile.description; - hardwareProfile.$$tmpWindowsboot = hardwareProfile.windowsboot; - } - - saveHardwareProfile(hardwareProfile) { - hardwareProfile.$$editing = false; - hardwareProfile.name = hardwareProfile.$$tmpName; - hardwareProfile.description = hardwareProfile.$$tmpDescription; - hardwareProfile.windowsboot = hardwareProfile.$$tmpWindowsboot; - const hpCopy = Object.assign({}, hardwareProfile); - // TODO - Llamar al servidor para guardar el cambio - this.hardwareProfileService.update(hpCopy).subscribe( - (response) => { - this.toaster.pop({type: 'success', title: 'success', body: this.translate.instant('successfully_saved')}); - }, - (error) => { - this.toaster.pop({type: 'error', title: 'error', body: error}); - } - ); - } - - deleteHardwareProfile(hardwareProfile) { - const self = this; - - this.ogSweetAlert.question(this.translate.instant('sure_to_delete') + '?', this.translate.instant('action_cannot_be_undone'), - function(result) { - if (result.value === true) { - self.hardwareProfileService.delete(hardwareProfile.id).subscribe( - (response) => { - self.toaster.pop({type: 'success', title: self.translate.instant('success'), body: self.translate.instant('successfully_deleted')}); - const index = self.profiles.indexOf(hardwareProfile); - if (index !== -1) { - self.profiles.splice(index, 1); - } - }, - (error) => { - self.toaster.pop({type: 'error', title: self.translate.instant('error'), body: error}); - } - ); - } - } - ); - } - - goToEditProfile(profile: HardwareProfile) { - this.router.navigate(['/app/hardware/profile', profile.id]).then( - success => { - console.log(success); - }, - error => { - console.log(error); - } - ); - } -} diff --git a/admin/WebConsole3/frontend/src/app/pages/image/edit/image-edit.component.ts b/admin/WebConsole3/frontend/src/app/pages/image/edit/image-edit.component.ts index 1117762b..8bc33f44 100644 --- a/admin/WebConsole3/frontend/src/app/pages/image/edit/image-edit.component.ts +++ b/admin/WebConsole3/frontend/src/app/pages/image/edit/image-edit.component.ts @@ -1,76 +1,100 @@ -import {Component, OnInit} from '@angular/core'; - -import { ImageService } from 'src/app/api/image.service'; -import {Image, PartitionInfo} from 'src/app/model/image'; - -import {ActivatedRoute, Router} from '@angular/router'; -import {ToasterService} from '../../../service/toaster.service'; -import {TranslateService} from '@ngx-translate/core'; -import {ImageFormType} from '../../../form-type/image.form-type'; -import {RepositoryService} from '../../../api/repository.service'; - -@Component({ - selector: 'app-image', - templateUrl: './image-edit.component.html', - styleUrls: [ './image-edit.component.scss' ] -}) -export class ImageEditComponent implements OnInit { - image: Image; - constants: any; - private formType = new ImageFormType(); - public form: any; - - // this tells the tabs component which Pages - // should be each tab's root Page - constructor(private router: Router, private activatedRouter: ActivatedRoute, private imageService: ImageService, private repositoryService: RepositoryService, private translate: TranslateService, private toaster: ToasterService) { - this.form = this.formType.getForm(); - } - - ngOnInit(): void { - this.image = new Image(); - this.activatedRouter.paramMap.subscribe( - (data: any) => { - if (data.params.id) { - this.imageService.read(data.params.id).subscribe( - image => { - this.image = image; - }, - error => { - this.toaster.pop({type: 'error', title: 'error', body: error}); - } - ); - } - } - ); - this.repositoryService.list().subscribe( - data => { - this.formType.getField(this.form, 'repository').options = { - items: data, - label: 'name', - value: 'id' - } - } - ) - } - - getImageFileSystem(image) { - const result = ''; - if (typeof image.partitionInfo === 'string') { - image.partitionInfo = JSON.parse(image.partitionInfo); - } else if (!image.partitionInfo) { - image.partitionInfo = {}; - } - return image.partitionInfo.filesystem; - } - - - getPartitionType(partition) { - // buscar la particion en el array global - let result = this.constants.partitionTypes.filter(function (obj) { - return obj.id === partition.id; - }); - result = result[0]; - return result.type; - } - -} +import {Component, OnInit} from '@angular/core'; + +import { ImageService } from 'src/app/api/image.service'; +import {Image, PartitionInfo} from 'src/app/model/image'; + +import {ActivatedRoute, Router} from '@angular/router'; +import {ToasterService} from '../../../service/toaster.service'; +import {TranslateService} from '@ngx-translate/core'; +import {ImageFormType} from '../../../form-type/image.form-type'; +import {RepositoryService} from '../../../api/repository.service'; +import {Observable} from 'rxjs'; + +@Component({ + selector: 'app-image', + templateUrl: './image-edit.component.html', + styleUrls: [ './image-edit.component.scss' ] +}) +export class ImageEditComponent implements OnInit { + image: Image; + constants: any; + private formType = new ImageFormType(); + public form: any; + + // this tells the tabs component which Pages + // should be each tab's root Page + constructor(private router: Router, private activatedRouter: ActivatedRoute, private imageService: ImageService, private repositoryService: RepositoryService, private translate: TranslateService, private toaster: ToasterService) { + this.form = this.formType.getForm(); + } + + ngOnInit(): void { + this.image = new Image(); + this.activatedRouter.paramMap.subscribe( + (data: any) => { + if (data.params.id) { + this.imageService.read(data.params.id).subscribe( + image => { + this.image = image; + if (typeof this.image.partitionInfo === 'string') { + this.image.partitionInfo = JSON.parse(this.image.partitionInfo); + } else if (!this.image.partitionInfo) { + this.image.partitionInfo = new PartitionInfo(); + } + }, + error => { + this.toaster.pop({type: 'error', title: 'error', body: error}); + } + ); + } + } + ); + this.repositoryService.list().subscribe( + data => { + this.formType.getField(this.form, 'repository').options = { + items: data, + label: 'name', + value: 'id' + }; + } + ); + } + + getImageFileSystem(image) { + const result = ''; + if (typeof image.partitionInfo === 'string') { + image.partitionInfo = JSON.parse(image.partitionInfo); + } else if (!image.partitionInfo) { + image.partitionInfo = {}; + } + return image.partitionInfo.filesystem; + } + + + getPartitionType(partition) { + // buscar la particion en el array global + let result = this.constants.partitionTypes.filter(function (obj) { + return obj.id === partition.id; + }); + result = result[0]; + return result.type; + } + + save() { + let request: Observable; + if (this.image.id !== 0) { + request = this.imageService.update(this.image); + } else { + request = this.imageService.create(this.image); + } + request.subscribe( + (response) => { + this.toaster.pop({type: 'success', title: this.translate.instant('success'), body: this.translate.instant('successfully_saved')}); + this.router.navigate(['/app/images']); + + }, + (error) => { + this.toaster.pop({type: 'error', title: 'error', body: error}); + } + ); + } +} diff --git a/admin/WebConsole3/frontend/src/app/pages/image/image.component.html b/admin/WebConsole3/frontend/src/app/pages/image/image.component.html index 09ba6036..a5b700ac 100644 --- a/admin/WebConsole3/frontend/src/app/pages/image/image.component.html +++ b/admin/WebConsole3/frontend/src/app/pages/image/image.component.html @@ -9,16 +9,16 @@
    -
    +
    - +
    -
    +
    diff --git a/admin/WebConsole3/frontend/src/app/pages/menu/edit/menu-edit.component.html b/admin/WebConsole3/frontend/src/app/pages/menu/edit/menu-edit.component.html new file mode 100644 index 00000000..9d96cde9 --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/menu/edit/menu-edit.component.html @@ -0,0 +1,34 @@ +
    +

    +

    + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    diff --git a/admin/WebConsole3/frontend/src/app/pages/menu/edit/menu-edit.component.scss b/admin/WebConsole3/frontend/src/app/pages/menu/edit/menu-edit.component.scss new file mode 100644 index 00000000..1382f194 --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/menu/edit/menu-edit.component.scss @@ -0,0 +1,3 @@ +image { + +} diff --git a/admin/WebConsole3/frontend/src/app/pages/menu/edit/menu-edit.component.ts b/admin/WebConsole3/frontend/src/app/pages/menu/edit/menu-edit.component.ts new file mode 100644 index 00000000..d52f53ad --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/menu/edit/menu-edit.component.ts @@ -0,0 +1,77 @@ +import {Component, OnInit} from '@angular/core'; + + +import {ActivatedRoute, Router} from '@angular/router'; +import {ToasterService} from '../../../service/toaster.service'; +import {TranslateService} from '@ngx-translate/core'; +import {MenuFormType} from '../../../form-type/menu.form-type'; +import {RepositoryService} from '../../../api/repository.service'; +import {Observable} from 'rxjs'; +import {MenuService} from '../../../api/menu.service'; +import {Menu} from '../../../model/menu'; +import {OgCommonService} from '../../../service/og-common.service'; + +@Component({ + selector: 'app-menu', + templateUrl: './menu-edit.component.html', + styleUrls: [ './menu-edit.component.scss' ] +}) +export class MenuEditComponent implements OnInit { + menu: Menu; + constants: any; + private formType = new MenuFormType(); + public form: any; + + // this tells the tabs component which Pages + // should be each tab's root Page + constructor(private router: Router, private activatedRouter: ActivatedRoute, private ogCommonService: OgCommonService, private menuService: MenuService, private translate: TranslateService, private toaster: ToasterService) { + this.form = this.formType.getForm(); + } + + ngOnInit(): void { + this.menu = new Menu(); + this.ogCommonService.loadEngineConfig().subscribe( + data => { + this.formType.getField(this.form, 'resolution').options = { + items: data.constants.menus.resolutions, + label: 'text', + value: 'id' + }; + } + ); + this.activatedRouter.paramMap.subscribe( + (data: any) => { + if (data.params.id) { + this.menuService.read(data.params.id).subscribe( + menu => { + this.menu = menu; + }, + error => { + this.toaster.pop({type: 'error', title: 'error', body: error}); + } + ); + } + } + ); + } + + + save() { + let request: Observable; + if (this.menu.id !== 0) { + request = this.menuService.update(this.menu); + } else { + request = this.menuService.create(this.menu); + } + request.subscribe( + (response) => { + this.toaster.pop({type: 'success', title: this.translate.instant('success'), body: this.translate.instant('successfully_saved')}); + this.router.navigate(['/app/menus']); + + }, + (error) => { + this.toaster.pop({type: 'error', title: 'error', body: error}); + } + ); + } +} diff --git a/admin/WebConsole3/frontend/src/app/pages/menu/menu.component.html b/admin/WebConsole3/frontend/src/app/pages/menu/menu.component.html index 93bab7ab..bc65667b 100644 --- a/admin/WebConsole3/frontend/src/app/pages/menu/menu.component.html +++ b/admin/WebConsole3/frontend/src/app/pages/menu/menu.component.html @@ -1 +1,51 @@ -
    Html template for class Menu
    \ No newline at end of file +
    +
    +

    +

    + +
    +
    +
    +
    +
    + + + + +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    +
    +
    + +
    +
    +

    +
    +
    + +
    + + +
    +
    +
    + +
    +
    diff --git a/admin/WebConsole3/frontend/src/app/pages/menu/menu.component.ts b/admin/WebConsole3/frontend/src/app/pages/menu/menu.component.ts index a5cecb4e..4c47eb73 100644 --- a/admin/WebConsole3/frontend/src/app/pages/menu/menu.component.ts +++ b/admin/WebConsole3/frontend/src/app/pages/menu/menu.component.ts @@ -1,17 +1,104 @@ -import { Component } from '@angular/core'; - -import { MenuService } from 'src/app/api/menu.service'; -import { Menu } from 'src/app/model/menu'; - -@Component({ - selector: 'menu', - templateUrl: './menu.component.html', - styleUrls: [ './menu.component.scss' ] -}) -export class MenuComponent { - // this tells the tabs component which Pages - // should be each tab's root Page - constructor(public menuService: MenuService) { - } - -} +import {Component, OnInit} from '@angular/core'; + +import { MenuService } from 'src/app/api/menu.service'; +import { Menu } from 'src/app/model/menu'; +import {PartitionInfo} from '../../model/image'; +import {Ng2TableActionComponent} from '../common/table-action/ng2-table-action.component'; +import {TranslateService} from '@ngx-translate/core'; +import {Router} from '@angular/router'; +import {OgSweetAlertService} from '../../service/og-sweet-alert.service'; + +@Component({ + selector: 'app-menu', + templateUrl: './menu.component.html', + styleUrls: [ './menu.component.scss' ] +}) +export class MenuComponent implements OnInit { + public menus: Menu[]; + private tableSettings: any; + // this tells the tabs component which Pages + // should be each tab's root Page + constructor(public menuService: MenuService, private router: Router, private ogSweetAlert: OgSweetAlertService, private translate: TranslateService) { + } + + ngOnInit(): void { + this.menuService.list().subscribe( + data => { + this.menus = data; + }, + error => { + + } + ); + const self = this; + this.tableSettings = { + columns: { + title: { + title: this.translate.instant('title') + }, + description: { + title: this.translate.instant('description') + }, + comments: { + title: this.translate.instant('comments'), + }, + resolution: { + title: this.translate.instant('resolution') + }, + options: { + title: 'Options', + filter: false, + sort: false, + type: 'custom', + renderComponent: Ng2TableActionComponent, + onComponentInitFunction(instance) { + instance.edit.subscribe(row => { + self.router.navigate(['/app/menus/edit/', row.id]); + }); + instance.delete.subscribe(row => { + self.deleteMenu(row); + }); + } + }, + }, + actions: { + position: 'right', + add: false, + edit: false, + delete: false + } + }; + } + + deleteMenu(menu) { + const self = this; + this.ogSweetAlert.swal({ + title: this.translate.instant('sure_to_delete') + '?', + message: this.translate.instant('action_cannot_be_undone'), + type: 'warning', + showCancelButton: true, + confirmButtonColor: '#3c8dbc', + confirmButtonText: this.translate.instant('yes_delete'), + closeOnConfirm: true + }).then( + function(result) { + if (result === true) { + + this.menuService.delete(menu.id).then( + function(response) { + this.toaster.pop({type: 'success', title: 'success', body: this.translate.instant('successfully_deleted')}); + // Buscar el elemento en el array y borrarlo + const index = this.images.indexOf(menu); + if (index !== -1) { + this.images.splice(menu, 1); + } + }, + function(error) { + this.toaster.pop({type: 'error', title: 'error', body: error}); + } + ); + } + }); + } + +} diff --git a/admin/WebConsole3/frontend/src/app/pages/organizational-unit/ou-clients/ou-client.component.html b/admin/WebConsole3/frontend/src/app/pages/organizational-unit/ou-clients/ou-client.component.html index 86508a31..32b0a4db 100644 --- a/admin/WebConsole3/frontend/src/app/pages/organizational-unit/ou-clients/ou-client.component.html +++ b/admin/WebConsole3/frontend/src/app/pages/organizational-unit/ou-clients/ou-client.component.html @@ -24,7 +24,7 @@ diff --git a/admin/WebConsole3/frontend/src/app/core/sidebar-left-inner/sidebar-left-inner.component.ts b/admin/WebConsole3/frontend/src/app/core/sidebar-left-inner/sidebar-left-inner.component.ts index 036da6cb..991abdb2 100644 --- a/admin/WebConsole3/frontend/src/app/core/sidebar-left-inner/sidebar-left-inner.component.ts +++ b/admin/WebConsole3/frontend/src/app/core/sidebar-left-inner/sidebar-left-inner.component.ts @@ -1,7 +1,15 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'app-sidebar-left-inner', - templateUrl: './sidebar-left-inner.component.html' -}) -export class SidebarLeftInnerComponent {} +import { Component } from '@angular/core'; +import {AuthModule} from 'globunet-angular/core'; + +@Component({ + selector: 'app-sidebar-left-inner', + templateUrl: './sidebar-left-inner.component.html' +}) +export class SidebarLeftInnerComponent { + user: any; + + constructor(private authModule: AuthModule) { + this.user = this.authModule.getLoggedUser(); + } + +} diff --git a/admin/WebConsole3/frontend/src/app/form-type/menu.form-type.ts b/admin/WebConsole3/frontend/src/app/form-type/menu.form-type.ts index 94a8d97b..b17cc7a0 100644 --- a/admin/WebConsole3/frontend/src/app/form-type/menu.form-type.ts +++ b/admin/WebConsole3/frontend/src/app/form-type/menu.form-type.ts @@ -6,7 +6,11 @@ export class MenuFormType extends GlobunetFormType { getForm() { const form: any[] = GlobunetFormType.getForm(new Menu()); this.setFieldType(form, 'description', 'textarea'); + this.setFieldType(form, 'comments', 'textarea'); this.setFieldType(form, 'resolution', 'select'); + this.getField(form, 'resolution').options = { + items: [] + }; return form; } } diff --git a/admin/WebConsole3/frontend/src/app/form-type/repository.form-type.ts b/admin/WebConsole3/frontend/src/app/form-type/repository.form-type.ts index 15b1b9f8..c0a8fffd 100644 --- a/admin/WebConsole3/frontend/src/app/form-type/repository.form-type.ts +++ b/admin/WebConsole3/frontend/src/app/form-type/repository.form-type.ts @@ -1,9 +1,11 @@ -import {Repository} from '../model/repository'; -import {GlobunetFormType} from './globunet.form-type'; - - -export class RepositoryFormType { - getForm() { - return GlobunetFormType.getForm(new Repository()); - } -} +import {Repository} from '../model/repository'; +import {GlobunetFormType} from './globunet.form-type'; + + +export class RepositoryFormType extends GlobunetFormType{ + getForm() { + const form = GlobunetFormType.getForm(new Repository()); + this.setFieldType(form, 'description', 'textarea'); + return form; + } +} diff --git a/admin/WebConsole3/frontend/src/app/model/image.ts b/admin/WebConsole3/frontend/src/app/model/image.ts index 2d52cf63..5df31b74 100644 --- a/admin/WebConsole3/frontend/src/app/model/image.ts +++ b/admin/WebConsole3/frontend/src/app/model/image.ts @@ -9,6 +9,7 @@ export class PartitionInfo { partitionCode: string; filesystem: string; osName: string; + type: string; } export class Image extends Resource { diff --git a/admin/WebConsole3/frontend/src/app/model/repository.ts b/admin/WebConsole3/frontend/src/app/model/repository.ts index 5b6756d2..36838128 100644 --- a/admin/WebConsole3/frontend/src/app/model/repository.ts +++ b/admin/WebConsole3/frontend/src/app/model/repository.ts @@ -1,25 +1,17 @@ -import { Resource } from 'globunet-angular/core/models/api/resource'; - -export class Repository extends Resource { - name: string; - ip: string; - port: number; - password: string; - configurationpath: string; - adminpath: string; - pxepath: string; - description: string; - info: any; - - constructor() { - super(); - this.name = ''; - this.ip = ''; - this.port = 0; - this.password = ''; - this.configurationpath = ''; - this.adminpath = ''; - this.pxepath = ''; - this.description = ''; - } -} +import { Resource } from 'globunet-angular/core/models/api/resource'; + +export class Repository extends Resource { + name: string; + ip: string; + password: string; + description: string; + info: any; + + constructor() { + super(); + this.name = ''; + this.ip = ''; + this.password = ''; + this.description = ''; + } +} diff --git a/admin/WebConsole3/frontend/src/app/pages/command/delete-cache-image-command/delete-cache-image-command.component.html b/admin/WebConsole3/frontend/src/app/pages/command/delete-cache-image-command/delete-cache-image-command.component.html new file mode 100644 index 00000000..5d09b0aa --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/command/delete-cache-image-command/delete-cache-image-command.component.html @@ -0,0 +1,62 @@ +
    +

    +

    + +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +

    + +
    + +
    +
    +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + +
    + + +
    + + + {{image.type}} + + {{image.name}} +
    +
    +
    +
    +
    +
    +
    diff --git a/admin/WebConsole3/frontend/src/app/pages/command/delete-cache-image-command/delete-cache-image-command.component.scss b/admin/WebConsole3/frontend/src/app/pages/command/delete-cache-image-command/delete-cache-image-command.component.scss new file mode 100644 index 00000000..08b1082b --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/command/delete-cache-image-command/delete-cache-image-command.component.scss @@ -0,0 +1,3 @@ +app-execute-command { + +} diff --git a/admin/WebConsole3/frontend/src/app/pages/command/delete-cache-image-command/delete-cache-image-command.component.ts b/admin/WebConsole3/frontend/src/app/pages/command/delete-cache-image-command/delete-cache-image-command.component.ts new file mode 100644 index 00000000..efc14d6d --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/command/delete-cache-image-command/delete-cache-image-command.component.ts @@ -0,0 +1,120 @@ +import {Component, OnInit} from '@angular/core'; + +import {ToasterService} from '../../../service/toaster.service'; +import {ActivatedRoute, Router} from '@angular/router'; +import {TranslateService} from '@ngx-translate/core'; +import {OgCommonService} from '../../../service/og-common.service'; +import {OgSweetAlertService} from '../../../service/og-sweet-alert.service'; +import {AuthModule} from 'globunet-angular/core'; +import {User} from '../../../model/user'; +import {OGCommandsService} from '../../../service/og-commands.service'; +import {CommandService} from '../../../api/command.service'; +import {Image} from '../../../model/image'; +import {Command, Excecution} from '../../../model/command'; +import {Client} from '../../../model/client'; +import {Repository} from '../../../model/repository'; +import {RepositoryService} from '../../../api/repository.service'; +import {ImageService} from '../../../api/image.service'; + +@Component({ + selector: 'app-delete-cache-image-command', + templateUrl: './delete-cache-image-command.component.html', + styleUrls: [ './delete-cache-image-command.component.scss' ] +}) +export class DeleteCacheImageCommandComponent implements OnInit { + private readonly user: User; + private constants: any; + public repositories: Repository[]; + public execution = new Excecution(); + public commands: Command[] = []; + public client: Client; + public cacheImages = []; + public command = {canonicalName: '', image: new Image()}; + + + // this tells the tabs component which Pages + // should be each tab's root Page + constructor(public ogCommandsService: OGCommandsService, + private authModule: AuthModule, + private router: Router, + private activatedRoute: ActivatedRoute, + private ogCommonService: OgCommonService, + private commandService: CommandService, + private imageService: ImageService, + private repositoryService: RepositoryService, + private ogSweetAlert: OgSweetAlertService, + private toaster: ToasterService, + private translate: TranslateService) { + this.user = this.authModule.getLoggedUser(); + } + + + + + ngOnInit() { + if (this.user && this.ogCommonService.selectedClients) { + this.ogCommonService.loadEngineConfig().subscribe( + data => { + this.constants = data.constants; + } + ); + const clientIds = Object.keys(this.ogCommonService.selectedClients); + this.execution.clients = clientIds.join(','); + // Capturar para todos los clientes todas las imágenes de cache + this.cacheImages = []; + for (let index = 0; index < clientIds.length; index++) { + const client = this.ogCommonService.selectedClients[clientIds[index]]; + const diskConfigs = this.ogCommonService.getDisksConfigFromPartitions(client.partitions); + for (let dc = 0; dc < diskConfigs.length; dc++) { + const diskConfig = diskConfigs[dc]; + for (let p = 0; p < diskConfig.partitions.length; p++) { + const partition = diskConfig.partitions[p]; + if (partition.partitionCode === 'ca') { + // Solo cogemos las imagenes .img, no los .sum + for (let f = 0; f < partition.cacheContent.files.length; f++) { + const file = partition.cacheContent.files[f]; + // Si no es un .sum + if (!file.name.match('.sum')) { + this.cacheImages.push(file); + } + } + } + } + } + } + } else { + // TODO - dar error? + this.ogSweetAlert.error(this.translate.instant('opengnsys_error'), this.translate.instant('not_clients_selected')); + this.router.navigate(['app.ous']); + } + } + + + sendCommand() { + this.execution.script = ''; + for (let f = 0; f < this.cacheImages.length; f++) { + if (this.cacheImages[f].selected === true) { + if (this.cacheImages[f].type !== 'D') { + this.execution.script += 'rm -rf $OGCAC/$OGIMG/' + this.cacheImages[f].name.trim() + '*'; + } else { + this.execution.script += 'rm -rf $OGCAC/$OGIMG/' + this.cacheImages[f].name.trim(); + } + this.execution.script += '\n'; + } + } + this.execution.script += this.constants.commands.REFRESH_INFO + '\n'; + this.execution.script = this.execution.script.replace(/\"/g, '\\"').replace(/\$/g, '\\\$'); + this.execution.type = 'RUN_SCRIPT'; + + this.commandService.execute(this.execution).subscribe( + (response) => { + this.toaster.pop({type: 'success', title: 'success', body: this.translate.instant('successfully_executed')}); + this.router.navigate(['/app/ous']); + }, + (error) => { + this.toaster.pop({type: 'error', title: 'error', body: error}); + } + ); + } + +} diff --git a/admin/WebConsole3/frontend/src/app/pages/command/format-command/format-command.component.html b/admin/WebConsole3/frontend/src/app/pages/command/format-command/format-command.component.html new file mode 100644 index 00000000..a14c8510 --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/command/format-command/format-command.component.html @@ -0,0 +1,96 @@ +
    +

    +

    + +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +

    + +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    + + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + +
    + + + {{partition.numDisk}} + + {{partition.numPartition}} + + + + + + {{ogCommonService.getUnits(partition.size*1024)}} + + {{partition.osName}} +
    +
    +
    +
    +
    +
    +
    +
    diff --git a/admin/WebConsole3/frontend/src/app/pages/command/format-command/format-command.component.scss b/admin/WebConsole3/frontend/src/app/pages/command/format-command/format-command.component.scss new file mode 100644 index 00000000..ccb34440 --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/command/format-command/format-command.component.scss @@ -0,0 +1,3 @@ +command { + +} diff --git a/admin/WebConsole3/frontend/src/app/pages/command/format-command/format-command.component.ts b/admin/WebConsole3/frontend/src/app/pages/command/format-command/format-command.component.ts new file mode 100644 index 00000000..62b733b8 --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/command/format-command/format-command.component.ts @@ -0,0 +1,150 @@ +import {Component, OnInit} from '@angular/core'; + +import {ToasterService} from '../../../service/toaster.service'; +import {ActivatedRoute, Router} from '@angular/router'; +import {TranslateService} from '@ngx-translate/core'; +import {OgCommonService} from '../../../service/og-common.service'; +import {OgSweetAlertService} from '../../../service/og-sweet-alert.service'; +import {AuthModule} from 'globunet-angular/core'; +import {User} from '../../../model/user'; +import {OGCommandsService} from '../../../service/og-commands.service'; +import {Client, Partition} from '../../../model/client'; +import {CommandService} from '../../../api/command.service'; +import {forkJoin} from 'rxjs'; + +@Component({ + selector: 'app-format-command', + templateUrl: './format-command.component.html', + styleUrls: [ './format-command.component.scss' ] +}) +export class FormatCommandComponent implements OnInit { + execution = {clients: '', script: '', type: ''}; + command = {}; + user: User; + clientGroups = {}; + constants: any; + + // this tells the tabs component which Pages + // should be each tab's root Page + constructor(public ogCommandsService: OGCommandsService, + private authModule: AuthModule, + private router: Router, + private activatedRoute: ActivatedRoute, + public ogCommonService: OgCommonService, + private commandService: CommandService, + private ogSweetAlert: OgSweetAlertService, + private toaster: ToasterService, + private translate: TranslateService) { + this.user = this.authModule.getLoggedUser(); + } + + + ngOnInit() { + if (this.user && this.ogCommonService.selectedClients) { + this.ogCommonService.loadEngineConfig().subscribe( + data => { + this.constants = data.constants; + } + ); + const clientIds = Object.keys(this.ogCommonService.selectedClients); + // Recorrer todos los clientes y formar los grupos según el partitionCode de sus particiones, deben coincidir todos + for (let index = 0; index < clientIds.length; index++) { + // Generamos una clave usando disco-particion-code para comparar + const client = this.ogCommonService.selectedClients[clientIds[index]]; + const key = this.getPartitionsCode(client.partitions); + + if (!this.clientGroups[key]) { + this.clientGroups[key] = []; + } + this.clientGroups[key].push(client); + } + } else { + // TODO - dar error? + this.ogSweetAlert.error(this.translate.instant('opengnsys_error'), this.translate.instant('not_clients_selected')); + this.router.navigate(['/app/ous']); + } + } + + getPartitionsCode(partitions) { + let key = ''; + for (let p = 0; p < partitions.length; p++) { + // Además de calcular la clave, alteramos el partitionCode pasandolo a mayusculas y aplicando padding de "0" a la izquierda si es necesario + partitions[p].partitionCode = partitions[p].partitionCode.toUpperCase(); + if (partitions[p].partitionCode.length === 1) { + partitions[p].partitionCode = '0' + partitions[p].partitionCode; + } + key += partitions[p].numDisk + partitions[p].numPartition + partitions[p].partitionCode; + } + return key; + } + + + sendCommand() { + // Comrobar qué particiones se han seleccionado de qué grupos + const executions = {}; + const groups = Object.keys(this.clientGroups); + for (let g = 0; g < groups.length; g++) { + if (!executions[g]) { + executions[g] = { + clients: '', + script: '' + }; + } + // Recorrer las particiones del primer cliente de la lista y ver si hay alguna seleccionada + const found = false; + // La partición 0 no se usa, solo indica las propiedades del disco + let index = 1; + const client = this.clientGroups[groups[g]][0]; + for (let c = 0; c < this.clientGroups[groups[g]].length; c++) { + executions[g].clients += client.id + ','; + } + while (!found && index < client.partitions.length) { + const partition = client.partitions[index]; + if (partition.selected === true) { + if(executions[g].script === '') { + executions[g].script = 'ogUnmountAll ' + partition.numDisk + '\n'; + } + // Si la particion es cache + if (partition.partitionCode.toUpperCase() === 'CA') { + executions[g].script += 'ogFormatCache' + '\n'; + } else { + executions[g].script += 'ogFormat ' + partition.numDisk + ' ' + partition.numPartition + ' ' + partition.filesystem + '\n'; + } + } + index++; + } + } + + // Creamos tantas promises como diferentes grupos de ejecución haya + const promises = []; + const len = Object.keys(executions).length; + for (let index = 0; index < len; index++) { + const execution = { + type: 'RUN_SCRIPT', + script: executions[index].script, + clients: executions[index].clients.substring(0, executions[index].clients.length - 1) // Quitar la ultima "," + }; + promises.push(this.commandService.execute(execution)); + } + forkJoin(promises).subscribe( + (response) => { + this.toaster.pop({type: 'success', title: 'success', body: this.translate.instant('successfully_executed')}); + this.router.navigate(['/app/ous']); + }, + (error) => { + this.toaster.pop({type: 'error', title: 'error', body: error}); + } + ); + } + + getPartitionTypes(partitions) { + let types = []; + const infoPart = partitions.filter((partition: Partition) => partition.numPartition === 0); + if (infoPart.length === 1) { + const partitionTable = this.ogCommonService.getPartitionTable(infoPart[0]); + types = partitionTable.partitions; + } + return types; + } + +} diff --git a/admin/WebConsole3/frontend/src/app/pages/command/partition-format-command/partition-format-command.component.html b/admin/WebConsole3/frontend/src/app/pages/command/partition-format-command/partition-format-command.component.html new file mode 100644 index 00000000..fab8b8d7 --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/command/partition-format-command/partition-format-command.component.html @@ -0,0 +1,164 @@ +
    +

    + +
    +
    +

    + +
    +
    +
    +
    +
    +
    + : +
    +
    + : + +
    +
    + : {{getSizeInGB(diskConfig.size)}} GB ({{getSizeInGB(diskConfig.size*diskConfig.remaining/100)}} GB ) +
    +
    +
    + +
    + +
    + +
    +
    +
    + + + + +
    + ({{partition.usage}}%) + + + + +
    + {{extendedPartition.type}} ({{extendedPartition.usage}}%) +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    (bytes)
    {{partition.partition}} ({{getSizeInGB(partition.size)}}GB) + + {{partition.filesystem}} + + + + % + +
    + +
    +
    + + + +
    {{extendedPartition.partition}} + + {{extendedPartition.filesystem}} + + % + +
    + +
    +
    + +
    +
    +
    + +
    + + +
    +
    +
    +
    + + +
    +
    diff --git a/admin/WebConsole3/frontend/src/app/pages/command/partition-format-command/partition-format-command.component.scss b/admin/WebConsole3/frontend/src/app/pages/command/partition-format-command/partition-format-command.component.scss new file mode 100644 index 00000000..97d2231d --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/command/partition-format-command/partition-format-command.component.scss @@ -0,0 +1,22 @@ +::ng-deep app-partition-format-command { + ::ng-deep table.disk-partitions { + min-height: 40px; + } + ::ng-deep table.disk-partitions td { + position: relative; + } + ::ng-deep span.resizer { + display: block; + position: absolute; + top: 0; + right: 0; + margin: 0; + background-color: black; + width: 2px; + height: 100%; + padding: 0 !important; + cursor: col-resize; + border: 1px solid transparent; + } + +} diff --git a/admin/WebConsole3/frontend/src/app/pages/command/partition-format-command/partition-format-command.component.ts b/admin/WebConsole3/frontend/src/app/pages/command/partition-format-command/partition-format-command.component.ts new file mode 100644 index 00000000..8c75fa2e --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/command/partition-format-command/partition-format-command.component.ts @@ -0,0 +1,618 @@ +import {Component, OnInit} from '@angular/core'; + +import {ToasterService} from '../../../service/toaster.service'; +import {ActivatedRoute, Router} from '@angular/router'; +import {TranslateService} from '@ngx-translate/core'; +import {OgCommonService} from '../../../service/og-common.service'; +import {OgSweetAlertService} from '../../../service/og-sweet-alert.service'; +import {AuthModule} from 'globunet-angular/core'; +import {User} from '../../../model/user'; +import {OGCommandsService} from '../../../service/og-commands.service'; +import {CommandService} from '../../../api/command.service'; +import {DomSanitizer} from '@angular/platform-browser'; +import {ChartOptions} from 'chart.js'; +import {Client} from '../../../model/client'; + +@Component({ + selector: 'app-partition-format-command', + templateUrl: './partition-format-command.component.html', + styleUrls: [ './partition-format-command.component.scss' ] +}) +export class PartitionFormatCommandComponent implements OnInit { + execution = {clients: '', script: '', type: ''}; + command = {}; + user: User; + constants: any; + diskConfig: any; + partitionTableTypes = ['MSDOS', 'GPT']; + partitionTypes = []; + editInstructions = false; + + // this tells the tabs component which Pages + // should be each tab's root Page + constructor(public ogCommandsService: OGCommandsService, + public sanitizer: DomSanitizer, + private authModule: AuthModule, + private router: Router, + private activatedRoute: ActivatedRoute, + public ogCommonService: OgCommonService, + private commandService: CommandService, + private ogSweetAlert: OgSweetAlertService, + private toaster: ToasterService, + private translate: TranslateService) { + this.user = this.authModule.getLoggedUser(); + this.diskConfig = {}; + this.ogCommonService.saveSelection(); + } + + ngOnInit() { + if (this.user) { + this.ogCommonService.loadEngineConfig().subscribe( + data => { + this.constants = data.constants; + // Comprobar la selección de clientes + if (this.ogCommonService.selectedClients) { + + // Recorrer todos los clientes seleccionados y usar el tamaño del disco de menor tamaño + const clientsId = Object.keys(this.ogCommonService.selectedClients); + let minSize = 0; + // por defecto la tabla de particiones msdos + let parttable = this.ogCommonService.getPartitionTable({partitionCode: 1}); + if (this.ogCommonService.selectedClients[clientsId[0]].partitions[0]) { + minSize = this.ogCommonService.selectedClients[clientsId[0]].partitions[0].size; + parttable = this.ogCommonService.getPartitionTable(this.ogCommonService.selectedClients[clientsId[0]].partitions[0]); + } + + for (let c = 1; c < clientsId.length; c++) { + if (this.ogCommonService.selectedClients[clientsId[0]].partitions[0].size < minSize) { + minSize = this.ogCommonService.selectedClients[clientsId[0]].partitions[0].size; + + } + } + + this.diskConfig = { + disk: 1, + parttable: parttable, + size: minSize, + partitions: [ + { + partition: 0, + type: 'free_space', + filesystem: '', + size: minSize, + usage: 100, + } + ] + }; + // TODO - Revisar Usamos la tabla de particiones del cliente seleccionado + const client: Client = this.ogCommonService.selectedClients[clientsId[0]]; + const clientPartitions = []; + client.partitions.forEach((partition) => { + if (partition.numPartition !== 0 && partition.filesystem !== 'EMPTY') { + + // Obtener el tipo de partición según su code + if (partition.partitionCode.length === 1) { + partition.partitionCode = '0' + partition.partitionCode; + } + const partTypes = this.diskConfig.parttable.partitions.filter(p => p.id === partition.partitionCode.toUpperCase()); + if (partTypes.length > 0) { + partition.type = partTypes[0].type; + } + clientPartitions.push(partition); + } + }); + this.diskConfig.partitions = clientPartitions.concat((this.diskConfig.partitions)); + this.reorderPartitions(); + + this.setChartData(this.diskConfig); + this.partitionTableTypes = this.constants.partitiontable; + } else { + // TODO - dar error? + this.ogSweetAlert.error(this.translate.instant('opengnsys_error'), this.translate.instant('not_clients_selected')); + this.router.navigate(['app/ous']); + } + + } + ); + } + } + + + partTableTypeIsGPT() { + return this.diskConfig.parttable.type === 'GPT'; + } + + partTableTypeIsMSDOS() { + return this.diskConfig.parttable.type === 'MSDOS'; + } + + partTableTypeIsLVM() { + return this.diskConfig.parttable.type === 'LVM'; + } + partTableTypeIsZPOOL() { + return this.diskConfig.parttable.type === 'ZPOOL'; + } + + isEFI(partition) { + return partition.type === 'EFI'; + } + + isCACHE(partition) { + return partition.type === 'CACHE'; + } + + isEXTENDED(partition) { + return partition.type === 'EXTENDED'; + } + + isWINDOWS(partition) { + return partition.type === 'NTFS' || partition.type === 'WINDOWS'; + } + + isLINUX(partition) { + return typeof partition.type === 'string' && partition.type.includes('LINUX'); + } + + isLINUXSWAP(partition) { + return partition.type === 'LINUX-SWAP'; + } + + isDATA(partition) { + return partition.type === 'DATA'; + } + + isUNKNOWN(partition) { + return partition.type === 'UNKNOWN'; + } + + isFreeSpace(partition) { + return partition.type === 'free_space'; + } + + + convertPartitionType(partition) { + if (this.partTableTypeIsMSDOS()) { + if (this.isWINDOWS(partition)) { + partition.type = 'NTFS'; + } else if (this.isUNKNOWN(partition)) { + partition.type = 'NTFS'; + } + } else if (this.partTableTypeIsGPT()) { + if (this.isWINDOWS(partition)) { + partition.type = 'WINDOWS'; + } else if (this.isDATA(partition)) { + partition.type = 'UNKNOWN'; + } + } else if (this.partTableTypeIsLVM()) { + partition.type = 'LVM-LV'; + } else if (this.partTableTypeIsZPOOL()) { + partition.type = 'ZFS-VOL'; + } + } + + checkPartitionTableType() { + const self = this; + if (this.partTableTypeIsMSDOS()) { + if (this.diskConfig.partitions.length > 5) { + this.ogSweetAlert.info('opengnsys_info', 'En MS-DOS sólo puede haber 4 particiones primarias, se creará una extendida con el resto de particiones'); + const tmpPartitions = []; + const extendedPartition = { + type: 'EXTENDED', + partitions: [], + size: 0, + usage: 0 + }; + const hasCache = (this.diskConfig.partitions.filter((partition) => partition.type === 'CACHE').length > 0); + // Si tiene cache se añaden 2 particiones, más la cache y el espacio libre + const numParts = hasCache ? 2 : 3; + this.diskConfig.partitions.forEach(function(partition, index) { + self.convertPartitionType(partition); + if (index < numParts || self.isFreeSpace(partition) || self.isCACHE(partition)) { + tmpPartitions.push(partition); + } else { + extendedPartition.partitions.push(partition); + extendedPartition.size += partition.size; + } + }); + // Actualizar porcentajes de las particiones extendidas + for (let p = 0; p < extendedPartition.partitions.length; p++) { + self.setPartitionUsage(extendedPartition, extendedPartition.partitions[p]); + } + tmpPartitions.push(extendedPartition); + self.diskConfig.partitions = tmpPartitions; + self.updatePartitionUsage(this.diskConfig.partitions[0]); + } else { + self.diskConfig.partitions.forEach(function(partition, index) { + self.convertPartitionType(partition); + }); + } + + } else { + const tmpPartitions = []; + // Para particiones GPT se crea una particion EFI en primer lugar de 512M + if (this.partTableTypeIsGPT()) { + // Comprobar si existe ya una partición EFI al principio del disco, sino, crearla + if (!this.isEFI(this.diskConfig.partitions[0])) { + tmpPartitions.push({ + type: 'EFI', + size: 512000, + usage: (512000 / this.diskConfig.size) * 100 + }); + } + } + + this.diskConfig.partitions.forEach(function(partition) { + self.convertPartitionType(partition); + if (!self.isEXTENDED(partition)) { + tmpPartitions.push(partition); + } else { + partition.partitions.forEach(function(extPart) { + self.convertPartitionType(extPart); + tmpPartitions.push(extPart); + self.setPartitionUsage(this.diskConfig, extPart); + }); + } + }); + this.diskConfig.partitions = tmpPartitions; + this.updatePartitionUsage(this.diskConfig.partitions[0]); + } + } + + addPartition() { + // Si el tipo de tabla de particiones es MSDOS, sólo se admiten 4 particiones + if (this.partTableTypeIsGPT() || (this.partTableTypeIsMSDOS() && this.diskConfig.partitions.length < 5)) { + this.diskConfig.partitions.push({ + partition: (this.diskConfig.partitions.length), + type: this.partTableTypeIsGPT() ? 'WINDOWS' : 'NTFS', + filesystem: '', + size: 0, + usage: 5 + + }); + this.updatePartitionUsage(this.diskConfig.partitions[this.diskConfig.partitions.length - 1]); + } else if (this.partTableTypeIsMSDOS()) { + this.ogSweetAlert.warning('opengnsys_warning', 'En MS-DOS sólo puede haber 4 particiones primarias, utilice alguna como extendida si necesita más particiones'); + } + // Actualizar información + // setChartData(this.diskConfig); + } + + addExtendedPartition(partition) { + partition.partitions.push({ + partition: (partition.partitions.length + 1), + type: 'NTFS', + filesystem: '', + size: 0, + usage: 0 + + }); + const extendedPartUsage = Math.round(100 / partition.partitions.length); + partition.partitions.forEach(function(extPart) { + extPart.usage = extendedPartUsage; + }); + // Actualiza tamaños en funcion del porcentaje de uso + this.updateExtendedPartitions(partition); + } + + updateExtendedPartitions(extPartition) { + const parentPartition = this.diskConfig.partitions.filter((partition) => partition.type === 'EXTENDED')[0]; + const totalSize = parentPartition.size; + parentPartition.partitions.forEach( function(extPart, index) { + extPart.partition = (index + 1); + extPart.size = Math.round((extPart.usage || 0) * totalSize / 100); + }); + } + + updateExtendedPartitionsUsage(extPartition) { + const parentPartition = this.diskConfig.partitions.filter((partition) => partition.type === 'EXTENDED')[0]; + const index = parentPartition.partitions.indexOf(extPartition); + let nextPart = null; + // si solo hay una partición el uso es siempre el 100% + if (parentPartition.partitions.length === 1) { + extPartition.usage = 100; + } else { + nextPart = null; + // el porcentaje que crezca la particion, se le resta a la siguiente o a la anterior si es la ultima + if (index === parentPartition.partitions.length - 1) { + nextPart = parentPartition.partitions[index - 1]; + } else { + nextPart = parentPartition.partitions[index + 1]; + } + let restPercent = 100; + parentPartition.partitions.forEach(function(extPart) { + restPercent -= (extPart.usage || 0); // Hay casos en los que se obtiene NaN + }); + // Le quitamos el porcentaje a la particion contigua hasta que quede con un mínimo de 1 + if (nextPart.usage > (restPercent * -1)) { + nextPart.usage += restPercent; + } else { + // restamos 1 al resto del porcentaje que será lo que ocupe la particion contigua + restPercent = Math.abs(restPercent) - (nextPart.usage - 1); + nextPart.usage = 1; + + extPartition.usage -= restPercent; + } + } + this.updateExtendedPartitions(extPartition); + } + + removeExtendedPartition(extPartition) { + const parentPartition = this.diskConfig.partitions.filter((partition) => partition.type === 'EXTENDED')[0]; + const index = parentPartition.partitions.indexOf(extPartition); + if (index !== -1) { + parentPartition.partitions.splice(index, 1); + } + // Comprobamos el % que queda libre ahora + const freePercent = Math.round(extPartition.usage / parentPartition.partitions.length); + parentPartition.partitions.forEach(function(extPart) { + extPart.usage += freePercent; + extPart.size = Math.round(extPart.usage * parentPartition.size / 100); + }); + } + + + reorderPartitions() { + const self = this; + const tmpPartitions = []; + let indexFreeSpace = -1; + let indexCache = -1; + this.diskConfig.partitions.forEach(function(partition, index) { + if (partition.type !== 'free_space' && !self.isCACHE(partition)) { + partition.partition = (tmpPartitions.length + 1); + tmpPartitions.push(partition); + } else if (self.isCACHE(partition)) { + indexCache = index; + } else if (partition.type === 'free_space') { + indexFreeSpace = index; + } + }); + // Añadir el espacio libre y la cache + if (indexFreeSpace !== -1) { + this.diskConfig.partitions[indexFreeSpace].usage = this.calculateFreeSpace(this.diskConfig.partitions[indexFreeSpace]); + tmpPartitions.push(this.diskConfig.partitions[indexFreeSpace]); + } + if (indexCache !== -1) { + tmpPartitions.push(this.diskConfig.partitions[indexCache]); + } + this.diskConfig.partitions = tmpPartitions; + } + + setChartData(diskConfig) { + const self = this; + const diskChartData = []; + const diskChartLabels = []; + const diskPieChartColors = [{ + backgroundColor: [] + }]; + let usedSpace = 0; + + diskConfig.partitions.forEach( function(partition) { + if (partition.size > 0) { + self.setPartitionUsage(diskConfig, partition); + if (partition.type === 'free_space') { + partition.usage = self.calculateFreeSpace(partition); + } + // El espacio libre solo se añade si es 0 + if (partition.type !== 'free_space' || (partition.type === 'free_space' && partition.usage > 0)) { + diskChartData.push(partition.usage); + diskChartLabels.push([ + self.translate.instant(partition.os || partition.filesystem || partition.type), + (partition.usage + '%') + ]); + diskPieChartColors[0].backgroundColor.push(self.getPartitionColor(partition)); + } + if (partition.type !== 'free_space') { + usedSpace += partition.usage; + } + } + }); + + this.diskConfig.remaining = Math.round(100 * (100 - usedSpace)) / 100; + + const diskChartOptions: ChartOptions = { + responsive: true, + legend: { + position: 'bottom' + }, + plugins: { + datalabels: { + formatter: (value, ctx) => { + const label = ctx.chart.data.labels[ctx.dataIndex]; + return label; + }, + }, + } + }; + + diskConfig.diskChartData = diskChartData; + diskConfig.diskChartOptions = diskChartOptions; + diskConfig.diskChartLabels = diskChartLabels; + diskConfig.diskPieChartColors = diskPieChartColors; + } + + getPartitionColor(partition) { + let color = '#c5e72b'; + // Para la partición de datos se usa un color específico + if (this.isDATA(partition)) { + color = 'rgb(237,194,64)'; + } else if (this.isEFI(partition)) { + color = '#bfe4e5'; + } else if (this.isWINDOWS(partition)) { + color = '#00c0ef'; + } else if (this.isLINUXSWAP(partition)) { + color = '#545454'; + } else if (this.isLINUX(partition)) { + color = '#605ca8'; + } else if (this.isCACHE(partition)) { + color = '#FC5A5A'; + } else if (this.isFreeSpace(partition)) { + color = '#bcbcbc'; + } + return color; + } + + /* + * Custom Label formatter + * ---------------------- + */ + labelFormatter(label, series) { + return '
    ' + + '
    ' + + series.usage + '%
    '; + } + + getSizeInGB(size) { + size = size / (1024 * 1024); + return Math.round(size * 100) / 100; + } + + setPartitionUsage(diskConfig, partition) { + partition.usage = Math.round(((partition.size * 100) / diskConfig.size) * 100) / 100; + } + + checkPartitionType(partition) { + let ok = true; + if (this.isCACHE(partition)) { + // Comprobar si ya hay alguna partición como CACHE + if (this.diskConfig.partitions.filter((p) => p.type === 'CACHE').length > 1) { + this.ogSweetAlert.error('opengnsys_error', 'Solo debe haber una CACHE'); + partition.type = 'NTFS'; + ok = false; + } + } else if (this.isEXTENDED(partition)) { + // Comprobar si ya hay alguna partición como EXTENDIDA + if (this.diskConfig.partitions.filter((p) => p.type === 'EXTENDED').length > 1) { + this.ogSweetAlert.error('opengnsys_error', 'Solo debe haber una EXTENDIDA'); + partition.type = 'NTFS'; + ok = false; + } else { + partition.partitions = [ + { + partition: 1, + type: 'NTFS', + filesystem: '', + size: partition.size, + usage: 100 + + } + ]; + } + } else if (typeof partition.partitions !== 'undefined' && partition.partitions.length > 0) { + ok = false; + const self = this; + this.ogSweetAlert.question('opengnsys_question', 'Esta particion contiene otras partitiones!, si continua, dichas particiones serán eliminadas....', + function(yes) { + partition.partitions = []; + self.updatePartitionUsage(partition); + }, + function(cancel) { + // Si contesta no se deja el tipo extendido + partition.type = 'EXTENDED'; + } + ); + } + + if (ok) { + this.updatePartitionUsage(partition); + } + } + + updatePartitionUsage(partition) { + const remaining = this.calculateFreeSpace(partition); + if (partition.usage > remaining) { + partition.usage = remaining; + } + partition.size = Math.round(this.diskConfig.size * partition.usage / 100); + this.setChartData(this.diskConfig); + this.reorderPartitions(); + // Si es una partición extendida + if (typeof partition.partitions !== 'undefined' && partition.partitions.length > 0) { + this.updateExtendedPartitions(partition.partitions[0]); + } + } + + calculateFreeSpace(asignedPartition) { + let usedSpace = 0; + this.diskConfig.partitions.forEach(function(partition, index) { + if (partition !== asignedPartition && partition.type !== 'free_space') { + usedSpace += partition.usage || 0; + } + }); + return Math.round(100 * (100 - usedSpace)) / 100; + } + + removePartition(partition) { + const index = this.diskConfig.partitions.indexOf(partition); + if (index !== -1) { + this.diskConfig.partitions.splice(index, 1); + } + + this.setChartData(this.diskConfig); + + } + + +// var RC='@'; +// document.fdatosejecucion.atributos.value="scp="+escape(document.fdatos.codigo.value)+RC; + + + /**/ + generateOgInstruction() { + const self = this; + let initPartitionTable = 'ogCreatePartitionTable ' + this.diskConfig.disk + ' ' + this.diskConfig.parttable.type + '\n'; + initPartitionTable += 'ogEcho log session "[0] $MSG_HELP_ogCreatePartitions"\n'; + initPartitionTable += 'ogEcho session "[10] $MSG_HELP_ogUnmountAll ' + this.diskConfig.disk + '"\n'; + initPartitionTable += 'ogUnmountAll ' + this.diskConfig.disk + ' 2>/dev/null\n'; + initPartitionTable += 'ogUnmountCache\n'; + initPartitionTable += 'ogEcho session "[30] $MSG_HELP_ogUpdatePartitionTable ' + this.diskConfig.disk + '"\n'; + initPartitionTable += 'ogDeletePartitionTable ' + this.diskConfig.disk + '\n'; + initPartitionTable += 'ogUpdatePartitionTable ' + this.diskConfig.disk + '\n'; + + let createPartitions = 'ogEcho session "[60] $MSG_HELP_ogListPartitions ' + this.diskConfig.disk + '"\n'; + createPartitions += 'ogExecAndLog command session ogListPartitions ' + this.diskConfig.disk + '\n'; + + let cacheInstruction = ''; + let partitionList = ''; + let formatInstructions = ''; + this.diskConfig.partitions.forEach(function(partition, index) { + if (partition.type !== 'free_space') { + // La unica particion especial es la 4 que es cache, para el resto + if (!self.isCACHE(partition)) { + partitionList += ' ' + partition.type + ':' + partition.size; + if (self.isEXTENDED(partition)) { + for (let p = 0; p < partition.partitions.length; p++) { + partitionList += ' ' + partition.partitions[p].type + ':' + partition.partitions[p].size; + if (partition.partitions[p].format === true) { + formatInstructions += 'ogUnmount ' + self.diskConfig.disk + ' ' + (partition.partition + (partition.partitions[p].partition - 1)) + '\n'; + formatInstructions += 'ogFormat ' + self.diskConfig.disk + ' ' + (partition.partition + (partition.partitions[p].partition - 1)) + '\n'; + } + } + } + if (partition.format === true) { + formatInstructions += 'ogUnmount ' + self.diskConfig.disk + ' ' + partition.partition + '\n'; + formatInstructions += 'ogFormat ' + self.diskConfig.disk + ' ' + partition.partition + '\n'; + } + } else { + cacheInstruction = 'ogEcho session "[50] $MSG_HELP_ogCreateCache"\n'; + cacheInstruction += 'initCache ' + self.diskConfig.disk + ' ' + partition.size + ' NOMOUNT &>/dev/null\n'; + + if (partition.format === true) { + formatInstructions += 'ogUnmountCache\n'; + formatInstructions += 'ogFormatCache\n'; + } + } + } + }); + + createPartitions += 'ogEcho session "[70] $MSG_HELP_ogCreatePartitions ' + partitionList + '"\n'; + createPartitions += 'ogExecAndLog command ogCreatePartitions ' + this.diskConfig.disk + partitionList + '\n'; + createPartitions += 'ogEcho session "[80] $MSG_HELP_ogSetPartitionActive ' + this.diskConfig.disk + ' 1"\n'; + createPartitions += 'ogSetPartitionActive ' + this.diskConfig.disk + ' 1\n'; + createPartitions += 'ogEcho log session "[100] $MSG_HELP_ogListPartitions ' + this.diskConfig.disk + '"\n'; + createPartitions += 'ogUpdatePartitionTable ' + this.diskConfig.disk + '\n'; + createPartitions += 'ms-sys /dev/sda | grep unknow && ms-sys /dev/sda\n'; + createPartitions += 'ogExecAndLog command session log ogListPartitions ' + this.diskConfig.disk + '\n'; + + this.ogCommandsService.ogInstructions = initPartitionTable + cacheInstruction + createPartitions + formatInstructions; + } +} diff --git a/admin/WebConsole3/frontend/src/app/pages/common/directive/col-resizable.directive.ts b/admin/WebConsole3/frontend/src/app/pages/common/directive/col-resizable.directive.ts new file mode 100644 index 00000000..7c32f406 --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/common/directive/col-resizable.directive.ts @@ -0,0 +1,81 @@ +import {Directive, DoCheck, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output, Renderer2} from '@angular/core'; + + +class ResizeInfo { + width: number; + percent: number; +} + +@Directive({ + selector: '[col-resizable]' +}) +export class ColResizableDirective implements OnInit, DoCheck { + private el: ElementRef; + private start: any; + private pressed: boolean; + private startX: number; + private startWidth: any; + + @Input() + elements: any[]; + + @Output() + onResize = new EventEmitter(); + private elementProperty: string; + + + constructor(el: ElementRef, private renderer: Renderer2) { + this.el = el; + + } + + ngOnInit() { + this.elementProperty = this.el.nativeElement.getAttribute('cr-update-property') || ''; + } + ngDoCheck(): void { + const table = this.el.nativeElement; + const trs = table.getElementsByTagName('tr'); + let tds = null; + + for (let i = 0; i < trs.length; i++) { + tds = trs[i].getElementsByTagName('td'); + if (tds.length > 0) { + for (let n = 0; n < tds.length; n++) { + + if (tds[n].getElementsByClassName('resizer').length === 0) { + const span = document.createElement('span'); + span.classList.add('resizer'); + tds[n].appendChild(span); + span.addEventListener('mousedown', (event) => { + this.start = event.target; + this.pressed = true; + this.startX = event.x; + this.startWidth = this.start.parentElement.offsetWidth; + this.initResizableColumns(); + }); + } + } + } + } + + } + + private initResizableColumns() { + this.renderer.listen('body', 'mousemove', (event) => { + if (this.pressed) { + const width = this.startWidth + (event.x - this.startX); + this.start.parentElement.style.width = width + 'px'; + const element = this.elements[this.start.parentElement.cellIndex]; + if (typeof element !== 'undefined' && this.elementProperty !== ''){ + element[this.elementProperty] = ((width / this.el.nativeElement.offsetWidth) * 100); + } + this.onResize.emit(element); + } + }) + this.renderer.listen('body', 'mouseup', (event) => { + if (this.pressed) { + this.pressed = false; + } + }); + } +} diff --git a/admin/WebConsole3/frontend/src/app/pages/common/og-options/og-selected-clients/og-selected-clients.component.html b/admin/WebConsole3/frontend/src/app/pages/common/og-options/og-selected-clients/og-selected-clients.component.html index ebb52d60..91d187ff 100644 --- a/admin/WebConsole3/frontend/src/app/pages/common/og-options/og-selected-clients/og-selected-clients.component.html +++ b/admin/WebConsole3/frontend/src/app/pages/common/og-options/og-selected-clients/og-selected-clients.component.html @@ -1,19 +1,19 @@
    -
    -
    +
    +
    + class="selection-checkbox" [(ngModel)]="client.value.selected" + (change)="ogCommonService.selectClient(client.value, client.value.parent)"/>
    - {{client.name}} - {{client.ip}} - {{client.mac}} + {{client.value.name}} + {{client.value.ip}} + {{client.value.mac}}
    diff --git a/admin/WebConsole3/frontend/src/app/pages/common/table-action/ng2-table-action.component.css b/admin/WebConsole3/frontend/src/app/pages/common/table-action/ng2-table-action.component.css index 4e8eee70..975006ac 100644 --- a/admin/WebConsole3/frontend/src/app/pages/common/table-action/ng2-table-action.component.css +++ b/admin/WebConsole3/frontend/src/app/pages/common/table-action/ng2-table-action.component.css @@ -1,3 +1,3 @@ -ul.dropdown-menu { - background-color: transparent; -} +::ng-deep ng2-smart-table ul.dropdown-menu { + background-color: transparent; +} diff --git a/admin/WebConsole3/frontend/src/app/pages/dashboard/dashboard.component.ts b/admin/WebConsole3/frontend/src/app/pages/dashboard/dashboard.component.ts index 97d26ae1..ef11a47f 100644 --- a/admin/WebConsole3/frontend/src/app/pages/dashboard/dashboard.component.ts +++ b/admin/WebConsole3/frontend/src/app/pages/dashboard/dashboard.component.ts @@ -87,11 +87,13 @@ export class DashboardComponent implements OnInit, OnDestroy { this.ogCommonService.loadEngineConfig().subscribe( (config) => { this.timers = config.timers; - if (this.timers.serverStatusInterval.object == null) { + if (this.timers.serverStatusInterval.object == null && this.timers.serverStatusInterval.tick > 0) { this.updateStatus(); this.timers.serverStatusInterval.object = setInterval(() => { this.updateStatus(); }, this.timers.serverStatusInterval.tick); + } else { + this.updateStatus(); } }, (error) => { diff --git a/admin/WebConsole3/frontend/src/app/pages/hardware-component/hardware-component.component.html b/admin/WebConsole3/frontend/src/app/pages/hardware-component/hardware-component.component.html index 0ddd6b5c..60c60cd1 100644 --- a/admin/WebConsole3/frontend/src/app/pages/hardware-component/hardware-component.component.html +++ b/admin/WebConsole3/frontend/src/app/pages/hardware-component/hardware-component.component.html @@ -11,7 +11,7 @@
    - +
    @@ -21,13 +21,12 @@
    -

    -

    +

    +

    -
    + -
    diff --git a/admin/WebConsole3/frontend/src/app/pages/hardware-component/hardware-component.component.ts b/admin/WebConsole3/frontend/src/app/pages/hardware-component/hardware-component.component.ts index a7ef127f..4b4306af 100644 --- a/admin/WebConsole3/frontend/src/app/pages/hardware-component/hardware-component.component.ts +++ b/admin/WebConsole3/frontend/src/app/pages/hardware-component/hardware-component.component.ts @@ -1,17 +1,48 @@ -import { Component } from '@angular/core'; - -import { HardwareComponentService } from 'src/app/api/hardware-component.service'; -import { HardwareComponent } from 'src/app/model/hardware-component'; - -@Component({ - selector: 'app-hardware-component', - templateUrl: './hardware-component.component.html', - styleUrls: [ './hardware-component.component.scss' ] -}) -export class HardwareComponentComponent { - // this tells the tabs component which Pages - // should be each tab's root Page - constructor(public hardwareComponentService: HardwareComponentService) { - } - -} +import { Component } from '@angular/core'; + +import { HardwareComponentService } from 'src/app/api/hardware-component.service'; +import { HardwareComponent } from 'src/app/model/hardware-component'; +import {Observable} from 'rxjs'; +import {ToasterService} from '../../service/toaster.service'; +import {TranslateService} from '@ngx-translate/core'; +import {Router} from '@angular/router'; + +@Component({ + selector: 'app-hardware-component', + templateUrl: './hardware-component.component.html', + styleUrls: [ './hardware-component.component.scss' ] +}) +export class HardwareComponentComponent { + // this tells the tabs component which Pages + public hardwareComponent: HardwareComponent; + formType: any; + // should be each tab's root Page + constructor(public hardwareComponentService: HardwareComponentService, private toaster: ToasterService, private translate: TranslateService, private router: Router) { + this.hardwareComponent = new HardwareComponent(); + this.formType = [{ + field: 'description', + name: 'description', + label: 'description', + type: 'textarea' + }]; + } + + save() { + let request: Observable; + if (this.hardwareComponent.id !== 0) { + request = this.hardwareComponentService.update(this.hardwareComponent); + } else { + request = this.hardwareComponentService.create(this.hardwareComponent); + } + + request.subscribe( + (response) => { + this.toaster.pop({type: this.translate.instant('success'), title: this.translate.instant('success'), body: this.translate.instant('successfully_saved')}); + this.router.navigate(['/app/hardware']); + }, + (error) => { + this.toaster.pop({type: 'error', title: 'error', body: error}); + } + ); + } +} diff --git a/admin/WebConsole3/frontend/src/app/pages/image/image.component.ts b/admin/WebConsole3/frontend/src/app/pages/image/image.component.ts index 821f63a4..76629163 100644 --- a/admin/WebConsole3/frontend/src/app/pages/image/image.component.ts +++ b/admin/WebConsole3/frontend/src/app/pages/image/image.component.ts @@ -1,146 +1,146 @@ -import {Component, OnInit} from '@angular/core'; - -import { ImageService } from 'src/app/api/image.service'; -import {Image, PartitionInfo} from 'src/app/model/image'; -import {OgCommonService} from '../../service/og-common.service'; -import {TranslateService} from '@ngx-translate/core'; -import {ToasterService} from '../../service/toaster.service'; -import {OgSweetAlertService} from '../../service/og-sweet-alert.service'; -import {Ng2TableActionComponent} from '../common/table-action/ng2-table-action.component'; -import {Router} from '@angular/router'; - -@Component({ - selector: 'app-image', - templateUrl: './image.component.html', - styleUrls: [ './image.component.scss' ] -}) -export class ImageComponent implements OnInit { - images: Image[]; - constants: any; - removeFile = false; - tableSettings: any; - - // this tells the tabs component which Pages - // should be each tab's root Page - constructor(private router: Router, public imageService: ImageService, private ogCommonService: OgCommonService, private translate: TranslateService, private toaster: ToasterService, private ogSweetAlert: OgSweetAlertService) { - this.ogCommonService.loadEngineConfig().subscribe( - data => { - this.constants = data.constants; - } - ); - } - - ngOnInit(): void { - this.imageService.list().subscribe( - data => { - this.images = data; - } - ); - const self = this; - this.tableSettings = { - columns: { - canonicalName: { - title: this.translate.instant('canonical_name') - }, - description: { - title: this.translate.instant('description') - }, - partitionInfo: { - title: this.translate.instant('filesystem'), - valuePrepareFunction: (cell, image) => { - return this.getImageFileSystem(image); - }, - filterFunction: (value: PartitionInfo, search: string) => { - return (value.filesystem) ? value.filesystem.includes(search) : false; - } - - }, - createdAt: { - title: this.translate.instant('createdAt') - }, - options: { - title: 'Options', - filter: false, - sort: false, - type: 'custom', - renderComponent: Ng2TableActionComponent, - onComponentInitFunction(instance) { - instance.edit.subscribe(row => { - self.router.navigate(['/app/images/edit/', row.id]); - }); - instance.delete.subscribe(row => { - self.deleteImage(row); - }); - } - }, - }, - actions: { - position: 'right', - add: false, - edit: false, - delete: false - } - }; - } - - getImageFileSystem(image) { - const result = ''; - if (typeof image.partitionInfo === 'string') { - image.partitionInfo = JSON.parse(image.partitionInfo); - } else if (!image.partitionInfo) { - image.partitionInfo = {}; - } - return image.partitionInfo.filesystem; - } - - - getPartitionType(partition) { - // buscar la particion en el array global - let result = this.constants.partitionTypes.filter(function(obj) { return obj.id === partition.id; }); - result = result[0]; - return result.type; - } - - deleteImage(image) { - const self = this; - this.removeFile = false; - this.ogSweetAlert.swal({ - title: this.translate.instant('sure_to_delete') + '?', - html: '
    \ -
    \ -
    \ -
    \ - \ -
    \ - ?\ -
    \ -
    ', - type: 'warning', - showCancelButton: true, - confirmButtonColor: '#3c8dbc', - confirmButtonText: this.translate.instant('yes_delete'), - closeOnConfirm: true - }).then( - function(result) { - if (result === true) { - if (self.removeFile === true) { - // TODO Borrar fichero físico... - } - this.imageService.delete(image.id).then( - function(response) { - this.toaster.pop({type: 'success', title: 'success', body: this.translate.instant('successfully_deleted')}); - // Buscar el elemento en el array y borrarlo - const index = this.images.indexOf(image); - if (index !== -1) { - this.images.splice(index, 1); - } - }, - function(error) { - this.toaster.pop({type: 'error', title: 'error', body: error}); - } - ); - } - }); - } -} +import {Component, OnInit} from '@angular/core'; + +import { ImageService } from 'src/app/api/image.service'; +import {Image, PartitionInfo} from 'src/app/model/image'; +import {OgCommonService} from '../../service/og-common.service'; +import {TranslateService} from '@ngx-translate/core'; +import {ToasterService} from '../../service/toaster.service'; +import {OgSweetAlertService} from '../../service/og-sweet-alert.service'; +import {Ng2TableActionComponent} from '../common/table-action/ng2-table-action.component'; +import {Router} from '@angular/router'; + +@Component({ + selector: 'app-image', + templateUrl: './image.component.html', + styleUrls: [ './image.component.scss' ] +}) +export class ImageComponent implements OnInit { + images: Image[]; + constants: any; + removeFile = false; + tableSettings: any; + + // this tells the tabs component which Pages + // should be each tab's root Page + constructor(private router: Router, public imageService: ImageService, private ogCommonService: OgCommonService, private translate: TranslateService, private toaster: ToasterService, private ogSweetAlert: OgSweetAlertService) { + this.ogCommonService.loadEngineConfig().subscribe( + data => { + this.constants = data.constants; + } + ); + } + + ngOnInit(): void { + this.imageService.list().subscribe( + data => { + this.images = data; + } + ); + const self = this; + this.tableSettings = { + columns: { + canonicalName: { + title: this.translate.instant('canonical_name') + }, + description: { + title: this.translate.instant('description') + }, + partitionInfo: { + title: this.translate.instant('filesystem'), + valuePrepareFunction: (cell, image) => { + return this.getImageFileSystem(image); + }, + filterFunction: (value: PartitionInfo, search: string) => { + return (value.filesystem) ? value.filesystem.includes(search) : false; + } + + }, + createdAt: { + title: this.translate.instant('createdAt') + }, + options: { + title: 'Options', + filter: false, + sort: false, + type: 'custom', + renderComponent: Ng2TableActionComponent, + onComponentInitFunction(instance) { + instance.edit.subscribe(row => { + self.router.navigate(['/app/images/edit/', row.id]); + }); + instance.delete.subscribe(row => { + self.deleteImage(row); + }); + } + }, + }, + actions: { + position: 'right', + add: false, + edit: false, + delete: false + } + }; + } + + getImageFileSystem(image) { + const result = ''; + if (typeof image.partitionInfo === 'string') { + image.partitionInfo = JSON.parse(image.partitionInfo); + } else if (!image.partitionInfo) { + image.partitionInfo = {}; + } + return image.partitionInfo.filesystem; + } + + + getPartitionType(partition) { + // buscar la particion en el array global + let result = this.constants.partitionTypes.filter(function(obj) { return obj.id === partition.id; }); + result = result[0]; + return result.type; + } + + deleteImage(image) { + const self = this; + this.removeFile = false; + this.ogSweetAlert.swal({ + title: this.translate.instant('sure_to_delete') + '?', + html: '
    \ +
    \ +
    \ +
    \ + \ +
    \ + ?\ +
    \ +
    ', + type: 'warning', + showCancelButton: true, + confirmButtonColor: '#3c8dbc', + confirmButtonText: this.translate.instant('yes_delete'), + closeOnConfirm: true + }).then( + function(result) { + if (result.value === true) { + if (self.removeFile === true) { + // TODO Borrar fichero físico... + } + self.imageService.delete(image.id).subscribe( + (response) => { + self.toaster.pop({type: 'success', title: 'success', body: self.translate.instant('successfully_deleted')}); + // Buscar el elemento en el array y borrarlo + const index = self.images.indexOf(image); + if (index !== -1) { + self.images.splice(index, 1); + } + }, + (error) => { + self.toaster.pop({type: 'error', title: 'error', body: error}); + } + ); + } + }); + } +} diff --git a/admin/WebConsole3/frontend/src/app/pages/menu/edit/menu-edit.component.html b/admin/WebConsole3/frontend/src/app/pages/menu/edit/menu-edit.component.html index 9d96cde9..dd147bf3 100644 --- a/admin/WebConsole3/frontend/src/app/pages/menu/edit/menu-edit.component.html +++ b/admin/WebConsole3/frontend/src/app/pages/menu/edit/menu-edit.component.html @@ -19,16 +19,19 @@
    -
    +
    -
    +
    +
    + +
    diff --git a/admin/WebConsole3/frontend/src/app/pages/menu/edit/menu-edit.component.ts b/admin/WebConsole3/frontend/src/app/pages/menu/edit/menu-edit.component.ts index d52f53ad..c16bf372 100644 --- a/admin/WebConsole3/frontend/src/app/pages/menu/edit/menu-edit.component.ts +++ b/admin/WebConsole3/frontend/src/app/pages/menu/edit/menu-edit.component.ts @@ -10,6 +10,7 @@ import {Observable} from 'rxjs'; import {MenuService} from '../../../api/menu.service'; import {Menu} from '../../../model/menu'; import {OgCommonService} from '../../../service/og-common.service'; +import {DomSanitizer} from '@angular/platform-browser'; @Component({ selector: 'app-menu', @@ -24,7 +25,7 @@ export class MenuEditComponent implements OnInit { // this tells the tabs component which Pages // should be each tab's root Page - constructor(private router: Router, private activatedRouter: ActivatedRoute, private ogCommonService: OgCommonService, private menuService: MenuService, private translate: TranslateService, private toaster: ToasterService) { + constructor(public sanitizer: DomSanitizer, private router: Router, private activatedRouter: ActivatedRoute, private ogCommonService: OgCommonService, private menuService: MenuService, private translate: TranslateService, private toaster: ToasterService) { this.form = this.formType.getForm(); } diff --git a/admin/WebConsole3/frontend/src/app/pages/menu/menu.component.ts b/admin/WebConsole3/frontend/src/app/pages/menu/menu.component.ts index 4c47eb73..2d803c86 100644 --- a/admin/WebConsole3/frontend/src/app/pages/menu/menu.component.ts +++ b/admin/WebConsole3/frontend/src/app/pages/menu/menu.component.ts @@ -7,6 +7,7 @@ import {Ng2TableActionComponent} from '../common/table-action/ng2-table-action.c import {TranslateService} from '@ngx-translate/core'; import {Router} from '@angular/router'; import {OgSweetAlertService} from '../../service/og-sweet-alert.service'; +import {ToasterService} from '../../service/toaster.service'; @Component({ selector: 'app-menu', @@ -18,7 +19,7 @@ export class MenuComponent implements OnInit { private tableSettings: any; // this tells the tabs component which Pages // should be each tab's root Page - constructor(public menuService: MenuService, private router: Router, private ogSweetAlert: OgSweetAlertService, private translate: TranslateService) { + constructor(public menuService: MenuService, private router: Router, private ogSweetAlert: OgSweetAlertService, private toaster: ToasterService, private translate: TranslateService) { } ngOnInit(): void { @@ -82,19 +83,19 @@ export class MenuComponent implements OnInit { closeOnConfirm: true }).then( function(result) { - if (result === true) { + if (result.value === true) { - this.menuService.delete(menu.id).then( - function(response) { - this.toaster.pop({type: 'success', title: 'success', body: this.translate.instant('successfully_deleted')}); + self.menuService.delete(menu.id).subscribe( + (response) => { + self.toaster.pop({type: 'success', title: 'success', body: self.translate.instant('successfully_deleted')}); // Buscar el elemento en el array y borrarlo - const index = this.images.indexOf(menu); + const index = self.menus.indexOf(menu); if (index !== -1) { - this.images.splice(menu, 1); + self.menus.splice(menu, 1); } }, - function(error) { - this.toaster.pop({type: 'error', title: 'error', body: error}); + (error) => { + self.toaster.pop({type: 'error', title: 'error', body: error}); } ); } diff --git a/admin/WebConsole3/frontend/src/app/pages/organizational-unit/organizational-unit.component.ts b/admin/WebConsole3/frontend/src/app/pages/organizational-unit/organizational-unit.component.ts index 8a59d77b..c020b7fc 100644 --- a/admin/WebConsole3/frontend/src/app/pages/organizational-unit/organizational-unit.component.ts +++ b/admin/WebConsole3/frontend/src/app/pages/organizational-unit/organizational-unit.component.ts @@ -55,7 +55,7 @@ export class OrganizationalUnitComponent implements OnInit, OnDestroy { } ngOnInit(): void { - this.ogCommonService.loadEngineConfig().subscribe( + this.ogCommonService.loadEngineConfig().subscribe( data => { this.config = data; @@ -74,7 +74,7 @@ export class OrganizationalUnitComponent implements OnInit, OnDestroy { (response) => { this.ous = Array.isArray(response) ? response : [response]; // La primera vez que entra - if (this.config.timers.clientsStatusInterval.object == null) { + if (this.config.timers.clientsStatusInterval.object == null && this.config.timers.clientsStatusInterval.tick > 0) { this.getClientStatus(); const self = this; this.config.timers.clientsStatusInterval.object = window.setInterval(function() { @@ -95,7 +95,6 @@ export class OrganizationalUnitComponent implements OnInit, OnDestroy { ); - } showGrid(show) { diff --git a/admin/WebConsole3/frontend/src/app/pages/organizational-unit/ou-clients/ou-client.component.html b/admin/WebConsole3/frontend/src/app/pages/organizational-unit/ou-clients/ou-client.component.html index 32b0a4db..02d60caa 100644 --- a/admin/WebConsole3/frontend/src/app/pages/organizational-unit/ou-clients/ou-client.component.html +++ b/admin/WebConsole3/frontend/src/app/pages/organizational-unit/ou-clients/ou-client.component.html @@ -49,7 +49,7 @@
    -
    +
    diff --git a/admin/WebConsole3/frontend/src/app/pages/organizational-unit/ou-clients/ou-client.component.scss b/admin/WebConsole3/frontend/src/app/pages/organizational-unit/ou-clients/ou-client.component.scss new file mode 100644 index 00000000..118db555 --- /dev/null +++ b/admin/WebConsole3/frontend/src/app/pages/organizational-unit/ou-clients/ou-client.component.scss @@ -0,0 +1,11 @@ +.og-client-box { + padding: 0; + border: 1px solid lightgray; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); + margin: 0 5px; + background: white; +} + +.og-client-box .info-box { + box-shadow: none; +} diff --git a/admin/WebConsole3/frontend/src/app/pages/organizational-unit/ou-clients/ou-client.component.ts b/admin/WebConsole3/frontend/src/app/pages/organizational-unit/ou-clients/ou-client.component.ts index 743ba965..0c5e8a14 100644 --- a/admin/WebConsole3/frontend/src/app/pages/organizational-unit/ou-clients/ou-client.component.ts +++ b/admin/WebConsole3/frontend/src/app/pages/organizational-unit/ou-clients/ou-client.component.ts @@ -9,7 +9,8 @@ import {OgCommonService} from '../../../service/og-common.service'; @Component({ selector: 'app-ou-client-component', - templateUrl: 'ou-client.component.html' + templateUrl: 'ou-client.component.html', + styleUrls: ['ou-client.component.scss'] }) export class OuClientComponent { private _ou: OrganizationalUnit; diff --git a/admin/WebConsole3/frontend/src/app/pages/organizational-unit/ou-group/ou-group.component.ts b/admin/WebConsole3/frontend/src/app/pages/organizational-unit/ou-group/ou-group.component.ts index 9d04c84e..e2f3d005 100644 --- a/admin/WebConsole3/frontend/src/app/pages/organizational-unit/ou-group/ou-group.component.ts +++ b/admin/WebConsole3/frontend/src/app/pages/organizational-unit/ou-group/ou-group.component.ts @@ -17,8 +17,20 @@ import {Router} from '@angular/router'; styleUrls: ['ou-group.component.css'] }) export class OuGroupComponent { + private _ou: OrganizationalUnit; @Input() ous; - @Input() content; + @Input() + set content(ou) { + this._ou = ou; + this._ou.clients.forEach((client) => { + if (this.ogCommonService.selectedClients[client.id]) { + client.selected = true; + } + }); + } + get content() { + return this._ou; + } @Input() clientStatus; @Input() showGrid; @Input() selectedStatus; diff --git a/admin/WebConsole3/frontend/src/app/pages/profile/profile.component.html b/admin/WebConsole3/frontend/src/app/pages/profile/profile.component.html index 97761b02..2f1b7bf5 100644 --- a/admin/WebConsole3/frontend/src/app/pages/profile/profile.component.html +++ b/admin/WebConsole3/frontend/src/app/pages/profile/profile.component.html @@ -16,6 +16,7 @@
    + {{user.preferences|json}}
    @@ -26,7 +27,7 @@
    - +
    @@ -52,11 +53,11 @@
    - +
    - +
    @@ -66,7 +67,7 @@
    -
    diff --git a/admin/WebConsole3/frontend/src/app/pages/profile/profile.component.ts b/admin/WebConsole3/frontend/src/app/pages/profile/profile.component.ts index 149ad6f3..da6859c2 100644 --- a/admin/WebConsole3/frontend/src/app/pages/profile/profile.component.ts +++ b/admin/WebConsole3/frontend/src/app/pages/profile/profile.component.ts @@ -42,7 +42,6 @@ export class ProfileComponent implements OnInit { } changeTheme() { - this.app.theme = this.user.preferences.theme; this.layoutStore.setSkin(this.user.preferences.theme); } diff --git a/admin/WebConsole3/frontend/src/app/pages/repository/repository.component.html b/admin/WebConsole3/frontend/src/app/pages/repository/repository.component.html index 38f08ade..a2d0cf28 100644 --- a/admin/WebConsole3/frontend/src/app/pages/repository/repository.component.html +++ b/admin/WebConsole3/frontend/src/app/pages/repository/repository.component.html @@ -1,100 +1,100 @@ -
    -

    -

    - -
    -
    -
    -
    -
    - - - - -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    - -
    - - - - -
    - - -
    -
    -
    +
    +

    +

    + +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    + +
    + +
    + + +
    +
    +
    diff --git a/admin/WebConsole3/frontend/src/app/pages/software/software.component.css b/admin/WebConsole3/frontend/src/app/pages/software/software.component.css deleted file mode 100644 index e69de29b..00000000 diff --git a/admin/WebConsole3/frontend/src/app/pages/software/software.component.scss b/admin/WebConsole3/frontend/src/app/pages/software/software.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/admin/WebConsole3/frontend/src/app/pages/software/software.component.ts b/admin/WebConsole3/frontend/src/app/pages/software/software.component.ts index a51d9560..59b81298 100644 --- a/admin/WebConsole3/frontend/src/app/pages/software/software.component.ts +++ b/admin/WebConsole3/frontend/src/app/pages/software/software.component.ts @@ -11,7 +11,7 @@ import {SoftwareTypeService} from '../../api/software-type.service'; @Component({ selector: 'app-software', templateUrl: './software.component.html', - styleUrls: ['./software.component.css'] + styleUrls: ['./software.component.scss'] }) export class SoftwareComponent implements OnInit { public softwareProfileGroups: any[] = []; diff --git a/admin/WebConsole3/frontend/src/app/pages/trace/trace.component.ts b/admin/WebConsole3/frontend/src/app/pages/trace/trace.component.ts index af1b2cf7..750e5096 100644 --- a/admin/WebConsole3/frontend/src/app/pages/trace/trace.component.ts +++ b/admin/WebConsole3/frontend/src/app/pages/trace/trace.component.ts @@ -1,261 +1,263 @@ -import {Component, OnDestroy, OnInit} from '@angular/core'; - -import { TraceService } from 'src/app/api/trace.service'; -import { Trace } from 'src/app/model/trace'; -import {ToasterService} from '../../service/toaster.service'; -import {OgSweetAlertService} from '../../service/og-sweet-alert.service'; -import {Router} from '@angular/router'; -import {OgCommonService} from '../../service/og-common.service'; -import {environment} from '../../../environments/environment'; -import {TranslateService} from '@ngx-translate/core'; -import {QueryOptions} from 'globunet-angular/core/providers/api/query-options'; -import {forkJoin} from 'rxjs'; - -import * as moment from 'moment'; - -@Component({ - selector: 'app-trace', - templateUrl: './trace.component.html', - styleUrls: [ './trace.component.scss' ] -}) -export class TraceComponent implements OnInit, OnDestroy { - public traces = []; - public selection = []; - public filters = { - searchText: '', - status: { - 'finished': { - name: 'finished', - selected: true - }, - 'execution': { - name: 'execution', - selected: true - } - }, - finishedStatus: { - 'noErrors': { - name: 'no-errors', - selected: true - }, - 'withErrors': { - name: 'with-errors', - selected: true - }, - }, - dateRange: { - startDate: null, - endDate: null - } - }; - config: { constants: any; timers: any; }; - - private datePickerOptions: { timePickerIncrement: number; timePicker: boolean; format: string; timePicker24Hour: boolean; locale: { fromLabel: any; toLabel: any; cancelLabel: any; firstDay: number; applyLabel: any; format: string; daysOfWeek: any[]; separator: string; customRangeLabel: any; weekLabel: string; monthNames: any[] } }; - private selectAll: any; - private executionTasks: Trace[]; - public showInfo: string; - // this tells the tabs component which Pages - // should be each tab's root Page - constructor(public traceService: TraceService, - private ogCommonService: OgCommonService, - private router: Router, - private ogSweetAlert: OgSweetAlertService, - private toaster: ToasterService, - private translate: TranslateService) { - } - - ngOnDestroy() { - if (this.config.timers && this.config.timers.executionsInterval) { - clearInterval(this.config.timers.executionsInterval.object); - } - } - -ngOnInit(): void { - const self = this; - this.ogCommonService.loadEngineConfig().subscribe( - data => { - this.config = data; - - if (this.config.timers.executionsInterval.object === null) { - this.config.timers.executionsInterval.object = setInterval(function() { - self.getExecutionTasks(); - }, this.config.timers.executionsInterval.tick); - } - - this.datePickerOptions = { - 'locale': { - 'format': 'DD/MM/YYYY HH:mm', - 'separator': ' - ', - 'applyLabel': this.translate.instant('apply'), - 'cancelLabel': this.translate.instant('cancel'), - 'fromLabel': this.translate.instant('from'), - 'toLabel': this.translate.instant('to'), - 'customRangeLabel': this.translate.instant('custom_range'), - 'weekLabel': 'W', - 'daysOfWeek': [ - this.translate.instant('sun'), - this.translate.instant('mon'), - this.translate.instant('tue'), - this.translate.instant('wed'), - this.translate.instant('thu'), - this.translate.instant('fri'), - this.translate.instant('sat') - ], - 'monthNames': [ - this.translate.instant('january'), - this.translate.instant('february'), - this.translate.instant('march'), - this.translate.instant('april'), - this.translate.instant('may'), - this.translate.instant('june'), - this.translate.instant('july'), - this.translate.instant('august'), - this.translate.instant('september'), - this.translate.instant('october'), - this.translate.instant('november'), - this.translate.instant('december') - ], - 'firstDay': 1 - }, - timePicker: true, - timePickerIncrement: 30, - timePicker24Hour: true, - format: 'DD/MM/YYYY HH:mm' - }; - this.traceService.list().subscribe( - (response) => { - this.traces = response; - }, - (error) => { - this.toaster.pop({type: 'error', title: 'error', body: error}); - } - ); - } - ); -} - - - selectTrace(trace) { - const index = this.selection.indexOf(trace); - if (trace.selected === true && index === -1) { - this.selection.push(trace); - } else if (trace.selected === false && index !== -1) { - this.selection.splice(index, 1); - } - } - - selectAllTraces() { - const filter = this.traces.filter(function(trace: Trace) { - return true; - }); - for (let index = 0; index < filter.length; index++) { - filter[index].selected = this.selectAll; - this.selectTrace(filter[index]); - } - } - - relaunchTraces() { - - } - - deleteTraces() { - this.ogSweetAlert.question( this.translate.instant('sure_to_delete') + '?', this.translate.instant('action_cannot_be_undone'), function(response) { - const promises = []; - for (let index = 0; index < this.selection.length; index++) { - promises.push(this.traceService.delete(this.selection[index].id)); - } - forkJoin(promises).subscribe( - (success) => { - this.toaster.pop({type: 'success', title: 'success', body: this.translate.instant('successfully_deleted')}); - this.selectAll = false; - this.selection = []; - this.searchText = ''; - }, - (error) => { - this.toaster.pop({type: 'error', title: 'error', body: error}); - } - ); - }); - } - - getExecutionTasks() { - this.traceService.list(new QueryOptions({finished: 0})).subscribe( - (result) => { - this.executionTasks = result; - }, - (error) => { - - } - ); - } - - deleteExecutionTace(task) { - this.ogSweetAlert.question( - this.translate.instant('delete_task'), - this.translate.instant('sure_to_delete_task') + '?', - function(result) { - if (result) { - this.traceService.delete(task.id).subscribe( - (response) => { - this.toaster.pop({type: 'success', title: 'success', body: this.translate.instant('successfully_deleted')}); - this.getExecutionTasks(); - }, - (error) => { - this.toaster.pop({type: 'error', title: 'error', body: error}); - } - ); - - } - } - ); - - } - - relaunchExecutionTask(task) { - this.ogSweetAlert.question( - this.translate.instant('relaunch_task'), - this.translate.instant('sure_to_relaunch_task') + '?', - function(result) { - if (result) { - - } - } - ); - } - - filterTraceStatus(trace, index, array) { - - // Comprobar si para el filtro de estado actual de la traza - let result = (trace.finishedAt != null && this.filters.status['finished'].selected === true) || (trace.finishedAt === null && this.filters.status['execution'].selected === true); - result = result && (trace.finishedAt != null && (trace.status === 0 && this.filters.finishedStatus['noErrors'].selected === true) || (trace.status !== 0 && this.filters.finishedStatus['withErrors'].selected === true)); - if (this.filters.dateRange.startDate != null) { - result = result && moment(trace.executedAt).isAfter(this.filters.dateRange.startDate); - } - if (this.filters.dateRange.endDate != null) { - result = result && moment(trace.executedAt).isBefore(this.filters.dateRange.endDate); - } - - return result; - } - - - filteredTraces() { - const self = this; - return this.traces.filter(function(trace, index, array) { - return self.filterTraceStatus(trace, index, array); - }); - } - - getTraceCssClass(trace: any) { - let result = ''; - if (!trace.finishedAt) { - result = 'fa-warning text-yellow'; - } - if (trace.status === 0) { - result += ' fa-check-circle text-green'; - } else { - result += ' fa-times-circle text-red'; - } - return result; - } -} +import {Component, OnDestroy, OnInit} from '@angular/core'; + +import { TraceService } from 'src/app/api/trace.service'; +import { Trace } from 'src/app/model/trace'; +import {ToasterService} from '../../service/toaster.service'; +import {OgSweetAlertService} from '../../service/og-sweet-alert.service'; +import {Router} from '@angular/router'; +import {OgCommonService} from '../../service/og-common.service'; +import {environment} from '../../../environments/environment'; +import {TranslateService} from '@ngx-translate/core'; +import {QueryOptions} from 'globunet-angular/core/providers/api/query-options'; +import {forkJoin} from 'rxjs'; + +import * as moment from 'moment'; + +@Component({ + selector: 'app-trace', + templateUrl: './trace.component.html', + styleUrls: [ './trace.component.scss' ] +}) +export class TraceComponent implements OnInit, OnDestroy { + public traces = []; + public selection = []; + public searchText = ''; + public filters = { + searchText: '', + status: { + 'finished': { + name: 'finished', + selected: true + }, + 'execution': { + name: 'execution', + selected: true + } + }, + finishedStatus: { + 'noErrors': { + name: 'no-errors', + selected: true + }, + 'withErrors': { + name: 'with-errors', + selected: true + }, + }, + dateRange: { + startDate: null, + endDate: null + } + }; + config: { constants: any; timers: any; }; + + private datePickerOptions: { timePickerIncrement: number; timePicker: boolean; format: string; timePicker24Hour: boolean; locale: { fromLabel: any; toLabel: any; cancelLabel: any; firstDay: number; applyLabel: any; format: string; daysOfWeek: any[]; separator: string; customRangeLabel: any; weekLabel: string; monthNames: any[] } }; + private selectAll: any; + private executionTasks: Trace[]; + public showInfo: string; + // this tells the tabs component which Pages + // should be each tab's root Page + constructor(public traceService: TraceService, + private ogCommonService: OgCommonService, + private router: Router, + private ogSweetAlert: OgSweetAlertService, + private toaster: ToasterService, + private translate: TranslateService) { + } + + ngOnDestroy() { + if (this.config.timers && this.config.timers.executionsInterval) { + clearInterval(this.config.timers.executionsInterval.object); + } + } + +ngOnInit(): void { + const self = this; + this.ogCommonService.loadEngineConfig().subscribe( + data => { + this.config = data; + + if (this.config.timers.executionsInterval.object === null && this.config.timers.executionsInterval.tick > 0) { + this.config.timers.executionsInterval.object = setInterval(function() { + self.getExecutionTasks(); + }, this.config.timers.executionsInterval.tick); + } + + this.datePickerOptions = { + 'locale': { + 'format': 'DD/MM/YYYY HH:mm', + 'separator': ' - ', + 'applyLabel': this.translate.instant('apply'), + 'cancelLabel': this.translate.instant('cancel'), + 'fromLabel': this.translate.instant('from'), + 'toLabel': this.translate.instant('to'), + 'customRangeLabel': this.translate.instant('custom_range'), + 'weekLabel': 'W', + 'daysOfWeek': [ + this.translate.instant('sun'), + this.translate.instant('mon'), + this.translate.instant('tue'), + this.translate.instant('wed'), + this.translate.instant('thu'), + this.translate.instant('fri'), + this.translate.instant('sat') + ], + 'monthNames': [ + this.translate.instant('january'), + this.translate.instant('february'), + this.translate.instant('march'), + this.translate.instant('april'), + this.translate.instant('may'), + this.translate.instant('june'), + this.translate.instant('july'), + this.translate.instant('august'), + this.translate.instant('september'), + this.translate.instant('october'), + this.translate.instant('november'), + this.translate.instant('december') + ], + 'firstDay': 1 + }, + timePicker: true, + timePickerIncrement: 30, + timePicker24Hour: true, + format: 'DD/MM/YYYY HH:mm' + }; + this.traceService.list().subscribe( + (response) => { + this.traces = response; + }, + (error) => { + this.toaster.pop({type: 'error', title: 'error', body: error}); + } + ); + } + ); +} + + + selectTrace(trace) { + const index = this.selection.indexOf(trace); + if (trace.selected === true && index === -1) { + this.selection.push(trace); + } else if (trace.selected === false && index !== -1) { + this.selection.splice(index, 1); + } + } + + selectAllTraces() { + const filter = this.traces.filter(function(trace: Trace) { + return true; + }); + for (let index = 0; index < filter.length; index++) { + filter[index].selected = this.selectAll; + this.selectTrace(filter[index]); + } + } + + relaunchTraces() { + + } + + deleteTraces() { + const self = this; + this.ogSweetAlert.question( this.translate.instant('sure_to_delete') + '?', this.translate.instant('action_cannot_be_undone'), function(response) { + const promises = []; + for (let index = 0; index < self.selection.length; index++) { + promises.push(self.traceService.delete(self.selection[index].id)); + } + forkJoin(promises).subscribe( + (success) => { + self.toaster.pop({type: 'success', title: 'success', body: self.translate.instant('successfully_deleted')}); + self.selectAll = false; + self.selection = []; + self.searchText = ''; + }, + (error) => { + self.toaster.pop({type: 'error', title: 'error', body: error}); + } + ); + }); + } + + getExecutionTasks() { + this.traceService.list(new QueryOptions({finished: 0})).subscribe( + (result) => { + this.executionTasks = result; + }, + (error) => { + + } + ); + } + + deleteExecutionTace(task) { + this.ogSweetAlert.question( + this.translate.instant('delete_task'), + this.translate.instant('sure_to_delete_task') + '?', + function(result) { + if (result) { + this.traceService.delete(task.id).subscribe( + (response) => { + this.toaster.pop({type: 'success', title: 'success', body: this.translate.instant('successfully_deleted')}); + this.getExecutionTasks(); + }, + (error) => { + this.toaster.pop({type: 'error', title: 'error', body: error}); + } + ); + + } + } + ); + + } + + relaunchExecutionTask(task) { + this.ogSweetAlert.question( + this.translate.instant('relaunch_task'), + this.translate.instant('sure_to_relaunch_task') + '?', + function(result) { + if (result) { + + } + } + ); + } + + filterTraceStatus(trace, index, array) { + + // Comprobar si para el filtro de estado actual de la traza + let result = (trace.finishedAt != null && this.filters.status['finished'].selected === true) || (trace.finishedAt === null && this.filters.status['execution'].selected === true); + result = result && (trace.finishedAt != null && (trace.status === 0 && this.filters.finishedStatus['noErrors'].selected === true) || (trace.status !== 0 && this.filters.finishedStatus['withErrors'].selected === true)); + if (this.filters.dateRange.startDate != null) { + result = result && moment(trace.executedAt).isAfter(this.filters.dateRange.startDate); + } + if (this.filters.dateRange.endDate != null) { + result = result && moment(trace.executedAt).isBefore(this.filters.dateRange.endDate); + } + + return result; + } + + + filteredTraces() { + const self = this; + return this.traces.filter(function(trace, index, array) { + return self.filterTraceStatus(trace, index, array); + }); + } + + getTraceCssClass(trace: any) { + let result = ''; + if (!trace.finishedAt) { + result = 'fa-warning text-yellow'; + } + if (trace.status === 0) { + result += ' fa-check-circle text-green'; + } else { + result += ' fa-times-circle text-red'; + } + return result; + } +} diff --git a/admin/WebConsole3/frontend/src/app/service/og-commands.service.ts b/admin/WebConsole3/frontend/src/app/service/og-commands.service.ts index 14e80e84..1ea33faa 100644 --- a/admin/WebConsole3/frontend/src/app/service/og-commands.service.ts +++ b/admin/WebConsole3/frontend/src/app/service/og-commands.service.ts @@ -14,15 +14,11 @@ import {environment} from '../../environments/environment'; export class OGCommandsService { public ogInstructions = ''; public execution: any; - private commands = []; + private commands: any; constructor(private router: Router, private ogCommonService: OgCommonService, private toaster: ToasterService, private ogSweetAlert: OgSweetAlertService, private commandService: CommandService, private translate: TranslateService) { this.execution = {}; - this.ogCommonService.loadEngineConfig().subscribe( - (response) => { - this.commands = response.constants.commandtypes; - } - ); + this.commands = environment.commands; } sendCommand() { @@ -114,15 +110,19 @@ export class OGCommandsService { // Comprobar tipo de cada particion para ver si es clonable // var parttable = $rootScope.constants.partitiontable[client.partitions[0].partitionCode-1]; // buscar las particiones que sean clonables + const clonablePartitions = []; for (let index = 1; index < client.partitions.length; index++) { if (client.partitions[index].osName !== 'DATA' && client.partitions[index].osName !== '') { // Crear como nombre para mostrar, el disco y partición del sistema const obj = Object.assign({}, client.partitions[index]); - obj.name = 'disco: ' + obj.numDisk + ', part: ' + obj.numPartition + ', SO: ' + client.partitions[index].osName; - options.scope.partitions.push(obj); + const str = 'disco: ' + obj.numDisk + ', part: ' + obj.numPartition + ', SO: ' + client.partitions[index].osName; + clonablePartitions.push(obj.numDisk + ' ' + obj.numPartition) + options.scope.partitions.push(str); } } + const self = this; + this.ogSweetAlert.swal({ title: this.translate.instant('select_partition_to_inventary'), // text: $filter("translate")("action_cannot_be_undone"), @@ -137,9 +137,9 @@ export class OGCommandsService { function(result) { if (result.value) { // Montar el script con el disco y partición elegida - this.execution.script = this.commands.SOFTWARE_INVENTORY + ' ' + result.value; - this.loadClients(); - this.sendCommand(); + self.execution.script = self.commands.SOFTWARE_INVENTORY + ' ' + clonablePartitions[result.value]; + self.loadClients(); + self.sendCommand(); } }, null); diff --git a/admin/WebConsole3/frontend/src/app/service/og-common.service.ts b/admin/WebConsole3/frontend/src/app/service/og-common.service.ts index 8a2bbe56..b529199d 100644 --- a/admin/WebConsole3/frontend/src/app/service/og-common.service.ts +++ b/admin/WebConsole3/frontend/src/app/service/og-common.service.ts @@ -26,10 +26,13 @@ export class OgCommonService { constructor(private layoutStore: LayoutStore, private adminLteConfig: AdminLteConf, private engineService: EngineService, private translate: TranslateService, private authModule: AuthModule) { this.app = {}; - this.selectedClients = []; + this.selectedClients = {}; this.selectedOu = null; this.movingOu = null; this.movingClients = false; + if (localStorage.getItem('selectedClients')) { + this.selectedClients = JSON.parse(localStorage.getItem('selectedClients')); + } } loadEngineConfig(): Observable<{constants: any, timers: any}> { @@ -43,21 +46,22 @@ export class OgCommonService { themes: environment.themes, menus: environment.menus, languages: environment.languages, - deployMethods: environment.deployMethods + deployMethods: environment.deployMethods, + commands: environment.commands }; this.constants = Object.assign(this.constants, data[0]); // inicializar timers generales para refresco de información this.timers = { serverStatusInterval: { - tick: 5000, + tick: 0, object: null }, clientsStatusInterval: { - tick: 5000, + tick: 0, object: null }, executionsInterval: { - tick: 5000, + tick: 0, object: null }, @@ -190,6 +194,19 @@ export class OgCommonService { } else { delete this.selectedClients[client.id]; } + this.saveSelection(); + } + + saveSelection() { + if (Object.keys(this.selectedClients).length > 0) { + localStorage.setItem('selectedClients', JSON.stringify(this.selectedClients, function (key, value) { + let result = value; + if (key === 'parent' && typeof value === 'object') { + result = value.id; + } + return result; + })); + } } getSelectionSize() { diff --git a/admin/WebConsole3/frontend/src/styles.scss b/admin/WebConsole3/frontend/src/styles.scss index 65c2fd6d..b0a5eaec 100644 --- a/admin/WebConsole3/frontend/src/styles.scss +++ b/admin/WebConsole3/frontend/src/styles.scss @@ -19,6 +19,14 @@ table.table-no-border { border: none; } +.loader { + position: absolute; + top: 0; + width: 100%; + height: 100%; + z-index: 999999; +} + #loading-bar .bar { background: white; } @@ -100,8 +108,7 @@ i.client { } .bg-lab{ - background-color: #d7dbef; - padding: 10px 10px 0 10px; + background-color: #d7dbef !important; } tr.odd { @@ -182,7 +189,7 @@ table.disk-partitions td { } table.disk-partitions td span { - padding: 5px 10px; + padding: 5px 5px; font-weight: bold; } @@ -306,3 +313,7 @@ ul.dropdown-menu.fit { ng2-smart-table { font-size: initial !important; } + +.swal2-popup { + font-size: 1em !important; +} -- cgit v1.2.3-18-g5258