diff --git a/.codeclimate.yml b/.codeclimate.yml index fd65fd830a..801ada6c4e 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -14,7 +14,7 @@ plugins: markdownlint: enabled: true scss-lint: - enabled: true + enabled: false exclude_patterns: - "config/" - "db/" diff --git a/.gitignore b/.gitignore index 21c2a5101c..b34c80c94b 100644 --- a/.gitignore +++ b/.gitignore @@ -52,7 +52,6 @@ environment.dev.ts #v1 *.iml docs/src -lib tools/test-backend/config/mock.config.json tools/.coverage-karma/ dev-certs/* @@ -81,6 +80,7 @@ deploy/ci/travis/temp/ deploy/kubernetes/console/imagelist.txt .dist/ +dist-devkit/ deploy/uaa/tmp/ src/backend/*/vendor/ .v8flags* @@ -96,8 +96,9 @@ src/jetstream/config.properties src/jetstream/db/dbconf.yml src/jetstream/plugins/monocular/chart-repo/chartrepo -# Customisations - +# Customisations - these can be removed in the future +# Left in for now to prevent these files being checked-in, if they are still present +# from a previous checkout src/frontend/packages/core/favicon.ico src/frontend/packages/core/sass/custom.scss src/frontend/packages/core/assets/eula.html @@ -110,6 +111,9 @@ src/frontend/packages/core/assets/custom src/frontend/packages/core/sass/custom src/frontend/packages/core/src/index.html +# Customisation - generated import module +src/frontend/packages/core/src/_custom-import.module.ts + # Prebuild package stratos-frontend-prebuild.zip diff --git a/CHANGELOG.md b/CHANGELOG.md index 576954b97b..161b42c8ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -155,7 +155,7 @@ Details: ## 2.6.1 -[Full Changelog](https://github.com/cloudfoundry/stratos/compare/2.6.0...2.6.1) +[Full Changelog](https://github.com/SUSE/stratos/compare/2.6.0...2.6.1) This release contains a few fixes: @@ -182,7 +182,7 @@ This release contains two fixes listed below. ## 2.5.3 -[Full Changelog](https://github.com/cloudfoundry-incubator/stratos/compare/2.5.2...2.5.3) +[Full Changelog](https://github.com/suse/stratos/compare/2.5.2...2.5.3) This release contains a number of fixes and improvements: @@ -200,7 +200,7 @@ This release contains a number of fixes and improvements: ## 2.5.2 -[Full Changelog](https://github.com/cloudfoundry-incubator/stratos/compare/2.5.1...2.5.2) +[Full Changelog](https://github.com/suse/stratos/compare/2.5.1...2.5.2) This release contains a number of fixes and improvements: @@ -222,7 +222,7 @@ This release contains a number of fixes and improvements: ## 2.5.1 -[Full Changelog](https://github.com/cloudfoundry-incubator/stratos/compare/2.5.0...2.5.1) +[Full Changelog](https://github.com/suse/stratos/compare/2.5.0...2.5.1) This release contains a number of fixes and improvements: diff --git a/angular.json b/angular.json index 75d6a32748..caa3bceaa9 100644 --- a/angular.json +++ b/angular.json @@ -4,14 +4,17 @@ "newProjectRoot": "src/frontend/packages", "projects": { "stratos": { - "root": "", + "root": "src/frontend/packages", "sourceRoot": "src/frontend/packages", "projectType": "application", "architect": { "build": { - "builder": "@angular-devkit/build-angular:browser", + "builder": "@angular-builders/custom-webpack:browser", "options": { - "aot": true, + "customWebpackConfig": { + "path": "./dist-devkit/build/main.js" + }, + "indexTransform": "./dist-devkit/build/index.transform.js", "preserveSymlinks": true, "outputPath": "dist", "index": "src/frontend/packages/core/src/index.html", @@ -36,10 +39,6 @@ }, "configurations": { "production": { - "budgets": [{ - "type": "anyComponentStyle", - "maximumWarning": "6kb" - }], "optimization": true, "outputHashing": "all", "sourceMap": false, @@ -57,7 +56,7 @@ } }, "serve": { - "builder": "@angular-devkit/build-angular:dev-server", + "builder": "@angular-builders/custom-webpack:dev-server", "options": { "aot": true, "sslCert": "dev-ssl/server.crt", @@ -94,36 +93,37 @@ } } }, + "theme": { + "root": "src/frontend/packages/theme/", + "sourceRoot": "", + "projectType": "library", + "architect": { + "build": { + "builder": "./dist-devkit:stratos-theme", + "options": { + "outputPath": "dist/theme" + } + } + } + }, "core": { "root": "src/frontend/packages/core/", - "sourceRoot": "src/frontend/packages/core/src", - "projectType": "application", + "sourceRoot": "src/frontend/packages/core", + "projectType": "library", "prefix": "app", "schematics": {}, "architect": { "build": { - "builder": "@angular-devkit/build-angular:browser", + "builder": "@angular-devkit/build-ng-packagr:build", "options": { - "aot": true, "preserveSymlinks": true, "outputPath": "dist/core", "index": "src/frontend/packages/core/src/index.html", "main": "src/frontend/packages/core/src/main.ts", "polyfills": "src/frontend/packages/core/src/polyfills.ts", "tsConfig": "src/frontend/packages/core/tsconfig.app.json", - "assets": [ - "src/frontend/packages/core/favicon.ico", - "src/frontend/packages/core/assets", - { - "glob": "**/*", - "input": "custom-src/frontend/assets/custom", - "output": "/core/assets/custom" - } - ], - "styles": [ - "src/frontend/packages/core/src/styles.css", - "src/frontend/packages/cf-autoscaler/src/styles.css" - ], + "assets": [], + "styles": [], "scripts": [] }, "configurations": { @@ -148,23 +148,6 @@ } } }, - "serve": { - "builder": "@angular-devkit/build-angular:dev-server", - "options": { - "browserTarget": "core:build" - }, - "configurations": { - "production": { - "browserTarget": "core:build:production" - } - } - }, - "extract-i18n": { - "builder": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "core:build" - } - }, "test": { "builder": "@angular-devkit/build-angular:karma", "options": { @@ -253,6 +236,37 @@ } } }, + "shared": { + "root": "src/frontend/packages/shared", + "sourceRoot": "src/frontend/packages/shared/src", + "projectType": "library", + "prefix": "lib", + "architect": { + "build": { + "builder": "@angular-devkit/build-ng-packagr:build", + "options": { + "tsConfig": "src/frontend/packages/shared/tsconfig.lib.json", + "project": "src/frontend/packages/shared/ng-package.json" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "main": "src/frontend/packages/shared/src/test.ts", + "tsConfig": "src/frontend/packages/shared/tsconfig.spec.json", + "karmaConfig": "src/frontend/packages/shared/karma.conf.js" + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": ["src/tsconfig.json"], + "tslintConfig": "src/frontend/packages/shared/tslint.json", + "files": ["src/frontend/packages/shared/src/**/*.ts"] + } + } + } + }, "cloud-foundry": { "root": "src/frontend/packages/cloud-foundry", "sourceRoot": "src/frontend/packages/cloud-foundry/src", @@ -349,8 +363,5 @@ "@schematics/angular:directive": { "prefix": "app" } - }, - "cli": { - "_defaultCollection": "@nrwl/angular" } } diff --git a/build/customize-build.js b/build/customize-build.js deleted file mode 100644 index fb98297c18..0000000000 --- a/build/customize-build.js +++ /dev/null @@ -1,316 +0,0 @@ -/** - * Gulp build file for applying cutomizations - */ - -/* eslint-disable angular/log,no-console,no-process-env,angular/json-functions,no-sync */ -(function () { - 'use strict'; - - var gulp = require('gulp'); - var path = require('path'); - var fs = require('fs-extra'); - var yaml = require('js-yaml'); - var replace = require('replace-in-file'); - var execSync = require('child_process').execSync; - - const CUSTOM_YAML_MANIFEST = path.resolve(__dirname, '../src/frontend/packages/core/misc/custom/custom.yaml'); - const INDEX_TEMPLATE = path.resolve(__dirname, '../src/frontend/packages/core/misc/custom/index.html'); - const INDEX_HTML = path.resolve(__dirname, '../src/frontend/packages/core/src/index.html'); - const CUSTOM_METADATA = path.resolve(__dirname, '../custom-src/stratos.yaml'); - const GIT_FOLDER = path.resolve(__dirname, '../.git'); - const GIT_METADATA = path.resolve(__dirname, '../.stratos-git-metadata.json'); - const INDEX_LOADING_HTML_CUSTOM = path.resolve(__dirname, '../custom-src/frontend/loading.html'); - const INDEX_LOADING_HTML_DEFAULT = path.resolve(__dirname, '../src/frontend/packages/core/misc/custom/loading.html'); - const INDEX_LOADING_CSS_CUSTOM = path.resolve(__dirname, '../custom-src/frontend/loading.css'); - const INDEX_LOADING_CSS_DEFAULT = path.resolve(__dirname, '../src/frontend/packages/core/misc/custom/loading.css'); - - // Apply any customizations - // Symlink customizations of the default resources for Stratos - gulp.task('customize', function (cb) { - doShowVersions() - doCustomize(false); - doGenerateIndexHtml(true); - console.log('Finished applying customizations') - cb(); - }); - - // Apply defaults instead of any customizations that are available in custom-src - gulp.task('customize-default', function (cb) { - doCustomize(true); - doGenerateIndexHtml(false); - console.log('Finished applying default customizations') - cb(); - }); - - // Remove all customizations (removes all symlinks as if customize had not been run) - gulp.task('customize-reset', function (cb) { - doCustomize(true, true); - doGenerateIndexHtml(false); - console.log('Finished resetting customizations') - cb(); - }); - - // Store git metadata so we have it when we are running the the non-git world (Docker) - gulp.task('store-git-metadata', function (cb) { - storeGitRepositoryMetadata(); - cb(); - }); - - function doShowVersions() { - console.log('Node Version: ' + process.versions.node || 'N/A'); - try { - var response = execSync('npm --v'); - var npmVersion = response.toString().trim(); - console.log('NPM Version : ' + npmVersion || 'N/A'); - } catch (e) { - console.log('NPM Version : N/A'); - } - } - - function doCustomize(forceDefaults, reset) { - var msg = !forceDefaults ? 'Checking for and applying customizations' : 'Removing customizations and applying defaults'; - var msg = !reset ? msg : 'Removing all customizations'; - console.log(msg); - var customConfig; - - try { - customConfig = yaml.safeLoad(fs.readFileSync(CUSTOM_YAML_MANIFEST, 'utf8')); - } catch (e) { - console.log('Could not read custom.yaml file'); - console.log(e); - process.exit(1); - } - - const baseFolder = path.resolve(__dirname, '../src/frontend/packages/core'); - const customBaseFolder = path.resolve(__dirname, '../custom-src/frontend'); - doCustomizeFiles(forceDefaults, reset, customConfig, baseFolder, customBaseFolder); - doCustomizeFolders(forceDefaults, reset, customConfig, baseFolder, customBaseFolder); - doCustomizeCreateModule(forceDefaults, reset, customConfig, baseFolder, customBaseFolder); - - const backendBaseFolder = path.resolve(__dirname, '../src/jetstream/plugins'); - const backendCustomBaseFolder = path.resolve(__dirname, '../custom-src/jetstream'); - - // There are no defaults for the backend - its the same as removing all of the custom plugins that are there - doCustomizeBackend(forceDefaults || reset, backendBaseFolder, backendCustomBaseFolder); - }; - - function doCustomizeFiles(forceDefaults, reset, customConfig, baseFolder, customBaseFolder) { - // This is where we find the default files, if there are no customizations - const defaultSrcFolder = path.resolve(__dirname, '../src/frontend/packages/core/misc/custom'); - // Symlink custom files - Object.keys(customConfig.files).forEach(file => { - const dest = customConfig.files[file]; - - var srcFile = path.join(defaultSrcFolder, file); - const destFile = path.join(baseFolder, dest); - const customSrcFile = path.join(customBaseFolder, dest); - - // Use the custom file if there is one - if (!forceDefaults && fs.existsSync(customSrcFile)) { - srcFile = customSrcFile; - } - - // Doing an exists check on a symlink will tell if the link dest exists, not the link itself - // So try and delete anyway and catch any exception - try { - const existingLink = fs.readlinkSync(destFile); - fs.unlinkSync(destFile); - } catch (e) { } - - if (!reset) { - fs.symlinkSync(srcFile, destFile); - console.log(' + Linking file : ' + srcFile + ' ==> ' + destFile); - } - }) - - } - - function doCustomizeFolders(forceDefaults, reset, customConfig, baseFolder, customBaseFolder) { - // Symlink custom app folders if they are present - customConfig.folders.forEach(folder => { - var parts = folder.split(':') - var src = parts[0]; - var dest = src; - if (parts.length > 1) { - dest = parts[1]; - } - var destFolder = path.join(baseFolder, dest); - var srcFolder = path.join(customBaseFolder, src); - if (fs.existsSync(destFolder)) { - fs.unlinkSync(destFolder); - } - if (!reset && fs.existsSync(srcFolder)) { - fs.symlinkSync(srcFolder, destFolder); - console.log(' + Linking folder : ' + srcFolder + ' ==> ' + destFolder); - } - }); - } - - // Copy the correct custom module to either import the supplied custom module or provide an empty module - function doCustomizeCreateModule(forceDefaults, reset, customConfig, baseFolder, customBaseFolder) { - const defaultSrcFolder = path.resolve(__dirname, '../src/frontend/packages/core/misc/custom'); - const destFile = path.join(baseFolder, 'src/custom-import.module.ts'); - const customModuleFile = path.join(baseFolder, 'src/custom/custom.module.ts'); - const customRoutingModuleFile = path.join(baseFolder, 'src/custom/custom-routing.module.ts'); - - // Delete the existing file if it exists - if (fs.existsSync(destFile)) { - fs.unlinkSync(destFile) - } - - if (!reset) { - let srcFile = 'custom.module.ts_'; - if (fs.existsSync(customModuleFile)) { - srcFile = 'custom-src.module.ts_'; - if (fs.existsSync(customRoutingModuleFile)) { - srcFile = 'custom-src-routing.module.ts_'; - console.log(' + Found custom module with routing'); - } else { - console.log(' + Found custom module without routing'); - } - } else { - console.log(' + No custom module found - linking empty custom module'); - } - fs.copySync(path.join(defaultSrcFolder, srcFile), destFile); - console.log(' + Copying file : ' + path.join(defaultSrcFolder, srcFile) + ' ==> ' + destFile); - } - } - - function doCustomizeBackend(reset, baseFolder, customBaseFolder) { - // Symlink custom backend plugin folders if they are present - // Get all of the sub-folders in the custom-src/backend folder and symlink - - // Update the git metadata if we can - storeGitRepositoryMetadata(); - - // Remove all existing symlinks first - var existing = fs.readdirSync(baseFolder); - existing.forEach(file => { - var pluginPath = path.join(baseFolder, file); - var stats = fs.lstatSync(pluginPath); - if (stats.isSymbolicLink()) { - fs.unlinkSync(pluginPath); - } - }) - - if (reset) { - // If we are reseting then we are done, just return now - return; - } - - // Check if we have a customization folder - if (!fs.existsSync(customBaseFolder)) { - return; - } - - // Symlink any custom plugins - var plugins = fs.readdirSync(customBaseFolder); - plugins.forEach(file => { - var srcFolder = path.join(customBaseFolder, file); - var stats = fs.statSync(srcFolder); - var destFolder = path.join(baseFolder, file); - if (stats.isDirectory()) { - if (fs.existsSync(destFolder)) { - fs.unlinkSync(destFolder); - } - fs.symlinkSync(srcFolder, destFolder); - } - }) - } - - // Generate index.html from template - function doGenerateIndexHtml(customize) { - - console.log(' + Generating index.html'); - // Copy the default - fs.copySync(INDEX_TEMPLATE, INDEX_HTML); - - // Read custom metadata if we are customizing and the file is present - var metadata = {}; - if (customize && fs.existsSync(CUSTOM_METADATA)) { - try { - metadata = yaml.safeLoad(fs.readFileSync(CUSTOM_METADATA, 'utf8')); - } catch (e) { - console.log('Could not read stratos.yaml file'); - console.log(e); - process.exit(1); - } - } - - if (metadata.title) { - console.log(' + Overridding title to: "' + metadata.title + '"'); - } - - // Patch different page title if there is one - var title = metadata.title || 'Stratos'; - replace.sync({ files: INDEX_HTML, from: /@@TITLE@@/g, to: title }); - - // Read in the stored Git metadata if it is there, default to empty metadata - var gitMetadata = { - project: process.env.project || process.env.STRATOS_PROJECT || '', - branch: process.env.branch || process.env.STRATOS_BRANCH || '', - commit: process.env.commit || process.env.STRATOS_COMMIT || '' - }; - - if (fs.existsSync(GIT_METADATA)) { - gitMetadata = JSON.parse(fs.readFileSync(GIT_METADATA)); - console.log(' + Project Metadata file read OK'); - } else { - console.log(' + Project Metadata file does not exist'); - } - - console.log(" + Project Metadata: " + JSON.stringify(gitMetadata)); - - // Git Information - replace.sync({ files: INDEX_HTML, from: '@@stratos_git_project@@', to: gitMetadata.project }); - replace.sync({ files: INDEX_HTML, from: '@@stratos_git_branch@@', to: gitMetadata.branch }); - replace.sync({ files: INDEX_HTML, from: '@@stratos_git_commit@@', to: gitMetadata.commit }); - - // Date and Time that the build was made (approximately => it is when this script is run) - replace.sync({ files: INDEX_HTML, from: '@@stratos_build_date@@', to: new Date() }); - - // Replace loading indicator - HTML - let loadingHtmlFile = INDEX_LOADING_HTML_DEFAULT; - if (fs.existsSync(INDEX_LOADING_HTML_CUSTOM)) { - loadingHtmlFile = INDEX_LOADING_HTML_CUSTOM - } - const loadingHtml = fs.readFileSync(loadingHtmlFile, 'utf8'); - replace.sync({ files: INDEX_HTML, from: '', to: loadingHtml }); - - // Replace loading indicator - CSS - let loadingCssFile = INDEX_LOADING_CSS_DEFAULT; - if (fs.existsSync(INDEX_LOADING_CSS_CUSTOM)) { - loadingCssFile = INDEX_LOADING_CSS_CUSTOM - } - const loadingCss = fs.readFileSync(loadingCssFile, 'utf8'); - replace.sync({ files: INDEX_HTML, from: '/** @@LOADING_CSS@@ **/', to: loadingCss }); - } - - // We can only do this if we have a git repository checkout - // We'll store this in a file which we will then use - when in environments like Docker, we will run this - // in the host environment so that we can pick it up when we're running in the Docker world - function storeGitRepositoryMetadata() { - // Do we have a git folder? - if (!fs.existsSync(GIT_FOLDER)) { - console.log(' + Unable to store git repository metadata - .git folder not found'); - return; - } - var gitMetadata = { - project: execGit('git config --get remote.origin.url'), - branch: execGit('git rev-parse --abbrev-ref HEAD'), - commit: execGit('git rev-parse HEAD') - }; - - fs.writeFileSync(GIT_METADATA, JSON.stringify(gitMetadata, null, 2)); - } - - function execGit(cmd) { - try { - var response = execSync(cmd + ' 2> /dev/null'); - return response.toString().trim(); - } catch (e) { - return ''; - } - } - -})(); \ No newline at end of file diff --git a/build/fe-build.js b/build/fe-build.js index 0542f8942c..75946dd93c 100644 --- a/build/fe-build.js +++ b/build/fe-build.js @@ -17,9 +17,6 @@ var config = require('./gulp.config'); var paths = config.paths; - // Import customization tasks - require('./customize-build'); - // Clean dist dir gulp.task('clean', function (next) { del(paths.dist + '**/*', { diff --git a/build/tools/v4-migration/migrate.sh b/build/tools/v4-migration/migrate.sh new file mode 100755 index 0000000000..0eb8bfd8c0 --- /dev/null +++ b/build/tools/v4-migration/migrate.sh @@ -0,0 +1,156 @@ +#!/usr/bin/env bash + +# Migrate custom theme and extensions into the new package structure + +set -e +set -o pipefail + +# Script folder +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" +STRATOS="`cd "${DIR}/../../..";pwd`" +CUSTOM="${STRATOS}/custom-src" +TEMPLATES=${DIR}/templates + +STRATOS_YML=${STRATOS}/stratos.yaml +PKGS=${STRATOS}/src/frontend/packages + +echo $CUSTOM + +function migrateTitle() { + if [ -f "${CUSTOM}/stratos.yaml" ]; then + DATA=$(cat "${CUSTOM}/stratos.yaml") + + # Make sure we have a Stratos.yaml file + touch ${STRATOS_YML} + + TITLE=$(grep -o 'title: .*' ${CUSTOM}/stratos.yaml) + sed -i.bak -e '/^title:/d' ${STRATOS_YML} + echo -e "${TITLE}" >> ${STRATOS_YML} + fi +} + +function migrateTheme() { + echo "Looking for custom theme" + + # Custom theme if we have custom-src/frontend/sass/custom.scss + CUSTOM_THEME=${CUSTOM}/frontend/sass/custom.scss + if [ ! -f ${CUSTOM_THEME} ]; then + echo "No custom theme found" + return + fi + + echo "Custom theme found ... migrating" + + # Create a new package for the theme + THEME_DIR=${PKGS}/custom_theme + + rm -rf ${THEME_DIR} + mkdir ${THEME_DIR} + mkdir ${THEME_DIR}/sass + mkdir -p ${THEME_DIR}/assets/core + mkdir -p ${THEME_DIR}/assets/custom + mkdir -p ${THEME_DIR}/loader + + cp -R ${CUSTOM}/frontend/sass/* ${THEME_DIR}/sass + + cp ${TEMPLATES}/theme.package.json ${THEME_DIR}/package.json + cp ${TEMPLATES}/_index.scss ${THEME_DIR} + + cp ${CUSTOM}/frontend/loading.* ${THEME_DIR}/loader/ + + # Update the theme in the top-level stratos.yml + sed -i.bak -e 's/theme: .*/theme: \"@custom\/theme\"/g' ${STRATOS_YML} + + # Copy assets + cp -R ${CUSTOM}/frontend/assets/* ${THEME_DIR}/assets/core + # Favicon + cp -R ${CUSTOM}/frontend/favicon.ico ${THEME_DIR}/assets + + # Remove lines from package.json that are not required + if [ ! -f "${THEME_DIR}/assets/favicon.ico" ]; then + sed -i.bak '/"favicon.ico"$/d' ${THEME_DIR}/package.json + fi + + # Loading screen + if [ ! -f "${THEME_DIR}/loader/loading.css" ]; then + sed -i.bak '/loading.css",$/d' ${THEME_DIR}/package.json + fi + + if [ ! -f "${THEME_DIR}/loader/loading.html" ]; then + sed -i.bak '/loading.html"$/d' ${THEME_DIR}/package.json + fi + + rm -rf ${THEME_DIR}/package.json.bak +} + +function migrateExtensions() { + echo "Looking for custom extensions" + + # Custom theme if we have custom-src/frontend/sass/custom.scss + CUSTOM_MODULE=${CUSTOM}/frontend/app/custom/custom.module.ts + if [ ! -f ${CUSTOM_MODULE} ]; then + echo "No custom extensions found" + return + fi + + echo "Custom extensions found ... migrating" + + # Create a new package for the extension(s) + EXT_DIR=${PKGS}/custom_extensions + + rm -rf ${EXT_DIR} + mkdir -p ${EXT_DIR}/src + cp ${TEMPLATES}/ext.package.json ${EXT_DIR}/package.json + + # Copy the source code into the src folder + cp -R ${CUSTOM}/frontend/app/custom/ ${EXT_DIR}/src + cp ${TEMPLATES}/public-api.ts_ ${EXT_DIR}/src/public-api.ts + + #IMPORT_LINE=$(awk '/imports:/{ print NR; exit }' ${CUSTOM_MODULE} + + sed -i '' "s/imports: \[/imports: \[ StratosComponentsModule,/" ${EXT_DIR}/src/custom.module.ts + + echo "import { StratosComponentsModule } from '@stratosui/shared';" | cat - ${EXT_DIR}/src/custom.module.ts > ${EXT_DIR}/temp.ts + mv -f ${EXT_DIR}/temp.ts ${EXT_DIR}/src/custom.module.ts + + if [ -f ${EXT_DIR}/src/custom-routing.module.ts ]; then + echo -e "\nexport * from './custom-routing.module';\n" >> ${EXT_DIR}/src/public-api.ts + + sed -i '' "s/_routingModule/routingModule/g" ${EXT_DIR}/package.json + fi + + # Need to update the import references as things will have moved + pushd ${EXT_DIR}/src + + # Not exhaustive, so extensions developers may need to manually fix imports + find . -name "*.ts" | xargs sed -i '' "s@'../../core@'../../../core/src/core@g" + find . -name "*.ts" | xargs sed -i '' "s@'../core/core.module@'../../core/src/core/core.module@g" + find . -name "*.ts" | xargs sed -i '' "s@'../core/customizations.types@'../../core/src/core/customizations.types@g" + find . -name "*.ts" | xargs sed -i '' 's@../core/md.module@../../core/src/core/md.module@g' + find . -name "*.ts" | xargs sed -i '' "s@'../shared/shared.module@'../../core/src/shared/shared.module@g" + find . -name "*.ts" | xargs sed -i '' "s@'../../../../store/src/app-state@'../../../store/src/app-state@g" + find . -name "*.ts" | xargs sed -i '' "s@'../../features/login/login-page/login-page.component@'../../../core/src/features/login/login-page/login-page.component@g" + + popd +} + +pushd "${STRATOS}" > /dev/null + +# Look for custom-src folder + + +if [ -d "${CUSTOM}" ]; then + echo "Found customizations to migrate" +else + echo "No custom src folder exists - nothing to migrate" + popd > /dev/null + exit 1 +fi + +migrateTitle +migrateTheme +migrateExtensions + +popd > /dev/null + +cat $STRATOS_YML \ No newline at end of file diff --git a/build/tools/v4-migration/templates/_index.scss b/build/tools/v4-migration/templates/_index.scss new file mode 100644 index 0000000000..a8d3f300e1 --- /dev/null +++ b/build/tools/v4-migration/templates/_index.scss @@ -0,0 +1,9 @@ +@import '~@stratosui/theme/helper'; + +// Custom Theme +@import './sass/custom'; + +@function stratos-theme() { + $theme: stratos-theme-helper($stratos-theme); + @return $theme +} \ No newline at end of file diff --git a/src/frontend/packages/store/testing/package.json b/build/tools/v4-migration/templates/ext.package.json similarity index 53% rename from src/frontend/packages/store/testing/package.json rename to build/tools/v4-migration/templates/ext.package.json index 7dd43ac8c1..e22a84b356 100644 --- a/src/frontend/packages/store/testing/package.json +++ b/build/tools/v4-migration/templates/ext.package.json @@ -1,8 +1,12 @@ { - "name": "store/testing", + "name": "@custom/extensions", "version": "0.0.1", "peerDependencies": { "@angular/common": "^6.0.0-rc.0 || ^6.0.0", "@angular/core": "^6.0.0-rc.0 || ^6.0.0" + }, + "stratos": { + "module": "CustomModule", + "_routingModule": "CustomRoutingModule" } } \ No newline at end of file diff --git a/build/tools/v4-migration/templates/public-api.ts_ b/build/tools/v4-migration/templates/public-api.ts_ new file mode 100644 index 0000000000..b78971cc53 --- /dev/null +++ b/build/tools/v4-migration/templates/public-api.ts_ @@ -0,0 +1,3 @@ +// Custom Extensions + +export * from './custom.module'; \ No newline at end of file diff --git a/build/tools/v4-migration/templates/theme.package.json b/build/tools/v4-migration/templates/theme.package.json new file mode 100644 index 0000000000..a588ac2e99 --- /dev/null +++ b/build/tools/v4-migration/templates/theme.package.json @@ -0,0 +1,19 @@ +{ + "name": "@custom/theme", + "version": "0.0.1", + "stratos": { + "assets": { + "assets/core": "core/assets", + "assets/favicon.ico": "favicon.ico" + }, + "theme":{ + "loadingCss": "loader/loading.css", + "loadingHtml": "loader/loading.html" + } + }, + "peerDependencies": { + }, + "scripts": { + "build": "rm -rf ../../../../dist/theme && mkdir -p ../../../../dist/theme && cp -R * ../../../../dist/theme" + } +} diff --git a/deploy/cloud-foundry/build.sh b/deploy/cloud-foundry/build.sh index 0d3f2eb8d3..3d89979b33 100755 --- a/deploy/cloud-foundry/build.sh +++ b/deploy/cloud-foundry/build.sh @@ -39,7 +39,6 @@ else # Build front-end log "Fetching front-end dependencies" $CYAN npm install - npm run customize log "Building front-end" $CYAN npm run build-cf diff --git a/deploy/kubernetes/README.md b/deploy/kubernetes/README.md index 10358b4ad5..6d8d583560 100644 --- a/deploy/kubernetes/README.md +++ b/deploy/kubernetes/README.md @@ -1,401 +1,15 @@ # Deploying in Kubernetes -The following guide details how to deploy Stratos in Kubernetes. +Stratos can be deployed to Kubernetes using [Helm](https://github.com/kubernetes/helm). - -- [Requirements](#requirements) - * [Kubernetes](#kubernetes) - * [Helm](#helm) - * [Storage Class](#storage-class) -- [Deploying Stratos](#deploying-stratos) - * [Deploy using the Helm repository](#deploy-using-the-helm-repository) - * [Deploy using an archive of the Helm Chart](#deploy-using-an-archive-of-the-helm-chart) - * [Deploying using the GitHub repository](#deploying-using-the-github-repository) -- [Accessing the Console](#accessing-the-console) -- [Advanced Topics](#advanced-topics) - * [Using a Load Balancer](#using-a-load-balancer) - * [Using an Ingress Controller](#ingress) - * [Specifying an External IP](#specifying-an-external-ip) - * [Upgrading your deployment](#upgrading-your-deployment) - * [Specifying UAA configuration](#specifying-uaa-configuration) - * [Configuring a local user account](#configuring-a-local-user-account) - * [Specifying a custom Storage Class](#specifying-a-custom-storage-class) - + [Providing Storage Class override](#providing-storage-class-override) - + [Create a default Storage Class](#create-a-default-storage-class) - * [Deploying Stratos with your own TLS certificates](#deploying-stratos-with-your-own-tls-certificates) - * [Using with a Secure Image Repostiory](#using-with-a-secure-image-repository) - * [Installing Nightly Release](#installing-a-nightly-release) - +As part of the Stratos release process, a Helm chart is generated and added to the release artifacts for a given release. In addition, we maintain a Helm Chart repository that can be used to install Stratos from: -## Requirements - -### Kubernetes +`https://cloudfoundry.github.io/stratos` You will need a suitable Kubernetes environment and a machine from which to run the deployment commands. -You will need to have the `kubectl` CLI installed and available on your path. It should be appropriately configured to be able to communicate with your Kubernetes environment. - -### Helm - -We use [Helm](https://github.com/kubernetes/helm) for deploying to Kubernetes. - -You will need the latest Helm client installed on the machine from which you are deploying and you will need to install the Helm Server (Tiller) into you Kubernetes environment. - -- Download the Helm client for your system from https://github.com/kubernetes/helm/releases. -For convenience the guide assumes that the helm client has been added to your PATH. -- To install the Helm server (Tiller) in your Kubernetes environment by running the following command: -``` -helm init -``` - -If you already Helm installed, please make sure it is the latest version. To update your Helm server (Tiller) in your Kubernetes environment after you download the latest Helm release, run the following command: -``` -helm init --upgrade -``` -### Storage Class - -Stratos uses persistent volumes. In order to deploy it in your Kubernetes environment, you must -have a storage class available. - -Without configuration, the Stratos Helm Chart will use the default storage class. If a default storage -class is not available, installation will fail. - -To check if a `default` storage class exists, you can list your configured storage classes with `kubectl get storageclass`. If no storage class has `(default)` after it, then you need to either specify a storage class override or declare a default storage class for your Kubernetes cluster. - -For non-production environments, you may want to use the `hostpath` storage class. See the [SCF instructions](https://github.com/SUSE/scf/wiki/How-to-Install-SCF#choosing-a-storage-class) for details on setting this up. Note that you will need to make this storage class the default storage class, e.g. - -``` -kubectl patch storageclass -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}' -``` -Where `` would be `hostpath` if you follow the SCF instructions. -## Deploying Stratos - -You can deploy Stratos from one of three different sources: - -1. Using our Helm repository -1. Using an archive file containing a given release of our Helm chart -1. Using the latest Helm chart directly from out GitHub repository - -> **Note**: By default each deployment method deploys Stratos with its default user authentication mechanism - which requires a UAA. If you wish to use Stratos without the requirement for a UAA component, use the deployment commands from the following section below: [Configuring a local user account](#configuring-a-local-user-account). All other steps for each deployment method remain the same, as detailed in the following sections. - -### Deploy using the Helm repository - -Add the Helm repository to your helm installation -``` -helm repo add stratos https://cloudfoundry.github.io/stratos -``` -Check the repository was successfully added by searching for the `console` -``` -helm search console -NAME VERSION DESCRIPTION -stratos/console 0.9.0 A Helm chart for deploying Console -``` -To install Stratos. - -``` -helm install stratos/console --namespace=console --name my-console -``` -> **Note**: The previous assumes that a storage class exists in the kubernetes cluster that has been marked as `default`. If no such storage class exists, a specific storage class needs to be specified, please see the following section *Specifying a custom Storage Class*. - -> You can change the namespace (--namespace) and the release name (--name) to values of your choice. - -This will create a Console instance named `my-console` in a namespace called `console` in your Kubernetes cluster. - -After the install, you should be able to access the Console in a web browser by following [the instructions](#accessing-the-console) below. - -### Deploy using an archive of the Helm Chart - -Helm chart archives are available for Stratos releases from our GitHub repository, under releases - see https://github.com/suse/stratos/releases. - -Download the appropriate release `console-helm-chart.X.Y.Z.tgz` from the GitHub repository and unpack the archive to a local folder. The Helm Chart will be extracted to a sub-folder named `console`. - -Deploy Stratos with: - -``` -helm install console --namespace=console --name my-console -``` - -### Deploying using the GitHub repository - -> Note: Deploying using the GitHub repository uses the latest Stratos images that are built nightly (tagged `latest`). While these contain the very latest updates, they may contain bugs or instabilities. - -Clone the Stratos GitHub repository: - -``` -git clone https://github.com/suse/stratos.git -``` - -Open a terminal and cd to the `deploy/kubernetes` directory: - -``` -$ cd deploy/kubernetes -``` - -Run helm install: - -``` -$ helm install console --namespace console --name my-console -``` - -> You can change the namespace (--namespace) and the release name (--name) to values of your choice. - -This will create a Console instance named `my-console` in a namespace called `console` in your Kubernetes cluster. - -You should now be able to access the Console in a web browser by following the instructions below. - -## Accessing the Console - -To check the status of the instance use the following command: -``` -helm status my-console -``` - -> Note: Replace `my-console` with the value you used for the `name` parameter, or if you did not provide one, use the `helm list` command to find the release name that was automatically generated for you. - -Once the instance is in `DEPLOYED` state, find the IP address and port that the console is running on: - -``` -$ helm status my-console | grep ui-ext -console-ui-ext 10.0.0.162 192.168.77.1 80:30933/TCP,443:30941/TCP 1m -``` - -In this example, the IP address is `192.168.77.1` and the node-port is `30941`, so the console is accessible on: - -`https://192.168.77.1:30941` - -The values will be different for your environment. - -You can now access the UI. - -> You may see a certificate warning which you can safely ignore. - -To login use the following credentials detailed [here](../../docs/access.md). - -> Note: For some environments like Minikube, you are not given an IP Address - it may show as ``. In this case, run `kubectl cluster-info` and use the IP address of your node shown in the output of this command. - -## Advanced Topics -### Using a Load Balancer -If your Kubernetes deployment supports automatic configuration of a load balancer (e.g. Google Container Engine), specify the parameters `console.service.type=LoadBalancer` when installing. - -``` -helm install stratos/console --namespace=console --name my-console --set console.service.type=LoadBalancer -``` - -### Using an Ingress Controller - -If your Kubernetes Cluster supports Ingress, you can expose Stratos through Ingress by supplying the appropriate ingress configuration when installing. - -This configuration is described below: - -|Parameter|Description|Default| -|----|---|---| -|console.service.ingress.enabled|Enables ingress|false| -|console.service.ingress.annotations|Annotations to be added to the ingress resource.|{}| -|console.service.ingress.extraLabels|Additional labels to be added to the ingress resource.|{}| -|console.service.ingress.host|The host name that will be used for the Stratos service.|| -|console.service.ingress.secretName|The existing TLS secret that contains the certificate for ingress.|| - -You must provide `console.service.ingress.host` when enabling ingress. - -By default a certificate will be generated for TLS. You can provide your own certificate by creating a secret and specifying this with `console.service.ingress.secretName`. - -> Note: If you do not supply `console.service.ingress.host` but do supply `env.DOMAIN` then the host `console.[env.DOMAIN]` will be used. - -### Specifying an External IP - -If the kubernetes cluster supports external IPs for services (see [ Service External IPs](https://kubernetes.io/docs/concepts/services-networking/service/#external-ips)), then the following arguments can be provided. In this following example the dashboard will be available at `https://192.168.100.100:5000`. - -``` -helm install stratos/console --namespace=console --name my-console --set console.service.externalIPs={192.168.100.100} --set console.service.servicePort=5000 -``` - -### Upgrading your deployment - -To upgrade your instance when using the Helm repository, fetch any updates to the repository: - -``` -$ helm repo update -``` - -To update an instance, the following assumes your instance is called `my-console`, and overrides have been specified in a file called `overrides.yaml`. - -``` -$ helm upgrade -f overrides.yaml my-console stratos/console -``` - -After the upgrade, perform a `helm list` to ensure your console is the latest version. - - - -### Specifying UAA configuration - -When deploying with SCF, the `scf-config-values.yaml` (see [SCF Wiki link](https://github.com/SUSE/scf/wiki/How-to-Install-SCF#configuring-the-deployment)) can be supplied when installing Stratos. -``` -$ helm install stratos/console -f scf-config-values.yaml -``` - -Alternatively, you can supply the following configuration. Edit according to your environment and save to a file called `uaa-config.yaml`. -``` -uaa: - protocol: https:// - port: 2793 - host: uaa.cf-dev.io - consoleClient: cf - consoleClientSecret: - consoleAdminIdentifier: cloud_controller.admin - skipSSLValidation: false -``` - -To install Stratos with the above specified configuration: -``` -$ helm install stratos/console -f uaa-config.yaml -``` - -### Configuring a local user account - -This allows for deployment without a UAA. To enable the local user account, supply a password for the local user in the deployment command, as follows. All other steps for each deployment method should be followed as in the preceding sections above. - -To deploy using our Helm repository: - -``` -helm install stratos/console --namespace=console --name my-console --set console.localAdminPassword= -``` - -To deploy using an archive file containing a given release of our Helm chart - -``` -helm install console --namespace=console --name my-console --set console.localAdminPassword= -``` - -To deploy using the latest Helm chart directly from out GitHub repository - -``` -$ helm install console --namespace console --name my-console --set console.localAdminPassword= -``` - -For console access via the local user account see: [*Accessing the Console*](#accessing-the-console) - -### Specifying a custom Storage Class - -If no default storage class has been defined in the Kubernetes cluster. The Stratos helm chart will fail to deploy successfully. To check if a `default` storage class exists, you can list your configured storage classes with `kubectl`. If no storage class has `(default)` after it, then you need to either specify a storage class override or declare a default storage class for your Kubernetes cluster. - -#### Providing Storage Class override -``` -$ kubectl get storageclass -NAME TYPE -ssd kubernetes.io/host-path -persistent kubernetes.io/host-path -``` - -For instance to use the storage class `persistent` to deploy Console persistent volume claims, store the following to a file called `override.yaml`. - -``` ---- -storageClass: persistent -``` - -If you want MariaDB to use a specific storage class (which can be different to that used for the other components), then specify the following: -``` ---- -storageClass: persistent -mariadb: - persistence: - storageClass: persistent -``` - -Run Helm with the override: -``` -helm install -f override.yaml stratos/console -``` - -#### Create a default Storage Class -Alternatively, you can configure a storage class with `storageclass.kubernetes.io/is-default-class` set to `true`. For instance the following storage class will be declared as the default. If you don't have the `hostpath` provisioner available in your local cluster, please follow the instructions on [link] (https://github.com/kubernetes-incubator/external-storage/tree/master/docs/demo/hostpath-provisioner), to deploy one. - -If the hostpath provisioner is available, save the file to `storageclass.yaml` - -``` ---- -kind: StorageClass -apiVersion: storage.k8s.io/v1beta1 -metadata: - name: default - annotations: - storageclass.kubernetes.io/is-default-class: "true" -provisioner: kubernetes.io/host-path # Or whatever the local hostpath provisioner is called -``` - -To create it in your kubernetes cluster, execute the following. -``` -kubectl create -f storageclass.yaml -``` - -See [Storage Class documentation] ( https://kubernetes.io/docs/tasks/administer-cluster/change-default-storage-class/) for more insformation. - -### Deploying Stratos with your own TLS certificates - -By default the console will generate self-signed certificates for demo purposes. To configure Stratos UI to use your provided TLS certificates set the `consoleCert` and `consoleCertKey` overrides. - -``` -consoleCert: | - -----BEGIN CERTIFICATE----- - MIIDXTCCAkWgAwIBAgIJAJooOiQWl1v1MA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV - ... - -----END CERTIFICATE----- -consoleCertKey: | - -----BEGIN PRIVATE KEY----- - MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDV9+ySh0xZzM41 - .... - -----END PRIVATE KEY----- -``` -Assuming the above is stored in a file called `override-ssl.yaml`, install the chart with the override specified. -``` -helm install -f override-ssl.yaml stratos/console --namespace console -``` - -### Using with a Secure Image Repository -If you are deploying the helm chart against images that are hosted in a secure image repository provide the following parameters ( store the following to a file called `docker-registry-secrets.yaml`). - - -``` -kube: - registry: - hostname: mysecure-dockerregistry.io - username: john.appleseed - password: sup3rs3cur3 - # `email` is an optional field - email: john.appleseed@foobar.com -``` - -Deploy the chart with the provided parameters: -``` -helm install -f docker-registry-secrets.yaml stratos/console -``` - -### Installing a Nightly Release -Nightly releases are pushed with a `dev` tag. These are strictly for development purposes and should be considered unstable and may contain bugs. - -To install the nightly release: - -Update your Helm repositories to ensure you have the latest nightly release information: - -``` -helm repo update -``` - -List all versions of the console, to determine the tag. -``` -helm search console -l -NAME CHART VERSION DESCRIPTION -stratos/console 2.0.0-dev-9a5611dc A Helm chart for deploying Stratos UI Consoles -stratos/console 1.0.2 A Helm chart for deploying Stratos UI Console -stratos/console 1.0.0 A Helm chart for deploying Stratos UI Console -stratos/console 0.9.9 A Helm chart for deploying Stratos UI Console -stratos/console 0.9.8 A Helm chart for deploying Stratos UI Console - -``` -Install +You will need to have both the `kubectl` and `helm` CLIs installed and available on your path. It should be appropriately configured to be able to communicate with your Kubernetes environment. -``` -helm install stratos/console --namespace=console --name my-console --version 2.0.0-dev-9a5611dc -``` +The Stratos Helm chart contains a `README.md` file that contains installation instructions and configuration documentation. +This document is also available in our GitHub repository here: [README.md](https://github.com/cloudfoundry/stratos/blob/master/deploy/kubernetes/console/README.md). diff --git a/deploy/stratos-ui-release/packages/backend/pre_packaging b/deploy/stratos-ui-release/packages/backend/pre_packaging index 99faea2123..ba252553a7 100644 --- a/deploy/stratos-ui-release/packages/backend/pre_packaging +++ b/deploy/stratos-ui-release/packages/backend/pre_packaging @@ -10,7 +10,6 @@ curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh # Build backend npm install -npm run customize export PATH=$PATH:$PWD/node_modules/.bin npm run bosh-build-backend diff --git a/deploy/stratos-ui-release/packages/frontend/pre_packaging b/deploy/stratos-ui-release/packages/frontend/pre_packaging index c2c28d2215..440e323fa2 100644 --- a/deploy/stratos-ui-release/packages/frontend/pre_packaging +++ b/deploy/stratos-ui-release/packages/frontend/pre_packaging @@ -4,7 +4,6 @@ set -e -x cd ${BUILD_DIR}/stratos npm install -npm run customize export PATH=$PATH:$PWD/node_modules/.bin npm run build diff --git a/docs/customizing.md b/docs/customizing.md index 496b7fddb6..e81f9ebabd 100644 --- a/docs/customizing.md +++ b/docs/customizing.md @@ -8,11 +8,44 @@ Stratos provides a mechanism for customization - the following customizations ar - Adding new functionality - Changing the initial loading indicator +# Migrating to Stratos V4 Customization +In V4 there are breaking customization changes. These changes allow a much improved approach to extensions by opening the door to npm style plugins. +To aid in migrating we've provided these instructions. + +1) Before updating to the latest code... + 1) Run `npm run customize-reset` to remove all previously created sym links. + 2) Read through the customization documentation below to get a better understanding of the new process. +1) Update your codebase with the desired v4 code. +1) Run `npm install` (only required first time, this will ensure you have the required version of Angular). +1) Change directory to `./build/tools/v4-migration` and run the migration script `./migrate.sh`. + - This will copy your customizations from `custom-src` to a new Angular package `src/frontend/packages/custom_extensions`. +1) Check that the new package exports your custom module and if applicable your custom-routing module. + - The migrate script should do this in `src/frontend/packages/custom_extensions/src/public-api.ts`. +1) Check that your ts config file defines the public api file. + - `src/tsconfig.json` file's `compilerOptions/paths` section should contain something like `"@custom/extensions": ["frontend/packages/custom_extensions/src/public-api.ts"]`. +1) Check that your new package's package.json defines your custom module and if application custom-routing module. + - See `src/frontend/packages/suse_extensions/package.json` file's `stratos` section. + - Note your `routingModule` entry label should not have a preceding `_`. +1) Build Stratos in your usual way, for instance `npm run build`. + - It could be that this fails due to TypeScript import issues, if so go through these and fix. + - During build time the custom packages will be discovered and output, see section starting `Building with these extensions`. These should contain the modules your require. +1) Run Stratos your usual way. Ensure you can navigate to all your custom parts. +1) Once you are happy everything works as intended remove the old `./custom-src` directory and commit you changes. + ## Approach In order to customize Stratos, you will need to fork the Stratos GitHub repository and apply customizations in your fork. Our aim is to minimize any merge conflicts that might occur when re-basing your fork with the upstream Stratos repository. -All customizations are placed within a top-level folder named `custom-src`. This folder should only exist in forks and will not exist in the main Stratos repository, so any changes made within this folder should be free from merge conflicts. + +Customizations are placed in angular packages in the folder named `src/frontend/packages`. In the future you will be able to host these packages in npm and bring them into Stratos in the usual npm dependency way. + +Each package should contain custom Stratos configuration in it's package.json pointing to the modules it will be required to import. + +stratos.yaml +custom theme +custom styles +custom assets + The Stratos approach to customization uses symbolic links. We maintain a default set of resources in the folder `src/misc/custom`. When you run `npm install` or when you explicitly run `npm run customize`, a gulp task (in the file `build/fe-build.js`) runs and creates symbolic links, linking the required files to their expected locations withing the `src` folder. diff --git a/package-lock.json b/package-lock.json index 200d6f47de..eec8e18f4e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,20 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@angular-builders/custom-webpack": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/@angular-builders/custom-webpack/-/custom-webpack-9.2.0.tgz", + "integrity": "sha512-0ivkjENONFm0oNy6hdCod4YaT4dUk80KuP9+eDliWuZIA70yKQgIYMLul0bz6/i+Cm24PaZ2tq4w7kW7AuSMoA==", + "dev": true, + "requires": { + "@angular-devkit/architect": ">=0.900.0 < 0.1000.0", + "@angular-devkit/build-angular": ">=0.900.0 < 0.1000.0", + "@angular-devkit/core": "^9.0.0", + "lodash": "^4.17.10", + "ts-node": "^8.5.2", + "webpack-merge": "^4.2.1" + } + }, "@angular-devkit/architect": { "version": "0.901.7", "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.901.7.tgz", @@ -618,6 +632,17 @@ "resolved": "https://registry.npmjs.org/@angular/router/-/router-9.1.9.tgz", "integrity": "sha512-4u+CWMPB4hCkAsFCEzC94YEWT0wVozqGkc/Dortt2hFaqvZpIegg6iJVZlDxuyDjzFYBPnnbTDdgiTTA8ckfuA==" }, + "@apidevtools/json-schema-ref-parser": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.1.tgz", + "integrity": "sha512-Qsdz0W0dyK84BuBh5KZATWXOtVDXIF2EeNRzpyWblPUeAmnIokwWcwrpAm5pTPMjuWoIQt9C67X3Af1OlL6oSw==", + "dev": true, + "requires": { + "@jsdevtools/ono": "^7.1.2", + "call-me-maybe": "^1.0.1", + "js-yaml": "^3.13.1" + } + }, "@babel/code-frame": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", @@ -2912,6 +2937,12 @@ } } }, + "@jsdevtools/ono": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.2.tgz", + "integrity": "sha512-qS/a24RA5FEoiJS9wiv6Pwg2c/kiUo3IVUQcfeM9JvsR6pM8Yx+yl/6xWYLckZCT5jpLNhslgjiA8p/XcGyMRQ==", + "dev": true + }, "@ngrx/effects": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/@ngrx/effects/-/effects-9.2.0.tgz", @@ -3944,6 +3975,12 @@ "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", "dev": true }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", + "dev": true + }, "anymatch": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", @@ -5250,6 +5287,12 @@ } } }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", + "dev": true + }, "caller-callsite": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", @@ -5465,6 +5508,20 @@ "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==", "dev": true }, + "cli-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.0.tgz", + "integrity": "sha512-a0VZ8LeraW0jTuCkuAGMNufareGHhyZU9z8OGsW0gXd1hZGi1SRuNRXdbGkraBBKnhyUhyebFWnRbp+dIn0f0A==", + "dev": true, + "requires": { + "ansi-regex": "^2.1.1", + "d": "^1.0.1", + "es5-ext": "^0.10.51", + "es6-iterator": "^2.0.3", + "memoizee": "^0.4.14", + "timers-ext": "^0.1.7" + } + }, "cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -7113,7 +7170,7 @@ }, "duplexer": { "version": "0.1.1", - "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", "dev": true }, @@ -7816,7 +7873,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { @@ -8760,7 +8817,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": true, "optional": true }, "function-bind": { @@ -10388,6 +10444,12 @@ "isobject": "^3.0.1" } }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + }, "is-property": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", @@ -11022,6 +11084,43 @@ "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", "dev": true }, + "json-schema-ref-parser": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-9.0.1.tgz", + "integrity": "sha512-KLrCjRjW5hMXxsX4osVBWpwixXL9NtICfpyNNS0eHguN5mP/I4UatI7i7PFS8jU94b1NHF4EbirACdCn0RFPBA==", + "dev": true, + "requires": { + "@apidevtools/json-schema-ref-parser": "9.0.1" + } + }, + "json-schema-to-typescript": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/json-schema-to-typescript/-/json-schema-to-typescript-9.1.0.tgz", + "integrity": "sha512-9/yDXQQyqtRDxohQGRCKht4Wjfg73TALi1yzy651EOo71a6aKFtIm2WUbDWSf8OitFGukUn00dx4t1kg0W6O4Q==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.4", + "cli-color": "^2.0.0", + "glob": "^7.1.6", + "is-glob": "^4.0.1", + "json-schema-ref-parser": "^9.0.1", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.15", + "minimist": "^1.2.5", + "mkdirp": "^1.0.4", + "mz": "^2.7.0", + "prettier": "^2.0.5", + "stdin": "0.0.1" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + } + } + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -11248,13 +11347,6 @@ "path-exists": "^4.0.0" } }, - "fsevents": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", - "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", - "dev": true, - "optional": true - }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -12017,6 +12109,15 @@ } } }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "dev": true, + "requires": { + "es5-ext": "~0.10.2" + } + }, "magic-string": { "version": "0.25.7", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", @@ -12140,7 +12241,7 @@ }, "map-stream": { "version": "0.1.0", - "resolved": "http://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", "dev": true }, @@ -12219,12 +12320,6 @@ "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", "dev": true }, - "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "optional": true - }, "glob-parent": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", @@ -12331,6 +12426,22 @@ } } }, + "memoizee": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", + "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.45", + "es6-weak-map": "^2.0.2", + "event-emitter": "^0.3.5", + "is-promise": "^2.1", + "lru-queue": "0.1", + "next-tick": "1", + "timers-ext": "^0.1.5" + } + }, "memory-fs": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", @@ -12854,6 +12965,17 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -14933,7 +15055,7 @@ }, "pause-stream": { "version": "0.0.11", - "resolved": "http://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", "dev": true, "requires": { @@ -15802,6 +15924,12 @@ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" }, + "prettier": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz", + "integrity": "sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==", + "dev": true + }, "pretty-hrtime": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", @@ -18516,7 +18644,7 @@ }, "split": { "version": "0.3.3", - "resolved": "http://registry.npmjs.org/split/-/split-0.3.3.tgz", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", "dev": true, "requires": { @@ -18628,6 +18756,12 @@ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", "dev": true }, + "stdin": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/stdin/-/stdin-0.0.1.tgz", + "integrity": "sha1-0wQZgarsPf28d6GzjWNy449ftx4=", + "dev": true + }, "stealthy-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", @@ -18693,7 +18827,7 @@ }, "stream-combiner": { "version": "0.0.4", - "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", "dev": true, "requires": { @@ -19604,6 +19738,24 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "requires": { + "any-promise": "^1.0.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", + "dev": true, + "requires": { + "thenify": ">= 3.1.0 < 4" + } + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -19651,6 +19803,16 @@ "setimmediate": "^1.0.4" } }, + "timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "dev": true, + "requires": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, "timsort": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", @@ -20657,13 +20819,6 @@ "to-regex-range": "^5.0.1" } }, - "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": true, - "optional": true - }, "glob-parent": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", @@ -20793,13 +20948,6 @@ "to-regex": "^3.0.1" } }, - "fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "dev": true, - "optional": true - }, "readdirp": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", @@ -20844,6 +20992,13 @@ "to-regex-range": "^2.1.0" } }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true + }, "is-binary-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", diff --git a/package.json b/package.json index 8e5d3381a3..17dd16aca8 100644 --- a/package.json +++ b/package.json @@ -14,12 +14,12 @@ "build": "node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng build --prod", "build-cf": "node --max_old_space_size=1500 --gc_interval=100 node_modules/@angular/cli/bin/ng build --prod", "build-dev": "ng build --dev", - "prebuild-ui": "npm run customize && npm run build && gulp package-prebuild", + "prebuild-ui": "npm run build && gulp package-prebuild", "ng": "ng", - "start": "npm run customize && ng serve", - "start-high-mem": "npm run customize && node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng serve", - "start-dev-high-mem": "npm run customize && node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng serve --aot=false", - "start-prod-high-mem": "npm run customize && node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng serve --prod", + "start": "ng serve", + "start-high-mem": "node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng serve", + "start-dev-high-mem": "node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng serve --aot=false", + "start-prod-high-mem": "node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng serve --prod", "start-dev": "ng serve --aot=false", "test-clean": "./build/clean-test-reports.sh", "test-reports": "./build/show-test-reports.sh", @@ -38,11 +38,9 @@ "headless-e2e": "xvfb-run --server-args='-screen 0 1920x1080x24' protractor ./protractor.conf.js", "climate": "codeclimate analyze $(git diff --name-only master)", "gate-check": "npm run lint && npm run test-headless", - "customize": "gulp customize", - "customize-default": "gulp customize-default", - "customize-reset": "gulp customize-reset", "store-git-metadata": "gulp store-git-metadata", - "postinstall": "npm run customize && gulp dev-setup" + "postinstall": "gulp dev-setup && npm run build-devkit", + "build-devkit": "cd src/frontend/packages/devkit && npm run build" }, "author": "", "license": "Apache-2.0", @@ -96,12 +94,16 @@ "node": "12.13.0" }, "devDependencies": { + "@angular-builders/custom-webpack": "^9.1.0", + "@angular-devkit/architect": "^0.901.7", "@angular-devkit/build-angular": "~0.901.5", "@angular-devkit/build-ng-packagr": "~0.901.5", + "@angular-devkit/core": "^9.1.7", "@angular-devkit/schematics": "^9.1.5", "@angular/cli": "^9.1.5", "@angular/compiler-cli": "^9.1.6", "@angular/language-service": "^9.1.6", + "@schematics/angular": "^9.1.5", "@types/jasmine": "^3.5.10", "@types/jasminewd2": "~2.0.8", "@types/karma": "^5.0.0", @@ -111,6 +113,7 @@ "browserstack-local": "^1.4.5", "codecov": "^3.6.5", "codelyzer": "^5.1.2", + "copy-webpack-plugin": "5.1.1", "delete": "^1.1.0", "fs-extra": "^9.0.0", "globby": "^11.0.0", @@ -122,6 +125,7 @@ "jasmine-core": "~3.5.0", "jasmine-spec-reporter": "~5.0.1", "js-yaml": "~3.13.1", + "json-schema-to-typescript": "^9.1.0", "karma": "~5.0.1", "karma-chrome-launcher": "~3.1.0", "karma-cli": "~2.0.0", diff --git a/src/frontend/packages/cf-autoscaler/src/cf-autoscaler.module.ts b/src/frontend/packages/cf-autoscaler/src/cf-autoscaler.module.ts index e7463eee23..e470be161e 100644 --- a/src/frontend/packages/cf-autoscaler/src/cf-autoscaler.module.ts +++ b/src/frontend/packages/cf-autoscaler/src/cf-autoscaler.module.ts @@ -52,7 +52,6 @@ const customRoutes: Routes = [ ], declarations: [ AutoscalerTabExtensionComponent - ], - entryComponents: [AutoscalerTabExtensionComponent] + ] }) export class CfAutoscalerModule { } diff --git a/src/frontend/packages/cf-autoscaler/src/core/autoscaler.module.ts b/src/frontend/packages/cf-autoscaler/src/core/autoscaler.module.ts index 2faabe86af..cb76b829f2 100644 --- a/src/frontend/packages/cf-autoscaler/src/core/autoscaler.module.ts +++ b/src/frontend/packages/cf-autoscaler/src/core/autoscaler.module.ts @@ -83,13 +83,6 @@ import { AutoscalerRoutingModule } from './autoscaler.routing'; ], providers: [ ApplicationService - ], - entryComponents: [ - AppAutoscalerMetricChartCardComponent, - AppAutoscalerComboChartComponent, - AppAutoscalerComboSeriesVerticalComponent, - TableCellAutoscalerEventChangeComponent, - TableCellAutoscalerEventStatusComponent ] }) export class AutoscalerModule { } diff --git a/src/frontend/packages/cf-autoscaler/src/features/autoscaler-tab-extension/autoscaler-tab-extension.component.spec.ts b/src/frontend/packages/cf-autoscaler/src/features/autoscaler-tab-extension/autoscaler-tab-extension.component.spec.ts index eff100853b..b96d66bdb5 100644 --- a/src/frontend/packages/cf-autoscaler/src/features/autoscaler-tab-extension/autoscaler-tab-extension.component.spec.ts +++ b/src/frontend/packages/cf-autoscaler/src/features/autoscaler-tab-extension/autoscaler-tab-extension.component.spec.ts @@ -15,6 +15,9 @@ import { import { RunningInstancesComponent, } from '../../../../cloud-foundry/src/shared/components/running-instances/running-instances.component'; +import { + cfCurrentUserPermissionsService, +} from '../../../../cloud-foundry/src/user-permissions/cf-user-permissions-checkers'; import { ApplicationServiceMock } from '../../../../cloud-foundry/test-framework/application-service-helper'; import { CoreModule } from '../../../../core/src/core/core.module'; import { SharedModule } from '../../../../core/src/shared/shared.module'; @@ -48,7 +51,8 @@ describe('AutoscalerTabExtensionComponent', () => { providers: [ DatePipe, { provide: ApplicationService, useClass: ApplicationServiceMock }, - TabNavService + TabNavService, + ...cfCurrentUserPermissionsService ] }) .compileComponents(); diff --git a/src/frontend/packages/cf-autoscaler/src/features/autoscaler-tab-extension/autoscaler-tab-extension.component.ts b/src/frontend/packages/cf-autoscaler/src/features/autoscaler-tab-extension/autoscaler-tab-extension.component.ts index dfee79bace..9b3b56c9b2 100644 --- a/src/frontend/packages/cf-autoscaler/src/features/autoscaler-tab-extension/autoscaler-tab-extension.component.ts +++ b/src/frontend/packages/cf-autoscaler/src/features/autoscaler-tab-extension/autoscaler-tab-extension.component.ts @@ -2,15 +2,25 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { MatSnackBar, MatSnackBarRef, SimpleSnackBar } from '@angular/material/snack-bar'; import { ActivatedRoute } from '@angular/router'; import { Store } from '@ngrx/store'; -import { combineLatest, Observable, Subscription } from 'rxjs'; -import { distinctUntilChanged, filter, first, map, pairwise, publishReplay, refCount } from 'rxjs/operators'; +import { combineLatest, Observable, of, Subscription } from 'rxjs'; +import { distinctUntilChanged, filter, first, map, pairwise, publishReplay, refCount, switchMap } from 'rxjs/operators'; -import { applicationEntityType } from '../../../../cloud-foundry/src/cf-entity-types'; -import { createEntityRelationPaginationKey } from '../../../../cloud-foundry/src/entity-relations/entity-relations.types'; +import { cfEntityCatalog } from '../../../../cloud-foundry/src/cf-entity-catalog'; +import { + applicationEntityType, + organizationEntityType, + spaceEntityType, +} from '../../../../cloud-foundry/src/cf-entity-types'; +import { + createEntityRelationKey, + createEntityRelationPaginationKey, +} from '../../../../cloud-foundry/src/entity-relations/entity-relations.types'; import { ApplicationMonitorService } from '../../../../cloud-foundry/src/features/applications/application-monitor.service'; import { ApplicationService } from '../../../../cloud-foundry/src/features/applications/application.service'; import { getGuids } from '../../../../cloud-foundry/src/features/applications/application/application-base.component'; +import { CfCurrentUserPermissions } from '../../../../cloud-foundry/src/user-permissions/cf-user-permissions-checkers'; import { StratosTab, StratosTabType } from '../../../../core/src/core/extension/extension-service'; +import { CurrentUserPermissionsService } from '../../../../core/src/core/permissions/current-user-permissions.service'; import { safeUnsubscribe } from '../../../../core/src/core/utils.service'; import { ConfirmationDialogConfig } from '../../../../core/src/shared/components/confirmation-dialog.config'; import { ConfirmationDialogService } from '../../../../core/src/shared/components/confirmation-dialog.service'; @@ -52,9 +62,32 @@ import { appAutoscalerAppMetricEntityType, autoscalerEntityFactory } from '../.. link: 'autoscale', icon: 'meter', iconFont: 'stratos-icons', - hidden: (store: Store, esf: EntityServiceFactory, activatedRoute: ActivatedRoute) => { + hidden: (store: Store, esf: EntityServiceFactory, activatedRoute: ActivatedRoute, cups: CurrentUserPermissionsService) => { const endpointGuid = getGuids('cf')(activatedRoute) || window.location.pathname.split('/')[2]; - return isAutoscalerEnabled(endpointGuid, esf).pipe(map(enabled => !enabled)); + const appGuid = getGuids()(activatedRoute) || window.location.pathname.split('/')[3]; + const appEntService = cfEntityCatalog.application.store.getEntityService(appGuid, endpointGuid, { + includeRelations: [ + createEntityRelationKey(applicationEntityType, spaceEntityType), + createEntityRelationKey(spaceEntityType, organizationEntityType), + ], + populateMissing: true + }) + + const canEditApp$ = appEntService.waitForEntity$.pipe( + switchMap(app => cups.can( + CfCurrentUserPermissions.APPLICATION_EDIT, + endpointGuid, + app.entity.entity.space.entity.organization_guid, + app.entity.entity.space.metadata.guid + )), + ) + + const autoscalerEnabled = isAutoscalerEnabled(endpointGuid, esf); + + return canEditApp$.pipe( + switchMap(canEditSpace => canEditSpace ? autoscalerEnabled : of(false)), + map(can => !can) + ) } }) @Component({ @@ -130,7 +163,7 @@ export class AutoscalerTabExtensionComponent implements OnInit, OnDestroy { private paginationMonitorFactory: PaginationMonitorFactory, private appAutoscalerPolicySnackBar: MatSnackBar, private appAutoscalerScalingHistorySnackBar: MatSnackBar, - private confirmDialog: ConfirmationDialogService, + private confirmDialog: ConfirmationDialogService ) { } ngOnInit() { diff --git a/src/frontend/packages/cf-autoscaler/src/shared/list-types/app-autoscaler-event/cf-app-autoscaler-events-config.service.spec.ts b/src/frontend/packages/cf-autoscaler/src/shared/list-types/app-autoscaler-event/cf-app-autoscaler-events-config.service.spec.ts index 56fe3b5865..fcfbc0bf81 100644 --- a/src/frontend/packages/cf-autoscaler/src/shared/list-types/app-autoscaler-event/cf-app-autoscaler-events-config.service.spec.ts +++ b/src/frontend/packages/cf-autoscaler/src/shared/list-types/app-autoscaler-event/cf-app-autoscaler-events-config.service.spec.ts @@ -5,9 +5,6 @@ import { inject, TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { createEmptyStoreModule } from '@stratosui/store/testing'; -import { GetApplication } from '../../../../../cloud-foundry/src/actions/application.actions'; -import { cfEntityFactory } from '../../../../../cloud-foundry/src/cf-entity-factory'; -import { applicationEntityType } from '../../../../../cloud-foundry/src/cf-entity-types'; import { ApplicationsModule } from '../../../../../cloud-foundry/src/features/applications/applications.module'; import { generateTestApplicationServiceProvider, @@ -15,7 +12,6 @@ import { import { CoreModule } from '../../../../../core/src/core/core.module'; import { SharedModule } from '../../../../../core/src/shared/shared.module'; import { AppTestModule } from '../../../../../core/test-framework/core-test.helper'; -import { generateTestEntityServiceProvider } from '../../../../../core/test-framework/entity-service.helper'; import { EntityCatalogHelper } from '../../../../../store/src/entity-catalog/entity-catalog-entity/entity-catalog.service'; import { EntityServiceFactory } from '../../../../../store/src/entity-service-factory.service'; import { EntityMonitorFactory } from '../../../../../store/src/monitors/entity-monitor.factory.service'; @@ -35,11 +31,6 @@ describe('CfAppAutoscalerEventsConfigService', () => { EntityServiceFactory, EntityMonitorFactory, EntityCatalogHelper, - generateTestEntityServiceProvider( - appGuid, - cfEntityFactory(applicationEntityType), - new GetApplication(appGuid, cfGuid) - ), generateTestApplicationServiceProvider(appGuid, cfGuid), HttpClient, ], diff --git a/src/frontend/packages/cf-autoscaler/src/shared/list-types/app-autoscaler-event/cf-app-autoscaler-events-config.service.ts b/src/frontend/packages/cf-autoscaler/src/shared/list-types/app-autoscaler-event/cf-app-autoscaler-events-config.service.ts index 98d5b15a48..8732d20bfb 100644 --- a/src/frontend/packages/cf-autoscaler/src/shared/list-types/app-autoscaler-event/cf-app-autoscaler-events-config.service.ts +++ b/src/frontend/packages/cf-autoscaler/src/shared/list-types/app-autoscaler-event/cf-app-autoscaler-events-config.service.ts @@ -8,8 +8,9 @@ import { ApplicationService } from '../../../../../cloud-foundry/src/features/ap import { ITableColumn } from '../../../../../core/src/shared/components/list/list-table/table.types'; import { IListConfig, ListConfig, ListViewTypes } from '../../../../../core/src/shared/components/list/list.component.types'; import { MetricsRangeSelectorService } from '../../../../../core/src/shared/services/metrics-range-selector.service'; -import { ITimeRange, MetricQueryType } from '../../../../../core/src/shared/services/metrics-range-selector.types'; +import { ITimeRange } from '../../../../../core/src/shared/services/metrics-range-selector.types'; import { APIResource } from '../../../../../store/src/types/api.types'; +import { MetricQueryType } from '../../../../../store/src/types/metric.types'; import { AppAutoscalerEvent } from '../../../store/app-autoscaler.types'; import { CfAppAutoscalerEventsDataSource } from './cf-app-autoscaler-events-data-source'; import { diff --git a/src/frontend/packages/cf-autoscaler/src/shared/list-types/app-autoscaler-metric-chart/app-autoscaler-metric-chart-list-config.service.ts b/src/frontend/packages/cf-autoscaler/src/shared/list-types/app-autoscaler-metric-chart/app-autoscaler-metric-chart-list-config.service.ts index 05e19cc82a..a5c3fd8aef 100644 --- a/src/frontend/packages/cf-autoscaler/src/shared/list-types/app-autoscaler-metric-chart/app-autoscaler-metric-chart-list-config.service.ts +++ b/src/frontend/packages/cf-autoscaler/src/shared/list-types/app-autoscaler-metric-chart/app-autoscaler-metric-chart-list-config.service.ts @@ -10,9 +10,10 @@ import { import { ITableColumn } from '../../../../../core/src/shared/components/list/list-table/table.types'; import { ListViewTypes } from '../../../../../core/src/shared/components/list/list.component.types'; import { MetricsRangeSelectorService } from '../../../../../core/src/shared/services/metrics-range-selector.service'; -import { ITimeRange, MetricQueryType } from '../../../../../core/src/shared/services/metrics-range-selector.types'; +import { ITimeRange } from '../../../../../core/src/shared/services/metrics-range-selector.types'; import { ListView } from '../../../../../store/src/actions/list.actions'; import { APIResource } from '../../../../../store/src/types/api.types'; +import { MetricQueryType } from '../../../../../store/src/types/metric.types'; import { AutoscalerConstants } from '../../../core/autoscaler-helpers/autoscaler-util'; import { AppScalingTrigger } from '../../../store/app-autoscaler.types'; import { diff --git a/src/frontend/packages/cf-autoscaler/src/store/autoscaler-entity-factory.ts b/src/frontend/packages/cf-autoscaler/src/store/autoscaler-entity-factory.ts index ecdddc9b8c..13c1ff8089 100644 --- a/src/frontend/packages/cf-autoscaler/src/store/autoscaler-entity-factory.ts +++ b/src/frontend/packages/cf-autoscaler/src/store/autoscaler-entity-factory.ts @@ -1,8 +1,8 @@ import { Schema, schema } from 'normalizr'; import { getAPIResourceGuid } from '../../../cloud-foundry/src/store/selectors/api.selectors'; -import { metricEntityType } from '../../../core/src/base-entity-schemas'; import { EntitySchema } from '../../../store/src/helpers/entity-schema'; +import { metricEntityType } from '../../../store/src/helpers/stratos-entity-factory'; export const appAutoscalerInfoEntityType = 'autoscalerInfo'; export const appAutoscalerHealthEntityType = 'autoscalerHealth'; @@ -10,7 +10,7 @@ export const appAutoscalerPolicyEntityType = 'autoscalerPolicy'; export const appAutoscalerPolicyTriggerEntityType = 'autoscalerPolicyTrigger'; export const appAutoscalerScalingHistoryEntityType = 'autoscalerScalingHistory'; export const appAutoscalerAppMetricEntityType = 'autoscalerAppMetric'; -export const appAutoscalerCredentialEntityType = 'autoscalerCredential' +export const appAutoscalerCredentialEntityType = 'autoscalerCredential'; export const AUTOSCALER_ENDPOINT_TYPE = 'autoscaler'; diff --git a/src/frontend/packages/cf-autoscaler/src/store/autoscaler-entity-generator.ts b/src/frontend/packages/cf-autoscaler/src/store/autoscaler-entity-generator.ts index 9e946fca20..4e71099074 100644 --- a/src/frontend/packages/cf-autoscaler/src/store/autoscaler-entity-generator.ts +++ b/src/frontend/packages/cf-autoscaler/src/store/autoscaler-entity-generator.ts @@ -1,10 +1,10 @@ import { IOrgFavMetadata } from '../../../cloud-foundry/src/cf-metadata-types'; -import { metricEntityType } from '../../../core/src/base-entity-schemas'; import { StratosBaseCatalogEntity, StratosCatalogEntity, } from '../../../store/src/entity-catalog/entity-catalog-entity/entity-catalog-entity'; import { IStratosEndpointDefinition } from '../../../store/src/entity-catalog/entity-catalog.types'; +import { metricEntityType } from '../../../store/src/helpers/stratos-entity-factory'; import { APIResource } from '../../../store/src/types/api.types'; import { IFavoriteMetadata } from '../../../store/src/types/user-favorites.types'; import { AppAutoscalerEvent, AppAutoscalerHealth, AppAutoscalerPolicy, AppScalingTrigger } from './app-autoscaler.types'; diff --git a/src/frontend/packages/cf-autoscaler/src/store/autoscaler.effects.ts b/src/frontend/packages/cf-autoscaler/src/store/autoscaler.effects.ts index e85527a5cd..98c2e1e7c1 100644 --- a/src/frontend/packages/cf-autoscaler/src/store/autoscaler.effects.ts +++ b/src/frontend/packages/cf-autoscaler/src/store/autoscaler.effects.ts @@ -7,9 +7,9 @@ import { catchError, mergeMap, withLatestFrom } from 'rxjs/operators'; import { PaginationResponse } from '../../../cloud-foundry/src/store/types/cf-api.types'; import { environment } from '../../../core/src/environments/environment'; -import { isHttpErrorResponse } from '../../../core/src/jetstream.helpers'; import { AppState } from '../../../store/src/app-state'; import { entityCatalog } from '../../../store/src/entity-catalog/entity-catalog'; +import { isHttpErrorResponse } from '../../../store/src/jetstream'; import { ApiRequestTypes } from '../../../store/src/reducers/api-request-reducer/request-helpers'; import { resultPerPageParam, diff --git a/src/frontend/packages/cloud-foundry/package.json b/src/frontend/packages/cloud-foundry/package.json index 989436cb0d..844bc32e3a 100644 --- a/src/frontend/packages/cloud-foundry/package.json +++ b/src/frontend/packages/cloud-foundry/package.json @@ -4,5 +4,9 @@ "peerDependencies": { "@angular/common": "^6.0.0-rc.0 || ^6.0.0", "@angular/core": "^6.0.0-rc.0 || ^6.0.0" + }, + "stratos": { + "theming": "sass/_all-theme#apply-theme-stratos-cloud-foundry" } + } \ No newline at end of file diff --git a/src/frontend/packages/cloud-foundry/sass/_all-theme.scss b/src/frontend/packages/cloud-foundry/sass/_all-theme.scss new file mode 100644 index 0000000000..fd92ae1354 --- /dev/null +++ b/src/frontend/packages/cloud-foundry/sass/_all-theme.scss @@ -0,0 +1,12 @@ +// Theming for the copmponents in the Cloud Foundry package + +@import '../src/features/applications/application-wall/application-wall.component.theme'; +@import '../src/shared/components/list/list-types/cf-security-groups/cf-security-groups-card/cf-security-groups-card.component.theme'; + +@mixin apply-theme-stratos-cloud-foundry($stratos-theme) { + + $theme: map-get($stratos-theme, theme); + $app-theme: map-get($stratos-theme, app-theme); + + @include cf-security-group-theme($theme); +} diff --git a/src/frontend/packages/cloud-foundry/src/actions/cf-event.actions.ts b/src/frontend/packages/cloud-foundry/src/actions/cf-event.actions.ts index ad2daf059f..c6bb0e3aff 100644 --- a/src/frontend/packages/cloud-foundry/src/actions/cf-event.actions.ts +++ b/src/frontend/packages/cloud-foundry/src/actions/cf-event.actions.ts @@ -1,6 +1,6 @@ import { HttpParams, HttpRequest } from '@angular/common/http'; -import { endpointSchemaKey } from '../../../store/src/helpers/entity-factory'; +import { endpointEntityType } from '../../../store/src/helpers/stratos-entity-factory'; import { PaginatedAction } from '../../../store/src/types/pagination.types'; import { cfEntityFactory } from '../cf-entity-factory'; import { cfEventEntityType } from '../cf-entity-types'; @@ -18,7 +18,7 @@ export class GetAllCfEvents extends CFStartAction implements PaginatedAction { constructor(public paginationKey: string, public endpointGuid) { super(); - this.paginationKey = this.paginationKey || createEntityRelationPaginationKey(endpointSchemaKey, endpointGuid); + this.paginationKey = this.paginationKey || createEntityRelationPaginationKey(endpointEntityType, endpointGuid); this.options = new HttpRequest( 'GET', 'events', diff --git a/src/frontend/packages/cloud-foundry/src/actions/cf-metrics.actions.ts b/src/frontend/packages/cloud-foundry/src/actions/cf-metrics.actions.ts index 4422c703f6..e57065e7f0 100644 --- a/src/frontend/packages/cloud-foundry/src/actions/cf-metrics.actions.ts +++ b/src/frontend/packages/cloud-foundry/src/actions/cf-metrics.actions.ts @@ -1,5 +1,5 @@ -import { MetricQueryType } from '../../../core/src/shared/services/metrics-range-selector.types'; import { MetricQueryConfig, MetricsAction, MetricsChartAction } from '../../../store/src/actions/metrics.actions'; +import { MetricQueryType } from '../../../store/src/types/metric.types'; import { PaginatedAction } from '../../../store/src/types/pagination.types'; import { CF_ENDPOINT_TYPE } from '../cf-types'; diff --git a/src/frontend/packages/cloud-foundry/src/actions/domains.actions.ts b/src/frontend/packages/cloud-foundry/src/actions/domains.actions.ts index 13d4f6d59b..d593428b5f 100644 --- a/src/frontend/packages/cloud-foundry/src/actions/domains.actions.ts +++ b/src/frontend/packages/cloud-foundry/src/actions/domains.actions.ts @@ -1,6 +1,6 @@ import { HttpRequest } from '@angular/common/http'; -import { endpointSchemaKey } from '../../../store/src/helpers/entity-factory'; +import { endpointEntityType } from '../../../store/src/helpers/stratos-entity-factory'; import { PaginatedAction } from '../../../store/src/types/pagination.types'; import { ICFAction } from '../../../store/src/types/request.types'; import { cfEntityFactory } from '../cf-entity-factory'; @@ -36,7 +36,7 @@ export class FetchAllDomains extends CFStartAction implements PaginatedAction { 'GET', 'domains', ); - this.paginationKey = this.paginationKey || createEntityRelationPaginationKey(endpointSchemaKey, endpointGuid); + this.paginationKey = this.paginationKey || createEntityRelationPaginationKey(endpointEntityType, endpointGuid); } actions = [GET_ALL_DOMAIN, GET_ALL_DOMAIN_SUCCESS, GET_ALL_DOMAIN_FAILED]; entity = [cfEntityFactory(domainEntityType)]; diff --git a/src/frontend/packages/cloud-foundry/src/actions/feature-flags.actions.ts b/src/frontend/packages/cloud-foundry/src/actions/feature-flags.actions.ts index 6ec461e70b..5c1967a0c1 100644 --- a/src/frontend/packages/cloud-foundry/src/actions/feature-flags.actions.ts +++ b/src/frontend/packages/cloud-foundry/src/actions/feature-flags.actions.ts @@ -1,7 +1,7 @@ import { HttpRequest } from '@angular/common/http'; import { getActions } from '../../../store/src/actions/action.helper'; -import { endpointSchemaKey } from '../../../store/src/helpers/entity-factory'; +import { endpointEntityType } from '../../../store/src/helpers/stratos-entity-factory'; import { PaginatedAction } from '../../../store/src/types/pagination.types'; import { RequestEntityLocation } from '../../../store/src/types/request.types'; import { cfEntityFactory } from '../cf-entity-factory'; @@ -12,7 +12,7 @@ import { CFStartAction } from './cf-action.types'; export class GetAllFeatureFlags extends CFStartAction implements PaginatedAction { constructor(public endpointGuid: string, public paginationKey: string = null) { super(); - this.paginationKey = this.paginationKey || createEntityRelationPaginationKey(endpointSchemaKey, this.endpointGuid); + this.paginationKey = this.paginationKey || createEntityRelationPaginationKey(endpointEntityType, this.endpointGuid); this.options = new HttpRequest( 'GET', `config/feature_flags` diff --git a/src/frontend/packages/cloud-foundry/src/actions/stack.action.ts b/src/frontend/packages/cloud-foundry/src/actions/stack.action.ts index b4a274ee38..ac77391430 100644 --- a/src/frontend/packages/cloud-foundry/src/actions/stack.action.ts +++ b/src/frontend/packages/cloud-foundry/src/actions/stack.action.ts @@ -2,7 +2,7 @@ import { HttpRequest } from '@angular/common/http'; import { getActions } from '../../../store/src/actions/action.helper'; import { entityCatalog } from '../../../store/src/entity-catalog/entity-catalog'; -import { endpointSchemaKey } from '../../../store/src/helpers/entity-factory'; +import { endpointEntityType } from '../../../store/src/helpers/stratos-entity-factory'; import { PaginatedAction } from '../../../store/src/types/pagination.types'; import { ICFAction } from '../../../store/src/types/request.types'; import { stackEntityType } from '../cf-entity-types'; @@ -38,7 +38,7 @@ export class GetAllStacks extends CFStartAction implements PaginatedAction { 'GET', 'stacks' ); - this.paginationKey = createEntityRelationKey(endpointSchemaKey, endpointGuid); + this.paginationKey = createEntityRelationKey(endpointEntityType, endpointGuid); } paginationKey: string; actions = getActions('Stack', 'Fetch all'); diff --git a/src/frontend/packages/cloud-foundry/src/actions/user-provided-service.actions.ts b/src/frontend/packages/cloud-foundry/src/actions/user-provided-service.actions.ts index 0080cf6962..6ef888f96d 100644 --- a/src/frontend/packages/cloud-foundry/src/actions/user-provided-service.actions.ts +++ b/src/frontend/packages/cloud-foundry/src/actions/user-provided-service.actions.ts @@ -2,7 +2,7 @@ import { HttpRequest } from '@angular/common/http'; import { getActions } from '../../../store/src/actions/action.helper'; import { EntityCatalogEntityConfig } from '../../../store/src/entity-catalog/entity-catalog.types'; -import { endpointSchemaKey } from '../../../store/src/helpers/entity-factory'; +import { endpointEntityType } from '../../../store/src/helpers/stratos-entity-factory'; import { PaginatedAction } from '../../../store/src/types/pagination.types'; import { ICFAction } from '../../../store/src/types/request.types'; import { cfEntityFactory } from '../cf-entity-factory'; @@ -39,7 +39,7 @@ export class GetAllUserProvidedServices extends CFStartAction implements Paginat ) { super(); this.paginationKey = paginationKey || (spaceGuid ? createEntityRelationPaginationKey(spaceEntityType, spaceGuid) : - createEntityRelationPaginationKey(endpointSchemaKey, endpointGuid)); + createEntityRelationPaginationKey(endpointEntityType, endpointGuid)); this.options = new HttpRequest( 'GET', `user_provided_service_instances`, diff --git a/src/frontend/packages/cloud-foundry/src/actions/users.actions.ts b/src/frontend/packages/cloud-foundry/src/actions/users.actions.ts index 40f7d57afc..73d008753b 100644 --- a/src/frontend/packages/cloud-foundry/src/actions/users.actions.ts +++ b/src/frontend/packages/cloud-foundry/src/actions/users.actions.ts @@ -1,8 +1,8 @@ import { HttpRequest } from '@angular/common/http'; import { getActions } from '../../../store/src/actions/action.helper'; -import { endpointSchemaKey } from '../../../store/src/helpers/entity-factory'; import { EntitySchema } from '../../../store/src/helpers/entity-schema'; +import { endpointEntityType } from '../../../store/src/helpers/stratos-entity-factory'; import { PaginatedAction } from '../../../store/src/types/pagination.types'; import { EntityRequestAction } from '../../../store/src/types/request.types'; import { cfEntityFactory } from '../cf-entity-factory'; @@ -51,7 +51,7 @@ export class GetAllCfUsersAsAdmin extends CFStartAction implements PaginatedActi paginationKey?: string ) { super(); - this.paginationKey = paginationKey || createEntityRelationPaginationKey(endpointSchemaKey, endpointGuid); + this.paginationKey = paginationKey || createEntityRelationPaginationKey(endpointEntityType, endpointGuid); this.options = new HttpRequest( 'GET', 'users' diff --git a/src/frontend/packages/cloud-foundry/src/cf-entity-factory.ts b/src/frontend/packages/cloud-foundry/src/cf-entity-factory.ts index 1112888031..33bbedf4f7 100644 --- a/src/frontend/packages/cloud-foundry/src/cf-entity-factory.ts +++ b/src/frontend/packages/cloud-foundry/src/cf-entity-factory.ts @@ -1,5 +1,5 @@ -import { metricEntityType } from '../../core/src/base-entity-schemas'; import { EntitySchema } from '../../store/src/helpers/entity-schema'; +import { metricEntityType } from '../../store/src/helpers/stratos-entity-factory'; import { APIResource } from '../../store/src/types/api.types'; import { CFApplicationEntitySchema, @@ -200,24 +200,24 @@ const CFUserSchema = new CFUserEntitySchema({ audited_spaces: [createUserOrgSpaceSchema(spaceEntityType, {}, CfUserRoleParams.AUDITED_SPACES)], } }, { - idAttribute: getAPIResourceGuid, - processStrategy: (user: APIResource) => { - if (user.entity.username) { - return user; - } - const entity = { - ...user.entity, - username: user.metadata.guid - }; - - return user.metadata ? { - entity, - metadata: user.metadata - } : { - entity - }; + idAttribute: getAPIResourceGuid, + processStrategy: (user: APIResource) => { + if (user.entity.username) { + return user; } - }); + const entity = { + ...user.entity, + username: user.metadata.guid + }; + + return user.metadata ? { + entity, + metadata: user.metadata + } : { + entity + }; + } +}); entityCache[cfUserEntityType] = CFUserSchema; const coreSpaceSchemaParams = { diff --git a/src/frontend/packages/cloud-foundry/src/cf-entity-generator.ts b/src/frontend/packages/cloud-foundry/src/cf-entity-generator.ts index beba13c732..89727e826e 100644 --- a/src/frontend/packages/cloud-foundry/src/cf-entity-generator.ts +++ b/src/frontend/packages/cloud-foundry/src/cf-entity-generator.ts @@ -3,10 +3,8 @@ import * as moment from 'moment'; import { combineLatest, Observable, of } from 'rxjs'; import { first, map } from 'rxjs/operators'; -import { EndpointHealthCheck } from '../../core/endpoints-health-checks'; -import { metricEntityType } from '../../core/src/base-entity-schemas'; +import { BaseEndpointAuth } from '../../core/src/core/endpoint-auth'; import { urlValidationExpression } from '../../core/src/core/utils.service'; -import { BaseEndpointAuth } from '../../core/src/features/endpoints/endpoint-auth'; import { AppState, GeneralEntityAppState } from '../../store/src/app-state'; import { StratosBaseCatalogEntity, @@ -14,6 +12,7 @@ import { StratosCatalogEntity, } from '../../store/src/entity-catalog/entity-catalog-entity/entity-catalog-entity'; import { + EndpointHealthCheck, IStratosEntityDefinition, StratosEndpointExtensionDefinition, } from '../../store/src/entity-catalog/entity-catalog.types'; @@ -22,6 +21,7 @@ import { } from '../../store/src/entity-request-pipeline/entity-request-base-handlers/handle-multi-endpoints.pipe'; import { ActionDispatcher, JetstreamResponse } from '../../store/src/entity-request-pipeline/entity-request-pipeline.types'; import { EntitySchema } from '../../store/src/helpers/entity-schema'; +import { metricEntityType } from '../../store/src/helpers/stratos-entity-factory'; import { RequestInfoState } from '../../store/src/reducers/api-request-reducer/types'; import { selectSessionData } from '../../store/src/reducers/auth.reducer'; import { APIResource, EntityInfo } from '../../store/src/types/api.types'; @@ -409,7 +409,9 @@ function generateCFQuotaDefinitionEntity(endpointDefinition: StratosEndpointExte const definition: IStratosEntityDefinition = { type: quotaDefinitionEntityType, schema: cfEntityFactory(quotaDefinitionEntityType), - endpoint: endpointDefinition + endpoint: endpointDefinition, + label: 'Organization Quota', + labelPlural: 'Organization Quotas', }; cfEntityCatalog.quotaDefinition = new StratosCatalogEntity< IBasicCFMetaData, @@ -451,6 +453,8 @@ function generateCFAppEnvVarEntity(endpointDefinition: StratosEndpointExtensionD } }; }, + label: 'App Env Var', + labelPlural: 'App Env Vars', }; cfEntityCatalog.appEnvVar = new StratosCatalogEntity< IBasicCFMetaData, @@ -478,6 +482,8 @@ function generateCFAppSummaryEntity(endpointDefinition: StratosEndpointExtension type: appSummaryEntityType, schema: cfEntityFactory(appSummaryEntityType), endpoint: endpointDefinition, + label: 'App Summary', + labelPlural: 'App Summaries', }; cfEntityCatalog.appSummary = new StratosCatalogEntity(definition, { dataReducers: [ @@ -500,7 +506,9 @@ function generateCFSpaceQuotaEntity(endpointDefinition: StratosEndpointExtension const definition: IStratosEntityDefinition = { type: spaceQuotaEntityType, schema: cfEntityFactory(spaceQuotaEntityType), - endpoint: endpointDefinition + endpoint: endpointDefinition, + label: 'Space Quota', + labelPlural: 'Space Quotas', }; cfEntityCatalog.spaceQuota = new StratosCatalogEntity< IBasicCFMetaData, @@ -518,7 +526,9 @@ function generateCFPrivateDomainEntity(endpointDefinition: StratosEndpointExtens const definition: IStratosEntityDefinition = { type: privateDomainsEntityType, schema: cfEntityFactory(privateDomainsEntityType), - endpoint: endpointDefinition + endpoint: endpointDefinition, + label: 'Private Domain', + labelPlural: 'Private Domains', }; cfEntityCatalog.privateDomain = new StratosCatalogEntity>(definition, { dataReducers: [ diff --git a/src/frontend/packages/cloud-foundry/src/cf-error-helpers.ts b/src/frontend/packages/cloud-foundry/src/cf-error-helpers.ts index 73c4b0c0d4..da3efe70ec 100644 --- a/src/frontend/packages/cloud-foundry/src/cf-error-helpers.ts +++ b/src/frontend/packages/cloud-foundry/src/cf-error-helpers.ts @@ -1,4 +1,4 @@ -import { JetStreamErrorResponse, jetStreamErrorResponseToSafeString } from '../../core/src/jetstream.helpers'; +import { JetStreamErrorResponse, jetStreamErrorResponseToSafeString } from '../../store/src/jetstream'; export interface CfErrorObject { code: number; diff --git a/src/frontend/packages/cloud-foundry/src/cf-favorites-helpers.ts b/src/frontend/packages/cloud-foundry/src/cf-favorites-helpers.ts index ec23f4125f..8f19d39a21 100644 --- a/src/frontend/packages/cloud-foundry/src/cf-favorites-helpers.ts +++ b/src/frontend/packages/cloud-foundry/src/cf-favorites-helpers.ts @@ -1,5 +1,5 @@ -import { FavoritesConfigMapper } from '../../core/src/shared/components/favorites-meta-card/favorite-config-mapper'; import { IEntityMetadata } from '../../store/src/entity-catalog/entity-catalog.types'; +import { FavoritesConfigMapper } from '../../store/src/favorite-config-mapper'; import { UserFavorite } from '../../store/src/types/user-favorites.types'; import { CfAPIResource } from './store/types/cf-api.types'; diff --git a/src/frontend/packages/cloud-foundry/src/cloud-foundry-test.module.ts b/src/frontend/packages/cloud-foundry/src/cloud-foundry-test.module.ts index 11769b81a4..99bfc37bbd 100644 --- a/src/frontend/packages/cloud-foundry/src/cloud-foundry-test.module.ts +++ b/src/frontend/packages/cloud-foundry/src/cloud-foundry-test.module.ts @@ -3,11 +3,11 @@ import { NgModule } from '@angular/core'; import { EffectsModule } from '@ngrx/effects'; import { generateASEntities } from '../../cf-autoscaler/src/store/autoscaler-entity-generator'; -import { generateStratosEntities } from '../../core/src/base-entity-types'; import { getGitHubAPIURL, GITHUB_API_URL } from '../../core/src/core/github.helpers'; import { LoggerService } from '../../core/src/core/logger.service'; import { CATALOGUE_ENTITIES, EntityCatalogFeatureModule } from '../../store/src/entity-catalog.module'; import { entityCatalog, TestEntityCatalog } from '../../store/src/entity-catalog/entity-catalog'; +import { generateStratosEntities } from '../../store/src/stratos-entity-generator'; import { testSCFEndpointGuid } from '../../store/testing/public-api'; import { BaseCfOrgSpaceRouteMock } from '../test-framework/cloud-foundry-endpoint-service.helper'; import { generateCFEntities } from './cf-entity-generator'; diff --git a/src/frontend/packages/cloud-foundry/src/entity-relations/entity-relations-list.spec.ts b/src/frontend/packages/cloud-foundry/src/entity-relations/entity-relations-list.spec.ts index 73851810cc..35679dc510 100644 --- a/src/frontend/packages/cloud-foundry/src/entity-relations/entity-relations-list.spec.ts +++ b/src/frontend/packages/cloud-foundry/src/entity-relations/entity-relations-list.spec.ts @@ -1,6 +1,7 @@ +import { EntitySchema } from '../../../store/src/helpers/entity-schema'; import { listEntityRelations } from './entity-relations'; import { createEntityRelationKey, EntityInlineParentAction } from './entity-relations.types'; -import { EntitySchema } from '../../../store/src/helpers/entity-schema'; + const endpointType = 'endpointtype1'; describe('Entity Relations - List relations', () => { diff --git a/src/frontend/packages/cloud-foundry/src/entity-relations/entity-relations.tree.spec.ts b/src/frontend/packages/cloud-foundry/src/entity-relations/entity-relations.tree.spec.ts index 6ce1b9126a..5383e22fbe 100644 --- a/src/frontend/packages/cloud-foundry/src/entity-relations/entity-relations.tree.spec.ts +++ b/src/frontend/packages/cloud-foundry/src/entity-relations/entity-relations.tree.spec.ts @@ -1,5 +1,5 @@ -import { CF_ENDPOINT_TYPE } from '../cf-types'; import { CFEntitySchema } from '../cf-entity-schema-types'; +import { CF_ENDPOINT_TYPE } from '../cf-types'; import { fetchEntityTree } from './entity-relations.tree'; import { createEntityRelationKey, EntityInlineParentAction } from './entity-relations.types'; diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/application-delete/application-delete.component.spec.ts b/src/frontend/packages/cloud-foundry/src/features/applications/application-delete/application-delete.component.spec.ts index 7e8ac98783..52aa6ff434 100644 --- a/src/frontend/packages/cloud-foundry/src/features/applications/application-delete/application-delete.component.spec.ts +++ b/src/frontend/packages/cloud-foundry/src/features/applications/application-delete/application-delete.component.spec.ts @@ -1,12 +1,8 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { GetApplication } from '../../../../../cloud-foundry/src/actions/application.actions'; -import { cfEntityFactory } from '../../../../../cloud-foundry/src/cf-entity-factory'; import { TabNavService } from '../../../../../core/tab-nav.service'; -import { generateTestEntityServiceProvider } from '../../../../../core/test-framework/entity-service.helper'; import { generateTestApplicationServiceProvider } from '../../../../test-framework/application-service-helper'; import { generateCfBaseTestModules } from '../../../../test-framework/cloud-foundry-endpoint-service.helper'; -import { applicationEntityType } from '../../../cf-entity-types'; import { ApplicationsModule } from '../applications.module'; import { ApplicationDeleteComponent } from './application-delete.component'; @@ -22,11 +18,6 @@ describe('ApplicationDeleteComponent', () => { ApplicationsModule ], providers: [ - generateTestEntityServiceProvider( - appId, - cfEntityFactory(applicationEntityType), - new GetApplication(appId, cfId) - ), generateTestApplicationServiceProvider(cfId, appId), TabNavService ] diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/application-delete/delete-app-instances/app-delete-instances-routes-list-config.service.ts b/src/frontend/packages/cloud-foundry/src/features/applications/application-delete/delete-app-instances/app-delete-instances-routes-list-config.service.ts index 91f805f77c..f8b961dfba 100644 --- a/src/frontend/packages/cloud-foundry/src/features/applications/application-delete/delete-app-instances/app-delete-instances-routes-list-config.service.ts +++ b/src/frontend/packages/cloud-foundry/src/features/applications/application-delete/delete-app-instances/app-delete-instances-routes-list-config.service.ts @@ -12,7 +12,7 @@ import { import { CurrentUserPermissionsService } from '../../../../../../core/src/core/permissions/current-user-permissions.service'; import { RowState } from '../../../../../../core/src/shared/components/list/data-sources-controllers/list-data-source-types'; import { ListViewTypes } from '../../../../../../core/src/shared/components/list/list.component.types'; -import { endpointSchemaKey } from '../../../../../../store/src/helpers/entity-factory'; +import { endpointEntityType } from '../../../../../../store/src/helpers/stratos-entity-factory'; import { PaginationMonitorFactory } from '../../../../../../store/src/monitors/pagination-monitor.factory'; import { APIResource } from '../../../../../../store/src/types/api.types'; import { IServiceBinding } from '../../../../cf-api-svc.types'; @@ -59,7 +59,7 @@ export class AppDeleteServiceInstancesListConfigService extends AppServiceBindin const action = cfEntityCatalog.serviceBinding.actions.getAllForServiceInstance( serviceBinding.entity.service_instance_guid, appService.cfGuid, - createEntityRelationPaginationKey(endpointSchemaKey, serviceBindingEntityType), + createEntityRelationPaginationKey(endpointEntityType, serviceBindingEntityType), { includeRelations: [], } diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/application-delete/delete-app-instances/delete-app-instances.component.spec.ts b/src/frontend/packages/cloud-foundry/src/features/applications/application-delete/delete-app-instances/delete-app-instances.component.spec.ts index cc133e9d3b..184b50070a 100644 --- a/src/frontend/packages/cloud-foundry/src/features/applications/application-delete/delete-app-instances/delete-app-instances.component.spec.ts +++ b/src/frontend/packages/cloud-foundry/src/features/applications/application-delete/delete-app-instances/delete-app-instances.component.spec.ts @@ -1,12 +1,8 @@ import { DatePipe } from '@angular/common'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { GetApplication } from '../../../../../../cloud-foundry/src/actions/application.actions'; -import { cfEntityFactory } from '../../../../../../cloud-foundry/src/cf-entity-factory'; -import { generateTestEntityServiceProvider } from '../../../../../../core/test-framework/entity-service.helper'; import { generateTestApplicationServiceProvider } from '../../../../../test-framework/application-service-helper'; import { generateCfBaseTestModules } from '../../../../../test-framework/cloud-foundry-endpoint-service.helper'; -import { applicationEntityType } from '../../../../cf-entity-types'; import { ServiceActionHelperService } from '../../../../shared/data-services/service-action-helper.service'; import { ApplicationEnvVarsHelper, @@ -24,11 +20,6 @@ describe('DeleteAppInstancesComponent', () => { declarations: [DeleteAppServiceInstancesComponent], imports: generateCfBaseTestModules(), providers: [ - generateTestEntityServiceProvider( - appId, - cfEntityFactory(applicationEntityType), - new GetApplication(appId, cfId) - ), generateTestApplicationServiceProvider(cfId, appId), ApplicationEnvVarsHelper, DatePipe, diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/application-delete/delete-app-routes/delete-app-routes.component.spec.ts b/src/frontend/packages/cloud-foundry/src/features/applications/application-delete/delete-app-routes/delete-app-routes.component.spec.ts index 28b04b412d..7e6b4e0ff6 100644 --- a/src/frontend/packages/cloud-foundry/src/features/applications/application-delete/delete-app-routes/delete-app-routes.component.spec.ts +++ b/src/frontend/packages/cloud-foundry/src/features/applications/application-delete/delete-app-routes/delete-app-routes.component.spec.ts @@ -1,12 +1,8 @@ import { DatePipe } from '@angular/common'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { GetApplication } from '../../../../../../cloud-foundry/src/actions/application.actions'; -import { cfEntityFactory } from '../../../../../../cloud-foundry/src/cf-entity-factory'; -import { generateTestEntityServiceProvider } from '../../../../../../core/test-framework/entity-service.helper'; import { generateTestApplicationServiceProvider } from '../../../../../test-framework/application-service-helper'; import { generateCfBaseTestModules } from '../../../../../test-framework/cloud-foundry-endpoint-service.helper'; -import { applicationEntityType } from '../../../../cf-entity-types'; import { ApplicationEnvVarsHelper, } from '../../application/application-tabs-base/tabs/build-tab/application-env-vars.service'; @@ -23,11 +19,6 @@ describe('DeleteAppRoutesComponent', () => { declarations: [DeleteAppRoutesComponent], imports: generateCfBaseTestModules(), providers: [ - generateTestEntityServiceProvider( - appId, - cfEntityFactory(applicationEntityType), - new GetApplication(appId, cfId) - ), generateTestApplicationServiceProvider(cfId, appId), ApplicationEnvVarsHelper, DatePipe, diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/application.service.spec.ts b/src/frontend/packages/cloud-foundry/src/features/applications/application.service.spec.ts index aba0ea3567..23282a262b 100644 --- a/src/frontend/packages/cloud-foundry/src/features/applications/application.service.spec.ts +++ b/src/frontend/packages/cloud-foundry/src/features/applications/application.service.spec.ts @@ -1,18 +1,14 @@ import { inject, TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; -import { GetApplication } from '../../../../cloud-foundry/src/actions/application.actions'; -import { cfEntityFactory } from '../../../../cloud-foundry/src/cf-entity-factory'; import { CoreModule } from '../../../../core/src/core/core.module'; import { ExtensionService } from '../../../../core/src/core/extension/extension-service'; import { getGitHubAPIURL, GITHUB_API_URL } from '../../../../core/src/core/github.helpers'; -import { generateTestEntityServiceProvider } from '../../../../core/test-framework/entity-service.helper'; import { EntityMonitorFactory } from '../../../../store/src/monitors/entity-monitor.factory.service'; import { PaginationMonitorFactory } from '../../../../store/src/monitors/pagination-monitor.factory'; import { AppStoreModule } from '../../../../store/src/store.module'; import { generateTestApplicationServiceProvider } from '../../../test-framework/application-service-helper'; import { generateCfStoreModules } from '../../../test-framework/cloud-foundry-endpoint-service.helper'; -import { applicationEntityType } from '../../cf-entity-types'; import { LongRunningCfOperationsService } from '../../shared/data-services/long-running-cf-op.service'; import { GitSCMService } from '../../shared/data-services/scm/scm.service'; import { ApplicationStateService } from '../../shared/services/application-state.service'; @@ -33,11 +29,6 @@ describe('ApplicationService', () => { generateCfStoreModules() ], providers: [ - generateTestEntityServiceProvider( - appId, - cfEntityFactory(applicationEntityType), - new GetApplication(appId, cfId) - ), generateTestApplicationServiceProvider(cfId, appId), ApplicationStateService, ApplicationEnvVarsHelper, diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/application.service.ts b/src/frontend/packages/cloud-foundry/src/features/applications/application.service.ts index d918209f4f..628b8560a4 100644 --- a/src/frontend/packages/cloud-foundry/src/features/applications/application.service.ts +++ b/src/frontend/packages/cloud-foundry/src/features/applications/application.service.ts @@ -44,13 +44,13 @@ export function createGetApplicationAction(guid: string, endpointGuid: string) { return new GetApplication( guid, endpointGuid, [ - createEntityRelationKey(applicationEntityType, routeEntityType), - createEntityRelationKey(applicationEntityType, spaceEntityType), - createEntityRelationKey(applicationEntityType, stackEntityType), - createEntityRelationKey(applicationEntityType, serviceBindingEntityType), - createEntityRelationKey(routeEntityType, domainEntityType), - createEntityRelationKey(spaceEntityType, organizationEntityType), - ] + createEntityRelationKey(applicationEntityType, routeEntityType), + createEntityRelationKey(applicationEntityType, spaceEntityType), + createEntityRelationKey(applicationEntityType, stackEntityType), + createEntityRelationKey(applicationEntityType, serviceBindingEntityType), + createEntityRelationKey(routeEntityType, domainEntityType), + createEntityRelationKey(spaceEntityType, organizationEntityType), + ] ); } @@ -64,7 +64,7 @@ export interface ApplicationData { @Injectable() export class ApplicationService { - private appEntityService: EntityService>; + public entityService: EntityService>; private appSummaryEntityService: EntityService; constructor( @@ -74,7 +74,7 @@ export class ApplicationService { private appStateService: ApplicationStateService, private appEnvVarsService: ApplicationEnvVarsHelper, ) { - this.appEntityService = cfEntityCatalog.application.store.getEntityService( + this.entityService = cfEntityCatalog.application.store.getEntityService( appGuid, cfGuid, { @@ -138,7 +138,7 @@ export class ApplicationService { private constructCoreObservables() { // First set up all the base observables - this.app$ = this.appEntityService.waitForEntity$; + this.app$ = this.entityService.waitForEntity$; const moreWaiting$ = this.app$.pipe( filter(entityInfo => !!(entityInfo.entity && entityInfo.entity.entity && entityInfo.entity.entity.cfGuid)), map(entityInfo => entityInfo.entity.entity)); @@ -162,9 +162,9 @@ export class ApplicationService { filter(org => !!org) ); - this.isDeletingApp$ = this.appEntityService.isDeletingEntity$.pipe(publishReplay(1), refCount()); + this.isDeletingApp$ = this.entityService.isDeletingEntity$.pipe(publishReplay(1), refCount()); - this.waitForAppEntity$ = this.appEntityService.waitForEntity$.pipe(publishReplay(1), refCount()); + this.waitForAppEntity$ = this.entityService.waitForEntity$.pipe(publishReplay(1), refCount()); this.appSummary$ = this.waitForAppEntity$.pipe( switchMap(() => this.appSummaryEntityService.entityObs$), @@ -231,9 +231,9 @@ export class ApplicationService { } private constructStatusObservables() { - this.isFetchingApp$ = this.appEntityService.isFetchingEntity$; + this.isFetchingApp$ = this.entityService.isFetchingEntity$; - this.isUpdatingApp$ = this.appEntityService.entityObs$.pipe(map(a => { + this.isUpdatingApp$ = this.entityService.entityObs$.pipe(map(a => { const updatingRoot = a.entityRequestInfo.updating[rootUpdatingKey] || { busy: false }; const updatingSection = a.entityRequestInfo.updating[UpdateExistingApplication.updateKey] || { busy: false }; return !!updatingRoot.busy || !!updatingSection.busy; diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-base.component.ts b/src/frontend/packages/cloud-foundry/src/features/applications/application/application-base.component.ts index a95f69f887..ba7fea321a 100644 --- a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-base.component.ts +++ b/src/frontend/packages/cloud-foundry/src/features/applications/application/application-base.component.ts @@ -3,10 +3,9 @@ import { ActivatedRoute } from '@angular/router'; import { Store } from '@ngrx/store'; import { CFAppState } from '../../../../../cloud-foundry/src/cf-app-state'; -import { APP_GUID, CF_GUID, ENTITY_SERVICE } from '../../../../../core/src/shared/entity.tokens'; -import { EntityServiceFactory } from '../../../../../store/src/entity-service-factory.service'; +import { APP_GUID, CF_GUID } from '../../../../../core/src/shared/entity.tokens'; import { ApplicationStateService } from '../../../shared/services/application-state.service'; -import { ApplicationService, createGetApplicationAction } from '../application.service'; +import { ApplicationService } from '../application.service'; import { ApplicationEnvVarsHelper } from './application-tabs-base/tabs/build-tab/application-env-vars.service'; export function applicationServiceFactory( @@ -25,17 +24,6 @@ export function applicationServiceFactory( ); } -export function cfApplicationEntityServiceFactory( - cfId: string, - id: string, - esf: EntityServiceFactory -) { - return esf.create( - id, - createGetApplicationAction(id, cfId) - ); -} - export function getGuids(type?: string) { return (activatedRoute: ActivatedRoute) => { const { id, endpointId } = activatedRoute.snapshot.params; @@ -72,13 +60,7 @@ export function getGuids(type?: string) { ApplicationStateService, ApplicationEnvVarsHelper, ] - }, - { - provide: ENTITY_SERVICE, - useFactory: cfApplicationEntityServiceFactory, - deps: [CF_GUID, APP_GUID, EntityServiceFactory] - }, - + } ] }) export class ApplicationBaseComponent { diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/application-poll/application-poll.component.spec.ts b/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/application-poll/application-poll.component.spec.ts index 096eebe3f7..d20348cc9f 100644 --- a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/application-poll/application-poll.component.spec.ts +++ b/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/application-poll/application-poll.component.spec.ts @@ -1,11 +1,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { generateTestEntityServiceProvider } from '../../../../../../../core/test-framework/entity-service.helper'; import { generateTestApplicationServiceProvider } from '../../../../../../test-framework/application-service-helper'; import { generateCfBaseTestModules } from '../../../../../../test-framework/cloud-foundry-endpoint-service.helper'; -import { GetApplication } from '../../../../../actions/application.actions'; -import { cfEntityFactory } from '../../../../../cf-entity-factory'; -import { applicationEntityType } from '../../../../../cf-entity-types'; import { ApplicationPollingService } from '../application-polling.service'; import { ApplicationEnvVarsHelper } from '../tabs/build-tab/application-env-vars.service'; import { ApplicationStateService } from './../../../../../shared/services/application-state.service'; @@ -23,11 +19,6 @@ describe('ApplicationPollComponent', () => { declarations: [ApplicationPollComponent], providers: [ ApplicationPollingService, - generateTestEntityServiceProvider( - appId, - cfEntityFactory(applicationEntityType), - new GetApplication(appId, cfId) - ), generateTestApplicationServiceProvider(cfId, appId), ApplicationEnvVarsHelper, ApplicationStateService, diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/application-polling.service.ts b/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/application-polling.service.ts index 39fd632931..046af5a750 100644 --- a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/application-polling.service.ts +++ b/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/application-polling.service.ts @@ -1,15 +1,11 @@ -import { Inject, Injectable, NgZone } from '@angular/core'; +import { Injectable, NgZone } from '@angular/core'; import { Store } from '@ngrx/store'; import { Observable, Subscription } from 'rxjs'; import { first, map, tap } from 'rxjs/operators'; import { safeUnsubscribe } from '../../../../../../core/src/core/utils.service'; -import { ENTITY_SERVICE } from '../../../../../../core/src/shared/entity.tokens'; import { AppState } from '../../../../../../store/src/app-state'; -import { EntityService } from '../../../../../../store/src/entity-service'; import { selectDashboardState } from '../../../../../../store/src/selectors/dashboard.selectors'; -import { APIResource } from '../../../../../../store/src/types/api.types'; -import { IApp } from '../../../../cf-api.types'; import { cfEntityCatalog } from '../../../../cf-entity-catalog'; import { ApplicationService } from '../../application.service'; @@ -19,7 +15,7 @@ export class ApplicationPollingService { private pollingSub: Subscription; private autoRefreshString = 'auto-refresh'; - public isPolling$ = this.entityService.updatingSection$.pipe(map( + public isPolling$ = this.applicationService.entityService.updatingSection$.pipe(map( update => update[this.autoRefreshString] && update[this.autoRefreshString].busy )); @@ -27,7 +23,6 @@ export class ApplicationPollingService { constructor( public applicationService: ApplicationService, - @Inject(ENTITY_SERVICE) private entityService: EntityService>, private store: Store, private ngZone: NgZone, ) { @@ -54,7 +49,7 @@ export class ApplicationPollingService { // Auto refresh this.ngZone.runOutsideAngular(() => { - this.pollingSub = this.entityService + this.pollingSub = this.applicationService.entityService .poll(10000, this.autoRefreshString).pipe( tap(() => this.ngZone.run(() => this.poll(false)))) .subscribe(); @@ -69,12 +64,12 @@ export class ApplicationPollingService { const { cfGuid, appGuid } = this.applicationService; if (withApp) { const updatingApp = { - ...this.entityService.action, + ...this.applicationService.entityService.action, updatingKey: this.autoRefreshString }; this.store.dispatch(updatingApp); } - this.entityService.entityObs$.pipe( + this.applicationService.entityService.entityObs$.pipe( first(), ).subscribe(resource => { cfEntityCatalog.appSummary.api.get(appGuid, cfGuid); diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/application-tabs-base.component.spec.ts b/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/application-tabs-base.component.spec.ts index 55f591b111..19c49370d4 100644 --- a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/application-tabs-base.component.spec.ts +++ b/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/application-tabs-base.component.spec.ts @@ -5,17 +5,13 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { RouterTestingModule } from '@angular/router/testing'; import { StoreModule } from '@ngrx/store'; -import { GetApplication } from '../../../../../../cloud-foundry/src/actions/application.actions'; -import { cfEntityFactory } from '../../../../../../cloud-foundry/src/cf-entity-factory'; import { CoreModule } from '../../../../../../core/src/core/core.module'; import { getGitHubAPIURL, GITHUB_API_URL } from '../../../../../../core/src/core/github.helpers'; import { MDAppModule } from '../../../../../../core/src/core/md.module'; import { SharedModule } from '../../../../../../core/src/shared/shared.module'; import { TabNavService } from '../../../../../../core/tab-nav.service'; -import { generateTestEntityServiceProvider } from '../../../../../../core/test-framework/entity-service.helper'; import { generateTestApplicationServiceProvider } from '../../../../../test-framework/application-service-helper'; import { generateCfStoreModules } from '../../../../../test-framework/cloud-foundry-endpoint-service.helper'; -import { applicationEntityType } from '../../../../cf-entity-types'; import { ApplicationStateService } from '../../../../shared/services/application-state.service'; import { ApplicationTabsBaseComponent } from './application-tabs-base.component'; import { ApplicationEnvVarsHelper } from './tabs/build-tab/application-env-vars.service'; @@ -44,11 +40,6 @@ describe('ApplicationTabsBaseComponent', () => { HttpClientTestingModule ], providers: [ - generateTestEntityServiceProvider( - appId, - cfEntityFactory(applicationEntityType), - new GetApplication(appId, cfId) - ), generateTestApplicationServiceProvider(cfId, appId), ApplicationStateService, ApplicationEnvVarsHelper, diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/application-tabs-base.component.ts b/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/application-tabs-base.component.ts index ca2194ba6e..362c6c37fd 100644 --- a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/application-tabs-base.component.ts +++ b/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/application-tabs-base.component.ts @@ -1,4 +1,4 @@ -import { Component, Inject, NgZone, OnDestroy, OnInit } from '@angular/core'; +import { Component, NgZone, OnDestroy, OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; import { combineLatest as observableCombineLatest, Observable, Subscription } from 'rxjs'; import { filter, first, map, startWith, switchMap, withLatestFrom } from 'rxjs/operators'; @@ -15,22 +15,18 @@ import { StratosTabType, } from '../../../../../../core/src/core/extension/extension-service'; import { CurrentUserPermissionsService } from '../../../../../../core/src/core/permissions/current-user-permissions.service'; -import { getFavoriteFromEntity } from '../../../../../../core/src/core/user-favorite-helpers'; import { safeUnsubscribe } from '../../../../../../core/src/core/utils.service'; import { IPageSideNavTab } from '../../../../../../core/src/features/dashboard/page-side-nav/page-side-nav.component'; -import { - FavoritesConfigMapper, -} from '../../../../../../core/src/shared/components/favorites-meta-card/favorite-config-mapper'; import { IHeaderBreadcrumb } from '../../../../../../core/src/shared/components/page-header/page-header.types'; -import { ENTITY_SERVICE } from '../../../../../../core/src/shared/entity.tokens'; import { RouterNav } from '../../../../../../store/src/actions/router.actions'; import { entityCatalog } from '../../../../../../store/src/entity-catalog/entity-catalog'; -import { EntityService } from '../../../../../../store/src/entity-service'; +import { FavoritesConfigMapper } from '../../../../../../store/src/favorite-config-mapper'; import { EntitySchema } from '../../../../../../store/src/helpers/entity-schema'; import { ActionState } from '../../../../../../store/src/reducers/api-request-reducer/types'; import { endpointEntitiesSelector } from '../../../../../../store/src/selectors/endpoint.selectors'; import { APIResource } from '../../../../../../store/src/types/api.types'; import { EndpointModel } from '../../../../../../store/src/types/endpoint.types'; +import { getFavoriteFromEntity } from '../../../../../../store/src/user-favorite-helpers'; import { UpdateExistingApplication } from '../../../../actions/application.actions'; import { IApp, IOrganization, ISpace } from '../../../../cf-api.types'; import { CF_ENDPOINT_TYPE } from '../../../../cf-types'; @@ -61,7 +57,6 @@ export class ApplicationTabsBaseComponent implements OnInit, OnDestroy { constructor( public applicationService: ApplicationService, - @Inject(ENTITY_SERVICE) private entityService: EntityService, private store: Store, private endpointsService: EndpointsService, private ngZone: NgZone, @@ -246,7 +241,7 @@ export class ApplicationTabsBaseComponent implements OnInit, OnDestroy { } ngOnInit() { - this.appSub$ = this.entityService.entityMonitor.entityRequest$.subscribe(requestInfo => { + this.appSub$ = this.applicationService.entityService.entityMonitor.entityRequest$.subscribe(requestInfo => { if ( requestInfo.deleting.deleted || requestInfo.error @@ -257,7 +252,7 @@ export class ApplicationTabsBaseComponent implements OnInit, OnDestroy { this.isFetching$ = this.applicationService.isFetchingApp$; - this.isBusyUpdating$ = this.entityService.updatingSection$.pipe( + this.isBusyUpdating$ = this.applicationService.entityService.updatingSection$.pipe( map(updatingSection => { const updating = this.updatingSectionBusy(updatingSection.restaging) || this.updatingSectionBusy(updatingSection[UpdateExistingApplication.updateKey]); diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/tabs/build-tab/build-tab.component.html b/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/tabs/build-tab/build-tab.component.html index a1ceaa6f53..de18350435 100644 --- a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/tabs/build-tab/build-tab.component.html +++ b/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/tabs/build-tab/build-tab.component.html @@ -149,12 +149,12 @@ - + Deployment Info - +
- - None - diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/tabs/build-tab/build-tab.component.spec.ts b/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/tabs/build-tab/build-tab.component.spec.ts index 71731cb35b..58a38edbe5 100644 --- a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/tabs/build-tab/build-tab.component.spec.ts +++ b/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/tabs/build-tab/build-tab.component.spec.ts @@ -6,17 +6,15 @@ import { RouterTestingModule } from '@angular/router/testing'; import { CoreModule } from '../../../../../../../../core/src/core/core.module'; import { GITHUB_API_URL } from '../../../../../../../../core/src/core/github.helpers'; -import { APP_GUID, CF_GUID, ENTITY_SERVICE } from '../../../../../../../../core/src/shared/entity.tokens'; +import { APP_GUID, CF_GUID } from '../../../../../../../../core/src/shared/entity.tokens'; import { SharedModule } from '../../../../../../../../core/src/shared/shared.module'; import { TabNavService } from '../../../../../../../../core/tab-nav.service'; -import { EntityServiceFactory } from '../../../../../../../../store/src/entity-service-factory.service'; import { AppStoreModule } from '../../../../../../../../store/src/store.module'; import { ApplicationServiceMock } from '../../../../../../../test-framework/application-service-helper'; import { generateCfStoreModules } from '../../../../../../../test-framework/cloud-foundry-endpoint-service.helper'; import { CloudFoundrySharedModule } from '../../../../../../shared/cf-shared.module'; import { ApplicationStateService } from '../../../../../../shared/services/application-state.service'; import { ApplicationService } from '../../../../application.service'; -import { cfApplicationEntityServiceFactory } from '../../../application-base.component'; import { ApplicationPollComponent } from '../../application-poll/application-poll.component'; import { ApplicationPollingService } from '../../application-polling.service'; import { ApplicationEnvVarsHelper } from './application-env-vars.service'; @@ -53,11 +51,6 @@ describe('BuildTabComponent', () => { TabNavService, { provide: CF_GUID, useValue: '' }, { provide: APP_GUID, useValue: '' }, - { - provide: ENTITY_SERVICE, - useFactory: cfApplicationEntityServiceFactory, - deps: [CF_GUID, APP_GUID, EntityServiceFactory] - }, ApplicationPollingService ] }) diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/tabs/build-tab/build-tab.component.ts b/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/tabs/build-tab/build-tab.component.ts index 57c88faeb4..5f3574c8d7 100644 --- a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/tabs/build-tab/build-tab.component.ts +++ b/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/tabs/build-tab/build-tab.component.ts @@ -1,20 +1,21 @@ -import { Component, Inject, OnInit } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { Store } from '@ngrx/store'; -import { combineLatest as observableCombineLatest, Observable, of as observableOf } from 'rxjs'; -import { combineLatest, delay, distinct, filter, first, map, mergeMap, startWith, tap } from 'rxjs/operators'; +import { combineLatest as observableCombineLatest, Observable, of as observableOf, of } from 'rxjs'; +import { combineLatest, delay, distinct, filter, first, map, mergeMap, startWith, switchMap, tap } from 'rxjs/operators'; import { AppMetadataTypes } from '../../../../../../../../cloud-foundry/src/actions/app-metadata.actions'; import { UpdateExistingApplication } from '../../../../../../../../cloud-foundry/src/actions/application.actions'; import { CFAppState } from '../../../../../../../../cloud-foundry/src/cf-app-state'; -import { getFullEndpointApiUrl } from '../../../../../../../../core/src/features/endpoints/endpoint-helpers'; +import { + CurrentUserPermissionsService, +} from '../../../../../../../../core/src/core/permissions/current-user-permissions.service'; import { ConfirmationDialogConfig } from '../../../../../../../../core/src/shared/components/confirmation-dialog.config'; import { ConfirmationDialogService } from '../../../../../../../../core/src/shared/components/confirmation-dialog.service'; -import { ENTITY_SERVICE } from '../../../../../../../../core/src/shared/entity.tokens'; import { ResetPagination } from '../../../../../../../../store/src/actions/pagination.actions'; -import { EntityService } from '../../../../../../../../store/src/entity-service'; +import { getFullEndpointApiUrl } from '../../../../../../../../store/src/endpoint-utils'; import { ActionState } from '../../../../../../../../store/src/reducers/api-request-reducer/types'; -import { APIResource, EntityInfo } from '../../../../../../../../store/src/types/api.types'; +import { EntityInfo } from '../../../../../../../../store/src/types/api.types'; import { IAppSummary } from '../../../../../../cf-api.types'; import { cfEntityCatalog } from '../../../../../../cf-entity-catalog'; import { GitSCMService, GitSCMType } from '../../../../../../shared/data-services/scm/scm.service'; @@ -62,11 +63,10 @@ export class BuildTabComponent implements OnInit { public applicationService: ApplicationService, private scmService: GitSCMService, private store: Store, - @Inject(ENTITY_SERVICE) private entityService: EntityService, private route: ActivatedRoute, private router: Router, private confirmDialog: ConfirmationDialogService, - + private cups: CurrentUserPermissionsService ) { } cardTwoFetching$: Observable; @@ -88,7 +88,7 @@ export class BuildTabComponent implements OnInit { return app.fetching || appSummary.entityRequestInfo.fetching; }), distinct()); - this.isBusyUpdating$ = this.entityService.updatingSection$.pipe( + this.isBusyUpdating$ = this.applicationService.entityService.updatingSection$.pipe( map(updatingSection => { const updating = this.updatingSectionBusy(updatingSection.restaging) || this.updatingSectionBusy(updatingSection[UpdateExistingApplication.updateKey]); @@ -108,8 +108,17 @@ export class BuildTabComponent implements OnInit { }) ); - this.deploySource$ = this.applicationService.applicationStratProject$.pipe( - combineLatest(this.applicationService.application$) + const canSeeEnvVars$ = this.applicationService.appSpace$.pipe( + switchMap(space => this.cups.can( + CfCurrentUserPermissions.APPLICATION_VIEW_ENV_VARS, + this.applicationService.cfGuid, + space.metadata.guid) + ) + ) + + const deploySource$ = observableCombineLatest( + this.applicationService.applicationStratProject$, + this.applicationService.application$ ).pipe( map(([project, app]) => { if (!!project) { @@ -149,6 +158,10 @@ export class BuildTabComponent implements OnInit { } }), startWith({ type: 'loading' }) + ) + + this.deploySource$ = canSeeEnvVars$.pipe( + switchMap(canSeeEnvVars => canSeeEnvVars ? deploySource$ : of(null)), ); } @@ -249,7 +262,7 @@ export class BuildTabComponent implements OnInit { } pollEntityService(state, stateString): Observable { - return this.entityService + return this.applicationService.entityService .poll(1000, state).pipe( delay(1), filter(({ resource }) => { diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/tabs/log-stream-tab/log-stream-tab.component.spec.ts b/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/tabs/log-stream-tab/log-stream-tab.component.spec.ts index b300ad4f84..03b62309d1 100644 --- a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/tabs/log-stream-tab/log-stream-tab.component.spec.ts +++ b/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/tabs/log-stream-tab/log-stream-tab.component.spec.ts @@ -3,18 +3,14 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { RouterTestingModule } from '@angular/router/testing'; import { StoreModule } from '@ngrx/store'; -import { GetApplication } from '../../../../../../../../cloud-foundry/src/actions/application.actions'; -import { cfEntityFactory } from '../../../../../../../../cloud-foundry/src/cf-entity-factory'; import { CoreModule } from '../../../../../../../../core/src/core/core.module'; import { MDAppModule } from '../../../../../../../../core/src/core/md.module'; import { LogViewerComponent } from '../../../../../../../../core/src/shared/components/log-viewer/log-viewer.component'; -import { generateTestEntityServiceProvider } from '../../../../../../../../core/test-framework/entity-service.helper'; import { EntityMonitorFactory } from '../../../../../../../../store/src/monitors/entity-monitor.factory.service'; import { PaginationMonitorFactory } from '../../../../../../../../store/src/monitors/pagination-monitor.factory'; import { AppStoreModule } from '../../../../../../../../store/src/store.module'; import { generateTestApplicationServiceProvider } from '../../../../../../../test-framework/application-service-helper'; import { generateCfStoreModules } from '../../../../../../../test-framework/cloud-foundry-endpoint-service.helper'; -import { applicationEntityType } from '../../../../../../cf-entity-types'; import { ApplicationStateService } from '../../../../../../shared/services/application-state.service'; import { ApplicationEnvVarsHelper } from '../build-tab/application-env-vars.service'; import { LogStreamTabComponent } from './log-stream-tab.component'; @@ -41,11 +37,6 @@ describe('LogStreamTabComponent', () => { LogStreamTabComponent ], providers: [ - generateTestEntityServiceProvider( - appId, - cfEntityFactory(applicationEntityType), - new GetApplication(appId, cfId) - ), generateTestApplicationServiceProvider(cfId, appId), AppStoreModule, ApplicationStateService, diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/tabs/metrics-tab/metrics-tab.component.spec.ts b/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/tabs/metrics-tab/metrics-tab.component.spec.ts index 6bb64cb28b..42bf58fa38 100644 --- a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/tabs/metrics-tab/metrics-tab.component.spec.ts +++ b/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/tabs/metrics-tab/metrics-tab.component.spec.ts @@ -1,14 +1,10 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { GetApplication } from '../../../../../../../../cloud-foundry/src/actions/application.actions'; -import { cfEntityFactory } from '../../../../../../../../cloud-foundry/src/cf-entity-factory'; import { MDAppModule } from '../../../../../../../../core/src/core/md.module'; import { SharedModule } from '../../../../../../../../core/src/shared/shared.module'; -import { generateTestEntityServiceProvider } from '../../../../../../../../core/test-framework/entity-service.helper'; import { generateTestApplicationServiceProvider } from '../../../../../../../test-framework/application-service-helper'; import { generateCfStoreModules } from '../../../../../../../test-framework/cloud-foundry-endpoint-service.helper'; -import { applicationEntityType } from '../../../../../../cf-entity-types'; import { ApplicationStateService } from '../../../../../../shared/services/application-state.service'; import { ApplicationEnvVarsHelper } from '../build-tab/application-env-vars.service'; import { MetricsTabComponent } from './metrics-tab.component'; @@ -30,11 +26,6 @@ describe('MetricsTabComponent', () => { providers: [ ApplicationStateService, ApplicationEnvVarsHelper, - generateTestEntityServiceProvider( - appId, - cfEntityFactory(applicationEntityType), - new GetApplication(appId, cfId) - ), generateTestApplicationServiceProvider(cfId, appId), ] }) diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/cli-info-application/cli-info-application.component.spec.ts b/src/frontend/packages/cloud-foundry/src/features/applications/cli-info-application/cli-info-application.component.spec.ts index c3ead1317a..ff36e161d2 100644 --- a/src/frontend/packages/cloud-foundry/src/features/applications/cli-info-application/cli-info-application.component.spec.ts +++ b/src/frontend/packages/cloud-foundry/src/features/applications/cli-info-application/cli-info-application.component.spec.ts @@ -1,16 +1,12 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; -import { GetApplication } from '../../../../../cloud-foundry/src/actions/application.actions'; -import { cfEntityFactory } from '../../../../../cloud-foundry/src/cf-entity-factory'; import { CoreModule } from '../../../../../core/src/core/core.module'; import { MDAppModule } from '../../../../../core/src/core/md.module'; import { SharedModule } from '../../../../../core/src/shared/shared.module'; import { TabNavService } from '../../../../../core/tab-nav.service'; -import { generateTestEntityServiceProvider } from '../../../../../core/test-framework/entity-service.helper'; import { generateTestApplicationServiceProvider } from '../../../../test-framework/application-service-helper'; import { generateCfStoreModules } from '../../../../test-framework/cloud-foundry-endpoint-service.helper'; -import { applicationEntityType } from '../../../cf-entity-types'; import { CloudFoundrySharedModule } from '../../../shared/cf-shared.module'; import { ApplicationStateService } from '../../../shared/services/application-state.service'; import { ApplicationEnvVarsHelper } from '../application/application-tabs-base/tabs/build-tab/application-env-vars.service'; @@ -35,11 +31,6 @@ describe('CliInfoApplicationComponent', () => { CloudFoundrySharedModule ], providers: [ - generateTestEntityServiceProvider( - appId, - cfEntityFactory(applicationEntityType), - new GetApplication(appId, cfId) - ), generateTestApplicationServiceProvider(cfId, appId), ApplicationStateService, ApplicationEnvVarsHelper, diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/cli-info-application/cli-info-application.component.ts b/src/frontend/packages/cloud-foundry/src/features/applications/cli-info-application/cli-info-application.component.ts index 9785603d75..1681bae4ad 100644 --- a/src/frontend/packages/cloud-foundry/src/features/applications/cli-info-application/cli-info-application.component.ts +++ b/src/frontend/packages/cloud-foundry/src/features/applications/cli-info-application/cli-info-application.component.ts @@ -2,11 +2,10 @@ import { Component, OnInit } from '@angular/core'; import { BehaviorSubject, combineLatest, Observable } from 'rxjs'; import { filter, first, map } from 'rxjs/operators'; -import { EntityService } from '../../../../../store/src/entity-service'; -import { EntityServiceFactory } from '../../../../../store/src/entity-service-factory.service'; -import { getFullEndpointApiUrl } from '../../../../../core/src/features/endpoints/endpoint-helpers'; import { IHeaderBreadcrumb } from '../../../../../core/src/shared/components/page-header/page-header.types'; -import { GetAllEndpoints } from '../../../../../store/src/actions/endpoint.actions'; +import { getFullEndpointApiUrl } from '../../../../../store/src/endpoint-utils'; +import { EntityService } from '../../../../../store/src/entity-service'; +import { stratosEntityCatalog } from '../../../../../store/src/stratos-entity-catalog'; import { EndpointModel } from '../../../../../store/src/types/endpoint.types'; import { CFAppCLIInfoContext } from '../../../shared/components/cli-info/cli-info.component'; import { ApplicationService } from '../application.service'; @@ -29,7 +28,6 @@ export class CliInfoApplicationComponent implements OnInit { constructor( private applicationService: ApplicationService, - private entityServiceFactory: EntityServiceFactory ) { this.breadcrumbs$ = new BehaviorSubject([]); } @@ -41,10 +39,7 @@ export class CliInfoApplicationComponent implements OnInit { } private setupObservables(cfGuid: string) { - this.cfEndpointEntityService = this.entityServiceFactory.create( - cfGuid, - new GetAllEndpoints() - ); + this.cfEndpointEntityService = stratosEntityCatalog.endpoint.store.getEntityService(cfGuid); this.context$ = combineLatest( this.applicationService.application$, diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/edit-application/edit-application.component.spec.ts b/src/frontend/packages/cloud-foundry/src/features/applications/edit-application/edit-application.component.spec.ts index f25b7fa87f..e5de781a2a 100644 --- a/src/frontend/packages/cloud-foundry/src/features/applications/edit-application/edit-application.component.spec.ts +++ b/src/frontend/packages/cloud-foundry/src/features/applications/edit-application/edit-application.component.spec.ts @@ -4,18 +4,14 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { RouterTestingModule } from '@angular/router/testing'; -import { GetApplication } from '../../../../../cloud-foundry/src/actions/application.actions'; -import { cfEntityFactory } from '../../../../../cloud-foundry/src/cf-entity-factory'; import { CoreModule } from '../../../../../core/src/core/core.module'; import { SharedModule } from '../../../../../core/src/shared/shared.module'; import { TabNavService } from '../../../../../core/tab-nav.service'; -import { generateTestEntityServiceProvider } from '../../../../../core/test-framework/entity-service.helper'; import { ApplicationServiceMock, generateTestApplicationServiceProvider, } from '../../../../test-framework/application-service-helper'; import { generateCfStoreModules } from '../../../../test-framework/cloud-foundry-endpoint-service.helper'; -import { applicationEntityType } from '../../../cf-entity-types'; import { ApplicationStateService } from '../../../shared/services/application-state.service'; import { ApplicationService } from '../application.service'; import { ApplicationEnvVarsHelper } from '../application/application-tabs-base/tabs/build-tab/application-env-vars.service'; @@ -42,11 +38,6 @@ describe('EditApplicationComponent', () => { ], providers: [ { provide: ApplicationService, useClass: ApplicationServiceMock }, - generateTestEntityServiceProvider( - appId, - cfEntityFactory(applicationEntityType), - new GetApplication(appId, cfId) - ), generateTestApplicationServiceProvider(cfId, appId), ApplicationStateService, ApplicationEnvVarsHelper, diff --git a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/add-organization/create-organization-step/create-organization-step.component.ts b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/add-organization/create-organization-step/create-organization-step.component.ts index c5e99f073c..acc4f55a0c 100644 --- a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/add-organization/create-organization-step/create-organization-step.component.ts +++ b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/add-organization/create-organization-step/create-organization-step.component.ts @@ -14,7 +14,7 @@ import { import { selectCfRequestInfo } from '../../../../../../cloud-foundry/src/store/selectors/api.selectors'; import { StepOnNextFunction } from '../../../../../../core/src/shared/components/stepper/step/step.component'; import { entityCatalog } from '../../../../../../store/src/entity-catalog/entity-catalog'; -import { endpointSchemaKey } from '../../../../../../store/src/helpers/entity-factory'; +import { endpointEntityType } from '../../../../../../store/src/helpers/stratos-entity-factory'; import { PaginationMonitorFactory } from '../../../../../../store/src/monitors/pagination-monitor.factory'; import { getPaginationObservables } from '../../../../../../store/src/reducers/pagination-reducer/pagination-reducer.helper'; import { APIResource } from '../../../../../../store/src/types/api.types'; @@ -75,7 +75,7 @@ export class CreateOrganizationStepComponent implements OnInit, OnDestroy { tap((o) => this.allOrgs = o) ); - const quotaPaginationKey = createEntityRelationPaginationKey(endpointSchemaKey, this.cfGuid); + const quotaPaginationKey = createEntityRelationPaginationKey(endpointEntityType, this.cfGuid); this.quotaDefinitions$ = cfEntityCatalog.quotaDefinition.store.getPaginationService( quotaPaginationKey, this.cfGuid, { includeRelations: [] } ).entities$.pipe( diff --git a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/cf-cell.helpers.ts b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/cf-cell.helpers.ts index c0673a5c49..375a28581a 100644 --- a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/cf-cell.helpers.ts +++ b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/cf-cell.helpers.ts @@ -3,12 +3,12 @@ import { Observable, of } from 'rxjs'; import { filter, first, map, publishReplay, refCount, switchMap } from 'rxjs/operators'; import { endpointHasMetricsByAvailable } from '../../../../core/src/features/endpoints/endpoint-helpers'; -import { MetricQueryType } from '../../../../core/src/shared/services/metrics-range-selector.types'; import { MetricQueryConfig } from '../../../../store/src/actions/metrics.actions'; import { AppState } from '../../../../store/src/app-state'; import { PaginationMonitorFactory } from '../../../../store/src/monitors/pagination-monitor.factory'; import { getPaginationObservables } from '../../../../store/src/reducers/pagination-reducer/pagination-reducer.helper'; import { IMetrics } from '../../../../store/src/types/base-metric.types'; +import { MetricQueryType } from '../../../../store/src/types/metric.types'; import { FetchCFCellMetricsPaginatedAction } from '../../actions/cf-metrics.actions'; import { CFEntityConfig } from '../../cf-types'; import { CellMetrics } from './tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell.service'; diff --git a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/cf.helpers.ts b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/cf.helpers.ts index 675a1f4758..e6e64456f7 100644 --- a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/cf.helpers.ts +++ b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/cf.helpers.ts @@ -28,9 +28,10 @@ import { APIResource } from '../../../../store/src/types/api.types'; import { EndpointModel } from '../../../../store/src/types/endpoint.types'; import { PaginatedAction, PaginationEntityState } from '../../../../store/src/types/pagination.types'; import { IServiceInstance, IUserProvidedServiceInstance } from '../../cf-api-svc.types'; -import { CFFeatureFlagTypes, ISpace } from '../../cf-api.types'; +import { CFFeatureFlagTypes, IApp, ISpace } from '../../cf-api.types'; import { cfEntityFactory } from '../../cf-entity-factory'; import { CFEntityConfig } from '../../cf-types'; +import { ListCfRoute } from '../../shared/components/list/list-types/cf-routes/cf-routes-data-source-base'; import { CfUser, CfUserRoleParams, @@ -350,12 +351,17 @@ export function fetchTotalResults( ); } +type CfOrgSpaceFilterTypes = IApp | ListCfRoute | IServiceInstance; export const cfOrgSpaceFilter = (entities: APIResource[], paginationState: PaginationEntityState) => { // Filtering is done remotely when maxedResults are hit (see `setMultiFilter`) if (!!paginationState.maxedState.isMaxedMode && !paginationState.maxedState.ignoreMaxed) { return entities; } + const fetchOrgGuid = (e: APIResource): string => { + return e.entity.space ? e.entity.space.entity.organization_guid : null; + } + // Filter by cf/org/space const cfGuid = paginationState.clientPagination.filter.items.cf; const orgGuid = paginationState.clientPagination.filter.items.org; @@ -363,7 +369,7 @@ export const cfOrgSpaceFilter = (entities: APIResource[], paginationState: Pagin return !cfGuid && !orgGuid && !spaceGuid ? entities : entities.filter(e => { e = extractActualListEntity(e); const validCF = !(cfGuid && cfGuid !== e.entity.cfGuid); - const validOrg = !(orgGuid && orgGuid !== e.entity.space.entity.organization_guid); + const validOrg = !(orgGuid && orgGuid !== fetchOrgGuid(e)); const validSpace = !(spaceGuid && spaceGuid !== e.entity.space_guid); return validCF && validOrg && validSpace; }); diff --git a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/cli-info-cloud-foundry/cli-info-cloud-foundry.component.ts b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/cli-info-cloud-foundry/cli-info-cloud-foundry.component.ts index 82ddcf4295..3449967904 100644 --- a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/cli-info-cloud-foundry/cli-info-cloud-foundry.component.ts +++ b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/cli-info-cloud-foundry/cli-info-cloud-foundry.component.ts @@ -5,9 +5,9 @@ import { first, map } from 'rxjs/operators'; import { CFAppState } from '../../../../../cloud-foundry/src/cf-app-state'; import { CFAppCLIInfoContext } from '../../../../../cloud-foundry/src/shared/components/cli-info/cli-info.component'; -import { getFullEndpointApiUrl } from '../../../../../core/src/features/endpoints/endpoint-helpers'; import { IHeaderBreadcrumb } from '../../../../../core/src/shared/components/page-header/page-header.types'; import { RouterNav } from '../../../../../store/src/actions/router.actions'; +import { getFullEndpointApiUrl } from '../../../../../store/src/endpoint-utils'; import { APIResource, EntityInfo } from '../../../../../store/src/types/api.types'; import { EndpointModel } from '../../../../../store/src/types/endpoint.types'; import { getPreviousRoutingState } from '../../../../../store/src/types/routing.type'; diff --git a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/cloud-foundry-tabs-base/cloud-foundry-tabs-base.component.ts b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/cloud-foundry-tabs-base/cloud-foundry-tabs-base.component.ts index 57ddd512a7..c086f9cd86 100644 --- a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/cloud-foundry-tabs-base/cloud-foundry-tabs-base.component.ts +++ b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/cloud-foundry-tabs-base/cloud-foundry-tabs-base.component.ts @@ -13,7 +13,7 @@ import { import { CurrentUserPermissionsService } from '../../../../../core/src/core/permissions/current-user-permissions.service'; import { environment } from '../../../../../core/src/environments/environment.prod'; import { IPageSideNavTab } from '../../../../../core/src/features/dashboard/page-side-nav/page-side-nav.component'; -import { FavoritesConfigMapper } from '../../../../../core/src/shared/components/favorites-meta-card/favorite-config-mapper'; +import { FavoritesConfigMapper } from '../../../../../store/src/favorite-config-mapper'; import { UserFavoriteEndpoint } from '../../../../../store/src/types/user-favorites.types'; import { CfCurrentUserPermissions } from '../../../user-permissions/cf-user-permissions-checkers'; import { CloudFoundryEndpointService } from '../services/cloud-foundry-endpoint.service'; diff --git a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/edit-organization/edit-organization-step/edit-organization-step.component.ts b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/edit-organization/edit-organization-step/edit-organization-step.component.ts index cc3e90927d..5a91738c56 100644 --- a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/edit-organization/edit-organization-step/edit-organization-step.component.ts +++ b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/edit-organization/edit-organization-step/edit-organization-step.component.ts @@ -11,7 +11,7 @@ import { } from '../../../../../../cloud-foundry/src/entity-relations/entity-relations.types'; import { safeUnsubscribe } from '../../../../../../core/src/core/utils.service'; import { StepOnNextFunction } from '../../../../../../core/src/shared/components/stepper/step/step.component'; -import { endpointSchemaKey } from '../../../../../../store/src/helpers/entity-factory'; +import { endpointEntityType } from '../../../../../../store/src/helpers/stratos-entity-factory'; import { PaginationMonitorFactory } from '../../../../../../store/src/monitors/pagination-monitor.factory'; import { ActionState } from '../../../../../../store/src/reducers/api-request-reducer/types'; import { getPaginationObservables } from '../../../../../../store/src/reducers/pagination-reducer/pagination-reducer.helper'; @@ -114,7 +114,7 @@ export class EditOrganizationStepComponent implements OnInit, OnDestroy { ); this.fetchOrgsSub = this.allOrgsInEndpoint$.subscribe(); - const quotaPaginationKey = createEntityRelationPaginationKey(endpointSchemaKey, this.cfGuid); + const quotaPaginationKey = createEntityRelationPaginationKey(endpointEntityType, this.cfGuid); this.quotaDefinitions$ = cfEntityCatalog.quotaDefinition.store.getPaginationService( quotaPaginationKey, this.cfGuid, { includeRelations: [] } ).entities$.pipe( diff --git a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/quota-definition-form/quota-definition-form.component.ts b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/quota-definition-form/quota-definition-form.component.ts index f271b4ec36..d330a31aec 100644 --- a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/quota-definition-form/quota-definition-form.component.ts +++ b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/quota-definition-form/quota-definition-form.component.ts @@ -8,7 +8,7 @@ import { createEntityRelationPaginationKey } from '../../../../../cloud-foundry/ import { ActiveRouteCfOrgSpace } from '../../../../../cloud-foundry/src/features/cloud-foundry/cf-page.types'; import { getActiveRouteCfOrgSpaceProvider } from '../../../../../cloud-foundry/src/features/cloud-foundry/cf.helpers'; import { safeUnsubscribe } from '../../../../../core/src/core/utils.service'; -import { endpointSchemaKey } from '../../../../../store/src/helpers/entity-factory'; +import { endpointEntityType } from '../../../../../store/src/helpers/stratos-entity-factory'; import { IQuotaDefinition } from '../../../cf-api.types'; export interface QuotaFormValues { @@ -71,7 +71,7 @@ export class QuotaDefinitionFormComponent implements OnInit, OnDestroy { } fetchQuotasDefinitions() { - const quotaPaginationKey = createEntityRelationPaginationKey(endpointSchemaKey, this.cfGuid); + const quotaPaginationKey = createEntityRelationPaginationKey(endpointEntityType, this.cfGuid); const quotaDefinitions$ = cfEntityCatalog.quotaDefinition.store.getPaginationService(quotaPaginationKey, this.cfGuid, {}) .entities$.pipe( filter(o => !!o), diff --git a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/services/cloud-foundry-endpoint.service.ts b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/services/cloud-foundry-endpoint.service.ts index 7f489dbfb6..eec79aba70 100644 --- a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/services/cloud-foundry-endpoint.service.ts +++ b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/services/cloud-foundry-endpoint.service.ts @@ -17,13 +17,12 @@ import { createEntityRelationPaginationKey, } from '../../../../../cloud-foundry/src/entity-relations/entity-relations.types'; import { CfApplicationState } from '../../../../../cloud-foundry/src/store/types/application.types'; -import { GetAllEndpoints } from '../../../../../store/src/actions/endpoint.actions'; import { EntityService } from '../../../../../store/src/entity-service'; -import { EntityServiceFactory } from '../../../../../store/src/entity-service-factory.service'; -import { endpointSchemaKey } from '../../../../../store/src/helpers/entity-factory'; +import { endpointEntityType } from '../../../../../store/src/helpers/stratos-entity-factory'; import { PaginationMonitorFactory } from '../../../../../store/src/monitors/pagination-monitor.factory'; import { getPaginationObservables } from '../../../../../store/src/reducers/pagination-reducer/pagination-reducer.helper'; import { PaginationObservables } from '../../../../../store/src/reducers/pagination-reducer/pagination-reducer.types'; +import { stratosEntityCatalog } from '../../../../../store/src/stratos-entity-catalog'; import { APIResource, EntityInfo } from '../../../../../store/src/types/api.types'; import { EndpointModel, EndpointUser } from '../../../../../store/src/types/endpoint.types'; import { PaginatedAction } from '../../../../../store/src/types/pagination.types'; @@ -69,8 +68,8 @@ export class CloudFoundryEndpointService { static createGetAllOrganizations(cfGuid: string) { const paginationKey = cfGuid ? - createEntityRelationPaginationKey(endpointSchemaKey, cfGuid) - : createEntityRelationPaginationKey(endpointSchemaKey); + createEntityRelationPaginationKey(endpointEntityType, cfGuid) + : createEntityRelationPaginationKey(endpointEntityType); const getAllOrganizationsAction = cfEntityCatalog.org.actions.getMultiple(cfGuid, paginationKey, { includeRelations: [ @@ -84,8 +83,8 @@ export class CloudFoundryEndpointService { } static createGetAllOrganizationsLimitedSchema(cfGuid: string) { const paginationKey = cfGuid ? - createEntityRelationPaginationKey(endpointSchemaKey, cfGuid) - : createEntityRelationPaginationKey(endpointSchemaKey); + createEntityRelationPaginationKey(endpointEntityType, cfGuid) + : createEntityRelationPaginationKey(endpointEntityType); const getAllOrganizationsAction = cfEntityCatalog.org.actions.getMultiple(cfGuid, paginationKey, { includeRelations: [ @@ -138,16 +137,12 @@ export class CloudFoundryEndpointService { constructor( public activeRouteCfOrgSpace: ActiveRouteCfOrgSpace, private store: Store, - private entityServiceFactory: EntityServiceFactory, private cfUserService: CfUserService, private pmf: PaginationMonitorFactory, ) { this.cfGuid = activeRouteCfOrgSpace.cfGuid; - this.cfEndpointEntityService = this.entityServiceFactory.create( - this.cfGuid, - new GetAllEndpoints() - ); + this.cfEndpointEntityService = stratosEntityCatalog.endpoint.store.getEntityService(this.cfGuid); this.cfInfoEntityService = cfEntityCatalog.cfInfo.store.getEntityService(this.cfGuid) this.constructCoreObservables(); diff --git a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/services/cloud-foundry-org-space-quota.ts b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/services/cloud-foundry-org-space-quota.ts index 0e89121107..e02ed1ae30 100644 --- a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/services/cloud-foundry-org-space-quota.ts +++ b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/services/cloud-foundry-org-space-quota.ts @@ -3,9 +3,9 @@ import { filter, first, map, switchMap } from 'rxjs/operators'; import { truthyIncludingZero } from '../../../../../core/src/core/utils.service'; import { determineCardStatus } from '../../../../../core/src/shared/components/cards/card-status/card-status.component'; -import { StratosStatus } from '../../../../../core/src/shared/shared.types'; import { EntityMonitorFactory } from '../../../../../store/src/monitors/entity-monitor.factory.service'; import { APIResource } from '../../../../../store/src/types/api.types'; +import { StratosStatus } from '../../../../../store/src/types/shared.types'; import { IApp, IOrganization, ISpace } from '../../../cf-api.types'; import { CFEntityConfig } from '../../../cf-types'; import { CloudFoundryEndpointService } from './cloud-foundry-endpoint.service'; diff --git a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/services/cloud-foundry-organization-quota.ts b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/services/cloud-foundry-organization-quota.ts index 932894115e..9c3bcbf845 100644 --- a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/services/cloud-foundry-organization-quota.ts +++ b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/services/cloud-foundry-organization-quota.ts @@ -1,9 +1,9 @@ import { Observable } from 'rxjs'; import { organizationEntityType } from '../../../../../cloud-foundry/src/cf-entity-types'; -import { StratosStatus } from '../../../../../core/src/shared/shared.types'; import { EntityMonitorFactory } from '../../../../../store/src/monitors/entity-monitor.factory.service'; import { APIResource } from '../../../../../store/src/types/api.types'; +import { StratosStatus } from '../../../../../store/src/types/shared.types'; import { IApp, IOrganization } from '../../../cf-api.types'; import { getEntityFlattenedList, getStartedAppInstanceCount } from '../../../cf.helpers'; import { CloudFoundryEndpointService } from './cloud-foundry-endpoint.service'; diff --git a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/services/cloud-foundry-space-quota.ts b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/services/cloud-foundry-space-quota.ts index 1be45b3e30..692fad26d8 100644 --- a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/services/cloud-foundry-space-quota.ts +++ b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/services/cloud-foundry-space-quota.ts @@ -1,9 +1,9 @@ import { Observable } from 'rxjs'; import { spaceEntityType } from '../../../../../cloud-foundry/src/cf-entity-types'; -import { StratosStatus } from '../../../../../core/src/shared/shared.types'; import { EntityMonitorFactory } from '../../../../../store/src/monitors/entity-monitor.factory.service'; import { APIResource } from '../../../../../store/src/types/api.types'; +import { StratosStatus } from '../../../../../store/src/types/shared.types'; import { IApp, ISpace } from '../../../cf-api.types'; import { getStartedAppInstanceCount } from '../../../cf.helpers'; import { CloudFoundryEndpointService } from './cloud-foundry-endpoint.service'; diff --git a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/space-quota-definition-form/space-quota-definition-form.component.ts b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/space-quota-definition-form/space-quota-definition-form.component.ts index a6bacfc2c6..5e648aba80 100644 --- a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/space-quota-definition-form/space-quota-definition-form.component.ts +++ b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/space-quota-definition-form/space-quota-definition-form.component.ts @@ -9,7 +9,7 @@ import { createEntityRelationPaginationKey } from '../../../../../cloud-foundry/ import { ActiveRouteCfOrgSpace } from '../../../../../cloud-foundry/src/features/cloud-foundry/cf-page.types'; import { getActiveRouteCfOrgSpaceProvider } from '../../../../../cloud-foundry/src/features/cloud-foundry/cf.helpers'; import { safeUnsubscribe } from '../../../../../core/src/core/utils.service'; -import { endpointSchemaKey } from '../../../../../store/src/helpers/entity-factory'; +import { endpointEntityType } from '../../../../../store/src/helpers/stratos-entity-factory'; import { IQuotaDefinition } from '../../../cf-api.types'; @@ -65,7 +65,7 @@ export class SpaceQuotaDefinitionFormComponent implements OnInit, OnDestroy { this.spaceQuotaDefinitions$ = cfEntityCatalog.spaceQuota.store.getAllInOrganization.getPaginationService( this.orgGuid, this.cfGuid, - createEntityRelationPaginationKey(endpointSchemaKey, this.cfGuid) + createEntityRelationPaginationKey(endpointEntityType, this.cfGuid) ).entities$ .pipe( filter(o => !!o), diff --git a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/space-quota-definition/space-quota-definition.component.spec.ts b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/space-quota-definition/space-quota-definition.component.spec.ts index 6ef73eb96f..ee79e073f2 100644 --- a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/space-quota-definition/space-quota-definition.component.spec.ts +++ b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/space-quota-definition/space-quota-definition.component.spec.ts @@ -3,10 +3,10 @@ import { ActivatedRoute } from '@angular/router'; import { Store } from '@ngrx/store'; import { testSCFEndpoint, testSCFEndpointGuid } from '@stratosui/store/testing'; -import { endpointEntitySchema } from '../../../../../core/src/base-entity-schemas'; import { TabNavService } from '../../../../../core/tab-nav.service'; import { EntityCatalogHelpers } from '../../../../../store/src/entity-catalog/entity-catalog.helper'; import { EntityCatalogEntityConfig } from '../../../../../store/src/entity-catalog/entity-catalog.types'; +import { endpointEntityType, stratosEntityFactory } from '../../../../../store/src/helpers/stratos-entity-factory'; import { NormalizedResponse } from '../../../../../store/src/types/api.types'; import { WrapperRequestActionSuccess } from '../../../../../store/src/types/request.types'; import { @@ -51,7 +51,7 @@ describe('SpaceQuotaDefinitionComponent', () => { .compileComponents(); - const stratosEndpointEntityConfig: EntityCatalogEntityConfig = endpointEntitySchema; + const stratosEndpointEntityConfig: EntityCatalogEntityConfig = stratosEntityFactory(endpointEntityType); const stratosEndpointEntityKey = EntityCatalogHelpers.buildEntityKey( stratosEndpointEntityConfig.entityType, stratosEndpointEntityConfig.endpointType diff --git a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell-base/cloud-foundry-cell-base.component.ts b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell-base/cloud-foundry-cell-base.component.ts index 07a77cddd6..cd137d502e 100644 --- a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell-base/cloud-foundry-cell-base.component.ts +++ b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell-base/cloud-foundry-cell-base.component.ts @@ -2,9 +2,9 @@ import { Component } from '@angular/core'; import { Observable } from 'rxjs'; import { first, map } from 'rxjs/operators'; -import { metricEntityType } from '../../../../../../../../core/src/base-entity-schemas'; import { IPageSideNavTab } from '../../../../../../../../core/src/features/dashboard/page-side-nav/page-side-nav.component'; import { IHeaderBreadcrumb } from '../../../../../../../../core/src/shared/components/page-header/page-header.types'; +import { metricEntityType } from '../../../../../../../../store/src/helpers/stratos-entity-factory'; import { cfEntityFactory } from '../../../../../../cf-entity-factory'; import { getActiveRouteCfCellProvider } from '../../../../cf.helpers'; import { CloudFoundryEndpointService } from '../../../../services/cloud-foundry-endpoint.service'; diff --git a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell-charts/cloud-foundry-cell-charts.component.ts b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell-charts/cloud-foundry-cell-charts.component.ts index 081ec14430..e43d9ca244 100644 --- a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell-charts/cloud-foundry-cell-charts.component.ts +++ b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell-charts/cloud-foundry-cell-charts.component.ts @@ -4,9 +4,8 @@ import { MetricsConfig } from '../../../../../../../../core/src/shared/component import { MetricsLineChartConfig, } from '../../../../../../../../core/src/shared/components/metrics-chart/metrics-chart.types'; -import { MetricQueryType } from '../../../../../../../../core/src/shared/services/metrics-range-selector.types'; import { IMetricMatrixResult } from '../../../../../../../../store/src/types/base-metric.types'; -import { IMetricCell } from '../../../../../../../../store/src/types/metric.types'; +import { IMetricCell, MetricQueryType } from '../../../../../../../../store/src/types/metric.types'; import { CloudFoundryCellService } from '../cloud-foundry-cell.service'; @Component({ diff --git a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell-summary/cloud-foundry-cell-summary.component.spec.ts b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell-summary/cloud-foundry-cell-summary.component.spec.ts index e8c160cbcf..669e75977b 100644 --- a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell-summary/cloud-foundry-cell-summary.component.spec.ts +++ b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell-summary/cloud-foundry-cell-summary.component.spec.ts @@ -10,8 +10,8 @@ import { import { MetricsChartHelpers, } from '../../../../../../../../core/src/shared/components/metrics-chart/metrics.component.helpers'; -import { MetricQueryType } from '../../../../../../../../core/src/shared/services/metrics-range-selector.types'; import { MetricQueryConfig } from '../../../../../../../../store/src/actions/metrics.actions'; +import { MetricQueryType } from '../../../../../../../../store/src/types/metric.types'; import { generateCfBaseTestModules } from '../../../../../../../test-framework/cloud-foundry-endpoint-service.helper'; import { FetchCFCellMetricsAction } from '../../../../../../actions/cf-metrics.actions'; import { ActiveRouteCfCell } from '../../../../cf-page.types'; diff --git a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell-summary/cloud-foundry-cell-summary.component.ts b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell-summary/cloud-foundry-cell-summary.component.ts index e3427cd79b..2109f6dee5 100644 --- a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell-summary/cloud-foundry-cell-summary.component.ts +++ b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell-summary/cloud-foundry-cell-summary.component.ts @@ -3,7 +3,7 @@ import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { ListConfig } from '../../../../../../../../core/src/shared/components/list/list.component.types'; -import { StratosStatus } from '../../../../../../../../core/src/shared/shared.types'; +import { StratosStatus } from '../../../../../../../../store/src/types/shared.types'; import { CfCellHealthListConfigService, } from '../../../../../../shared/components/list/list-types/cf-cell-health/cf-cell-health-list-config.service'; diff --git a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell.service.ts b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell.service.ts index fb6c1e76ec..708a438723 100644 --- a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell.service.ts +++ b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell.service.ts @@ -8,13 +8,12 @@ import { MetricsLineChartConfig } from '../../../../../../../core/src/shared/com import { MetricsChartHelpers, } from '../../../../../../../core/src/shared/components/metrics-chart/metrics.component.helpers'; -import { MetricQueryType } from '../../../../../../../core/src/shared/services/metrics-range-selector.types'; import { MetricQueryConfig } from '../../../../../../../store/src/actions/metrics.actions'; import { AppState } from '../../../../../../../store/src/app-state'; import { EntityServiceFactory } from '../../../../../../../store/src/entity-service-factory.service'; import { PaginationMonitorFactory } from '../../../../../../../store/src/monitors/pagination-monitor.factory'; import { IMetricMatrixResult, IMetrics, IMetricVectorResult } from '../../../../../../../store/src/types/base-metric.types'; -import { IMetricCell } from '../../../../../../../store/src/types/metric.types'; +import { IMetricCell, MetricQueryType } from '../../../../../../../store/src/types/metric.types'; import { FetchCFCellMetricsAction } from '../../../../../actions/cf-metrics.actions'; import { CfCellHelper } from '../../../cf-cell.helpers'; import { ActiveRouteCfCell } from '../../../cf-page.types'; diff --git a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-organizations/cloud-foundry-organization-base/cloud-foundry-organization-base.component.ts b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-organizations/cloud-foundry-organization-base/cloud-foundry-organization-base.component.ts index 0c83c22d0f..f9a24ac961 100644 --- a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-organizations/cloud-foundry-organization-base/cloud-foundry-organization-base.component.ts +++ b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-organizations/cloud-foundry-organization-base/cloud-foundry-organization-base.component.ts @@ -11,15 +11,13 @@ import { StratosActionType, StratosTabType, } from '../../../../../../../core/src/core/extension/extension-service'; -import { getFavoriteFromEntity } from '../../../../../../../core/src/core/user-favorite-helpers'; import { environment } from '../../../../../../../core/src/environments/environment.prod'; import { IPageSideNavTab } from '../../../../../../../core/src/features/dashboard/page-side-nav/page-side-nav.component'; -import { - FavoritesConfigMapper, -} from '../../../../../../../core/src/shared/components/favorites-meta-card/favorite-config-mapper'; import { IHeaderBreadcrumb } from '../../../../../../../core/src/shared/components/page-header/page-header.types'; +import { FavoritesConfigMapper } from '../../../../../../../store/src/favorite-config-mapper'; import { EntitySchema } from '../../../../../../../store/src/helpers/entity-schema'; import { UserFavorite } from '../../../../../../../store/src/types/user-favorites.types'; +import { getFavoriteFromEntity } from '../../../../../../../store/src/user-favorite-helpers'; import { cfEntityFactory } from '../../../../../cf-entity-factory'; import { CF_ENDPOINT_TYPE } from '../../../../../cf-types'; import { CfUserService } from '../../../../../shared/data-services/cf-user.service'; diff --git a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-organizations/cloud-foundry-organization-spaces/cloud-foundry-space-base/cloud-foundry-space-base.component.ts b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-organizations/cloud-foundry-organization-spaces/cloud-foundry-space-base/cloud-foundry-space-base.component.ts index c8c42c5c5a..5ae190a43b 100644 --- a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-organizations/cloud-foundry-organization-spaces/cloud-foundry-space-base/cloud-foundry-space-base.component.ts +++ b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-organizations/cloud-foundry-organization-spaces/cloud-foundry-space-base/cloud-foundry-space-base.component.ts @@ -13,16 +13,14 @@ import { StratosActionType, StratosTabType, } from '../../../../../../../../core/src/core/extension/extension-service'; -import { getFavoriteFromEntity } from '../../../../../../../../core/src/core/user-favorite-helpers'; import { environment } from '../../../../../../../../core/src/environments/environment.prod'; import { IPageSideNavTab } from '../../../../../../../../core/src/features/dashboard/page-side-nav/page-side-nav.component'; import { ConfirmationDialogService } from '../../../../../../../../core/src/shared/components/confirmation-dialog.service'; -import { - FavoritesConfigMapper, -} from '../../../../../../../../core/src/shared/components/favorites-meta-card/favorite-config-mapper'; import { IHeaderBreadcrumb } from '../../../../../../../../core/src/shared/components/page-header/page-header.types'; import { RouterNav } from '../../../../../../../../store/src/actions/router.actions'; +import { FavoritesConfigMapper } from '../../../../../../../../store/src/favorite-config-mapper'; import { UserFavorite } from '../../../../../../../../store/src/types/user-favorites.types'; +import { getFavoriteFromEntity } from '../../../../../../../../store/src/user-favorite-helpers'; import { cfEntityFactory } from '../../../../../../cf-entity-factory'; import { CF_ENDPOINT_TYPE } from '../../../../../../cf-types'; import { CfUserService } from '../../../../../../shared/data-services/cf-user.service'; diff --git a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/user-invites/user-invite.service.ts b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/user-invites/user-invite.service.ts index 755128bd1b..7331193e11 100644 --- a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/user-invites/user-invite.service.ts +++ b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/user-invites/user-invite.service.ts @@ -10,7 +10,7 @@ import { CurrentUserPermissionsService } from '../../../../../core/src/core/perm import { environment } from '../../../../../core/src/environments/environment.prod'; import { ConfirmationDialogConfig } from '../../../../../core/src/shared/components/confirmation-dialog.config'; import { ConfirmationDialogService } from '../../../../../core/src/shared/components/confirmation-dialog.service'; -import { GetSystemInfo } from '../../../../../store/src/actions/system.actions'; +import { stratosEntityCatalog } from '../../../../../store/src/stratos-entity-catalog'; import { CfCurrentUserPermissions } from '../../../user-permissions/cf-user-permissions-checkers'; import { ActiveRouteCfOrgSpace } from '../cf-page.types'; import { waitForCFPermissions } from '../cf.helpers'; @@ -57,7 +57,6 @@ interface UserInviteSend { export class UserInviteConfigureService { constructor( - private store: Store, private http: HttpClient, private snackBar: MatSnackBar, private confirmDialog: ConfirmationDialogService, @@ -70,7 +69,7 @@ export class UserInviteConfigureService { const url = `/pp/${proxyAPIVersion}/invite/${cfGUID}`; const obs$ = this.http.post(url, formData).pipe( map(v => { - this.store.dispatch(new GetSystemInfo()); + stratosEntityCatalog.systemInfo.api.getSystemInfo() return { error: false }; @@ -99,7 +98,7 @@ export class UserInviteConfigureService { const url = `/pp/${proxyAPIVersion}/invite/${cfGUID}`; this.http.delete(url).pipe( map(v => { - this.store.dispatch(new GetSystemInfo()); + stratosEntityCatalog.systemInfo.api.getSystemInfo() return { error: false, errorMessage: '' diff --git a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/users/manage-users/cf-roles.service.ts b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/users/manage-users/cf-roles.service.ts index 56a88ed334..faa4668b08 100644 --- a/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/users/manage-users/cf-roles.service.ts +++ b/src/frontend/packages/cloud-foundry/src/features/cloud-foundry/users/manage-users/cf-roles.service.ts @@ -18,7 +18,7 @@ import { createEntityRelationPaginationKey, } from '../../../../../../cloud-foundry/src/entity-relations/entity-relations.types'; import { CurrentUserPermissionsService } from '../../../../../../core/src/core/permissions/current-user-permissions.service'; -import { endpointSchemaKey } from '../../../../../../store/src/helpers/entity-factory'; +import { endpointEntityType } from '../../../../../../store/src/helpers/stratos-entity-factory'; import { APIResource, EntityInfo } from '../../../../../../store/src/types/api.types'; import { UsersRolesSetChanges } from '../../../../actions/users-roles.actions'; import { IOrganization, ISpace } from '../../../../cf-api.types'; @@ -239,7 +239,7 @@ export class CfRolesService { fetchOrgs(cfGuid: string): Observable[]> { if (!this.cfOrgs[cfGuid]) { - const paginationKey = createEntityRelationPaginationKey(endpointSchemaKey, cfGuid); + const paginationKey = createEntityRelationPaginationKey(endpointEntityType, cfGuid); const orgs$ = cfEntityCatalog.org.store.getPaginationService( cfGuid, paginationKey, diff --git a/src/frontend/packages/cloud-foundry/src/features/service-catalog/service-tabs-base/service-tabs-base.component.html b/src/frontend/packages/cloud-foundry/src/features/service-catalog/service-tabs-base/service-tabs-base.component.html index f6b4c53c11..4a7bb72774 100644 --- a/src/frontend/packages/cloud-foundry/src/features/service-catalog/service-tabs-base/service-tabs-base.component.html +++ b/src/frontend/packages/cloud-foundry/src/features/service-catalog/service-tabs-base/service-tabs-base.component.html @@ -1,11 +1,11 @@
- {{ getServiceLabel() | async }} + {{ serviceLabel$ | async }}
- diff --git a/src/frontend/packages/cloud-foundry/src/features/service-catalog/service-tabs-base/service-tabs-base.component.ts b/src/frontend/packages/cloud-foundry/src/features/service-catalog/service-tabs-base/service-tabs-base.component.ts index 817f55a6e2..763af35529 100644 --- a/src/frontend/packages/cloud-foundry/src/features/service-catalog/service-tabs-base/service-tabs-base.component.ts +++ b/src/frontend/packages/cloud-foundry/src/features/service-catalog/service-tabs-base/service-tabs-base.component.ts @@ -6,6 +6,7 @@ import { map, publishReplay, refCount } from 'rxjs/operators'; import { CFAppState } from '../../../../../cloud-foundry/src/cf-app-state'; import { IPageSideNavTab } from '../../../../../core/src/features/dashboard/page-side-nav/page-side-nav.component'; import { IHeaderBreadcrumb } from '../../../../../core/src/shared/components/page-header/page-header.types'; +import { CSI_CANCEL_URL } from '../../../shared/components/add-service-instance/csi-mode.service'; import { CfCurrentUserPermissions } from '../../../user-permissions/cf-user-permissions-checkers'; import { getServiceName } from '../services-helper'; import { ServicesService } from '../services.service'; @@ -20,6 +21,9 @@ export class ServiceTabsBaseComponent { toolTipText$: Observable; hasVisiblePlans$: Observable; servicesSubscription: Subscription; + isServiceSpaceScoped$: Observable; + addServiceInstanceLink: string[]; + serviceLabel$: Observable; tabLinks: IPageSideNavTab[] = [ { @@ -59,24 +63,23 @@ export class ServiceTabsBaseComponent { return 'Cannot create service instance (no public or visible plans exist for service)'; } })); - - } - - addServiceInstanceLink = () => [ - '/marketplace', - this.servicesService.cfGuid, - this.servicesService.serviceGuid, - 'create' - ] - - isServiceSpaceScoped = () => this.servicesService.isSpaceScoped$; - - getServiceLabel = (): Observable => { - return this.servicesService.service$.pipe( + this.isServiceSpaceScoped$ = this.servicesService.isSpaceScoped$.pipe( + map(queryParams => ({ + ...queryParams, + [CSI_CANCEL_URL]: `/marketplace/${this.servicesService.cfGuid}/${this.servicesService.serviceGuid}/instances` + })) + ) + this.addServiceInstanceLink = [ + '/marketplace', + this.servicesService.cfGuid, + this.servicesService.serviceGuid, + 'create' + ] + this.serviceLabel$ = this.servicesService.service$.pipe( map(getServiceName), publishReplay(1), refCount() - ); + ) } } diff --git a/src/frontend/packages/cloud-foundry/src/features/service-catalog/services-helper.ts b/src/frontend/packages/cloud-foundry/src/features/service-catalog/services-helper.ts index 9f55596f21..d3fce2628e 100644 --- a/src/frontend/packages/cloud-foundry/src/features/service-catalog/services-helper.ts +++ b/src/frontend/packages/cloud-foundry/src/features/service-catalog/services-helper.ts @@ -5,10 +5,10 @@ import { combineLatest, filter, first, map, share, switchMap } from 'rxjs/operat import { createEntityRelationPaginationKey } from '../../../../cloud-foundry/src/entity-relations/entity-relations.types'; import { getIdFromRoute, safeStringToObj } from '../../../../core/src/core/utils.service'; -import { StratosStatus } from '../../../../core/src/shared/shared.types'; import { EntityService } from '../../../../store/src/entity-service'; import { PaginationMonitorFactory } from '../../../../store/src/monitors/pagination-monitor.factory'; import { APIResource } from '../../../../store/src/types/api.types'; +import { StratosStatus } from '../../../../store/src/types/shared.types'; import { IService, IServiceBroker, diff --git a/src/frontend/packages/cloud-foundry/src/features/service-catalog/services.service.ts b/src/frontend/packages/cloud-foundry/src/features/service-catalog/services.service.ts index a550800a57..05d65754d3 100644 --- a/src/frontend/packages/cloud-foundry/src/features/service-catalog/services.service.ts +++ b/src/frontend/packages/cloud-foundry/src/features/service-catalog/services.service.ts @@ -132,6 +132,7 @@ export class ServicesService { map(o => (o.length === 0 ? null : o[0])) ); this.isSpaceScoped$ = this.serviceBroker$.pipe( + first(), map(o => o ? o.entity.space_guid : null), switchMap(spaceGuid => { if (!spaceGuid) { @@ -151,7 +152,8 @@ export class ServicesService { })), ); } - }) + }), + first() ); this.serviceInstances$ = this.allServiceInstances$.pipe( map(instances => instances.filter(instance => instance.entity.service_guid === this.serviceGuid)) diff --git a/src/frontend/packages/cloud-foundry/src/features/services/services-wall/services-wall.component.html b/src/frontend/packages/cloud-foundry/src/features/services/services-wall/services-wall.component.html index cf6322f5e7..b47b7c7e12 100644 --- a/src/frontend/packages/cloud-foundry/src/features/services/services-wall/services-wall.component.html +++ b/src/frontend/packages/cloud-foundry/src/features/services/services-wall/services-wall.component.html @@ -3,7 +3,7 @@

Services

- diff --git a/src/frontend/packages/cloud-foundry/src/features/services/services-wall/services-wall.component.ts b/src/frontend/packages/cloud-foundry/src/features/services/services-wall/services-wall.component.ts index 96d806b0c5..be3e78240d 100644 --- a/src/frontend/packages/cloud-foundry/src/features/services/services-wall/services-wall.component.ts +++ b/src/frontend/packages/cloud-foundry/src/features/services/services-wall/services-wall.component.ts @@ -14,6 +14,7 @@ import { } from '../../../../../cloud-foundry/src/shared/data-services/cf-org-space-service.service'; import { CloudFoundryService } from '../../../../../cloud-foundry/src/shared/data-services/cloud-foundry.service'; import { ListConfig } from '../../../../../core/src/shared/components/list/list.component.types'; +import { CSI_CANCEL_URL } from '../../../shared/components/add-service-instance/csi-mode.service'; import { CfCurrentUserPermissions } from '../../../user-permissions/cf-user-permissions-checkers'; @Component({ @@ -35,6 +36,7 @@ export class ServicesWallComponent implements OnDestroy { canCreateServiceInstance: CfCurrentUserPermissions; initCfOrgSpaceService: Subscription; cfIds$: Observable; + location: { [CSI_CANCEL_URL]: string }; constructor( public cloudFoundryService: CloudFoundryService, @@ -57,6 +59,10 @@ export class ServicesWallComponent implements OnDestroy { this.haveConnectedCf$ = cloudFoundryService.connectedCFEndpoints$.pipe( map(endpoints => !!endpoints && endpoints.length > 0) ); + + this.location = { + [CSI_CANCEL_URL]: `/services` + } } ngOnDestroy(): void { diff --git a/src/frontend/packages/cloud-foundry/src/features/services/services/services-wall.service.ts b/src/frontend/packages/cloud-foundry/src/features/services/services/services-wall.service.ts index c6ebd18e85..eadc97f032 100644 --- a/src/frontend/packages/cloud-foundry/src/features/services/services/services-wall.service.ts +++ b/src/frontend/packages/cloud-foundry/src/features/services/services/services-wall.service.ts @@ -3,7 +3,7 @@ import { Observable } from 'rxjs'; import { filter, map, publishReplay, refCount } from 'rxjs/operators'; import { serviceEntityType } from '../../../../../cloud-foundry/src/cf-entity-types'; -import { endpointSchemaKey } from '../../../../../store/src/helpers/entity-factory'; +import { endpointEntityType } from '../../../../../store/src/helpers/stratos-entity-factory'; import { APIResource } from '../../../../../store/src/types/api.types'; import { IService } from '../../../cf-api-svc.types'; import { cfEntityCatalog } from '../../../cf-entity-catalog'; @@ -18,7 +18,7 @@ export class ServicesWallService { } initServicesObservable = () => { - const paginationKey = createEntityRelationPaginationKey(endpointSchemaKey); + const paginationKey = createEntityRelationPaginationKey(endpointEntityType); return cfEntityCatalog.service.store.getPaginationService(null, paginationKey, {}).entities$ } diff --git a/src/frontend/packages/cloud-foundry/src/public_api.ts b/src/frontend/packages/cloud-foundry/src/public_api.ts index eef53f2d79..dbe7a16cbd 100644 --- a/src/frontend/packages/cloud-foundry/src/public_api.ts +++ b/src/frontend/packages/cloud-foundry/src/public_api.ts @@ -5,3 +5,5 @@ // export * from './lib/cloud-foundry.service'; export * from './lib/cloud-foundry.component'; export * from './lib/cloud-foundry.module'; + +export * from './cf-api-svc.types'; \ No newline at end of file diff --git a/src/frontend/packages/cloud-foundry/src/shared/cf-shared.module.ts b/src/frontend/packages/cloud-foundry/src/shared/cf-shared.module.ts index 7da0831fa8..aeef92fd78 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/cf-shared.module.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/cf-shared.module.ts @@ -5,9 +5,6 @@ import { MaterialDesignFrameworkModule } from '@cfstratos/ajsf-material'; import { CoreModule } from '../../../core/src/core/core.module'; import { CardCell, TableCellCustom } from '../../../core/src/shared/components/list/list.types'; import { SharedModule } from '../../../core/src/shared/shared.module'; -import { - ApplicationInstanceChartComponent, -} from '../features/applications/application/application-instance-chart/application-instance-chart.component'; import { AddServiceInstanceBaseStepComponent, } from './components/add-service-instance/add-service-instance-base-step/add-service-instance-base-step.component'; @@ -23,6 +20,9 @@ import { import { SpecifyUserProvidedDetailsComponent, } from './components/add-service-instance/specify-user-provided-details/specify-user-provided-details.component'; +import { + ApplicationInstanceChartComponent, +} from './components/application-instance-chart/application-instance-chart.component'; import { CardAppInstancesComponent } from './components/cards/card-app-instances/card-app-instances.component'; import { CardAppStatusComponent } from './components/cards/card-app-status/card-app-status.component'; import { CardAppUptimeComponent } from './components/cards/card-app-uptime/card-app-uptime.component'; diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/add-service-instance/add-service-instance-base-step/add-service-instance-base-step.component.html b/src/frontend/packages/cloud-foundry/src/shared/components/add-service-instance/add-service-instance-base-step/add-service-instance-base-step.component.html index bdb623280b..20a2ba742b 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/add-service-instance/add-service-instance-base-step/add-service-instance-base-step.component.html +++ b/src/frontend/packages/cloud-foundry/src/shared/components/add-service-instance/add-service-instance-base-step/add-service-instance-base-step.component.html @@ -1,7 +1,7 @@ Choose Service Type - +

Choose service type to {{ bindApp ? 'bind' : 'create' }}

diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/add-service-instance/add-service-instance-base-step/add-service-instance-base-step.component.ts b/src/frontend/packages/cloud-foundry/src/shared/components/add-service-instance/add-service-instance-base-step/add-service-instance-base-step.component.ts index 06f9214b75..2daa17cb4a 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/add-service-instance/add-service-instance-base-step/add-service-instance-base-step.component.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/add-service-instance/add-service-instance-base-step/add-service-instance-base-step.component.ts @@ -1,12 +1,14 @@ import { Component } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute } from '@angular/router'; import { Store } from '@ngrx/store'; import { CFAppState } from '../../../../../../cloud-foundry/src/cf-app-state'; +import { getIdFromRoute } from '../../../../../../core/src/core/utils.service'; import { BASE_REDIRECT_QUERY } from '../../../../../../core/src/shared/components/stepper/stepper.types'; import { TileConfigManager } from '../../../../../../core/src/shared/components/tile/tile-selector.helpers'; import { ITileConfig, ITileData } from '../../../../../../core/src/shared/components/tile/tile-selector.types'; import { RouterNav } from '../../../../../../store/src/actions/router.actions'; +import { CSI_CANCEL_URL } from '../csi-mode.service'; import { SERVICE_INSTANCE_TYPES } from './add-service-instance.types'; interface ICreateServiceTilesData extends ITileData { @@ -21,6 +23,7 @@ interface ICreateServiceTilesData extends ITileData { export class AddServiceInstanceBaseStepComponent { private tileManager = new TileConfigManager(); public serviceType: string; + public cancelUrl = '/services'; public tileSelectorConfig = [ this.tileManager.getNextTileConfig( @@ -44,16 +47,39 @@ export class AddServiceInstanceBaseStepComponent { this.serviceType = tile ? tile.data.type : null; this.pSelectedTile = tile; if (tile) { - const baseUrl = this.bindApp ? this.router.routerState.snapshot.url : '/services/new'; + const baseUrl = this.createServiceTileUrl(); this.store.dispatch(new RouterNav({ path: `${baseUrl}/${this.serviceType}`, query: { - [BASE_REDIRECT_QUERY]: baseUrl + [BASE_REDIRECT_QUERY]: baseUrl, // 'previous' destination + [CSI_CANCEL_URL]: this.cancelUrl // 'cancel' + 'success' destination } })); } } - constructor(private route: ActivatedRoute, private router: Router, public store: Store) { + + private cfId: string; + private appId: string; + + constructor( + private route: ActivatedRoute, + public store: Store + ) { this.bindApp = !!this.route.snapshot.data.bind; + if (this.bindApp) { + this.cfId = getIdFromRoute(this.route, 'endpointId'); + this.appId = getIdFromRoute(this.route, 'id'); + } + this.cancelUrl = this.createCancelUrl(); + } + + private createServiceTileUrl(): string { + return this.bindApp ? `/applications/${this.cfId}/${this.appId}/bind` : '/services/new' } + + private createCancelUrl(): string { + return this.bindApp ? `/applications/${this.cfId}/${this.appId}/services` : '/services' + } + + } diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/add-service-instance/csi-mode.service.ts b/src/frontend/packages/cloud-foundry/src/shared/components/add-service-instance/csi-mode.service.ts index 3c4fa72df5..ad65ce4410 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/add-service-instance/csi-mode.service.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/add-service-instance/csi-mode.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; +import { ActivatedRoute, Router } from '@angular/router'; import { filter, map, pairwise } from 'rxjs/operators'; import { SpaceScopedService } from '../../../../../cloud-foundry/src/features/service-catalog/services.service'; @@ -19,8 +19,23 @@ export const enum CreateServiceFormMode { BindServiceInstance = 'bind-service-instance', } +/** + * Where should the user be taken on cancel (and success). If not supplied will fall back on previous location and then deduced from + * params + */ +export const CSI_CANCEL_URL = 'cancel' + +/** + * Used when `CSI_CANCEL_URL` is not supplied + */ export const CANCEL_SPACE_ID_PARAM = 'space-guid'; +/** + * Used when `CSI_CANCEL_URL` is not supplied + */ export const CANCEL_ORG_ID_PARAM = 'org-guid'; +/** + * Used when `CSI_CANCEL_URL` is not supplied + */ export const CANCEL_USER_PROVIDED = 'up'; interface ViewDetail { @@ -44,12 +59,16 @@ export class CsiModeService { private mode: string; public viewDetail: ViewDetail; + /** + * Where should the user be taken on cancel (and success). Taken from url param, previous location or deduced + */ public cancelUrl: string; // This property is only used when launching the Create Service Instance Wizard from the Marketplace spaceScopedDetails: SpaceScopedService = { isSpaceScoped: false }; constructor( private activatedRoute: ActivatedRoute, + router: Router ) { const serviceId = getIdFromRoute(activatedRoute, 'serviceId'); const serviceInstanceId = getIdFromRoute(activatedRoute, 'serviceInstanceId'); @@ -118,6 +137,7 @@ export class CsiModeService { `/cloud-foundry/${cfId}/organizations/${orgGuid}/spaces/${spaceGuid}/${isUserProvided ? 'user-service-instances' : 'service-instances'}`; } + this.updateCancelUrl(this.activatedRoute, router); } getViewDetail = () => this.viewDetail; @@ -148,4 +168,33 @@ export class CsiModeService { ); } + private updateCancelUrl( + activatedRoute: ActivatedRoute, + router: Router + ) { + // cancelUrl determines where we go on cancel AND success + const cancelUrl = activatedRoute.snapshot.queryParamMap.get(CSI_CANCEL_URL); + if (cancelUrl) { + // Override cancelUrl with what's been passed in (probably came from the service selection pre-step) + this.cancelUrl = cancelUrl; + } else { + // There's some holes with the way cancelUrl in ctor is calculated + // - marketplace/service/instances list --> cancel goes to space service instance list + // - marketplace/service create instance --> cancel goes to marketplace/service/instance regardless of starting tab + // - .. others?? + // For simplicity always go back to the previous location + // - good catch all + // - doesn't work that well for marketplace/service create instance --> success (should go to marketplace/service/instance) + // - if user has refreshed on stepper (previous url was login) use the old cancelUrl best-guess value + const currentNavigation = router.getCurrentNavigation(); + if (currentNavigation && + currentNavigation.previousNavigation && + currentNavigation.previousNavigation.finalUrl && + currentNavigation.previousNavigation.finalUrl.toString() !== '/login' + ) { + this.cancelUrl = currentNavigation.previousNavigation.finalUrl.toString(); + } + } + } + } diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/add-service-instance/select-plan-step/select-plan-step.component.ts b/src/frontend/packages/cloud-foundry/src/shared/components/add-service-instance/select-plan-step/select-plan-step.component.ts index 961ada73a1..e1b2c4d645 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/add-service-instance/select-plan-step/select-plan-step.component.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/add-service-instance/select-plan-step/select-plan-step.component.ts @@ -39,8 +39,8 @@ import { } from '../../../../../../cloud-foundry/src/store/selectors/create-service-instance.selectors'; import { safeUnsubscribe } from '../../../../../../core/src/core/utils.service'; import { StepOnNextResult } from '../../../../../../core/src/shared/components/stepper/step/step.component'; -import { StratosStatus } from '../../../../../../core/src/shared/shared.types'; import { APIResource } from '../../../../../../store/src/types/api.types'; +import { StratosStatus } from '../../../../../../store/src/types/shared.types'; import { IServicePlan } from '../../../../cf-api-svc.types'; import { CreateServiceInstanceHelperServiceFactory } from '../create-service-instance-helper-service-factory.service'; import { CreateServiceInstanceHelper } from '../create-service-instance-helper.service'; diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/add-service-instance/specify-details-step/specify-details-step.component.ts b/src/frontend/packages/cloud-foundry/src/shared/components/add-service-instance/specify-details-step/specify-details-step.component.ts index 80ed214a56..ae2ed8a868 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/add-service-instance/specify-details-step/specify-details-step.component.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/add-service-instance/specify-details-step/specify-details-step.component.ts @@ -31,7 +31,6 @@ import { } from '../../../../../../cloud-foundry/src/actions/create-service-instance.actions'; import { pathGet, safeStringToObj } from '../../../../../../core/src/core/utils.service'; import { StepOnNextResult } from '../../../../../../core/src/shared/components/stepper/step/step.component'; -import { RouterNav } from '../../../../../../store/src/actions/router.actions'; import { getDefaultRequestState, RequestInfoState } from '../../../../../../store/src/reducers/api-request-reducer/types'; import { APIResource, NormalizedResponse } from '../../../../../../store/src/types/api.types'; import { UpdateServiceInstance } from '../../../../actions/service-instances.actions'; @@ -297,7 +296,7 @@ export class SpecifyDetailsStepComponent implements OnDestroy, AfterContentInit this.longRunningOpService.handleLongRunningCreateService(bindApp); // Return to app page instead of falling through to service page if (bindApp) { - return observableOf(this.routeToServices(state.cfGuid, state.bindAppGuid)); + return observableOf(this.routeToServices()); } } else if (request.error) { // The request has errored, report this back @@ -318,7 +317,7 @@ export class SpecifyDetailsStepComponent implements OnDestroy, AfterContentInit } else { // Refetch env vars for app, since they have been changed by CF cfEntityCatalog.appEnvVar.api.getMultiple(state.bindAppGuid, state.cfGuid); - return this.routeToServices(state.cfGuid, state.bindAppGuid); + return this.routeToServices(); } }) ); @@ -356,13 +355,12 @@ export class SpecifyDetailsStepComponent implements OnDestroy, AfterContentInit ); } - routeToServices = (cfGuid: string = null, appGuid: string = null): StepOnNextResult => { - if (this.modeService.isAppServicesMode()) { - this.store.dispatch(new RouterNav({ path: ['/applications', cfGuid, appGuid, 'services'] })); - } else { - this.store.dispatch(new RouterNav({ path: ['/services'] })); - } - return { success: true }; + routeToServices = (): StepOnNextResult => { + return { + success: true, + // We should always go back to where we came from, aka 'cancel' location. + redirect: true, + }; } private setServiceInstanceGuid = (request: { creating: boolean; error: boolean; response: { result: any[]; }; }) => diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/add-service-instance/specify-user-provided-details/specify-user-provided-details.component.ts b/src/frontend/packages/cloud-foundry/src/shared/components/add-service-instance/specify-user-provided-details/specify-user-provided-details.component.ts index a5d2b02b09..258727a9cc 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/add-service-instance/specify-user-provided-details/specify-user-provided-details.component.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/add-service-instance/specify-user-provided-details/specify-user-provided-details.component.ts @@ -27,6 +27,7 @@ import { IUserProvidedServiceInstance } from '../../../../cf-api-svc.types'; import { cfEntityCatalog } from '../../../../cf-entity-catalog'; import { AppNameUniqueChecking } from '../../../directives/app-name-unique.directive/app-name-unique.directive'; import { CloudFoundryUserProvidedServicesService } from '../../../services/cloud-foundry-user-provided-services.service'; +import { AppServiceBindingDataSource } from '../../list/list-types/app-sevice-bindings/app-service-binding-data-source'; import { CreateServiceFormMode, CsiModeService } from './../csi-mode.service'; const { proxyAPIVersion, cfAPIVersion } = environment; @@ -38,7 +39,7 @@ const { proxyAPIVersion, cfAPIVersion } = environment; export class SpecifyUserProvidedDetailsComponent implements OnDestroy { constructor( - route: ActivatedRoute, + private route: ActivatedRoute, private upsService: CloudFoundryUserProvidedServicesService, public modeService: CsiModeService, private store: Store, @@ -297,11 +298,24 @@ export class SpecifyUserProvidedDetailsComponent implements OnDestroy { this.serviceInstanceId, updateData ).pipe( - map(er => ({ - success: !er.error, - redirect: !er.error, - message: `Failed to update service instance: ${er.message}` - })) + map(er => { + if (!er.error) { + // Update the application binding list + const appId = this.appId || this.route.snapshot.queryParamMap.get('appId'); + if (appId) { + this.store.dispatch(AppServiceBindingDataSource.createGetAllServiceBindings(appId, this.cfGuid)); + } + return { + success: true, + redirect: true, + }; + } + return { + success: false, + redirect: false, + message: `Failed to update service instance: ${er.message}` + }; + }) ); } diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-instance-chart/application-instance-chart.component.html b/src/frontend/packages/cloud-foundry/src/shared/components/application-instance-chart/application-instance-chart.component.html similarity index 100% rename from src/frontend/packages/cloud-foundry/src/features/applications/application/application-instance-chart/application-instance-chart.component.html rename to src/frontend/packages/cloud-foundry/src/shared/components/application-instance-chart/application-instance-chart.component.html diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-instance-chart/application-instance-chart.component.scss b/src/frontend/packages/cloud-foundry/src/shared/components/application-instance-chart/application-instance-chart.component.scss similarity index 100% rename from src/frontend/packages/cloud-foundry/src/features/applications/application/application-instance-chart/application-instance-chart.component.scss rename to src/frontend/packages/cloud-foundry/src/shared/components/application-instance-chart/application-instance-chart.component.scss diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-instance-chart/application-instance-chart.component.spec.ts b/src/frontend/packages/cloud-foundry/src/shared/components/application-instance-chart/application-instance-chart.component.spec.ts similarity index 74% rename from src/frontend/packages/cloud-foundry/src/features/applications/application/application-instance-chart/application-instance-chart.component.spec.ts rename to src/frontend/packages/cloud-foundry/src/shared/components/application-instance-chart/application-instance-chart.component.spec.ts index 07fb0f11ed..fc47c9f6b3 100644 --- a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-instance-chart/application-instance-chart.component.spec.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/application-instance-chart/application-instance-chart.component.spec.ts @@ -2,10 +2,10 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { RouterTestingModule } from '@angular/router/testing'; -import { CoreModule } from '../../../../../../core/src/core/core.module'; -import { SharedModule } from '../../../../../../core/src/shared/shared.module'; -import { generateCfStoreModules } from '../../../../../test-framework/cloud-foundry-endpoint-service.helper'; -import { CloudFoundrySharedModule } from './../../../../shared/cf-shared.module'; +import { CoreModule } from '../../../../../core/src/core/core.module'; +import { SharedModule } from '../../../../../core/src/shared/shared.module'; +import { generateCfStoreModules } from '../../../../test-framework/cloud-foundry-endpoint-service.helper'; +import { CloudFoundrySharedModule } from '../../cf-shared.module'; import { ApplicationInstanceChartComponent } from './application-instance-chart.component'; describe('ApplicationInstanceChartComponent', () => { diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-instance-chart/application-instance-chart.component.ts b/src/frontend/packages/cloud-foundry/src/shared/components/application-instance-chart/application-instance-chart.component.ts similarity index 66% rename from src/frontend/packages/cloud-foundry/src/features/applications/application/application-instance-chart/application-instance-chart.component.ts rename to src/frontend/packages/cloud-foundry/src/shared/components/application-instance-chart/application-instance-chart.component.ts index 5401a177bc..3a54bec82d 100644 --- a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-instance-chart/application-instance-chart.component.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/application-instance-chart/application-instance-chart.component.ts @@ -1,13 +1,12 @@ import { Component, Input, OnInit } from '@angular/core'; -import { MetricsConfig } from '../../../../../../core/src/shared/components/metrics-chart/metrics-chart.component'; -import { MetricsLineChartConfig } from '../../../../../../core/src/shared/components/metrics-chart/metrics-chart.types'; -import { MetricsChartHelpers } from '../../../../../../core/src/shared/components/metrics-chart/metrics.component.helpers'; -import { MetricQueryType } from '../../../../../../core/src/shared/services/metrics-range-selector.types'; -import { MetricQueryConfig } from '../../../../../../store/src/actions/metrics.actions'; -import { IMetricMatrixResult } from '../../../../../../store/src/types/base-metric.types'; -import { IMetricApplication } from '../../../../../../store/src/types/metric.types'; -import { FetchApplicationMetricsAction } from '../../../../actions/cf-metrics.actions'; +import { MetricsConfig } from '../../../../../core/src/shared/components/metrics-chart/metrics-chart.component'; +import { MetricsLineChartConfig } from '../../../../../core/src/shared/components/metrics-chart/metrics-chart.types'; +import { MetricsChartHelpers } from '../../../../../core/src/shared/components/metrics-chart/metrics.component.helpers'; +import { MetricQueryConfig } from '../../../../../store/src/actions/metrics.actions'; +import { IMetricMatrixResult } from '../../../../../store/src/types/base-metric.types'; +import { IMetricApplication, MetricQueryType } from '../../../../../store/src/types/metric.types'; +import { FetchApplicationMetricsAction } from '../../../actions/cf-metrics.actions'; @Component({ selector: 'app-application-instance-chart', diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/cards/card-app-instances/card-app-instances.component.html b/src/frontend/packages/cloud-foundry/src/shared/components/cards/card-app-instances/card-app-instances.component.html index bf67158f11..4c5cd00b6f 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/cards/card-app-instances/card-app-instances.component.html +++ b/src/frontend/packages/cloud-foundry/src/shared/components/cards/card-app-instances/card-app-instances.component.html @@ -5,7 +5,8 @@
- +
@@ -14,23 +15,27 @@
- - - - - - - - - - + + + + + \ No newline at end of file diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/cards/card-app-instances/card-app-instances.component.ts b/src/frontend/packages/cloud-foundry/src/shared/components/cards/card-app-instances/card-app-instances.component.ts index c3524019b6..6604494482 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/cards/card-app-instances/card-app-instances.component.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/cards/card-app-instances/card-app-instances.component.ts @@ -1,13 +1,15 @@ -import { Component, ElementRef, Input, OnDestroy, OnInit, ViewChild, Renderer2 } from '@angular/core'; +import { Component, ElementRef, Input, OnDestroy, OnInit, Renderer2, ViewChild } from '@angular/core'; import { MatSnackBar, MatSnackBarRef, SimpleSnackBar } from '@angular/material/snack-bar'; -import { Observable, Subscription } from 'rxjs'; -import { first, map } from 'rxjs/operators'; +import { combineLatest, Observable, Subscription } from 'rxjs'; +import { first, map, switchMap } from 'rxjs/operators'; import { AppMetadataTypes } from '../../../../../../cloud-foundry/src/actions/app-metadata.actions'; import { ApplicationService } from '../../../../../../cloud-foundry/src/features/applications/application.service'; +import { CurrentUserPermissionsService } from '../../../../../../core/src/core/permissions/current-user-permissions.service'; import { ConfirmationDialogConfig } from '../../../../../../core/src/shared/components/confirmation-dialog.config'; import { ConfirmationDialogService } from '../../../../../../core/src/shared/components/confirmation-dialog.service'; -import { StratosStatus } from '../../../../../../core/src/shared/shared.types'; +import { StratosStatus } from '../../../../../../store/src/types/shared.types'; +import { CfCurrentUserPermissions } from '../../../../user-permissions/cf-user-permissions-checkers'; const appInstanceScaleToZeroConfirmation = new ConfirmationDialogConfig('Set Instance count to 0', 'Are you sure you want to set the instance count to 0?', 'Confirm', true); @@ -28,14 +30,26 @@ export class CardAppInstancesComponent implements OnInit, OnDestroy { status$: Observable; + public canEditApp$: Observable; + constructor( public appService: ApplicationService, private renderer: Renderer2, private confirmDialog: ConfirmationDialogService, - private snackBar: MatSnackBar) { + private snackBar: MatSnackBar, + cups: CurrentUserPermissionsService + ) { this.status$ = this.appService.applicationState$.pipe( map(state => state.indicator) ); + this.canEditApp$ = combineLatest( + appService.appOrg$, + appService.appSpace$ + ).pipe( + switchMap(([org, space]) => + cups.can(CfCurrentUserPermissions.APPLICATION_EDIT, appService.cfGuid, org.metadata.guid, space.metadata.guid) + )) + } private currentCount = 0; diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/cards/card-app-status/card-app-status.component.ts b/src/frontend/packages/cloud-foundry/src/shared/components/cards/card-app-status/card-app-status.component.ts index def16fda0d..c7e9633951 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/cards/card-app-status/card-app-status.component.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/cards/card-app-status/card-app-status.component.ts @@ -3,7 +3,7 @@ import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { ApplicationService } from '../../../../../../cloud-foundry/src/features/applications/application.service'; -import { StratosStatus } from '../../../../../../core/src/shared/shared.types'; +import { StratosStatus } from '../../../../../../store/src/types/shared.types'; @Component({ selector: 'app-card-app-status', diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/cards/card-app-usage/card-app-usage.component.ts b/src/frontend/packages/cloud-foundry/src/shared/components/cards/card-app-usage/card-app-usage.component.ts index b8dcea269a..8e47a9ab46 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/cards/card-app-usage/card-app-usage.component.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/cards/card-app-usage/card-app-usage.component.ts @@ -7,7 +7,7 @@ import { } from '../../../../../../cloud-foundry/src/features/applications/application-monitor.service'; import { ApplicationService } from '../../../../../../cloud-foundry/src/features/applications/application.service'; import { pathGet } from '../../../../../../core/src/core/utils.service'; -import { StratosStatus } from '../../../../../../core/src/shared/shared.types'; +import { StratosStatus } from '../../../../../../store/src/types/shared.types'; @Component({ selector: 'app-card-app-usage', diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/cards/card-cf-recent-apps/compact-app-card/compact-app-card.component.ts b/src/frontend/packages/cloud-foundry/src/shared/components/cards/card-cf-recent-apps/compact-app-card/compact-app-card.component.ts index a6c13b1af5..d982f91991 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/cards/card-cf-recent-apps/compact-app-card/compact-app-card.component.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/cards/card-cf-recent-apps/compact-app-card/compact-app-card.component.ts @@ -7,7 +7,7 @@ import { CFAppState } from '../../../../../../../cloud-foundry/src/cf-app-state' import { ApplicationService } from '../../../../../../../cloud-foundry/src/features/applications/application.service'; import { ActiveRouteCfOrgSpace } from '../../../../../../../cloud-foundry/src/features/cloud-foundry/cf-page.types'; import { BREADCRUMB_URL_PARAM } from '../../../../../../../core/src/shared/components/breadcrumbs/breadcrumbs.types'; -import { StratosStatus } from '../../../../../../../core/src/shared/shared.types'; +import { StratosStatus } from '../../../../../../../store/src/types/shared.types'; import { ApplicationStateData, ApplicationStateService } from '../../../../services/application-state.service'; diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/cards/card-cf-space-details/card-cf-space-details.component.ts b/src/frontend/packages/cloud-foundry/src/shared/components/cards/card-cf-space-details/card-cf-space-details.component.ts index 1e20e5ab65..555865d96e 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/cards/card-cf-space-details/card-cf-space-details.component.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/cards/card-cf-space-details/card-cf-space-details.component.ts @@ -8,8 +8,8 @@ import { CloudFoundrySpaceService, } from '../../../../../../cloud-foundry/src/features/cloud-foundry/services/cloud-foundry-space.service'; import { safeUnsubscribe } from '../../../../../../core/src/core/utils.service'; +import { SnackBarService } from '../../../../../../core/src/shared/services/snackbar.service'; import { RouterNav } from '../../../../../../store/src/actions/router.actions'; -import { ShowReturnSnackBar } from '../../../../../../store/src/actions/snackBar.actions'; import { AppState } from '../../../../../../store/src/app-state'; @Component({ @@ -24,7 +24,8 @@ export class CardCfSpaceDetailsComponent implements OnDestroy { constructor( public cfSpaceService: CloudFoundrySpaceService, private store: Store, - private router: Router + private router: Router, + private snackBarService: SnackBarService ) { this.allowSshStatus$ = cfSpaceService.allowSsh$.pipe( map(status => status === 'false' ? 'Disabled' : 'Enabled') @@ -34,7 +35,7 @@ export class CardCfSpaceDetailsComponent implements OnDestroy { goToOrgQuota() { this.quotaLinkSub = this.cfSpaceService.quotaLink$.subscribe(quotaLink => { this.store.dispatch(new RouterNav({ path: quotaLink })); - this.store.dispatch(new ShowReturnSnackBar('You were switched to an organization', this.router.url, 'Return to space')); + this.snackBarService.showReturn('You were switched to an organization', this.router.url, 'Return to space'); }); } diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/cf-role-checkbox/cf-role-checkbox.component.ts b/src/frontend/packages/cloud-foundry/src/shared/components/cf-role-checkbox/cf-role-checkbox.component.ts index 8472dd6633..f2337914c2 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/cf-role-checkbox/cf-role-checkbox.component.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/cf-role-checkbox/cf-role-checkbox.component.ts @@ -46,6 +46,7 @@ export class CfRoleCheckboxComponent implements OnInit, OnDestroy { @Input() cfGuid: string; + @Input() orgGuid: string; @Input() spaceGuid: string; @Input() orgName: string; @Input() spaceName: string; @@ -60,7 +61,6 @@ export class CfRoleCheckboxComponent implements OnInit, OnDestroy { sub: Subscription; isOrgRole = false; disabled = false; - orgGuid: string; private static hasExistingRole(role: string, roles: CfUserRolesSelected, userGuid: string, orgGuid: string, spaceGuid: string): boolean { if (roles && roles[userGuid] && roles[userGuid][orgGuid]) { @@ -266,7 +266,6 @@ export class CfRoleCheckboxComponent implements OnInit, OnDestroy { combineLatestOp(this.cfRolesService.newRoles$, users$, canEditRole$, selectUsersIsSetByUsername$), filter(([existingRoles, newRoles, users, canEditRole, isSetByUsername]) => !!users.length && !!newRoles.orgGuid) ).subscribe(([existingRoles, newRoles, users, canEditRole, isSetByUsername]) => { - this.orgGuid = newRoles.orgGuid; const { checked, tooltip } = CfRoleCheckboxComponent.getCheckedState( this.role, users, existingRoles, newRoles, this.orgGuid, this.spaceGuid); this.checked = checked; diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-instance/cf-app-instances-config.service.spec.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-instance/cf-app-instances-config.service.spec.ts index dd2d9a08a4..3966e4880a 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-instance/cf-app-instances-config.service.spec.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-instance/cf-app-instances-config.service.spec.ts @@ -6,15 +6,11 @@ import { testSCFEndpointGuid } from '@stratosui/store/testing'; import { CoreModule } from '../../../../../../../core/src/core/core.module'; import { CF_GUID } from '../../../../../../../core/src/shared/entity.tokens'; import { SharedModule } from '../../../../../../../core/src/shared/shared.module'; -import { generateTestEntityServiceProvider } from '../../../../../../../core/test-framework/entity-service.helper'; import { generateTestApplicationServiceProvider } from '../../../../../../test-framework/application-service-helper'; import { generateCfStoreModules, generateTestCfEndpointServiceProvider, } from '../../../../../../test-framework/cloud-foundry-endpoint-service.helper'; -import { GetApplication } from '../../../../../actions/application.actions'; -import { cfEntityFactory } from '../../../../../cf-entity-factory'; -import { applicationEntityType } from '../../../../../cf-entity-types'; import { ApplicationsModule } from '../../../../../features/applications/applications.module'; import { CfAppInstancesConfigService } from './cf-app-instances-config.service'; @@ -27,11 +23,6 @@ describe('CfAppInstancesConfigService', () => { TestBed.configureTestingModule({ providers: [ CfAppInstancesConfigService, - generateTestEntityServiceProvider( - appGuid, - cfEntityFactory(applicationEntityType), - new GetApplication(appGuid, cfGuid) - ), generateTestApplicationServiceProvider(appGuid, cfGuid), generateTestCfEndpointServiceProvider(), { diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-instance/cf-app-instances-config.service.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-instance/cf-app-instances-config.service.ts index 1559dfec06..2753ce8909 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-instance/cf-app-instances-config.service.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-instance/cf-app-instances-config.service.ts @@ -1,12 +1,15 @@ import { Injectable } from '@angular/core'; import { Router } from '@angular/router'; import { Store } from '@ngrx/store'; -import { Observable } from 'rxjs'; +import { combineLatest as combineLatestObs, Observable } from 'rxjs'; import { combineLatest, map, switchMap } from 'rxjs/operators'; import { DeleteApplicationInstance } from '../../../../../../../cloud-foundry/src/actions/application.actions'; import { FetchApplicationMetricsAction } from '../../../../../../../cloud-foundry/src/actions/cf-metrics.actions'; import { CFAppState } from '../../../../../../../cloud-foundry/src/cf-app-state'; +import { + CurrentUserPermissionsService, +} from '../../../../../../../core/src/core/permissions/current-user-permissions.service'; import { UtilsService } from '../../../../../../../core/src/core/utils.service'; import { ConfirmationDialogConfig } from '../../../../../../../core/src/shared/components/confirmation-dialog.config'; import { ConfirmationDialogService } from '../../../../../../../core/src/shared/components/confirmation-dialog.service'; @@ -19,14 +22,14 @@ import { IListConfig, ListViewTypes, } from '../../../../../../../core/src/shared/components/list/list.component.types'; -import { MetricQueryType } from '../../../../../../../core/src/shared/services/metrics-range-selector.types'; import { MetricQueryConfig } from '../../../../../../../store/src/actions/metrics.actions'; import { EntityServiceFactory } from '../../../../../../../store/src/entity-service-factory.service'; import { PaginationMonitorFactory } from '../../../../../../../store/src/monitors/pagination-monitor.factory'; import { IMetricMatrixResult, IMetrics } from '../../../../../../../store/src/types/base-metric.types'; -import { IMetricApplication } from '../../../../../../../store/src/types/metric.types'; +import { IMetricApplication, MetricQueryType } from '../../../../../../../store/src/types/metric.types'; import { ApplicationService } from '../../../../../features/applications/application.service'; import { CfCellHelper } from '../../../../../features/cloud-foundry/cf-cell.helpers'; +import { CfCurrentUserPermissions } from '../../../../../user-permissions/cf-user-permissions-checkers'; import { ListAppInstance } from './app-instance-types'; import { CfAppInstancesDataSource } from './cf-app-instances-data-source'; import { TableCellCfCellComponent } from './table-cell-cf-cell/table-cell-cf-cell.component'; @@ -158,7 +161,7 @@ export class CfAppInstancesConfigService implements IListConfig }, label: 'Terminate', description: ``, // Description depends on console user permission - + createVisible: () => this.canEditApp$ }; private listActionSsh: IListAction = { @@ -182,7 +185,8 @@ export class CfAppInstancesConfigService implements IListConfig space.entity.allow_ssh; }) ); - })) + })), + createVisible: () => this.canEditApp$ }; private singleActions = [ @@ -190,6 +194,8 @@ export class CfAppInstancesConfigService implements IListConfig this.listActionSsh, ]; + private canEditApp$: Observable; + constructor( private store: Store, private appService: ApplicationService, @@ -197,7 +203,8 @@ export class CfAppInstancesConfigService implements IListConfig private router: Router, private confirmDialog: ConfirmationDialogService, entityServiceFactory: EntityServiceFactory, - paginationMonitorFactory: PaginationMonitorFactory + paginationMonitorFactory: PaginationMonitorFactory, + cups: CurrentUserPermissionsService ) { const cellHelper = new CfCellHelper(store, paginationMonitorFactory); @@ -220,6 +227,15 @@ export class CfAppInstancesConfigService implements IListConfig this.appService.appGuid, this, ); + + this.canEditApp$ = combineLatestObs( + appService.appOrg$, + appService.appSpace$ + ).pipe( + switchMap(([org, space]) => + cups.can(CfCurrentUserPermissions.APPLICATION_EDIT, appService.cfGuid, org.metadata.guid, space.metadata.guid) + ) + ) } getGlobalActions = () => null; diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-instance/table-cell-cf-cell/table-cell-cf-cell.component.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-instance/table-cell-cf-cell/table-cell-cf-cell.component.ts index 64ccc8b4f4..651c1b90ac 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-instance/table-cell-cf-cell/table-cell-cf-cell.component.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-instance/table-cell-cf-cell/table-cell-cf-cell.component.ts @@ -2,8 +2,8 @@ import { Component, Input, OnDestroy } from '@angular/core'; import { Observable, Subscription } from 'rxjs'; import { filter, map, tap } from 'rxjs/operators'; -import { EntityService } from '../../../../../../../../store/src/entity-service'; import { TableCellCustom } from '../../../../../../../../core/src/shared/components/list/list.types'; +import { EntityService } from '../../../../../../../../store/src/entity-service'; import { IMetricMatrixResult, IMetrics } from '../../../../../../../../store/src/types/base-metric.types'; import { IMetricCell } from '../../../../../../../../store/src/types/metric.types'; import { ListAppInstance } from '../app-instance-types'; diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-route/cf-app-routes-list-config.service.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-route/cf-app-routes-list-config.service.ts index a631fac6ae..b69eb4ab15 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-route/cf-app-routes-list-config.service.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-route/cf-app-routes-list-config.service.ts @@ -1,7 +1,8 @@ import { DatePipe } from '@angular/common'; import { Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; -import { take } from 'rxjs/operators'; +import { combineLatest } from 'rxjs'; +import { switchMap, take } from 'rxjs/operators'; import { CFAppState } from '../../../../../../../cloud-foundry/src/cf-app-state'; import { @@ -12,6 +13,7 @@ import { IGlobalListAction, IListConfig } from '../../../../../../../core/src/sh import { RouterNav } from '../../../../../../../store/src/actions/router.actions'; import { APIResource } from '../../../../../../../store/src/types/api.types'; import { ApplicationService } from '../../../../../features/applications/application.service'; +import { CfCurrentUserPermissions } from '../../../../../user-permissions/cf-user-permissions-checkers'; import { CfAppRoutesListConfigServiceBase } from './cf-app-routes-list-config-base'; @@ -23,11 +25,12 @@ export class CfAppRoutesListConfigService extends CfAppRoutesListConfigServiceBa appService: ApplicationService, confirmDialog: ConfirmationDialogService, datePipe: DatePipe, - currentUserPermissionsService: CurrentUserPermissionsService, + private currentUserPermissionsService: CurrentUserPermissionsService, ) { super(store, appService, confirmDialog, datePipe, currentUserPermissionsService, null, true); this.setupList(store, appService); + this.allowSelection = false; // Allow the multi action visibility to determine this } private setupList(store: Store, appService: ApplicationService) { @@ -51,7 +54,18 @@ export class CfAppRoutesListConfigService extends CfAppRoutesListConfigServiceBa }, icon: 'add', label: 'Add', - description: 'Add new route' + description: 'Add new route', + visible$: combineLatest( + appService.appOrg$, + appService.appSpace$ + ).pipe( + switchMap(([org, space]) => this.currentUserPermissionsService.can( + CfCurrentUserPermissions.ROUTE_CREATE, + appService.cfGuid, + org.metadata.guid, + space.metadata.guid + )) + ) }; this.getGlobalActions = () => [listActionAddRoute]; } diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-sevice-bindings/app-service-binding-card/app-service-binding-card.component.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-sevice-bindings/app-service-binding-card/app-service-binding-card.component.ts index 5f15687925..50fb563f34 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-sevice-bindings/app-service-binding-card/app-service-binding-card.component.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-sevice-bindings/app-service-binding-card/app-service-binding-card.component.ts @@ -8,12 +8,10 @@ import { CurrentUserPermissionsService, } from '../../../../../../../../core/src/core/permissions/current-user-permissions.service'; import { AppChip } from '../../../../../../../../core/src/shared/components/chips/chips.component'; -import { - MetaCardMenuItem, -} from '../../../../../../../../core/src/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component'; import { CardCell, IListRowCell } from '../../../../../../../../core/src/shared/components/list/list.types'; -import { ComponentEntityMonitorConfig } from '../../../../../../../../core/src/shared/shared.types'; import { APIResource, EntityInfo } from '../../../../../../../../store/src/types/api.types'; +import { MenuItem } from '../../../../../../../../store/src/types/menu-item.types'; +import { ComponentEntityMonitorConfig } from '../../../../../../../../store/src/types/shared.types'; import { IService, IServiceBinding, @@ -34,6 +32,7 @@ import { import { AppEnvVarsState } from '../../../../../../store/types/app-metadata.types'; import { CfCurrentUserPermissions } from '../../../../../../user-permissions/cf-user-permissions-checkers'; import { ServiceActionHelperService } from '../../../../../data-services/service-action-helper.service'; +import { CSI_CANCEL_URL } from '../../../../add-service-instance/csi-mode.service'; import { EnvVarViewComponent } from '../../../../env-var-view/env-var-view.component'; @@ -54,7 +53,7 @@ export class AppServiceBindingCardComponent extends CardCell; customStyle?: string; }[]; - cardMenu: MetaCardMenuItem[]; + cardMenu: MenuItem[]; service$: Observable> | null>; serviceInstance$: Observable>>; tags$: Observable[]>; @@ -241,7 +240,10 @@ export class AppServiceBindingCardComponent extends CardCell this.serviceActionHelperService.startEditServiceBindingStepper( this.row.entity.service_instance_guid, this.appService.cfGuid, - { appId: this.appService.appGuid }, + { + appId: this.appService.appGuid, + [CSI_CANCEL_URL]: `/applications/${this.appService.cfGuid}/${this.appService.appGuid}/services` + }, this.isUserProvidedServiceInstance ) } diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-sevice-bindings/app-service-binding-list-config.service.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-sevice-bindings/app-service-binding-list-config.service.ts index 68288fa9ec..2d39cd38df 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-sevice-bindings/app-service-binding-list-config.service.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-sevice-bindings/app-service-binding-list-config.service.ts @@ -19,12 +19,12 @@ import { import { ListView } from '../../../../../../../store/src/actions/list.actions'; import { RouterNav } from '../../../../../../../store/src/actions/router.actions'; import { APIResource } from '../../../../../../../store/src/types/api.types'; -import { GetAppServiceBindings } from '../../../../../actions/application-service-routes.actions'; import { IServiceBinding } from '../../../../../cf-api-svc.types'; import { ApplicationService } from '../../../../../features/applications/application.service'; import { isServiceInstance, isUserProvidedServiceInstance } from '../../../../../features/cloud-foundry/cf.helpers'; import { CfCurrentUserPermissions } from '../../../../../user-permissions/cf-user-permissions-checkers'; import { ServiceActionHelperService } from '../../../../data-services/service-action-helper.service'; +import { CSI_CANCEL_URL } from '../../../add-service-instance/csi-mode.service'; import { BaseCfListConfig } from '../base-cf/base-cf-list-config'; import { TableCellServiceInstanceTagsComponent, @@ -57,17 +57,15 @@ export class AppServiceBindingListConfigService extends BaseCfListConfig> = { action: (item) => { - // FIXME: If the user cancels stepper this leaks #4295 this.serviceActionHelperService.startEditServiceBindingStepper( item.entity.service_instance_guid, this.appService.cfGuid, - { appId: this.appService.appGuid }, + { + appId: this.appService.appGuid, + [CSI_CANCEL_URL]: `/applications/${this.appService.cfGuid}/${this.appService.appGuid}/services` + }, !!isUserProvidedServiceInstance(item.entity.service_instance.entity) - ).subscribe(res => { - if (!res.error) { - this.store.dispatch(new GetAppServiceBindings(this.appService.appGuid, this.appService.cfGuid)); - } - }); + ); }, label: 'Edit', createVisible: () => this.appService.waitForAppEntity$.pipe( @@ -104,7 +102,7 @@ export class AppServiceBindingListConfigService extends BaseCfListConfig 'Service Instances', + headerCell: () => 'Name', cellDefinition: { getValue: (row) => row.entity.service_instance.entity.name }, diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-variables/cf-app-variables-list-config.service.spec.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-variables/cf-app-variables-list-config.service.spec.ts index 4eea9c86fc..b2a3d64486 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-variables/cf-app-variables-list-config.service.spec.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app-variables/cf-app-variables-list-config.service.spec.ts @@ -4,12 +4,8 @@ import { RouterTestingModule } from '@angular/router/testing'; import { CoreModule } from '../../../../../../../core/src/core/core.module'; import { SharedModule } from '../../../../../../../core/src/shared/shared.module'; -import { generateTestEntityServiceProvider } from '../../../../../../../core/test-framework/entity-service.helper'; import { generateTestApplicationServiceProvider } from '../../../../../../test-framework/application-service-helper'; import { generateCfStoreModules } from '../../../../../../test-framework/cloud-foundry-endpoint-service.helper'; -import { GetApplication } from '../../../../../actions/application.actions'; -import { cfEntityFactory } from '../../../../../cf-entity-factory'; -import { applicationEntityType } from '../../../../../cf-entity-types'; import { ApplicationsModule } from '../../../../../features/applications/applications.module'; import { CfAppVariablesListConfigService } from './cf-app-variables-list-config.service'; @@ -22,11 +18,6 @@ describe('CfAppVariablesListConfigService', () => { TestBed.configureTestingModule({ providers: [ CfAppVariablesListConfigService, - generateTestEntityServiceProvider( - appGuid, - cfEntityFactory(applicationEntityType), - new GetApplication(appGuid, cfGuid) - ), generateTestApplicationServiceProvider(appGuid, cfGuid) ], imports: [ diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app/card/card-app.component.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app/card/card-app.component.ts index 8236ed5d64..39a18e5336 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app/card/card-app.component.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/app/card/card-app.component.ts @@ -6,14 +6,12 @@ import { map, startWith } from 'rxjs/operators'; import { CFAppState } from '../../../../../../../../cloud-foundry/src/cf-app-state'; import { applicationEntityType } from '../../../../../../../../cloud-foundry/src/cf-entity-types'; import { IAppFavMetadata } from '../../../../../../../../cloud-foundry/src/cf-metadata-types'; -import { getFavoriteFromEntity } from '../../../../../../../../core/src/core/user-favorite-helpers'; -import { - FavoritesConfigMapper, -} from '../../../../../../../../core/src/shared/components/favorites-meta-card/favorite-config-mapper'; import { CardCell } from '../../../../../../../../core/src/shared/components/list/list.types'; -import { ComponentEntityMonitorConfig, StratosStatus } from '../../../../../../../../core/src/shared/shared.types'; +import { FavoritesConfigMapper } from '../../../../../../../../store/src/favorite-config-mapper'; import { APIResource } from '../../../../../../../../store/src/types/api.types'; +import { ComponentEntityMonitorConfig, StratosStatus } from '../../../../../../../../store/src/types/shared.types'; import { UserFavorite } from '../../../../../../../../store/src/types/user-favorites.types'; +import { getFavoriteFromEntity } from '../../../../../../../../store/src/user-favorite-helpers'; import { IApp, ISpace } from '../../../../../../cf-api.types'; import { cfEntityFactory } from '../../../../../../cf-entity-factory'; import { CF_ENDPOINT_TYPE } from '../../../../../../cf-types'; diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-buildpacks/cf-buildpacks-data-source.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-buildpacks/cf-buildpacks-data-source.ts index ae5065e46e..fbc40398d9 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-buildpacks/cf-buildpacks-data-source.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-buildpacks/cf-buildpacks-data-source.ts @@ -9,7 +9,7 @@ import { ListDataSource, } from '../../../../../../../core/src/shared/components/list/data-sources-controllers/list-data-source'; import { IListConfig } from '../../../../../../../core/src/shared/components/list/list.component.types'; -import { endpointSchemaKey } from '../../../../../../../store/src/helpers/entity-factory'; +import { endpointEntityType } from '../../../../../../../store/src/helpers/stratos-entity-factory'; import { getRowMetadata } from '../../../../../../../store/src/public-api'; import { APIResource } from '../../../../../../../store/src/types/api.types'; import { cfEntityCatalog } from '../../../../../cf-entity-catalog'; @@ -17,7 +17,7 @@ import { cfEntityFactory } from '../../../../../cf-entity-factory'; export class CfBuildpacksDataSource extends ListDataSource { constructor(store: Store, cfGuid: string, listConfig?: IListConfig) { - const paginationKey = createEntityRelationPaginationKey(endpointSchemaKey, cfGuid); + const paginationKey = createEntityRelationPaginationKey(endpointEntityType, cfGuid); const action = cfEntityCatalog.buildPack.actions.getMultiple(cfGuid, paginationKey) super({ store, diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-cell-apps/cf-cell-apps-list-config.service.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-cell-apps/cf-cell-apps-list-config.service.ts index 6bc5cdfb94..6d4c6d7b02 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-cell-apps/cf-cell-apps-list-config.service.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-cell-apps/cf-cell-apps-list-config.service.ts @@ -5,7 +5,6 @@ import { CFAppState } from '../../../../../../../cloud-foundry/src/cf-app-state' import { ITableColumn } from '../../../../../../../core/src/shared/components/list/list-table/table.types'; import { ListViewTypes } from '../../../../../../../core/src/shared/components/list/list.component.types'; import { ListView } from '../../../../../../../store/src/actions/list.actions'; -import { EntityServiceFactory } from '../../../../../../../store/src/entity-service-factory.service'; import { APIResource } from '../../../../../../../store/src/types/api.types'; import { IApp, ISpace } from '../../../../../cf-api.types'; import { ActiveRouteCfCell } from '../../../../../features/cloud-foundry/cf-page.types'; @@ -24,9 +23,9 @@ export class CfCellAppsListConfigService extends BaseCfListConfig { noEntries: 'There are no applications' }; - constructor(store: Store, private activeRouteCfCell: ActiveRouteCfCell, entityServiceFactory: EntityServiceFactory) { + constructor(store: Store, private activeRouteCfCell: ActiveRouteCfCell) { super(); - this.dataSource = new CfCellAppsDataSource(store, activeRouteCfCell.cfGuid, activeRouteCfCell.cellId, this, entityServiceFactory); + this.dataSource = new CfCellAppsDataSource(store, activeRouteCfCell.cfGuid, activeRouteCfCell.cellId, this); } getColumns = (): ITableColumn[] => [ diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-cell-apps/cf-cell-apps-source.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-cell-apps/cf-cell-apps-source.ts index 6e834f3121..ba9148a902 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-cell-apps/cf-cell-apps-source.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-cell-apps/cf-cell-apps-source.ts @@ -2,7 +2,6 @@ import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; -import { GetApplication } from '../../../../../../../cloud-foundry/src/actions/application.actions'; import { CFAppState } from '../../../../../../../cloud-foundry/src/cf-app-state'; import { applicationEntityType, @@ -13,14 +12,13 @@ import { ListDataSource, } from '../../../../../../../core/src/shared/components/list/data-sources-controllers/list-data-source'; import { IListConfig } from '../../../../../../../core/src/shared/components/list/list.component.types'; -import { MetricQueryType } from '../../../../../../../core/src/shared/services/metrics-range-selector.types'; import { MetricQueryConfig } from '../../../../../../../store/src/actions/metrics.actions'; -import { EntityServiceFactory } from '../../../../../../../store/src/entity-service-factory.service'; import { APIResource } from '../../../../../../../store/src/types/api.types'; import { IMetrics, IMetricVectorResult } from '../../../../../../../store/src/types/base-metric.types'; -import { IMetricApplication } from '../../../../../../../store/src/types/metric.types'; +import { IMetricApplication, MetricQueryType } from '../../../../../../../store/src/types/metric.types'; import { FetchCFMetricsPaginatedAction } from '../../../../../actions/cf-metrics.actions'; import { IApp } from '../../../../../cf-api.types'; +import { cfEntityCatalog } from '../../../../../cf-entity-catalog'; import { cfEntityFactory } from '../../../../../cf-entity-factory'; import { createEntityRelationKey } from '../../../../../entity-relations/entity-relations.types'; @@ -41,7 +39,6 @@ export class CfCellAppsDataSource cfGuid: string, cellId: string, listConfig: IListConfig, - entityServiceFactory: EntityServiceFactory ) { const action = new FetchCFMetricsPaginatedAction( cellId, @@ -64,7 +61,7 @@ export class CfCellAppsDataSource return response[0].data.result.map(res => ({ metric: res.metric, appGuid: res.metric.application_id, - appEntityService: this.createAppEntityService(res.metric.application_id, cfGuid, entityServiceFactory) + appEntityService: this.createAppEntityService(res.metric.application_id, cfGuid) })); }), listConfig @@ -74,15 +71,18 @@ export class CfCellAppsDataSource private createAppEntityService( appGuid: string, - cfGuid: string, - entityServiceFactory: EntityServiceFactory): Observable> { + cfGuid: string + ): Observable> { if (!this.appEntityServices[appGuid]) { - this.appEntityServices[appGuid] = entityServiceFactory.create>( + this.appEntityServices[appGuid] = cfEntityCatalog.application.store.getEntityService( appGuid, - new GetApplication(appGuid, cfGuid, [ + cfGuid, { + includeRelations: [ createEntityRelationKey(applicationEntityType, spaceEntityType), createEntityRelationKey(spaceEntityType, organizationEntityType) - ]) + ], + populateMissing: true + } ).waitForEntity$.pipe( map(entityInfo => entityInfo.entity) ); diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-endpoints/cf-endpoints-data-source.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-endpoints/cf-endpoints-data-source.ts index a9e6b2856e..591c35bf58 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-endpoints/cf-endpoints-data-source.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-endpoints/cf-endpoints-data-source.ts @@ -9,7 +9,7 @@ import { IListConfig } from '../../../../../../../core/src/shared/components/lis import { EntityMonitorFactory } from '../../../../../../../store/src/monitors/entity-monitor.factory.service'; import { InternalEventMonitorFactory } from '../../../../../../../store/src/monitors/internal-event-monitor.factory'; import { PaginationMonitorFactory } from '../../../../../../../store/src/monitors/pagination-monitor.factory'; -import { GetAllEndpoints } from '../../../../../../../store/src/actions/endpoint.actions'; +import { stratosEntityCatalog } from '../../../../../../../store/src/stratos-entity-catalog'; import { EndpointModel } from '../../../../../../../store/src/types/endpoint.types'; export class CFEndpointsDataSource extends BaseEndpointsDataSource { @@ -22,7 +22,7 @@ export class CFEndpointsDataSource extends BaseEndpointsDataSource { entityMonitorFactory: EntityMonitorFactory, internalEventMonitorFactory: InternalEventMonitorFactory ) { - const action = new GetAllEndpoints(); + const action = stratosEntityCatalog.endpoint.actions.getAll(); const paginationKey = 'cf-endpoints'; // We do this here to ensure we sync up with main endpoint table data. syncPaginationSection(store, action, paginationKey); diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-orgs/cf-org-card/cf-org-card.component.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-orgs/cf-org-card/cf-org-card.component.ts index c8275787bf..f7e4ff459b 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-orgs/cf-org-card/cf-org-card.component.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-orgs/cf-org-card/cf-org-card.component.ts @@ -8,24 +8,20 @@ import { organizationEntityType } from '../../../../../../../../cloud-foundry/sr import { CurrentUserPermissionsService, } from '../../../../../../../../core/src/core/permissions/current-user-permissions.service'; -import { getFavoriteFromEntity } from '../../../../../../../../core/src/core/user-favorite-helpers'; import { truthyIncludingZeroString } from '../../../../../../../../core/src/core/utils.service'; import { ConfirmationDialogConfig } from '../../../../../../../../core/src/shared/components/confirmation-dialog.config'; import { ConfirmationDialogService } from '../../../../../../../../core/src/shared/components/confirmation-dialog.service'; -import { - FavoritesConfigMapper, -} from '../../../../../../../../core/src/shared/components/favorites-meta-card/favorite-config-mapper'; -import { - MetaCardMenuItem, -} from '../../../../../../../../core/src/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component'; import { CardCell } from '../../../../../../../../core/src/shared/components/list/list.types'; -import { ComponentEntityMonitorConfig, StratosStatus } from '../../../../../../../../core/src/shared/shared.types'; import { RouterNav } from '../../../../../../../../store/src/actions/router.actions'; +import { FavoritesConfigMapper } from '../../../../../../../../store/src/favorite-config-mapper'; import { EntityMonitorFactory } from '../../../../../../../../store/src/monitors/entity-monitor.factory.service'; import { PaginationMonitorFactory } from '../../../../../../../../store/src/monitors/pagination-monitor.factory'; import { APIResource } from '../../../../../../../../store/src/types/api.types'; import { EndpointUser } from '../../../../../../../../store/src/types/endpoint.types'; +import { MenuItem } from '../../../../../../../../store/src/types/menu-item.types'; +import { ComponentEntityMonitorConfig, StratosStatus } from '../../../../../../../../store/src/types/shared.types'; import { IFavoriteMetadata, UserFavorite } from '../../../../../../../../store/src/types/user-favorites.types'; +import { getFavoriteFromEntity } from '../../../../../../../../store/src/user-favorite-helpers'; import { IApp, IOrganization } from '../../../../../../cf-api.types'; import { cfEntityFactory } from '../../../../../../cf-entity-factory'; import { getStartedAppInstanceCount } from '../../../../../../cf.helpers'; @@ -49,7 +45,7 @@ import { CF_ENDPOINT_TYPE } from './../../../../../../cf-types'; styleUrls: ['./cf-org-card.component.scss'] }) export class CfOrgCardComponent extends CardCell> implements OnInit, OnDestroy { - cardMenu: MetaCardMenuItem[]; + cardMenu: MenuItem[]; orgGuid: string; normalisedMemoryUsage: number; memoryLimit: string; diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-quotas/cf-quotas-data-source.service.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-quotas/cf-quotas-data-source.service.ts index d5018ccb88..ef96d027fc 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-quotas/cf-quotas-data-source.service.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-quotas/cf-quotas-data-source.service.ts @@ -11,10 +11,10 @@ import { getDefaultRowState, } from '../../../../../../../core/src/shared/components/list/data-sources-controllers/list-data-source-types'; import { IListConfig } from '../../../../../../../core/src/shared/components/list/list.component.types'; -import { endpointSchemaKey } from '../../../../../../../store/src/helpers/entity-factory'; -import { EntityMonitor } from '../../../../../../../store/src/monitors/entity-monitor'; +import { endpointEntityType } from '../../../../../../../store/src/helpers/stratos-entity-factory'; import { APIResource } from '../../../../../../../store/src/types/api.types'; import { CFAppState } from '../../../../../cf-app-state'; +import { cfEntityCatalog } from '../../../../../cf-entity-catalog'; import { cfEntityFactory } from '../../../../../cf-entity-factory'; import { quotaDefinitionEntityType } from '../../../../../cf-entity-types'; import { createEntityRelationPaginationKey } from '../../../../../entity-relations/entity-relations.types'; @@ -22,7 +22,7 @@ import { createEntityRelationPaginationKey } from '../../../../../entity-relatio export class CfQuotasDataSourceService extends ListDataSource { constructor(store: Store, cfGuid: string, listConfig?: IListConfig) { - const quotaPaginationKey = createEntityRelationPaginationKey(endpointSchemaKey, cfGuid); + const quotaPaginationKey = createEntityRelationPaginationKey(endpointEntityType, cfGuid); const action = new GetQuotaDefinitions(quotaPaginationKey, cfGuid); super({ @@ -44,8 +44,7 @@ export class CfQuotasDataSourceService extends ListDataSource { if (!this.sourceScheme || !row) { return of(getDefaultRowState()); } - const entityMonitor = new EntityMonitor(this.store, this.getRowUniqueId(row), this.entityKey, this.sourceScheme); - return entityMonitor.entityRequest$.pipe( + return cfEntityCatalog.quotaDefinition.store.getEntityMonitor(this.getRowUniqueId(row)).entityRequest$.pipe( distinctUntilChanged(), map(requestInfo => ({ deleting: requestInfo.deleting.busy, diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-security-groups/cf-security-groups-data-source.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-security-groups/cf-security-groups-data-source.ts index 42b046e9dd..2f0b04583f 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-security-groups/cf-security-groups-data-source.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-security-groups/cf-security-groups-data-source.ts @@ -10,14 +10,14 @@ import { ListDataSource, } from '../../../../../../../core/src/shared/components/list/data-sources-controllers/list-data-source'; import { IListConfig } from '../../../../../../../core/src/shared/components/list/list.component.types'; -import { endpointSchemaKey } from '../../../../../../../store/src/helpers/entity-factory'; +import { endpointEntityType } from '../../../../../../../store/src/helpers/stratos-entity-factory'; import { APIResource } from '../../../../../../../store/src/types/api.types'; import { cfEntityCatalog } from '../../../../../cf-entity-catalog'; import { cfEntityFactory } from '../../../../../cf-entity-factory'; export class CfSecurityGroupsDataSource extends ListDataSource { constructor(store: Store, cfGuid: string, listConfig?: IListConfig) { - const paginationKey = createEntityRelationPaginationKey(endpointSchemaKey, cfGuid); + const paginationKey = createEntityRelationPaginationKey(endpointEntityType, cfGuid); const action = cfEntityCatalog.securityGroup.actions.getMultiple(cfGuid, paginationKey, {}); super({ store, diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-services/cf-service-instances-list-config.base.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-services/cf-service-instances-list-config.base.ts index 52b60a12ee..b1ecf9ef80 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-services/cf-service-instances-list-config.base.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-services/cf-service-instances-list-config.base.ts @@ -21,9 +21,10 @@ import { import { ListView } from '../../../../../../../store/src/actions/list.actions'; import { APIResource } from '../../../../../../../store/src/types/api.types'; import { IServiceInstance } from '../../../../../cf-api-svc.types'; +import { isUserProvidedServiceInstance } from '../../../../../features/cloud-foundry/cf.helpers'; import { CfCurrentUserPermissions } from '../../../../../user-permissions/cf-user-permissions-checkers'; import { ServiceActionHelperService } from '../../../../data-services/service-action-helper.service'; -import { CANCEL_ORG_ID_PARAM, CANCEL_SPACE_ID_PARAM } from '../../../add-service-instance/csi-mode.service'; +import { CANCEL_ORG_ID_PARAM, CANCEL_SPACE_ID_PARAM, CSI_CANCEL_URL } from '../../../add-service-instance/csi-mode.service'; import { TableCellAppCfOrgSpaceHeaderComponent, } from '../app/table-cell-app-cforgspace-header/table-cell-app-cforgspace-header.component'; @@ -61,7 +62,7 @@ export class CfServiceInstancesListConfigBase implements IListConfig>[] = [ { columnId: 'name', - headerCell: () => 'Service Instance', + headerCell: () => 'Name', cellDefinition: { getValue: (row) => `${row.entity.name}` }, @@ -149,10 +150,15 @@ export class CfServiceInstancesListConfigBase implements IListConfig = { action: (item: APIResource) => - this.serviceActionHelperService.startEditServiceBindingStepper(item.metadata.guid, item.entity.cfGuid, { - [CANCEL_SPACE_ID_PARAM]: item.entity.space_guid, - [CANCEL_ORG_ID_PARAM]: item.entity.space.entity.organization_guid - }), + this.serviceActionHelperService.startEditServiceBindingStepper( + item.metadata.guid, + item.entity.cfGuid, + { + [CANCEL_SPACE_ID_PARAM]: item.entity.space_guid, + [CANCEL_ORG_ID_PARAM]: item.entity.space.entity.organization_guid, + [CSI_CANCEL_URL]: this.rootLocation + }, + !!isUserProvidedServiceInstance(item.entity)), label: 'Edit', description: 'Edit Service Instance', createVisible: (row$: Observable>) => @@ -176,7 +182,8 @@ export class CfServiceInstancesListConfigBase implements IListConfig, protected datePipe: DatePipe, protected currentUserPermissionsService: CurrentUserPermissionsService, - private serviceActionHelperService: ServiceActionHelperService + private serviceActionHelperService: ServiceActionHelperService, + private rootLocation: string ) { } diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-services/cf-services-data-source.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-services/cf-services-data-source.ts index 334d992dd6..58e54ea397 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-services/cf-services-data-source.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-services/cf-services-data-source.ts @@ -11,7 +11,7 @@ import { } from '../../../../../../../core/src/shared/components/list/data-sources-controllers/list-data-source'; import { IListConfig } from '../../../../../../../core/src/shared/components/list/list.component.types'; import { entityCatalog } from '../../../../../../../store/src/entity-catalog/entity-catalog'; -import { endpointSchemaKey } from '../../../../../../../store/src/helpers/entity-factory'; +import { endpointEntityType } from '../../../../../../../store/src/helpers/stratos-entity-factory'; import { APIResource } from '../../../../../../../store/src/types/api.types'; import { PaginationEntityState } from '../../../../../../../store/src/types/pagination.types'; import { cfEntityCatalog } from '../../../../../cf-entity-catalog'; @@ -19,7 +19,7 @@ import { CF_ENDPOINT_TYPE } from '../../../../../cf-types'; export class CfServicesDataSource extends ListDataSource { constructor(store: Store, endpointGuid: string, listConfig?: IListConfig) { - const paginationKey = createEntityRelationPaginationKey(endpointSchemaKey); + const paginationKey = createEntityRelationPaginationKey(endpointEntityType); const getServicesAction = cfEntityCatalog.service.actions.getMultiple(endpointGuid, paginationKey, {}); super({ store, diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-services/cf-user-service-instances-list-config.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-services/cf-user-service-instances-list-config.ts index 9f653f851f..4a9ee537ec 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-services/cf-user-service-instances-list-config.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-services/cf-user-service-instances-list-config.ts @@ -28,6 +28,7 @@ import { CANCEL_ORG_ID_PARAM, CANCEL_SPACE_ID_PARAM, CANCEL_USER_PROVIDED, + CSI_CANCEL_URL, } from '../../../add-service-instance/csi-mode.service'; import { CfSpacesUserServiceInstancesDataSource, @@ -64,7 +65,7 @@ export class CfUserServiceInstancesListConfigBase implements IListConfig>[] = [ { columnId: 'name', - headerCell: () => 'Service Instance', + headerCell: () => 'Name', cellDefinition: { getValue: (row) => `${row.entity.name}` }, @@ -152,7 +153,8 @@ export class CfUserServiceInstancesListConfigBase implements IListConfig, - cfSpaceService: CloudFoundrySpaceService, + private cfSpaceService: CloudFoundrySpaceService, protected datePipe: DatePipe, protected currentUserPermissionsService: CurrentUserPermissionsService, private serviceActionHelperService: ServiceActionHelperService diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-space-quotas/cf-space-quotas-data-source.service.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-space-quotas/cf-space-quotas-data-source.service.ts index ccfb93879a..fa308e0b71 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-space-quotas/cf-space-quotas-data-source.service.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-space-quotas/cf-space-quotas-data-source.service.ts @@ -10,11 +10,11 @@ import { getDefaultRowState, } from '../../../../../../../core/src/shared/components/list/data-sources-controllers/list-data-source-types'; import { IListConfig } from '../../../../../../../core/src/shared/components/list/list.component.types'; -import { endpointSchemaKey } from '../../../../../../../store/src/helpers/entity-factory'; -import { EntityMonitor } from '../../../../../../../store/src/monitors/entity-monitor'; +import { endpointEntityType } from '../../../../../../../store/src/helpers/stratos-entity-factory'; import { APIResource } from '../../../../../../../store/src/types/api.types'; import { GetOrganizationSpaceQuotaDefinitions } from '../../../../../actions/quota-definitions.actions'; import { CFAppState } from '../../../../../cf-app-state'; +import { cfEntityCatalog } from '../../../../../cf-entity-catalog'; import { cfEntityFactory } from '../../../../../cf-entity-factory'; import { spaceQuotaEntityType } from '../../../../../cf-entity-types'; import { createEntityRelationPaginationKey } from '../../../../../entity-relations/entity-relations.types'; @@ -22,7 +22,7 @@ import { createEntityRelationPaginationKey } from '../../../../../entity-relatio export class CfOrgSpaceQuotasDataSourceService extends ListDataSource { constructor(store: Store, orgGuid: string, cfGuid: string, listConfig?: IListConfig) { - const quotaPaginationKey = createEntityRelationPaginationKey(endpointSchemaKey, cfGuid); + const quotaPaginationKey = createEntityRelationPaginationKey(endpointEntityType, cfGuid); const action = new GetOrganizationSpaceQuotaDefinitions(quotaPaginationKey, orgGuid, cfGuid); super({ @@ -44,8 +44,8 @@ export class CfOrgSpaceQuotasDataSourceService extends ListDataSource ({ deleting: requestInfo.deleting.busy, diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-spaces-service-instances/cf-spaces-service-instances-list-config.service.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-spaces-service-instances/cf-spaces-service-instances-list-config.service.ts index e87ed733c5..f747341abe 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-spaces-service-instances/cf-spaces-service-instances-list-config.service.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-spaces-service-instances/cf-spaces-service-instances-list-config.service.ts @@ -30,7 +30,13 @@ export class CfSpacesServiceInstancesListConfigService extends CfServiceInstance datePipe: DatePipe, currentUserPermissionsService: CurrentUserPermissionsService, serviceActionHelperService: ServiceActionHelperService) { - super(store, datePipe, currentUserPermissionsService, serviceActionHelperService); + super( + store, + datePipe, + currentUserPermissionsService, + serviceActionHelperService, + `/cloud-foundry/${cfSpaceService.cfGuid}/organizations/${cfSpaceService.orgGuid}/spaces/${cfSpaceService.spaceGuid}/service-instances` + ); this.dataSource = new CfSpacesServiceInstancesDataSource(cfSpaceService.cfGuid, cfSpaceService.spaceGuid, this.store, this); this.serviceInstanceColumns.find(column => column.columnId === 'attachedApps').cellConfig = { breadcrumbs: 'space-services' diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-spaces/cf-space-card/cf-space-card.component.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-spaces/cf-space-card/cf-space-card.component.ts index d124f0d47e..322d4bc454 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-spaces/cf-space-card/cf-space-card.component.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-spaces/cf-space-card/cf-space-card.component.ts @@ -9,24 +9,20 @@ import { ISpaceFavMetadata } from '../../../../../../../../cloud-foundry/src/cf- import { CurrentUserPermissionsService, } from '../../../../../../../../core/src/core/permissions/current-user-permissions.service'; -import { getFavoriteFromEntity } from '../../../../../../../../core/src/core/user-favorite-helpers'; import { truthyIncludingZeroString } from '../../../../../../../../core/src/core/utils.service'; import { ConfirmationDialogConfig } from '../../../../../../../../core/src/shared/components/confirmation-dialog.config'; import { ConfirmationDialogService } from '../../../../../../../../core/src/shared/components/confirmation-dialog.service'; -import { - FavoritesConfigMapper, -} from '../../../../../../../../core/src/shared/components/favorites-meta-card/favorite-config-mapper'; -import { - MetaCardMenuItem, -} from '../../../../../../../../core/src/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component'; import { CardCell } from '../../../../../../../../core/src/shared/components/list/list.types'; -import { ComponentEntityMonitorConfig, StratosStatus } from '../../../../../../../../core/src/shared/shared.types'; import { RouterNav } from '../../../../../../../../store/src/actions/router.actions'; +import { FavoritesConfigMapper } from '../../../../../../../../store/src/favorite-config-mapper'; import { EntityMonitorFactory } from '../../../../../../../../store/src/monitors/entity-monitor.factory.service'; import { PaginationMonitorFactory } from '../../../../../../../../store/src/monitors/pagination-monitor.factory'; import { APIResource } from '../../../../../../../../store/src/types/api.types'; import { EndpointUser } from '../../../../../../../../store/src/types/endpoint.types'; +import { MenuItem } from '../../../../../../../../store/src/types/menu-item.types'; +import { ComponentEntityMonitorConfig, StratosStatus } from '../../../../../../../../store/src/types/shared.types'; import { UserFavorite } from '../../../../../../../../store/src/types/user-favorites.types'; +import { getFavoriteFromEntity } from '../../../../../../../../store/src/user-favorite-helpers'; import { IApp, ISpace } from '../../../../../../cf-api.types'; import { cfEntityFactory } from '../../../../../../cf-entity-factory'; import { CF_ENDPOINT_TYPE } from '../../../../../../cf-types'; @@ -49,7 +45,7 @@ import { CfUserService } from '../../../../../data-services/cf-user.service'; styleUrls: ['./cf-space-card.component.scss'] }) export class CfSpaceCardComponent extends CardCell> implements OnInit, OnDestroy { - cardMenu: MetaCardMenuItem[]; + cardMenu: MenuItem[]; spaceGuid: string; appInstancesCount: number; appInstancesLimit: string; diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-users-org-space-roles/table-cell-org-space-role/table-cell-org-space-role.component.html b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-users-org-space-roles/table-cell-org-space-role/table-cell-org-space-role.component.html index 76bda159ca..427d921780 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-users-org-space-roles/table-cell-org-space-role/table-cell-org-space-role.component.html +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/cf-users-org-space-roles/table-cell-org-space-role/table-cell-org-space-role.component.html @@ -1,4 +1,5 @@ \ No newline at end of file diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/service-instances/service-instances-data-source.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/service-instances/service-instances-data-source.ts index b99fead8d1..7c3cc59981 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/service-instances/service-instances-data-source.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/service-instances/service-instances-data-source.ts @@ -31,6 +31,7 @@ export class ServiceInstancesDataSource extends ListDataSource { paginationKey, isLocal: true, transformEntities: [ + { type: 'filter', field: 'entity.name' }, (entities: APIResource[], paginationState: PaginationEntityState) => { return entities.filter(e => e.entity.service_guid === serviceGuid); } diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/service-instances/service-instances-list-config.service.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/service-instances/service-instances-list-config.service.ts index 20878f7924..89c39ee4fa 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/service-instances/service-instances-list-config.service.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/service-instances/service-instances-list-config.service.ts @@ -6,6 +6,7 @@ import { CFAppState } from '../../../../../../../cloud-foundry/src/cf-app-state' import { CurrentUserPermissionsService, } from '../../../../../../../core/src/core/permissions/current-user-permissions.service'; +import { ITableText } from '../../../../../../../core/src/shared/components/list/list-table/table.types'; import { ServicesService } from '../../../../../features/service-catalog/services.service'; import { ServiceActionHelperService } from '../../../../data-services/service-action-helper.service'; import { CfServiceInstancesListConfigBase } from '../cf-services/cf-service-instances-list-config.base'; @@ -20,13 +21,26 @@ import { ServiceInstancesDataSource } from './service-instances-data-source'; @Injectable() export class ServiceInstancesListConfigService extends CfServiceInstancesListConfigBase { + enableTextFilter = true; + text: ITableText = { + title: null, + filter: 'Search by name', + noEntries: 'There are no service instances', + }; + constructor( store: Store, servicesService: ServicesService, datePipe: DatePipe, currentUserPermissionsService: CurrentUserPermissionsService, serviceActionHelperService: ServiceActionHelperService) { - super(store, datePipe, currentUserPermissionsService, serviceActionHelperService); + super( + store, + datePipe, + currentUserPermissionsService, + serviceActionHelperService, + `/marketplace/${servicesService.cfGuid}/${servicesService.serviceGuid}/instances` + ); // Remove 'Service' column this.serviceInstanceColumns.splice(1, 1); this.dataSource = new ServiceInstancesDataSource(servicesService.cfGuid, servicesService.serviceGuid, store, this); diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/services-wall/service-instance-card/service-instance-card.component.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/services-wall/service-instance-card/service-instance-card.component.ts index 649162074c..640c95bcf2 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/services-wall/service-instance-card/service-instance-card.component.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/services-wall/service-instance-card/service-instance-card.component.ts @@ -8,12 +8,10 @@ import { CurrentUserPermissionsService, } from '../../../../../../../../core/src/core/permissions/current-user-permissions.service'; import { AppChip } from '../../../../../../../../core/src/shared/components/chips/chips.component'; -import { - MetaCardMenuItem, -} from '../../../../../../../../core/src/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component'; import { CardCell } from '../../../../../../../../core/src/shared/components/list/list.types'; -import { ComponentEntityMonitorConfig } from '../../../../../../../../core/src/shared/shared.types'; import { APIResource } from '../../../../../../../../store/src/types/api.types'; +import { MenuItem } from '../../../../../../../../store/src/types/menu-item.types'; +import { ComponentEntityMonitorConfig } from '../../../../../../../../store/src/types/shared.types'; import { IServiceInstance } from '../../../../../../cf-api-svc.types'; import { cfEntityFactory } from '../../../../../../cf-entity-factory'; import { @@ -25,6 +23,7 @@ import { import { CfCurrentUserPermissions } from '../../../../../../user-permissions/cf-user-permissions-checkers'; import { ServiceActionHelperService } from '../../../../../data-services/service-action-helper.service'; import { CfOrgSpaceLabelService } from '../../../../../services/cf-org-space-label.service'; +import { CSI_CANCEL_URL } from '../../../../add-service-instance/csi-mode.service'; @Component({ selector: 'app-service-instance-card', @@ -103,7 +102,7 @@ export class ServiceInstanceCardComponent extends CardCell; cfGuid: string; - cardMenu: MetaCardMenuItem[]; + cardMenu: MenuItem[]; serviceInstanceTags: AppChip[]; hasMultipleBindings = new BehaviorSubject(true); @@ -130,7 +129,9 @@ export class ServiceInstanceCardComponent extends CardCell this.serviceActionHelperService.startEditServiceBindingStepper( this.serviceInstanceEntity.metadata.guid, this.serviceInstanceEntity.entity.cfGuid, - null + { + [CSI_CANCEL_URL]: '/services' + } ) getServiceName = () => { diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/services-wall/service-instances-wall-list-config.service.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/services-wall/service-instances-wall-list-config.service.ts index f3a4c57132..0f597ef543 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/services-wall/service-instances-wall-list-config.service.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/services-wall/service-instances-wall-list-config.service.ts @@ -70,7 +70,13 @@ export class ServiceInstancesWallListConfigService extends CfServiceInstancesLis currentUserPermissionsService: CurrentUserPermissionsService, serviceActionHelperService: ServiceActionHelperService ) { - super(store, datePipe, currentUserPermissionsService, serviceActionHelperService); + super( + store, + datePipe, + currentUserPermissionsService, + serviceActionHelperService, + `/services` + ); const multiFilterConfigs = [ createCfOrgSpaceFilterConfig('cf', 'Cloud Foundry', this.cfOrgSpaceService.cf), createCfOrgSpaceFilterConfig('org', 'Organization', this.cfOrgSpaceService.org), diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/services-wall/user-provided-service-instance-card/user-provided-service-instance-card.component.ts b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/services-wall/user-provided-service-instance-card/user-provided-service-instance-card.component.ts index 0b2fdcf274..0103bc36be 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/services-wall/user-provided-service-instance-card/user-provided-service-instance-card.component.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/list/list-types/services-wall/user-provided-service-instance-card/user-provided-service-instance-card.component.ts @@ -8,17 +8,16 @@ import { CurrentUserPermissionsService, } from '../../../../../../../../core/src/core/permissions/current-user-permissions.service'; import { AppChip } from '../../../../../../../../core/src/shared/components/chips/chips.component'; -import { - MetaCardMenuItem, -} from '../../../../../../../../core/src/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component'; import { CardCell } from '../../../../../../../../core/src/shared/components/list/list.types'; -import { ComponentEntityMonitorConfig } from '../../../../../../../../core/src/shared/shared.types'; import { APIResource } from '../../../../../../../../store/src/types/api.types'; +import { MenuItem } from '../../../../../../../../store/src/types/menu-item.types'; +import { ComponentEntityMonitorConfig } from '../../../../../../../../store/src/types/shared.types'; import { IUserProvidedServiceInstance } from '../../../../../../cf-api-svc.types'; import { cfEntityFactory } from '../../../../../../cf-entity-factory'; import { CfCurrentUserPermissions } from '../../../../../../user-permissions/cf-user-permissions-checkers'; import { ServiceActionHelperService } from '../../../../../data-services/service-action-helper.service'; import { CfOrgSpaceLabelService } from '../../../../../services/cf-org-space-label.service'; +import { CSI_CANCEL_URL } from '../../../../add-service-instance/csi-mode.service'; @Component({ @@ -29,7 +28,7 @@ import { CfOrgSpaceLabelService } from '../../../../../services/cf-org-space-lab export class UserProvidedServiceInstanceCardComponent extends CardCell> { serviceInstanceEntity: APIResource; cfGuid: string; - cardMenu: MetaCardMenuItem[]; + cardMenu: MenuItem[]; serviceInstanceTags: AppChip[]; hasMultipleBindings = new BehaviorSubject(true); @@ -120,7 +119,9 @@ export class UserProvidedServiceInstanceCardComponent extends CardCell this.serviceActionHelperService.startEditServiceBindingStepper( this.serviceInstanceEntity.metadata.guid, this.serviceInstanceEntity.entity.cfGuid, - null, + { + [CSI_CANCEL_URL]: '/services' + }, true ) diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/service-plan-public/service-plan-public.component.spec.ts b/src/frontend/packages/cloud-foundry/src/shared/components/service-plan-public/service-plan-public.component.spec.ts index 0ecf090c2a..d7788eb41e 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/service-plan-public/service-plan-public.component.spec.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/service-plan-public/service-plan-public.component.spec.ts @@ -1,9 +1,9 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { of } from 'rxjs'; -import { StratosStatus } from '../../../../../core/src/shared/shared.types'; import { EntityService } from '../../../../../store/src/entity-service'; import { EntityMonitorFactory } from '../../../../../store/src/monitors/entity-monitor.factory.service'; +import { StratosStatus } from '../../../../../store/src/types/shared.types'; import { generateCfBaseTestModulesNoShared } from '../../../../test-framework/cloud-foundry-endpoint-service.helper'; import * as servicesHelpers from '../../../features/service-catalog/services-helper'; import { ServicesService } from '../../../features/service-catalog/services.service'; diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/service-plan-public/service-plan-public.component.ts b/src/frontend/packages/cloud-foundry/src/shared/components/service-plan-public/service-plan-public.component.ts index e4e4ba6ef9..8d47ae46c6 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/components/service-plan-public/service-plan-public.component.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/service-plan-public/service-plan-public.component.ts @@ -6,8 +6,8 @@ import { getServicePlanAccessibilityCardStatus, } from '../../../../../cloud-foundry/src/features/service-catalog/services-helper'; import { ServicesService } from '../../../../../cloud-foundry/src/features/service-catalog/services.service'; -import { StratosStatus } from '../../../../../core/src/shared/shared.types'; import { APIResource } from '../../../../../store/src/types/api.types'; +import { StratosStatus } from '../../../../../store/src/types/shared.types'; import { IServiceBroker, IServicePlan } from '../../../cf-api-svc.types'; import { cfEntityCatalog } from '../../../cf-entity-catalog'; diff --git a/src/frontend/packages/cloud-foundry/src/shared/data-services/cf-user.service.ts b/src/frontend/packages/cloud-foundry/src/shared/data-services/cf-user.service.ts index 30a0022d4b..e797eab3c8 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/data-services/cf-user.service.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/data-services/cf-user.service.ts @@ -7,10 +7,8 @@ import { CFAppState } from '../../../../cloud-foundry/src/cf-app-state'; import { cfUserEntityType, organizationEntityType, spaceEntityType } from '../../../../cloud-foundry/src/cf-entity-types'; import { createEntityRelationPaginationKey } from '../../../../cloud-foundry/src/entity-relations/entity-relations.types'; import { getCurrentUserCFGlobalStates } from '../../../../cloud-foundry/src/store/selectors/cf-current-user-role.selectors'; -import { - LocalPaginationHelpers, -} from '../../../../core/src/shared/components/list/data-sources-controllers/local-list.helpers'; import { entityCatalog } from '../../../../store/src/entity-catalog/entity-catalog'; +import { LocalPaginationHelpers } from '../../../../store/src/helpers/local-list.helpers'; import { PaginationMonitorFactory } from '../../../../store/src/monitors/pagination-monitor.factory'; import { getDefaultPaginationEntityState, diff --git a/src/frontend/packages/cloud-foundry/src/shared/data-services/cloud-foundry.service.ts b/src/frontend/packages/cloud-foundry/src/shared/data-services/cloud-foundry.service.ts index fe0acd6e1b..2482601268 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/data-services/cloud-foundry.service.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/data-services/cloud-foundry.service.ts @@ -1,13 +1,11 @@ import { Injectable } from '@angular/core'; -import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; -import { CFAppState } from '../../../../cloud-foundry/src/cf-app-state'; -import { endpointEntitySchema } from '../../../../core/src/base-entity-schemas'; import { PaginationMonitor } from '../../../../store/src/monitors/pagination-monitor'; +import { stratosEntityCatalog } from '../../../../store/src/stratos-entity-catalog'; import { APIResource, EntityInfo } from '../../../../store/src/types/api.types'; -import { endpointListKey, EndpointModel } from '../../../../store/src/types/endpoint.types'; +import { EndpointModel } from '../../../../store/src/types/endpoint.types'; @Injectable() export class CloudFoundryService { @@ -18,11 +16,9 @@ export class CloudFoundryService { cfEndpointsMonitor: PaginationMonitor; waitForAppEntity$: Observable>; - constructor( - store: Store - ) { + constructor() { - this.cfEndpointsMonitor = new PaginationMonitor(store, endpointListKey, endpointEntitySchema, true); + this.cfEndpointsMonitor = stratosEntityCatalog.endpoint.store.getPaginationMonitor(); this.cFEndpoints$ = this.cfEndpointsMonitor.currentPage$.pipe( map(endpoints => endpoints.filter(e => e.cnsi_type === 'cf')) diff --git a/src/frontend/packages/cloud-foundry/src/shared/data-services/long-running-cf-op.service.ts b/src/frontend/packages/cloud-foundry/src/shared/data-services/long-running-cf-op.service.ts index 443247c3a3..acec511ca3 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/data-services/long-running-cf-op.service.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/data-services/long-running-cf-op.service.ts @@ -2,14 +2,17 @@ import { Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; import { LongRunningOperationsService } from '../../../../core/src/shared/services/long-running-op.service'; -import { ShowSnackBar } from '../../../../store/src/actions/snackBar.actions'; +import { SnackBarService } from '../../../../core/src/shared/services/snackbar.service'; import { AppState } from '../../../../store/src/app-state'; -import { GetServiceInstance } from '../../actions/service-instances.actions'; +import { cfEntityCatalog } from '../../cf-entity-catalog'; @Injectable() export class LongRunningCfOperationsService extends LongRunningOperationsService { - constructor(store: Store) { + constructor( + store: Store, + private snackBarService: SnackBarService + ) { super(store); } @@ -17,23 +20,23 @@ export class LongRunningCfOperationsService extends LongRunningOperationsService const message = `The operation to create the service instance is taking a long time and will continue in the background. Please refresh the service instance list to check it's status ${bindApp ? ` and then bind the application via the Application page.` : '.'}`; - this.store.dispatch(new ShowSnackBar(message, 'Dismiss')); + this.snackBarService.show(message, 'Dismiss'); } handleLongRunningUpdateService(serviceInstanceGuid: string, cfGuid: string) { const message = `The operation to update the service instance is taking a long time and will continue in the background. Please refresh the service instance list to check it's status`; - this.store.dispatch(new ShowSnackBar(message, 'Dismiss')); // Also attempt to fetch the service instance, this will update the `last operation` value to `update` and `in progress` - this.store.dispatch(new GetServiceInstance(serviceInstanceGuid, cfGuid)); + this.snackBarService.show(message, 'Dismiss'); + cfEntityCatalog.serviceInstance.api.get(serviceInstanceGuid, cfGuid); } handleLongRunningDeleteService(serviceInstanceGuid: string, cfGuid: string) { const message = `The operation to delete the service instance is taking a long time and will continue in the background. Please refresh the service instance list to check it's status`; - this.store.dispatch(new ShowSnackBar(message, 'Dismiss')); + this.snackBarService.show(message, 'Dismiss'); // Also attempt to fetch the service instance, this will update the `last operation` value to `delete` and `in progress` - this.store.dispatch(new GetServiceInstance(serviceInstanceGuid, cfGuid)); + cfEntityCatalog.serviceInstance.api.get(serviceInstanceGuid, cfGuid); } } diff --git a/src/frontend/packages/cloud-foundry/src/shared/services/application-state.service.ts b/src/frontend/packages/cloud-foundry/src/shared/services/application-state.service.ts index 751994c0f0..af5283b27f 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/services/application-state.service.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/services/application-state.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; -import { StratosStatus, StratosStatusMetadata } from '../../../../core/src/shared/shared.types'; +import { StratosStatus, StratosStatusMetadata } from '../../../../store/src/types/shared.types'; import { AppStat } from '../../store/types/app-metadata.types'; export interface ApplicationStateData extends StratosStatusMetadata { diff --git a/src/frontend/packages/cloud-foundry/src/shared/services/cf-org-space-label.service.ts b/src/frontend/packages/cloud-foundry/src/shared/services/cf-org-space-label.service.ts index 585f41ed42..36c9cb2e38 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/services/cf-org-space-label.service.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/services/cf-org-space-label.service.ts @@ -2,9 +2,8 @@ import { Store } from '@ngrx/store'; import { combineLatest, Observable } from 'rxjs'; import { filter, first, map } from 'rxjs/operators'; -import { STRATOS_ENDPOINT_TYPE } from '../../../../core/src/base-entity-schemas'; import { entityCatalog } from '../../../../store/src/entity-catalog/entity-catalog'; -import { endpointSchemaKey } from '../../../../store/src/helpers/entity-factory'; +import { endpointEntityType, STRATOS_ENDPOINT_TYPE } from '../../../../store/src/helpers/stratos-entity-factory'; import { selectEntity } from '../../../../store/src/selectors/api.selectors'; import { APIResource } from '../../../../store/src/types/api.types'; import { EndpointModel } from '../../../../store/src/types/endpoint.types'; @@ -33,7 +32,7 @@ export class CfOrgSpaceLabelService { private spaceGuid?: string) { this.multipleConnectedEndpoints$ = haveMultiConnectedCfs(this.store); // FIXME: hide STRATOS_ENDPOINT_TYPE from extensions - STRAT-154 - const endpointEntityKey = entityCatalog.getEntityKey(STRATOS_ENDPOINT_TYPE, endpointSchemaKey); + const endpointEntityKey = entityCatalog.getEntityKey(STRATOS_ENDPOINT_TYPE, endpointEntityType); this.cf$ = this.store.select(selectEntity(endpointEntityKey, this.cfGuid)); diff --git a/src/frontend/packages/cloud-foundry/src/shared/services/current-user-permissions.service.spec.ts b/src/frontend/packages/cloud-foundry/src/shared/services/current-user-permissions.service.spec.ts index 99dcb96deb..ddf7d54350 100644 --- a/src/frontend/packages/cloud-foundry/src/shared/services/current-user-permissions.service.spec.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/services/current-user-permissions.service.spec.ts @@ -12,8 +12,6 @@ import { CfPermissionTypes, CfScopeStrings, } from '../../../../cloud-foundry/src/user-permissions/cf-user-permissions-checkers'; -import { endpointEntitySchema } from '../../../../core/src/base-entity-schemas'; -import { generateStratosEntities } from '../../../../core/src/base-entity-types'; import { PermissionConfig } from '../../../../core/src/core/permissions/current-user-permissions.config'; import { CurrentUserPermissionsService } from '../../../../core/src/core/permissions/current-user-permissions.service'; import { StratosScopeStrings } from '../../../../core/src/core/permissions/stratos-user-permissions.checker'; @@ -21,6 +19,8 @@ import { AppTestModule } from '../../../../core/test-framework/core-test.helper' import { AppState } from '../../../../store/src/app-state'; import { EntityCatalogTestModule, TEST_CATALOGUE_ENTITIES } from '../../../../store/src/entity-catalog-test.module'; import { EntityCatalogEntityConfig } from '../../../../store/src/entity-catalog/entity-catalog.types'; +import { endpointEntityType, stratosEntityFactory } from '../../../../store/src/helpers/stratos-entity-factory'; +import { generateStratosEntities } from '../../../../store/src/stratos-entity-generator'; import { APIResource } from '../../../../store/src/types/api.types'; import { EndpointModel } from '../../../../store/src/types/endpoint.types'; import { BaseEntityValues } from '../../../../store/src/types/entity.types'; @@ -588,7 +588,7 @@ describe('CurrentUserPermissionsService with CF checker', () => { // Create request and requestData sections const entityMap = new Map>([ [ - endpointEntitySchema, + stratosEntityFactory(endpointEntityType), endpoints.map(endpoint => ({ guid: endpoint.guid, data: endpoint diff --git a/src/frontend/packages/cloud-foundry/src/store/reducers/cf-users.reducer.ts b/src/frontend/packages/cloud-foundry/src/store/reducers/cf-users.reducer.ts index 71079d216e..2395df2ff6 100644 --- a/src/frontend/packages/cloud-foundry/src/store/reducers/cf-users.reducer.ts +++ b/src/frontend/packages/cloud-foundry/src/store/reducers/cf-users.reducer.ts @@ -12,6 +12,7 @@ import { } from '../../actions/users.actions'; import { IOrganization, ISpace } from '../../cf-api.types'; import { cfUserEntityType } from '../../cf-entity-types'; +import { CF_ENDPOINT_TYPE } from '../../cf-types'; import { CfUser, CfUserMissingOrgRoles, @@ -61,7 +62,7 @@ export function cfUserReducer(state: IRequestEntityTypeState } export function endpointDisconnectUserReducer(state: IRequestEntityTypeState>, action: DisconnectEndpoint) { - if (action.endpointType === 'cf') { + if (action.endpointType === CF_ENDPOINT_TYPE) { switch (action.type) { case DISCONNECT_ENDPOINTS_SUCCESS: const cfGuid = action.guid; diff --git a/src/frontend/packages/cloud-foundry/src/store/selectors/cf-current-user-role.selectors.ts b/src/frontend/packages/cloud-foundry/src/store/selectors/cf-current-user-role.selectors.ts index c3df05ca37..ee2fd00471 100644 --- a/src/frontend/packages/cloud-foundry/src/store/selectors/cf-current-user-role.selectors.ts +++ b/src/frontend/packages/cloud-foundry/src/store/selectors/cf-current-user-role.selectors.ts @@ -1,7 +1,7 @@ import { compose } from '@ngrx/store'; -import { PermissionValues } from '../../../../core/src/core/permissions/current-user-permissions.config'; import { + PermissionValues, selectCurrentUserGlobalHasScopes, selectCurrentUserRolesState, } from '../../../../store/src/selectors/current-user-role.selectors'; diff --git a/src/frontend/packages/cloud-foundry/src/user-permissions/cf-user-permissions-checkers.ts b/src/frontend/packages/cloud-foundry/src/user-permissions/cf-user-permissions-checkers.ts index b38816caf9..1aead1cd0f 100644 --- a/src/frontend/packages/cloud-foundry/src/user-permissions/cf-user-permissions-checkers.ts +++ b/src/frontend/packages/cloud-foundry/src/user-permissions/cf-user-permissions-checkers.ts @@ -7,7 +7,6 @@ import { PermissionConfig, PermissionConfigLink, PermissionTypes, - PermissionValues, } from '../../../core/src/core/permissions/current-user-permissions.config'; import { CurrentUserPermissionsService, @@ -21,6 +20,7 @@ import { IPermissionCheckCombiner, } from '../../../core/src/core/permissions/current-user-permissions.types'; import { GeneralEntityAppState } from '../../../store/src/app-state'; +import { PermissionValues } from '../../../store/src/selectors/current-user-role.selectors'; import { connectedEndpointsSelector } from '../../../store/src/selectors/endpoint.selectors'; import { CFFeatureFlagTypes, IFeatureFlag } from '../cf-api.types'; import { cfEntityCatalog } from '../cf-entity-catalog'; @@ -396,7 +396,7 @@ export class CfUserPermissionsChecker extends BaseCurrentUserPermissionsChecker } private getAllEndpointGuids() { - return this.store.select(connectedEndpointsSelector).pipe( + return this.store.select(connectedEndpointsSelector()).pipe( map(endpoints => Object.values(endpoints).filter(e => e.cnsi_type === CF_ENDPOINT_TYPE).map(endpoint => endpoint.guid)) ); } diff --git a/src/frontend/packages/cloud-foundry/src/user-permissions/cf-user-roles-fetch.ts b/src/frontend/packages/cloud-foundry/src/user-permissions/cf-user-roles-fetch.ts index ec6687ced1..06340d5496 100644 --- a/src/frontend/packages/cloud-foundry/src/user-permissions/cf-user-roles-fetch.ts +++ b/src/frontend/packages/cloud-foundry/src/user-permissions/cf-user-roles-fetch.ts @@ -3,7 +3,6 @@ import { Action, Store } from '@ngrx/store'; import { combineLatest, Observable, of } from 'rxjs'; import { catchError, first, map, pairwise, share, skipWhile, switchMap, tap } from 'rxjs/operators'; -import { LoggerService } from '../../../core/src/core/logger.service'; import { AppState } from '../../../store/src/app-state'; import { entityCatalog } from '../../../store/src/entity-catalog/entity-catalog'; import { @@ -50,7 +49,6 @@ const createEndpointArray = (store: Store, endpoints: string[] | Entit export const cfUserRolesFetch: EntityUserRolesFetch = ( endpoints: string[] | EntityUserRolesEndpoint[], store: Store, - logService: LoggerService, httpClient: HttpClient ) => { return createEndpointArray(store, endpoints).pipe( @@ -61,7 +59,7 @@ export const cfUserRolesFetch: EntityUserRolesFetch = ( cfEndpoints.forEach(endpoint => store.dispatch(new GetCfUserRelations(endpoint.guid, GET_CURRENT_CF_USER_RELATIONS_SUCCESS))) } else { // If some endpoints are not connected as admin, go out and fetch the current user's specific roles - const flagsAndRoleRequests = dispatchRoleRequests(cfEndpoints, store, logService, httpClient); + const flagsAndRoleRequests = dispatchRoleRequests(cfEndpoints, store, httpClient); const allRequestsCompleted = handleCfRequests(flagsAndRoleRequests); return combineLatest(allRequestsCompleted).pipe( map(succeeds => succeeds.every(succeeded => !!succeeded)), @@ -84,7 +82,6 @@ interface IEndpointConnectionInfo { function dispatchRoleRequests( endpoints: EntityUserRolesEndpoint[], store: Store, - logService: LoggerService, httpClient: HttpClient ): CfsRequestState { const requests: CfsRequestState = {}; @@ -117,7 +114,7 @@ function dispatchRoleRequests( ); }), catchError(err => { - logService.warn('Failed to fetch current user permissions for a cf: ', err); + console.warn('Failed to fetch current user permissions for a cf: ', err); store.dispatch(new GetCfUserRelations(endpoint.guid, GET_CURRENT_CF_USER_RELATIONS_FAILED)); return of(err); }) diff --git a/src/frontend/packages/cloud-foundry/test-framework/application-service-helper.ts b/src/frontend/packages/cloud-foundry/test-framework/application-service-helper.ts index 6c07e9ba8f..18ed991825 100644 --- a/src/frontend/packages/cloud-foundry/test-framework/application-service-helper.ts +++ b/src/frontend/packages/cloud-foundry/test-framework/application-service-helper.ts @@ -1,7 +1,8 @@ import { Store } from '@ngrx/store'; -import { Observable, of as observableOf } from 'rxjs'; +import { Observable, of as observableOf, of } from 'rxjs'; import { map } from 'rxjs/internal/operators/map'; +import { EntityService } from '../../store/src/entity-service'; import { RequestInfoState } from '../../store/src/reducers/api-request-reducer/types'; import { APIResource, EntityInfo } from '../../store/src/types/api.types'; import { IApp, IAppSummary, IDomain, ISpace } from '../src/cf-api.types'; @@ -81,6 +82,10 @@ export class ApplicationServiceMock { appSpace$: Observable> = observableOf(createEntity({} as ISpace)); applicationRunning$: Observable = observableOf(false); orgDomains$: Observable[]> = observableOf([]); + entityService: EntityService>> = { + waitForEntity$: of({}), + updatingSection$: of({}) + } as EntityService>> } export function generateTestApplicationServiceProvider(appGuid: string, cfGuid: string) { diff --git a/src/frontend/packages/cloud-foundry/test-framework/cf-test-helper.ts b/src/frontend/packages/cloud-foundry/test-framework/cf-test-helper.ts index 0ef667db7e..c22514e227 100644 --- a/src/frontend/packages/cloud-foundry/test-framework/cf-test-helper.ts +++ b/src/frontend/packages/cloud-foundry/test-framework/cf-test-helper.ts @@ -1,7 +1,7 @@ import { BaseTestModules } from '../../core/test-framework/core-test.helper'; import { EntityCatalogTestModule, TEST_CATALOGUE_ENTITIES } from '../../store/src/entity-catalog-test.module'; +import { generateStratosEntities } from '../../store/src/stratos-entity-generator'; import { generateCFEntities } from '../src/cf-entity-generator'; -import { generateStratosEntities } from '../../core/src/base-entity-types'; export const CFBaseTestModules = [ ...BaseTestModules, diff --git a/src/frontend/packages/cloud-foundry/test-framework/cloud-foundry-endpoint-service.helper.ts b/src/frontend/packages/cloud-foundry/test-framework/cloud-foundry-endpoint-service.helper.ts index 2174658903..3fc7ed40e9 100644 --- a/src/frontend/packages/cloud-foundry/test-framework/cloud-foundry-endpoint-service.helper.ts +++ b/src/frontend/packages/cloud-foundry/test-framework/cloud-foundry-endpoint-service.helper.ts @@ -114,7 +114,7 @@ export function generateTestCfServiceProvider() { useFactory: ( store: Store, ) => { - const appService = new CloudFoundryService(store); + const appService = new CloudFoundryService(); return appService; }, deps: [Store] diff --git a/src/frontend/packages/core/endpoints-health-checks.ts b/src/frontend/packages/core/endpoints-health-checks.ts index 2c7624fd76..11e46ae3fc 100644 --- a/src/frontend/packages/core/endpoints-health-checks.ts +++ b/src/frontend/packages/core/endpoints-health-checks.ts @@ -1,20 +1,9 @@ import { Injectable } from '@angular/core'; import { entityCatalog } from '../store/src/entity-catalog/entity-catalog'; +import { EndpointHealthCheck } from '../store/src/entity-catalog/entity-catalog.types'; import { EndpointModel } from '../store/src/types/endpoint.types'; - -export class EndpointHealthCheck { - /** - * @param check To show an error, the check should either call a WrapperRequestActionFailed - * or kick off a chain that eventually calls a WrapperRequestActionFailed - */ - constructor( - public endpointType: string, - public check: (endpoint: EndpointModel) => void - ) { } -} - @Injectable({ providedIn: 'root' }) diff --git a/src/frontend/packages/core/misc/custom/custom-src-routing.module.ts_ b/src/frontend/packages/core/misc/custom/custom-src-routing.module.ts_ deleted file mode 100644 index a1f9fa4457..0000000000 --- a/src/frontend/packages/core/misc/custom/custom-src-routing.module.ts_ +++ /dev/null @@ -1,21 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CustomModule } from './custom/custom.module'; -import { CustomRoutingModule } from './custom/custom-routing.module'; - -// Default import customization module - DO NOT EDIT - -// This file is in the .gitignore - changes will not be flagged - -@NgModule({ - imports: [ - CustomModule, - ] -}) -export class CustomImportModule { } - -@NgModule({ - imports: [ - CustomRoutingModule, - ] -}) -export class CustomRoutingImportModule { } diff --git a/src/frontend/packages/core/misc/custom/custom-src.module.ts_ b/src/frontend/packages/core/misc/custom/custom-src.module.ts_ deleted file mode 100644 index 3e536cc582..0000000000 --- a/src/frontend/packages/core/misc/custom/custom-src.module.ts_ +++ /dev/null @@ -1,16 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CustomModule } from './custom/custom.module'; - -// Default import customization module - DO NOT EDIT - -// This file is in the .gitignore - changes will not be flagged - -@NgModule({ - imports: [ - CustomModule, - ] -}) -export class CustomImportModule { } - -@NgModule() -export class CustomRoutingImportModule { } diff --git a/src/frontend/packages/core/misc/custom/custom.scss b/src/frontend/packages/core/misc/custom/custom.scss deleted file mode 100644 index f6d83b743c..0000000000 --- a/src/frontend/packages/core/misc/custom/custom.scss +++ /dev/null @@ -1,5 +0,0 @@ -// Empty customization file - DO NOT EDIT - -// This file is in the .gitignore - changes will not be flagged - -// The customization build step will replace this file with the custom one if provided diff --git a/src/frontend/packages/core/misc/custom/custom.yaml b/src/frontend/packages/core/misc/custom/custom.yaml deleted file mode 100644 index db58c36ad7..0000000000 --- a/src/frontend/packages/core/misc/custom/custom.yaml +++ /dev/null @@ -1,14 +0,0 @@ -# Customization manifest - -files: - custom.scss: "sass/custom.scss" - favicon.ico: "favicon.ico" - login-bg.jpg: "assets/login-bg.jpg" - logo.png: "assets/logo.png" - nav-logo.png: "assets/nav-logo.png" - eula.html: "assets/eula.html" - -folders: - - "app/custom:src/custom" - - "assets/custom" - - "sass/custom" diff --git a/src/frontend/packages/core/misc/custom/eula.html b/src/frontend/packages/core/misc/custom/eula.html deleted file mode 100644 index dfd92e3d98..0000000000 --- a/src/frontend/packages/core/misc/custom/eula.html +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/src/frontend/packages/core/ng-package.json b/src/frontend/packages/core/ng-package.json new file mode 100644 index 0000000000..9a348247b8 --- /dev/null +++ b/src/frontend/packages/core/ng-package.json @@ -0,0 +1,7 @@ +{ + "$schema": "../../../../node_modules/ng-packagr/ng-package.schema.json", + "dest": "../../../../dist/core", + "lib": { + "entryFile": "src/public-api.ts" + } +} \ No newline at end of file diff --git a/src/frontend/packages/core/package.json b/src/frontend/packages/core/package.json new file mode 100644 index 0000000000..63f4668511 --- /dev/null +++ b/src/frontend/packages/core/package.json @@ -0,0 +1,9 @@ +{ + "name": "@stratosui/core", + "version": "0.0.1", + "stratos": { + "assets": { + "assets": "core/assets" + } + } +} diff --git a/src/frontend/packages/core/sass/_all-theme.scss b/src/frontend/packages/core/sass/_all-theme.scss index 9fc21b86f9..67ae92ae8b 100644 --- a/src/frontend/packages/core/sass/_all-theme.scss +++ b/src/frontend/packages/core/sass/_all-theme.scss @@ -48,7 +48,6 @@ @import '../src/shared/components/user-avatar/user-avatar.component.theme'; @import './components/text-status.theme'; @import './components/hyperlinks.theme'; -@import './mat-themes'; @import './mat-desktop'; @import './fonts'; @import './ansi-colors'; @@ -57,53 +56,28 @@ @import '../../cloud-foundry/src/shared/components/schema-form/schema-form.component.theme'; @import '../../cloud-foundry/src/features/services/services-wall/services-wall.component.theme'; -@import '../../cloud-foundry/src/shared/components/list/list-types/cf-security-groups/cf-security-groups-card/cf-security-groups-card.component.theme'; @import '../../cloud-foundry/src/features/cloud-foundry/tabs/cf-admin-add-user-warning/cf-admin-add-user-warning.component.theme'; @import '../../cloud-foundry/src/features/applications/application/application-base.component.theme'; @import '../../cloud-foundry/src/features/applications/deploy-application/deploy-application.component.theme'; @import '../../cloud-foundry/src/features/applications/deploy-application/deploy-application-step2/deploy-application-fs/deploy-application-fs.component.theme'; @import '../../cloud-foundry/src/features/cloud-foundry/tabs/cloud-foundry-firehose/cloud-foundry-firehose.component.theme'; @import '../../cloud-foundry/src/features/service-catalog/service-catalog-page/service-catalog-page.component.theme'; -@import '../../cloud-foundry/src/features/applications/application-wall/application-wall.component.theme'; @import '../../core/src/features/error-page/error-page/error-page.component.theme'; @import '../../core/src/features/endpoints/backup-restore/restore-endpoints/restore-endpoints.component.theme'; @import '../../core/src/features/metrics/metrics/metrics.component.theme'; - -// Defaults -$side-nav-light-text: #fff; -$side-nav-light-bg: #333; -$side-nav-light-hover: #555; -$side-nav-light-active: #484848; - // Creates the app theme and applies it to the application // $theme = Angular Material Theme // $nav-theme - Colors for the Side Nav (optional) // $status-theme - Colors for status (optional) -@mixin app-theme($theme, $nav-theme: null, $status-theme: null) { - $background-colors: map-get($theme, background); - $foreground-colors: map-get($theme, foreground); - $is-dark: map-get($theme, is-dark); - $app-background-color: white; - $app-background-text-color: rgba(mat-color($foreground-colors, base), .65); - $primary: map-get($theme, primary); - $accent: map-get($theme, accent); - $warn: map-get($theme, warn); - $subdued: mat-contrast($primary, 50); - - @if $is-dark == true { - $app-background-color: lighten(mat-color($background-colors, background), 10%); - $subdued: lighten($subdued, 90); - } @else { - $app-background-color: darken(mat-color($background-colors, background), 2%); - $subdued: lighten($subdued, 50); - } +@mixin app-theme($stratos-theme, $nav-theme: null, $status-theme: null) { + $theme: map-get($stratos-theme, theme); + $app-theme: map-get($stratos-theme, app-theme); + $app-background-color: map-get($app-theme, app-background-color); html { background-color: $app-background-color; } - // App Theme defines a set of colors used by stratos components - $app-theme: (app-background-color: $app-background-color, app-background-text-color: rgba(mat-color($foreground-colors, base), .65), side-nav: app-generate-nav-theme($theme, $nav-theme), status: app-generate-status-theme($theme, $status-theme), subdued-color: $subdued, ansi-colors: $ansi-color-palette); // Pass the Material theme and the App Theme to components that need to be themed @include dialog-error-theme($theme, $app-theme); @include login-page-theme($theme, $app-theme); @include side-nav-theme($theme, $app-theme); @@ -122,7 +96,6 @@ $side-nav-light-active: #484848; @include app-hyperlinks($theme, $app-theme); @include app-no-content-message-theme($theme, $app-theme); @include app-boolean-indicator-theme($theme, $app-theme); - @include cf-security-group-theme($theme); @include loading-page-theme($theme, $app-theme); @include app-log-viewer-theme($theme, $app-theme); @include app-deploy-app-theme($theme, $app-theme); @@ -164,23 +137,3 @@ $side-nav-light-active: #484848; @include restore-endpoints-theme($theme, $app-theme); @include metrics-component-theme($theme, $app-theme); } - -@function app-generate-nav-theme($theme, $nav-theme: null) { - @if ($nav-theme) { - @return $nav-theme; - } @else { - // Use default palette for side navigation - @return (background: $side-nav-light-bg, background-top: $side-nav-light-bg, text: darken($side-nav-light-text, 10%), active: $side-nav-light-active, active-text: $side-nav-light-text, hover: $side-nav-light-hover, hover-text: $side-nav-light-text); - } -} - -@function app-generate-status-theme($theme, $status-theme: null) { - @if ($status-theme) { - @return $status-theme; - } @else { - $warn: map-get($theme, warn); - $primary: map-get($theme, primary); - $white: #fff; // Use default palette for status - @return (success: map-get($mat-green, 500), warning: map-get($mat-orange, 500), danger: mat-color($warn), tentative: map-get($mat-grey, 500), busy: mat-color($primary), text: $white, info: map-get($mat-blue, 500)); - } -} diff --git a/src/frontend/packages/core/sass/colors.scss b/src/frontend/packages/core/sass/colors.scss deleted file mode 100644 index 75071fe6ba..0000000000 --- a/src/frontend/packages/core/sass/colors.scss +++ /dev/null @@ -1,7 +0,0 @@ -// @import './suse-theme'; -$dark-grey: rgb(95, 95, 95); -$middle-grey: rgb(167, 169, 172); -$light-grey: rgb(220, 221, 222); -// $blue: map-get($suse-blue, 500); - -// See here for palette info: https://github.com/angular/material2/blob/master/src/lib/core/theming/_palette.scss diff --git a/src/frontend/packages/core/sass/theme.scss b/src/frontend/packages/core/sass/theme.scss index 365cd4750e..11ba592a9f 100644 --- a/src/frontend/packages/core/sass/theme.scss +++ b/src/frontend/packages/core/sass/theme.scss @@ -1,45 +1,46 @@ @import '~@angular/material/theming'; -@import './mat-themes'; @import './all-theme'; -@import './mat-colors'; -// Custom theme support -@import './custom'; +// Import the theme +@import '~@stratosui/theme'; -body.stratos { - .dark-theme { - // Dark Theme defaults - $dark-primary: mat-palette($mat-blue); - $dark-accent: mat-palette($mat-amber, A400, A100, A700); - $dark-warn: mat-palette($mat-red); - $dark-theme: mat-dark-theme($dark-primary, $dark-accent, $dark-warn); +$stratos-dark-theme-supported: false !default; - $stratos-dark-theme: $dark-theme !default; - $stratos-dark-nav-theme: null !default; - $stratos-dark-status-theme: null !default; +// Themes - stratos-theme() function must be supplied by the theme +$stratos-themes: stratos-theme(); - @include angular-material-theme($stratos-dark-theme); - @include app-theme($stratos-dark-theme, $stratos-dark-nav-theme, $stratos-dark-status-theme); +// stratos-theme() can return a single theme rather than a map of default and dark themes +@if not map-has-key($stratos-themes, 'default') { + $tmp: $stratos-themes; + $stratos-themes: ( + default: $tmp + ) +} + +// Import any custom scss that the theme defines +@import '~@stratosui/theme/extensions'; + +// Default theme ( = light theme) +$stratos-theme: map-get($stratos-themes, default); +$theme: map-get($stratos-theme, theme); + +@if map-has-key($stratos-themes, 'dark') { + $stratos-dark-theme-supported: true; + $dark-stratos-theme: map-get($stratos-themes, dark); + $dark-theme: map-get($dark-stratos-theme, theme); + + body.stratos { + .dark-theme { + @include angular-material-theme($dark-theme); + @include app-theme($dark-stratos-theme); + } } } .default { - // Themes palettes and colors - $oss-theme-primary: mat-palette($mat-blue); - $oss-theme-accent: mat-palette($mat-blue); - $oss-theme-warn: mat-palette($mat-red); - $oss-theme: mat-light-theme($oss-theme-primary, $oss-theme-accent, $oss-theme-warn); - - // Default to using the open source theme - $stratos-theme: $oss-theme !default; - $stratos-nav-theme: null !default; - $stratos-status-theme: null !default; - - @include angular-material-theme($stratos-theme); - @include app-theme($stratos-theme, $stratos-nav-theme, $stratos-status-theme); + @include angular-material-theme($theme); + @include app-theme($stratos-theme); } -$stratos-dark-theme-supported: true !default; - -// Create the theme +// Import mat-core @include mat-core; diff --git a/src/frontend/packages/core/src/app.component.ts b/src/frontend/packages/core/src/app.component.ts index 542077cb5e..7e7be0556e 100644 --- a/src/frontend/packages/core/src/app.component.ts +++ b/src/frontend/packages/core/src/app.component.ts @@ -1,13 +1,13 @@ -import { AfterContentInit, Component, HostBinding, OnDestroy, OnInit, Inject } from '@angular/core'; +import { DOCUMENT } from '@angular/common'; +import { AfterContentInit, Component, HostBinding, Inject, OnDestroy, OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; import { create } from 'rxjs-spy'; import { AuthOnlyAppState } from '../../store/src/app-state'; -import { ThemeService } from './core/theme.service'; +import { ThemeService } from '../../store/src/theme.service'; import { environment } from './environments/environment'; import { LoggedInService } from './logged-in.service'; -import { DOCUMENT } from '@angular/common'; @Component({ selector: 'app-root', diff --git a/src/frontend/packages/core/src/app.module.ts b/src/frontend/packages/core/src/app.module.ts index 7ba9fb46a1..24bfcbbe56 100644 --- a/src/frontend/packages/core/src/app.module.ts +++ b/src/frontend/packages/core/src/app.module.ts @@ -4,40 +4,40 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { Params, RouteReuseStrategy, RouterStateSnapshot } from '@angular/router'; import { DefaultRouterStateSerializer, RouterStateSerializer, StoreRouterConnectingModule } from '@ngrx/router-store'; import { Store } from '@ngrx/store'; +import { StoreDevtoolsModule } from '@ngrx/store-devtools'; import { debounceTime, filter, withLatestFrom } from 'rxjs/operators'; import { CfAutoscalerModule } from '../../cf-autoscaler/src/cf-autoscaler.module'; import { CloudFoundryPackageModule } from '../../cloud-foundry/src/cloud-foundry-package.module'; import { SetRecentlyVisitedEntityAction } from '../../store/src/actions/recently-visited.actions'; -import { - UpdateUserFavoriteMetadataAction, -} from '../../store/src/actions/user-favourites-actions/update-user-favorite-metadata-action'; import { GeneralEntityAppState, GeneralRequestDataState } from '../../store/src/app-state'; import { EntityCatalogModule } from '../../store/src/entity-catalog.module'; import { entityCatalog } from '../../store/src/entity-catalog/entity-catalog'; import { EntityCatalogHelper } from '../../store/src/entity-catalog/entity-catalog-entity/entity-catalog.service'; import { EntityCatalogHelpers } from '../../store/src/entity-catalog/entity-catalog.helper'; -import { endpointSchemaKey } from '../../store/src/helpers/entity-factory'; +import { FavoritesConfigMapper } from '../../store/src/favorite-config-mapper'; +import { endpointEntityType, STRATOS_ENDPOINT_TYPE } from '../../store/src/helpers/stratos-entity-factory'; import { getAPIRequestDataState, selectEntity } from '../../store/src/selectors/api.selectors'; import { internalEventStateSelector } from '../../store/src/selectors/internal-events.selectors'; import { recentlyVisitedSelector } from '../../store/src/selectors/recently-visitied.selectors'; import { AppStoreModule } from '../../store/src/store.module'; +import { stratosEntityCatalog } from '../../store/src/stratos-entity-catalog'; +import { generateStratosEntities } from '../../store/src/stratos-entity-generator'; import { EndpointModel } from '../../store/src/types/endpoint.types'; import { IFavoriteMetadata, UserFavorite } from '../../store/src/types/user-favorites.types'; +import { UserFavoriteManager } from '../../store/src/user-favorite-manager'; import { TabNavService } from '../tab-nav.service'; import { XSRFModule } from '../xsrf.module'; import { AppComponent } from './app.component'; import { RouteModule } from './app.routing'; -import { STRATOS_ENDPOINT_TYPE } from './base-entity-schemas'; -import { generateStratosEntities } from './base-entity-types'; import { CoreModule } from './core/core.module'; import { CustomizationService } from './core/customizations.types'; import { DynamicExtensionRoutes } from './core/extension/dynamic-extension-routes'; import { ExtensionService } from './core/extension/extension-service'; import { getGitHubAPIURL, GITHUB_API_URL } from './core/github.helpers'; import { CurrentUserPermissionsService } from './core/permissions/current-user-permissions.service'; -import { UserFavoriteManager } from './core/user-favorite-manager'; import { CustomImportModule } from './custom-import.module'; +import { environment } from './environments/environment'; import { AboutModule } from './features/about/about.module'; import { DashboardModule } from './features/dashboard/dashboard.module'; import { HomeModule } from './features/home/home.module'; @@ -46,7 +46,6 @@ import { NoEndpointsNonAdminComponent } from './features/no-endpoints-non-admin/ import { SetupModule } from './features/setup/setup.module'; import { LoggedInService } from './logged-in.service'; import { CustomReuseStrategy } from './route-reuse-stragegy'; -import { FavoritesConfigMapper } from './shared/components/favorites-meta-card/favorite-config-mapper'; import { endpointEventKey, GlobalEventData, GlobalEventService } from './shared/global-events.service'; import { SidePanelService } from './shared/services/side-panel.service'; import { SharedModule } from './shared/shared.module'; @@ -80,6 +79,18 @@ export class CustomRouterStateSerializer } } +const storeDebugImports = environment.production ? [] : [ + StoreDevtoolsModule.instrument({ + maxAge: 100, + logOnly: !environment.production + }) +]; + +@NgModule({ + imports: storeDebugImports +}) +class AppStoreDebugModule { } + /** * `HttpXsrfTokenExtractor` which retrieves the token from a cookie. */ @@ -94,6 +105,7 @@ export class CustomRouterStateSerializer RouteModule, CloudFoundryPackageModule, AppStoreModule, + AppStoreDebugModule, BrowserModule, SharedModule, BrowserAnimationsModule, @@ -159,7 +171,7 @@ export class AppModule { if (!backendErrors.length) { return res; } - const entityConfig = entityCatalog.getEntity(STRATOS_ENDPOINT_TYPE, endpointSchemaKey); + const entityConfig = entityCatalog.getEntity(STRATOS_ENDPOINT_TYPE, endpointEntityType); res.push(new GlobalEventData(true, { endpoint: selectEntity(entityConfig.entityKey, eventId)(state), count: backendErrors.length @@ -248,7 +260,7 @@ export class AppModule { private syncFavorite(favorite: UserFavorite, entities: GeneralRequestDataState) { if (favorite) { - const isEndpoint = (favorite.entityType === endpointSchemaKey); + const isEndpoint = (favorite.entityType === endpointEntityType); // If the favorite is an endpoint ensure we look in the stratosEndpoint part of the store instead of, for example, cfEndpoint const entityKey = isEndpoint ? entityCatalog.getEntityKey({ ...favorite, @@ -258,10 +270,10 @@ export class AppModule { if (entity) { const newMetadata = this.favoritesConfigMapper.getEntityMetadata(favorite, entity); if (this.metadataHasChanged(favorite.metadata, newMetadata)) { - this.store.dispatch(new UpdateUserFavoriteMetadataAction({ + stratosEntityCatalog.userFavorite.api.updateFavorite({ ...favorite, metadata: newMetadata - })); + }); } } } diff --git a/src/frontend/packages/core/src/base-entity-schemas.ts b/src/frontend/packages/core/src/base-entity-schemas.ts deleted file mode 100644 index 19da225c8b..0000000000 --- a/src/frontend/packages/core/src/base-entity-schemas.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { - endpointSchemaKey, - entityFactory, - systemInfoSchemaKey, - userFavouritesSchemaKey, - userProfileSchemaKey, -} from '../../store/src/helpers/entity-factory'; -import { EntitySchema } from '../../store/src/helpers/entity-schema'; - -export const metricEntityType = 'metrics'; - -export const STRATOS_ENDPOINT_TYPE = 'stratos'; -export const ENDPOINT_TYPE = 'endpoint'; - -class StratosEntitySchema extends EntitySchema { - constructor(entityType: string) { - super(entityType, STRATOS_ENDPOINT_TYPE); - } -} - -export const userFavoritesEntitySchema = new StratosEntitySchema(entityFactory(userFavouritesSchemaKey).entityType); -export const endpointEntitySchema = new StratosEntitySchema(entityFactory(endpointSchemaKey).entityType); -export const userProfileEntitySchema = new StratosEntitySchema(entityFactory(userProfileSchemaKey).entityType); -export const systemInfoEntitySchema = new StratosEntitySchema(entityFactory(systemInfoSchemaKey).entityType); diff --git a/src/frontend/packages/core/src/base-entity-types.ts b/src/frontend/packages/core/src/base-entity-types.ts deleted file mode 100644 index 15cee657b0..0000000000 --- a/src/frontend/packages/core/src/base-entity-types.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { - StratosCatalogEndpointEntity, - StratosCatalogEntity, -} from '../../store/src/entity-catalog/entity-catalog-entity/entity-catalog-entity'; -import { - addOrUpdateUserFavoriteMetadataReducer, - deleteUserFavoriteMetadataReducer, -} from '../../store/src/reducers/favorite.reducer'; -import { systemEndpointsReducer } from '../../store/src/reducers/system-endpoints.reducer'; -import { - endpointEntitySchema, - STRATOS_ENDPOINT_TYPE, - systemInfoEntitySchema, - userFavoritesEntitySchema, - userProfileEntitySchema, -} from './base-entity-schemas'; -import { BaseEndpointAuth } from './features/endpoints/endpoint-auth'; -import { - MetricsEndpointDetailsComponent, -} from './features/metrics/metrics-endpoint-details/metrics-endpoint-details.component'; - -// -// These types are used to represent the base stratos types. -// - -/** - * This is used as a fake endpoint type to allow the store to be initiated correctly - */ -const stratosType = { - logoUrl: '', - authTypes: [], - type: STRATOS_ENDPOINT_TYPE, - schema: null -}; - -/** - * DefaultEndpointEntityType is used to represent a general endpoint - * This should not be used to actually attempt to render an endpoint and is instead used as a way to fill the - */ -class DefaultEndpointCatalogEntity extends StratosCatalogEntity { - constructor() { - super({ - schema: endpointEntitySchema, - type: endpointEntitySchema.entityType, - endpoint: stratosType, - }, { - dataReducers: [ - systemEndpointsReducer - ] - }); - } -} - -class UserFavoriteCatalogEntity extends StratosCatalogEntity { - constructor() { - super({ - schema: userFavoritesEntitySchema, - type: userFavoritesEntitySchema.entityType, - endpoint: stratosType, - }, { - dataReducers: [ - addOrUpdateUserFavoriteMetadataReducer, - deleteUserFavoriteMetadataReducer, - ] - }); - } -} - -class UserProfileCatalogEntity extends StratosCatalogEntity { - constructor() { - super({ - schema: userProfileEntitySchema, - type: userProfileEntitySchema.entityType, - endpoint: stratosType, - }); - } -} - -class SystemInfoCatalogEntity extends StratosCatalogEntity { - constructor() { - super({ - schema: systemInfoEntitySchema, - type: systemInfoEntitySchema.entityType, - endpoint: stratosType, - }); - } -} - -export function generateStratosEntities() { - return [ - new DefaultEndpointCatalogEntity(), - new SystemInfoCatalogEntity(), - new UserFavoriteCatalogEntity(), - new UserProfileCatalogEntity(), - // TODO: metrics location to be sorted - STRAT-152 - new StratosCatalogEndpointEntity({ - type: 'metrics', - label: 'Metrics', - labelPlural: 'Metrics', - tokenSharing: true, - logoUrl: '/core/assets/endpoint-icons/metrics.svg', - authTypes: [BaseEndpointAuth.UsernamePassword, BaseEndpointAuth.None], - renderPriority: 1, - listDetailsComponent: MetricsEndpointDetailsComponent, - }, - metadata => `/endpoints/metrics/${metadata.guid}` - ) - ]; -} - diff --git a/src/frontend/packages/core/src/features/endpoints/endpoint-auth.ts b/src/frontend/packages/core/src/core/endpoint-auth.ts similarity index 60% rename from src/frontend/packages/core/src/features/endpoints/endpoint-auth.ts rename to src/frontend/packages/core/src/core/endpoint-auth.ts index 757b0677e5..0fa06e90d1 100644 --- a/src/frontend/packages/core/src/features/endpoints/endpoint-auth.ts +++ b/src/frontend/packages/core/src/core/endpoint-auth.ts @@ -1,9 +1,17 @@ -import { EndpointAuthTypeNames } from './endpoint-helpers'; import { Validators } from '@angular/forms'; -import { EndpointType, EndpointAuthTypeConfig } from '../../core/extension/extension-types'; -import { CredentialsAuthFormComponent } from './connect-endpoint-dialog/auth-forms/credentials-auth-form.component'; -import { SSOAuthFormComponent } from './connect-endpoint-dialog/auth-forms/sso-auth-form.component'; -import { NoneAuthFormComponent } from './connect-endpoint-dialog/auth-forms/none-auth-form.component'; + +import { EndpointAuthTypeConfig, EndpointType } from '../../../store/src/extension-types'; +import { + CredentialsAuthFormComponent, +} from '../features/endpoints/connect-endpoint-dialog/auth-forms/credentials-auth-form.component'; +import { NoneAuthFormComponent } from '../features/endpoints/connect-endpoint-dialog/auth-forms/none-auth-form.component'; +import { SSOAuthFormComponent } from '../features/endpoints/connect-endpoint-dialog/auth-forms/sso-auth-form.component'; + +export enum EndpointAuthTypeNames { + CREDS = 'creds', + SSO = 'sso', + NONE = 'none' +} export abstract class BaseEndpointAuth { static readonly UsernamePassword = { diff --git a/src/frontend/packages/core/src/core/endpoints.service.spec.ts b/src/frontend/packages/core/src/core/endpoints.service.spec.ts index 006d10ccb7..3ac576abcd 100644 --- a/src/frontend/packages/core/src/core/endpoints.service.spec.ts +++ b/src/frontend/packages/core/src/core/endpoints.service.spec.ts @@ -1,8 +1,8 @@ import { inject, TestBed } from '@angular/core/testing'; - -import { CoreTestingModule } from '../../test-framework/core-test.modules'; import { createBasicStoreModule } from '@stratosui/store/testing'; + import { PaginationMonitorFactory } from '../../../store/src/monitors/pagination-monitor.factory'; +import { CoreTestingModule } from '../../test-framework/core-test.modules'; import { CoreModule } from './core.module'; import { EndpointsService } from './endpoints.service'; import { UtilsService } from './utils.service'; diff --git a/src/frontend/packages/core/src/core/endpoints.service.ts b/src/frontend/packages/core/src/core/endpoints.service.ts index 7160d50652..6354590f8a 100644 --- a/src/frontend/packages/core/src/core/endpoints.service.ts +++ b/src/frontend/packages/core/src/core/endpoints.service.ts @@ -7,10 +7,11 @@ import { first, map, skipWhile, withLatestFrom } from 'rxjs/operators'; import { RouterNav } from '../../../store/src/actions/router.actions'; import { EndpointOnlyAppState, IRequestEntityTypeState } from '../../../store/src/app-state'; import { entityCatalog } from '../../../store/src/entity-catalog/entity-catalog'; +import { EndpointHealthCheck } from '../../../store/src/entity-catalog/entity-catalog.types'; import { AuthState } from '../../../store/src/reducers/auth.reducer'; import { endpointEntitiesSelector, endpointStatusSelector } from '../../../store/src/selectors/endpoint.selectors'; import { EndpointModel, EndpointState } from '../../../store/src/types/endpoint.types'; -import { EndpointHealthCheck, EndpointHealthChecks } from '../../endpoints-health-checks'; +import { EndpointHealthChecks } from '../../endpoints-health-checks'; import { endpointHasMetricsByAvailable } from '../features/endpoints/endpoint-helpers'; import { UserService } from './user.service'; diff --git a/src/frontend/packages/core/src/core/entity-favorite-star/entity-favorite-star.component.spec.ts b/src/frontend/packages/core/src/core/entity-favorite-star/entity-favorite-star.component.spec.ts index 5aee8a1959..067a4e1f69 100644 --- a/src/frontend/packages/core/src/core/entity-favorite-star/entity-favorite-star.component.spec.ts +++ b/src/frontend/packages/core/src/core/entity-favorite-star/entity-favorite-star.component.spec.ts @@ -2,13 +2,13 @@ import { OverlayContainer } from '@angular/cdk/overlay'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { BehaviorSubject, of } from 'rxjs'; +import { FavoritesConfigMapper } from '../../../../store/src/favorite-config-mapper'; import { PaginationMonitorFactory } from '../../../../store/src/monitors/pagination-monitor.factory'; import { IFavoriteMetadata, UserFavorite } from '../../../../store/src/types/user-favorites.types'; +import { UserFavoriteManager } from '../../../../store/src/user-favorite-manager'; import { BaseTestModulesNoShared } from '../../../test-framework/core-test.helper'; import { ConfirmationDialogService } from '../../shared/components/confirmation-dialog.service'; import { DialogConfirmComponent } from '../../shared/components/dialog-confirm/dialog-confirm.component'; -import { FavoritesConfigMapper } from '../../shared/components/favorites-meta-card/favorite-config-mapper'; -import { UserFavoriteManager } from '../user-favorite-manager'; import { EntityFavoriteStarComponent } from './entity-favorite-star.component'; describe('EntityFavoriteStarComponent', () => { diff --git a/src/frontend/packages/core/src/core/entity-favorite-star/entity-favorite-star.component.ts b/src/frontend/packages/core/src/core/entity-favorite-star/entity-favorite-star.component.ts index 6487ce3708..c345e7d523 100644 --- a/src/frontend/packages/core/src/core/entity-favorite-star/entity-favorite-star.component.ts +++ b/src/frontend/packages/core/src/core/entity-favorite-star/entity-favorite-star.component.ts @@ -2,12 +2,12 @@ import { Component, Input } from '@angular/core'; import { Observable } from 'rxjs'; import { first, tap } from 'rxjs/operators'; +import { FavoritesConfigMapper } from '../../../../store/src/favorite-config-mapper'; import { IFavoriteMetadata, UserFavorite } from '../../../../store/src/types/user-favorites.types'; +import { UserFavoriteManager } from '../../../../store/src/user-favorite-manager'; import { ConfirmationDialogConfig } from '../../shared/components/confirmation-dialog.config'; import { ConfirmationDialogService } from '../../shared/components/confirmation-dialog.service'; -import { FavoritesConfigMapper } from '../../shared/components/favorites-meta-card/favorite-config-mapper'; import { EndpointsService } from '../endpoints.service'; -import { UserFavoriteManager } from '../user-favorite-manager'; @Component({ selector: 'app-entity-favorite-star', diff --git a/src/frontend/packages/core/src/core/extension/extension-service.ts b/src/frontend/packages/core/src/core/extension/extension-service.ts index 82b7a305ff..c71151f5b7 100644 --- a/src/frontend/packages/core/src/core/extension/extension-service.ts +++ b/src/frontend/packages/core/src/core/extension/extension-service.ts @@ -1,4 +1,4 @@ -import { Injectable, NgModule, ModuleWithProviders } from '@angular/core'; +import { Injectable, ModuleWithProviders, NgModule } from '@angular/core'; import { ActivatedRoute, Route, Router } from '@angular/router'; import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; @@ -6,6 +6,7 @@ import { Observable } from 'rxjs'; import { AppState, GeneralEntityAppState } from '../../../../store/src/app-state'; import { EntityServiceFactory } from '../../../../store/src/entity-service-factory.service'; import { IPageSideNavTab } from '../../features/dashboard/page-side-nav/page-side-nav.component'; +import { CurrentUserPermissionsService } from '../permissions/current-user-permissions.service'; export const extensionsActionRouteKey = 'extensionsActionsKey'; @@ -23,7 +24,12 @@ export interface StratosTabMetadata { link: string; icon?: string; iconFont?: string; - hidden?: (store: Store, esf: EntityServiceFactory, activatedRoute: ActivatedRoute) => Observable; + hidden?: ( + store: Store, + esf: EntityServiceFactory, + activatedRoute: ActivatedRoute, + cups: CurrentUserPermissionsService + ) => Observable; } export interface StratosTabMetadataConfig extends StratosTabMetadata { @@ -97,7 +103,7 @@ function addExtensionTab(tab: StratosTabType, target: any, props: StratosTabMeta }); extensionMetadata.tabs[tab].push({ ...props - }); + }); } function addExtensionAction(action: StratosActionType, target: any, props: StratosActionMetadata) { diff --git a/src/frontend/packages/core/src/core/logger.service.spec.ts b/src/frontend/packages/core/src/core/logger.service.spec.ts index e2f904e060..1720fe0b84 100644 --- a/src/frontend/packages/core/src/core/logger.service.spec.ts +++ b/src/frontend/packages/core/src/core/logger.service.spec.ts @@ -1,7 +1,7 @@ import { inject, TestBed } from '@angular/core/testing'; +import { createBasicStoreModule } from '@stratosui/store/testing'; import { CoreTestingModule } from '../../test-framework/core-test.modules'; -import { createBasicStoreModule } from '@stratosui/store/testing'; import { LoggerService } from './logger.service'; describe('LoggerService', () => { diff --git a/src/frontend/packages/core/src/core/permissions/current-user-permissions.config.ts b/src/frontend/packages/core/src/core/permissions/current-user-permissions.config.ts index a91481dd62..9e08107255 100644 --- a/src/frontend/packages/core/src/core/permissions/current-user-permissions.config.ts +++ b/src/frontend/packages/core/src/core/permissions/current-user-permissions.config.ts @@ -1,3 +1,5 @@ +import { PermissionValues } from '../../../../store/src/selectors/current-user-role.selectors'; + export type PermissionConfigType = PermissionConfig[] | PermissionConfig | PermissionConfigLink; export interface IPermissionConfigs { [permissionString: string]: PermissionConfigType; @@ -6,7 +8,6 @@ export interface IPermissionConfigs { export type PermissionTypes = string; export type CurrentUserPermissions = string; export type ScopeStrings = string; -export type PermissionValues = string; export class PermissionConfig { constructor( public type: PermissionTypes, diff --git a/src/frontend/packages/core/src/core/permissions/current-user-permissions.service.spec.ts b/src/frontend/packages/core/src/core/permissions/current-user-permissions.service.spec.ts index e8e69c7782..90d5401db5 100644 --- a/src/frontend/packages/core/src/core/permissions/current-user-permissions.service.spec.ts +++ b/src/frontend/packages/core/src/core/permissions/current-user-permissions.service.spec.ts @@ -5,12 +5,12 @@ import { first, tap } from 'rxjs/operators'; import { AppState } from '../../../../store/src/app-state'; import { EntityCatalogTestModule, TEST_CATALOGUE_ENTITIES } from '../../../../store/src/entity-catalog-test.module'; import { EntityCatalogEntityConfig } from '../../../../store/src/entity-catalog/entity-catalog.types'; +import { endpointEntityType, stratosEntityFactory } from '../../../../store/src/helpers/stratos-entity-factory'; +import { generateStratosEntities } from '../../../../store/src/stratos-entity-generator'; import { EndpointModel } from '../../../../store/src/types/endpoint.types'; import { BaseEntityValues } from '../../../../store/src/types/entity.types'; import { PaginationState } from '../../../../store/src/types/pagination.types'; import { AppTestModule } from '../../../test-framework/core-test.helper'; -import { endpointEntitySchema } from '../../base-entity-schemas'; -import { generateStratosEntities } from '../../base-entity-types'; import { PermissionConfig } from './current-user-permissions.config'; import { CurrentUserPermissionsService } from './current-user-permissions.service'; import { StratosPermissionStrings, StratosPermissionTypes, StratosScopeStrings } from './stratos-user-permissions.checker'; @@ -138,7 +138,7 @@ describe('CurrentUserPermissionsService', () => { // Create request and requestData sections const entityMap = new Map>([ [ - endpointEntitySchema, + stratosEntityFactory(endpointEntityType), endpoints.map(endpoint => ({ guid: endpoint.guid, data: endpoint diff --git a/src/frontend/packages/core/src/core/permissions/current-user-permissions.service.ts b/src/frontend/packages/core/src/core/permissions/current-user-permissions.service.ts index 0a7490fb0c..4ad096b7c5 100644 --- a/src/frontend/packages/core/src/core/permissions/current-user-permissions.service.ts +++ b/src/frontend/packages/core/src/core/permissions/current-user-permissions.service.ts @@ -4,10 +4,7 @@ import { combineLatest, Observable, of } from 'rxjs'; import { distinctUntilChanged, map, switchMap } from 'rxjs/operators'; import { InternalAppState } from '../../../../store/src/app-state'; -import { entityCatalog } from '../../../../store/src/entity-catalog/entity-catalog'; -import { selectEntity } from '../../../../store/src/selectors/api.selectors'; -import { EndpointModel } from '../../../../store/src/types/endpoint.types'; -import { ENDPOINT_TYPE, STRATOS_ENDPOINT_TYPE } from '../../base-entity-schemas'; +import { stratosEntityCatalog } from '../../../../store/src/stratos-entity-catalog'; import { LoggerService } from '../logger.service'; import { CurrentUserPermissions, @@ -23,7 +20,7 @@ import { import { StratosUserPermissionsChecker } from './stratos-user-permissions.checker'; -export const CUSTOM_USER_PERMISSION_CHECKERS = 'custom_user_perm_checkers' +export const CUSTOM_USER_PERMISSION_CHECKERS = 'custom_user_perm_checkers'; @Injectable() export class CurrentUserPermissionsService { @@ -38,7 +35,7 @@ export class CurrentUserPermissionsService { this.allCheckers = [ new StratosUserPermissionsChecker(store), ...nullSafeCustomCheckers - ] + ]; } /** * @param action The action we're going to check the user's access to. @@ -56,13 +53,13 @@ export class CurrentUserPermissionsService { ): Observable { let actionConfig; if (typeof action === 'string') { - let permConfigType = this.getPermissionConfig(action); + const permConfigType = this.getPermissionConfig(action); if (!permConfigType) { return of(false); // Logging handled in getPermissionConfig } actionConfig = this.getConfig(permConfigType); } else { - actionConfig = this.getConfig(action) + actionConfig = this.getConfig(action); } const obs$ = this.getCanObservable(actionConfig, endpointGuid, ...args); return obs$ ? @@ -79,8 +76,7 @@ export class CurrentUserPermissionsService { } else if (actionConfig) { return this.getSimplePermission(actionConfig, endpointGuid, ...args); } else if (endpointGuid) { - const key = entityCatalog.getEntityKey(STRATOS_ENDPOINT_TYPE, ENDPOINT_TYPE); - return this.store.select(selectEntity(key, endpointGuid)).pipe( + return stratosEntityCatalog.endpoint.store.getEntityMonitor(endpointGuid).entity$.pipe( switchMap(endpoint => endpoint ? this.getFallbackPermission(endpointGuid, endpoint.cnsi_type) : of(false) @@ -96,7 +92,7 @@ export class CurrentUserPermissionsService { 'permissions check', actionConfig.type, of(false) - ) + ); } private getComplexPermission(permissionConfig: PermissionConfig[], endpointGuid?: string, ...args: any[]) { @@ -116,7 +112,7 @@ export class CurrentUserPermissionsService { [{ checks: [of(false)] }] - ) + ); } private getConfig(config: PermissionConfigType, tries = 0): PermissionConfig[] | PermissionConfig { @@ -152,7 +148,7 @@ export class CurrentUserPermissionsService { 'fallback permission', 'N/A', of(null) - ) + ); } private getPermissionConfig(key: CurrentUserPermissions): PermissionConfigType { @@ -161,7 +157,7 @@ export class CurrentUserPermissionsService { 'permissions checker', key, null - ) + ); } /** diff --git a/src/frontend/packages/core/src/core/permissions/stratos-user-permissions.checker.ts b/src/frontend/packages/core/src/core/permissions/stratos-user-permissions.checker.ts index a0bcb58695..db4c382b26 100644 --- a/src/frontend/packages/core/src/core/permissions/stratos-user-permissions.checker.ts +++ b/src/frontend/packages/core/src/core/permissions/stratos-user-permissions.checker.ts @@ -5,8 +5,9 @@ import { GeneralEntityAppState } from '../../../../store/src/app-state'; import { getCurrentUserStratosHasScope, getCurrentUserStratosRole, + PermissionValues, } from '../../../../store/src/selectors/current-user-role.selectors'; -import { IPermissionConfigs, PermissionConfig, PermissionTypes, PermissionValues } from './current-user-permissions.config'; +import { IPermissionConfigs, PermissionConfig, PermissionTypes } from './current-user-permissions.config'; import { BaseCurrentUserPermissionsChecker, IConfigGroups, diff --git a/src/frontend/packages/core/src/core/stateful-icon/stateful-icon.component.spec.ts b/src/frontend/packages/core/src/core/stateful-icon/stateful-icon.component.spec.ts index f258f527ae..1a8cd63bc7 100644 --- a/src/frontend/packages/core/src/core/stateful-icon/stateful-icon.component.spec.ts +++ b/src/frontend/packages/core/src/core/stateful-icon/stateful-icon.component.spec.ts @@ -1,6 +1,6 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { StratosStatus } from '../../shared/shared.types'; +import { StratosStatus } from '../../../../store/src/types/shared.types'; import { MDAppModule } from '../md.module'; import { StatefulIconComponent } from './stateful-icon.component'; diff --git a/src/frontend/packages/core/src/core/stateful-icon/stateful-icon.component.ts b/src/frontend/packages/core/src/core/stateful-icon/stateful-icon.component.ts index 5ad05aa35d..fdcd63847a 100644 --- a/src/frontend/packages/core/src/core/stateful-icon/stateful-icon.component.ts +++ b/src/frontend/packages/core/src/core/stateful-icon/stateful-icon.component.ts @@ -1,5 +1,6 @@ -import { Component, Input, OnInit, TemplateRef, ViewChild } from '@angular/core'; -import { StratosStatus } from '../../shared/shared.types'; +import { Component, Input, TemplateRef } from '@angular/core'; + +import { StratosStatus } from '../../../../store/src/types/shared.types'; interface IconDefinition { icon: string; diff --git a/src/frontend/packages/core/src/core/user-profile.service.ts b/src/frontend/packages/core/src/core/user-profile.service.ts index f83b16a256..0a496d3adc 100644 --- a/src/frontend/packages/core/src/core/user-profile.service.ts +++ b/src/frontend/packages/core/src/core/user-profile.service.ts @@ -1,24 +1,15 @@ import { Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; -import { combineLatest, Observable, of as observableOf, of } from 'rxjs'; +import { combineLatest, Observable, of as observableOf } from 'rxjs'; import { filter, first, map, publishReplay, refCount, switchMap } from 'rxjs/operators'; -import { - FetchUserProfileAction, - UpdateUserPasswordAction, - UpdateUserProfileAction, -} from '../../../store/src/actions/user-profile.actions'; import { AppState } from '../../../store/src/app-state'; -import { userProfilePasswordUpdatingKey } from '../../../store/src/effects/user-profile.effects'; -import { entityCatalog } from '../../../store/src/entity-catalog/entity-catalog'; import { EntityService } from '../../../store/src/entity-service'; -import { EntityServiceFactory } from '../../../store/src/entity-service-factory.service'; -import { ActionState, getDefaultActionState, rootUpdatingKey } from '../../../store/src/reducers/api-request-reducer/types'; +import { ActionState, getDefaultActionState } from '../../../store/src/reducers/api-request-reducer/types'; import { AuthState } from '../../../store/src/reducers/auth.reducer'; -import { selectRequestInfo, selectUpdateInfo } from '../../../store/src/selectors/api.selectors'; +import { stratosEntityCatalog } from '../../../store/src/stratos-entity-catalog'; import { SessionData } from '../../../store/src/types/auth.types'; import { UserProfileInfo, UserProfileInfoEmail, UserProfileInfoUpdates } from '../../../store/src/types/user-profile.types'; -import { userProfileEntitySchema } from '../base-entity-schemas'; @Injectable() @@ -32,21 +23,22 @@ export class UserProfileService { userProfile$: Observable; - private stratosUserConfig = entityCatalog.getEntity(userProfileEntitySchema.endpointType, userProfileEntitySchema.entityType); + private userGuid$: Observable; constructor( private store: Store, - esf: EntityServiceFactory ) { - if (!this.stratosUserConfig) { - console.error('Can not get user profile entity'); - this.userProfile$ = of({} as UserProfileInfo); - return; - } + this.userGuid$ = this.store.select(s => s.auth).pipe( + filter((auth: AuthState) => !!(auth && auth.sessionData)), + map((auth: AuthState) => auth.sessionData), + filter((sessionData: SessionData) => !!sessionData.user), + first(), + map(data => data.user.guid) + ); - this.entityService = this.createFetchUserAction().pipe( + this.entityService = this.userGuid$.pipe( first(), - map(action => esf.create(action.guid, action)), + map(userGuid => stratosEntityCatalog.userProfile.store.getEntityService(userGuid)), publishReplay(1), refCount() ); @@ -60,27 +52,16 @@ export class UserProfileService { switchMap(service => service.isFetchingEntity$) ); - this.isError$ = this.store.select(selectRequestInfo(this.stratosUserConfig.entityKey, FetchUserProfileAction.guid)).pipe( + this.isError$ = this.entityService.pipe( + switchMap(es => es.entityMonitor.entityRequest$), filter(requestInfo => !!requestInfo && !requestInfo.fetching), map(requestInfo => requestInfo.error) - ); - } - - private createFetchUserAction(): Observable { - return this.store.select(s => s.auth).pipe( - filter((auth: AuthState) => !!(auth && auth.sessionData)), - map((auth: AuthState) => auth.sessionData), - filter((sessionData: SessionData) => !!sessionData.user), - first(), - map(data => new FetchUserProfileAction(data.user.guid)) - ); + ) } fetchUserProfile() { // Once we have the user's guid, fetch their profile - this.createFetchUserAction().pipe(first()).subscribe(action => { - this.store.dispatch(action); - }); + this.userGuid$.pipe(first()).subscribe(userGuid => stratosEntityCatalog.userProfile.api.get(userGuid)); } getPrimaryEmailAddress(profile: UserProfileInfo): string { @@ -135,11 +116,8 @@ export class UserProfileService { if (profileChanges.emailAddress) { this.setPrimaryEmailAddress(updatedProfile, profileChanges.emailAddress); } - this.store.dispatch(new UpdateUserProfileAction(updatedProfile, profileChanges.currentPassword)); - const actionState = selectUpdateInfo(this.stratosUserConfig.entityKey, - FetchUserProfileAction.guid, - rootUpdatingKey); - return this.store.select(actionState).pipe( + + return stratosEntityCatalog.userProfile.api.updateProfile(updatedProfile, profileChanges.currentPassword).pipe( filter(item => item && !item.busy) ); } @@ -149,11 +127,7 @@ export class UserProfileService { oldPassword: profileChanges.currentPassword, password: profileChanges.newPassword }; - this.store.dispatch(new UpdateUserPasswordAction(profile.id, passwordUpdates)); - const actionState = selectUpdateInfo(this.stratosUserConfig.entityKey, - FetchUserProfileAction.guid, - userProfilePasswordUpdatingKey); - return this.store.select(actionState).pipe( + return stratosEntityCatalog.userProfile.api.updatePassword(profile.id, passwordUpdates).pipe( filter(item => item && !item.busy) ); } diff --git a/src/frontend/packages/core/src/core/user.service.spec.ts b/src/frontend/packages/core/src/core/user.service.spec.ts index 6fdaab8b3a..f831c61b18 100644 --- a/src/frontend/packages/core/src/core/user.service.spec.ts +++ b/src/frontend/packages/core/src/core/user.service.spec.ts @@ -1,7 +1,7 @@ import { inject, TestBed } from '@angular/core/testing'; +import { createBasicStoreModule } from '@stratosui/store/testing'; import { CoreTestingModule } from '../../test-framework/core-test.modules'; -import { createBasicStoreModule } from '@stratosui/store/testing'; import { SharedModule } from '../shared/shared.module'; import { CoreModule } from './core.module'; import { UserService } from './user.service'; diff --git a/src/frontend/packages/core/src/core/utils.service.ts b/src/frontend/packages/core/src/core/utils.service.ts index 83de981544..d3d1c3f837 100644 --- a/src/frontend/packages/core/src/core/utils.service.ts +++ b/src/frontend/packages/core/src/core/utils.service.ts @@ -11,56 +11,6 @@ export function getIdFromRoute(activatedRoute: ActivatedRoute, id: string) { return null; } -export type OptionalKeys = Exclude<{ - [K in keyof T]: T extends Record - ? K - : never -}[keyof T], undefined> - - -export type NonOptionalKeys = Exclude<{ - [K in keyof T]: T extends Record - ? K - : never -}[keyof T], undefined> - -export type NeverKeys = Exclude<{ - [K in keyof T]: T[K] extends never - ? K - : never -}[keyof T], undefined> - - -/** - * Remove keys such as typed indexes (i.e. [key: string]) - * For magic see - * - https://github.com/Microsoft/TypeScript/issues/25987#issuecomment-441224690 - * - https://github.com/Microsoft/TypeScript/issues/12215#issuecomment-414808995 - */ -export type KnownKeys = { - [K in keyof T]: string extends K ? never : number extends K ? never : K -} extends { [_ in keyof T]: infer U } ? ({} extends U ? never : U) : never; - -/** - * Pick all properties who's function has the specified return type U - */ -export type FilteredByReturnType any }, U> = { - [P in keyof T]: ReturnType extends U ? T[P] : never -}; - -/** - * Pick all properties who's function do not have the specified return type U - */ -export type FilteredByNotReturnType any }, U> = { - [P in keyof T]: ReturnType extends U ? never : T[P] -}; - -// Note - Adding }[keyof T] to [P in keyof T] types should filter out properties of type `never`, however this fails with generics! -export type FilteredByValueType any }, U> = { - [P in keyof T]: T[P] extends U ? never : T[P] -}; - - export const urlValidationExpression = '^' + // protocol identifier @@ -319,13 +269,6 @@ export const safeUnsubscribe = (...subs: Subscription[]) => { export const truthyIncludingZero = (obj: any): boolean => !!obj || obj === 0; export const truthyIncludingZeroString = (obj: any): string => truthyIncludingZero(obj) ? obj.toString() : null; -export const sortStringify = (obj: { [key: string]: string | string[] | number }): string => { - const keys = Object.keys(obj).sort(); - return keys.reduce((res, key) => { - return res += `${key}-${obj[key]},`; - }, ''); -}; - /** * Real basic, shallow check */ diff --git a/src/frontend/packages/core/misc/custom/custom.module.ts_ b/src/frontend/packages/core/src/custom-import.module.ts similarity index 57% rename from src/frontend/packages/core/misc/custom/custom.module.ts_ rename to src/frontend/packages/core/src/custom-import.module.ts index b4118c293d..3d84d8fdec 100644 --- a/src/frontend/packages/core/misc/custom/custom.module.ts_ +++ b/src/frontend/packages/core/src/custom-import.module.ts @@ -2,7 +2,8 @@ import { NgModule } from '@angular/core'; // Default empty customization module - DO NOT EDIT -// This file is in the .gitignore - changes will not be flagged +// These modules will be intercepted by the custom webpack configuration +// They are only here so that on a fresh checkout, both modules are defined @NgModule() export class CustomImportModule { } diff --git a/src/frontend/packages/core/src/environments/environment.prod.ts b/src/frontend/packages/core/src/environments/environment.prod.ts index 651a68d984..da8e7d8dbd 100644 --- a/src/frontend/packages/core/src/environments/environment.prod.ts +++ b/src/frontend/packages/core/src/environments/environment.prod.ts @@ -1,10 +1,11 @@ +import { cfAPIVersion, proxyAPIVersion } from '../../../store/src/jetstream'; import { LogLevel } from './../../../store/src/actions/log.actions'; export const environment = { production: true, logLevel: LogLevel.WARN, - proxyAPIVersion: 'v1', - cfAPIVersion: 'v2', + proxyAPIVersion, + cfAPIVersion, logToConsole: true, logEnableConsoleActions: false, showObsDebug: false, diff --git a/src/frontend/packages/core/src/environments/environment.ts b/src/frontend/packages/core/src/environments/environment.ts index bb1db6f839..e10f7527a5 100644 --- a/src/frontend/packages/core/src/environments/environment.ts +++ b/src/frontend/packages/core/src/environments/environment.ts @@ -1,4 +1,5 @@ import { LogLevel } from '../../../store/src/actions/log.actions'; +import { cfAPIVersion, proxyAPIVersion } from '../../../store/src/jetstream'; // The file contents for the current environment will overwrite these during build. // The build system defaults to the dev environment which uses `environment.ts`, but if you do @@ -7,8 +8,8 @@ import { LogLevel } from '../../../store/src/actions/log.actions'; export const environment = { production: false, - proxyAPIVersion: 'v1', - cfAPIVersion: 'v2', + proxyAPIVersion, + cfAPIVersion, logLevel: LogLevel.DEBUG, logToConsole: true, logEnableConsoleActions: false, diff --git a/src/frontend/packages/core/src/features/about/about.module.ts b/src/frontend/packages/core/src/features/about/about.module.ts index c71cd11f55..9fe18f06af 100644 --- a/src/frontend/packages/core/src/features/about/about.module.ts +++ b/src/frontend/packages/core/src/features/about/about.module.ts @@ -5,8 +5,7 @@ import { SharedModule } from '../../shared/shared.module'; import { AboutPageComponent } from './about-page/about-page.component'; import { AboutRoutingModule } from './about.routing'; import { DiagnosticsPageComponent } from './diagnostics-page/diagnostics-page.component'; -import { EulaPageComponent, EulaPageContentComponent } from './eula-page/eula-page.component'; - +import { EulaPageComponent } from './eula-page/eula-page.component'; @NgModule({ @@ -17,7 +16,6 @@ import { EulaPageComponent, EulaPageContentComponent } from './eula-page/eula-pa ], declarations: [ AboutPageComponent, - EulaPageContentComponent, EulaPageComponent, DiagnosticsPageComponent ] diff --git a/src/frontend/packages/core/src/features/about/eula-page/eula-page.component.html b/src/frontend/packages/core/src/features/about/eula-page/eula-page.component.html index 27791db6f3..3a40946d0b 100644 --- a/src/frontend/packages/core/src/features/about/eula-page/eula-page.component.html +++ b/src/frontend/packages/core/src/features/about/eula-page/eula-page.component.html @@ -8,4 +8,4 @@

EULA

- \ No newline at end of file +
diff --git a/src/frontend/packages/core/src/features/about/eula-page/eula-page.component.spec.ts b/src/frontend/packages/core/src/features/about/eula-page/eula-page.component.spec.ts index 20023d114b..113aac37d3 100644 --- a/src/frontend/packages/core/src/features/about/eula-page/eula-page.component.spec.ts +++ b/src/frontend/packages/core/src/features/about/eula-page/eula-page.component.spec.ts @@ -1,3 +1,5 @@ +import { HttpClientModule } from '@angular/common/http'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { createBasicStoreModule } from '@stratosui/store/testing'; @@ -5,7 +7,7 @@ import { createBasicStoreModule } from '@stratosui/store/testing'; import { TabNavService } from '../../../../tab-nav.service'; import { CoreModule } from '../../../core/core.module'; import { SharedModule } from '../../../shared/shared.module'; -import { EulaPageComponent, EulaPageContentComponent } from './eula-page.component'; +import { EulaPageComponent } from './eula-page.component'; describe('EulaPageComponent', () => { let component: EulaPageComponent; @@ -13,11 +15,13 @@ describe('EulaPageComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [EulaPageComponent, EulaPageContentComponent], + declarations: [EulaPageComponent], imports: [ CoreModule, RouterTestingModule, SharedModule, + HttpClientModule, + HttpClientTestingModule, createBasicStoreModule(), ], providers: [TabNavService] diff --git a/src/frontend/packages/core/src/features/about/eula-page/eula-page.component.ts b/src/frontend/packages/core/src/features/about/eula-page/eula-page.component.ts index 8271e24c66..a93e345bf3 100644 --- a/src/frontend/packages/core/src/features/about/eula-page/eula-page.component.ts +++ b/src/frontend/packages/core/src/features/about/eula-page/eula-page.component.ts @@ -1,17 +1,12 @@ -import { Component, OnInit } from '@angular/core'; - -@Component({ - selector: 'app-eula-content', - templateUrl: '../../../../assets/eula.html' -}) -export class EulaPageContentComponent { } +import { Component } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; @Component({ selector: 'app-eula-page', templateUrl: './eula-page.component.html', styleUrls: ['./eula-page.component.scss'] }) -export class EulaPageComponent implements OnInit { +export class EulaPageComponent { public breadcrumbs = [ { @@ -19,10 +14,14 @@ export class EulaPageComponent implements OnInit { } ]; - constructor() { } - - ngOnInit() { + public eulaHtml = ''; + // Load the EULA + constructor(http: HttpClient) { + http.get('/core/assets/eula.html', {responseType: 'text'}).subscribe( + html => this.eulaHtml = html, + () => this.eulaHtml = 'An error occurred retrieving the EULA' + ); } } diff --git a/src/frontend/packages/core/src/features/dashboard/dashboard-base/dashboard-base.component.scss b/src/frontend/packages/core/src/features/dashboard/dashboard-base/dashboard-base.component.scss index d212cac3c2..26a2d129ce 100644 --- a/src/frontend/packages/core/src/features/dashboard/dashboard-base/dashboard-base.component.scss +++ b/src/frontend/packages/core/src/features/dashboard/dashboard-base/dashboard-base.component.scss @@ -1,4 +1,3 @@ -@import '../../../../sass/colors'; @import '../../../../sass/mixins'; $app-sub-header-height: 48px; diff --git a/src/frontend/packages/core/src/features/dashboard/dashboard-base/dashboard-base.component.ts b/src/frontend/packages/core/src/features/dashboard/dashboard-base/dashboard-base.component.ts index c409c37976..8310e6723e 100644 --- a/src/frontend/packages/core/src/features/dashboard/dashboard-base/dashboard-base.component.ts +++ b/src/frontend/packages/core/src/features/dashboard/dashboard-base/dashboard-base.component.ts @@ -9,11 +9,11 @@ import { distinctUntilChanged, filter, map, startWith, withLatestFrom } from 'rx import { CloseSideNav, DisableMobileNav, EnableMobileNav } from '../../../../../store/src/actions/dashboard-actions'; import { GetCurrentUsersRelations } from '../../../../../store/src/actions/permissions.actions'; -import { GetUserFavoritesAction } from '../../../../../store/src/actions/user-favourites-actions/get-user-favorites-action'; import { DashboardOnlyAppState } from '../../../../../store/src/app-state'; import { entityCatalog } from '../../../../../store/src/entity-catalog/entity-catalog'; import { DashboardState } from '../../../../../store/src/reducers/dashboard-reducer'; import { selectDashboardState } from '../../../../../store/src/selectors/dashboard.selectors'; +import { stratosEntityCatalog } from '../../../../../store/src/stratos-entity-catalog'; import { TabNavService } from '../../../../tab-nav.service'; import { CustomizationService } from '../../../core/customizations.types'; import { EndpointsService } from '../../../core/endpoints.service'; @@ -144,7 +144,7 @@ export class DashboardBaseComponent implements OnInit, OnDestroy, AfterViewInit }); this.dispatchRelations(); - this.store.dispatch(new GetUserFavoritesAction()); + stratosEntityCatalog.userFavorite.api.getAll(); } ngOnDestroy() { @@ -190,7 +190,7 @@ export class DashboardBaseComponent implements OnInit, OnDestroy, AfterViewInit link: path + '/' + route.path }; if (item.requiresEndpointType) { - // Upstream always likes to show Cloud Foundry related endpoints - other distributions can chane this behaviour + // Upstream always likes to show Cloud Foundry related endpoints - other distributions can change this behaviour const alwaysShow = this.cs.get().alwaysShowNavForEndpointTypes ? this.cs.get().alwaysShowNavForEndpointTypes(item.requiresEndpointType) : (item.requiresEndpointType === 'cf'); item.hidden = alwaysShow ? of(false) : this.endpointsService.doesNotHaveConnectedEndpointType(item.requiresEndpointType); diff --git a/src/frontend/packages/core/src/features/dashboard/page-side-nav/page-side-nav.component.ts b/src/frontend/packages/core/src/features/dashboard/page-side-nav/page-side-nav.component.ts index a91f4bd200..b74dbed831 100644 --- a/src/frontend/packages/core/src/features/dashboard/page-side-nav/page-side-nav.component.ts +++ b/src/frontend/packages/core/src/features/dashboard/page-side-nav/page-side-nav.component.ts @@ -4,12 +4,15 @@ import { Store } from '@ngrx/store'; import { Observable, of } from 'rxjs'; import { AppState } from '../../../../../store/src/app-state'; +import { EntityServiceFactory } from '../../../../../store/src/entity-service-factory.service'; import { selectIsMobile } from '../../../../../store/src/selectors/dashboard.selectors'; import { TabNavService } from '../../../../tab-nav.service'; -import { EntityServiceFactory } from '../../../../../store/src/entity-service-factory.service'; import { StratosTabMetadata } from '../../../core/extension/extension-service'; +import { CurrentUserPermissionsService } from '../../../core/permissions/current-user-permissions.service'; import { IBreadcrumb } from '../../../shared/components/breadcrumbs/breadcrumbs.types'; + + export interface IPageSideNavTab extends StratosTabMetadata { hidden$?: Observable; } @@ -28,7 +31,7 @@ export class PageSideNavComponent implements OnInit { } this.pTabs = tabs.map(tab => ({ ...tab, - hidden$: tab.hidden$ || (tab.hidden ? tab.hidden(this.store, this.esf, this.activatedRoute) : of(false)) + hidden$: tab.hidden$ || (tab.hidden ? tab.hidden(this.store, this.esf, this.activatedRoute, this.cups) : of(false)) })); } get tabs(): IPageSideNavTab[] { @@ -45,6 +48,7 @@ export class PageSideNavComponent implements OnInit { private store: Store, private esf: EntityServiceFactory, private activatedRoute: ActivatedRoute, + private cups: CurrentUserPermissionsService ) { this.isMobile$ = this.store.select(selectIsMobile); } diff --git a/src/frontend/packages/core/src/features/dashboard/side-nav/side-nav.component.theme.scss b/src/frontend/packages/core/src/features/dashboard/side-nav/side-nav.component.theme.scss index 7c2b8a671e..e4023c6b4c 100644 --- a/src/frontend/packages/core/src/features/dashboard/side-nav/side-nav.component.theme.scss +++ b/src/frontend/packages/core/src/features/dashboard/side-nav/side-nav.component.theme.scss @@ -4,6 +4,17 @@ $side-nav-colors: map-get($app-theme, side-nav); $side-nav-bottom-color: map-get($app-theme, subdued-color); $side-nav-hover-color: mat-color($side-nav-colors, hover); + $header-span: map-get($app-theme, header-background-span); + + $side-nav-top-background: map-get($side-nav-colors, background); + $side-nav-top-foreground: map-get($side-nav-colors, text); + + // Does the header background color span across the top, or is the sidenav background color used for the top-left portion + @if $header-span == true { + $side-nav-top-background: map-get($app-theme, header-background-color); + $side-nav-top-foreground: map-get($app-theme, header-foreground-color); + } + .side-nav { &__nav-toggle { color: mat-color($side-nav-colors, text); @@ -12,7 +23,8 @@ background-color: mat-color($side-nav-colors, background); } &__top { - background-color: mat-color($side-nav-colors, background-top); + background-color: $side-nav-top-background; + color: $side-nav-top-foreground; } &__item { color: mat-color($side-nav-colors, text); diff --git a/src/frontend/packages/core/src/features/endpoints/backup-restore/backup-endpoints.service.ts b/src/frontend/packages/core/src/features/endpoints/backup-restore/backup-endpoints.service.ts index 5251a66479..2aee2629c1 100644 --- a/src/frontend/packages/core/src/features/endpoints/backup-restore/backup-endpoints.service.ts +++ b/src/frontend/packages/core/src/features/endpoints/backup-restore/backup-endpoints.service.ts @@ -5,9 +5,9 @@ import { BehaviorSubject, Observable } from 'rxjs'; import { first, map } from 'rxjs/operators'; import { GeneralEntityAppState } from '../../../../../store/src/app-state'; +import { BrowserStandardEncoder } from '../../../../../store/src/browser-encoder'; import { entityCatalog } from '../../../../../store/src/entity-catalog/entity-catalog'; import { EndpointModel } from '../../../../../store/src/types/endpoint.types'; -import { BrowserStandardEncoder } from '../../../helper'; import { BackupEndpointConfigUI, BackupEndpointConnectionTypes, diff --git a/src/frontend/packages/core/src/features/endpoints/backup-restore/backup-endpoints/backup-endpoints.component.ts b/src/frontend/packages/core/src/features/endpoints/backup-restore/backup-endpoints/backup-endpoints.component.ts index 3ad6856b48..9c41ea8a3d 100644 --- a/src/frontend/packages/core/src/features/endpoints/backup-restore/backup-endpoints/backup-endpoints.component.ts +++ b/src/frontend/packages/core/src/features/endpoints/backup-restore/backup-endpoints/backup-endpoints.component.ts @@ -1,17 +1,13 @@ import { Component } from '@angular/core'; import { FormControl, FormGroup, Validators } from '@angular/forms'; -import { Store } from '@ngrx/store'; import * as moment from 'moment'; import { Observable, of, Subject } from 'rxjs'; import { filter, first, map } from 'rxjs/operators'; -import { GetAllEndpoints } from '../../../../../../store/src/actions/endpoint.actions'; -import { AppState } from '../../../../../../store/src/app-state'; import { entityCatalog } from '../../../../../../store/src/entity-catalog/entity-catalog'; -import { PaginationMonitorFactory } from '../../../../../../store/src/monitors/pagination-monitor.factory'; -import { getPaginationObservables } from '../../../../../../store/src/reducers/pagination-reducer/pagination-reducer.helper'; +import { httpErrorResponseToSafeString } from '../../../../../../store/src/jetstream'; +import { stratosEntityCatalog } from '../../../../../../store/src/stratos-entity-catalog'; import { EndpointModel } from '../../../../../../store/src/types/endpoint.types'; -import { httpErrorResponseToSafeString } from '../../../../jetstream.helpers'; import { ConfirmationDialogConfig } from '../../../../shared/components/confirmation-dialog.config'; import { ConfirmationDialogService } from '../../../../shared/components/confirmation-dialog.service'; import { ITableListDataSource } from '../../../../shared/components/list/data-sources-controllers/list-data-source-types'; @@ -74,8 +70,6 @@ export class BackupEndpointsComponent { constructor( public service: BackupEndpointsService, - private store: Store, - private paginationMonitorFactory: PaginationMonitorFactory, private confirmDialog: ConfirmationDialogService, ) { this.setupSelectStep(); @@ -84,17 +78,7 @@ export class BackupEndpointsComponent { setupSelectStep() { - const action = new GetAllEndpoints(); - const endpointObs = getPaginationObservables({ - store: this.store, - action, - paginationMonitor: this.paginationMonitorFactory.create( - action.paginationKey, - action, - true - ) - }, true); - + const endpointObs = stratosEntityCatalog.endpoint.store.getAll.getPaginationService(); const endpoints$ = endpointObs.entities$.pipe( filter(entities => !!entities), diff --git a/src/frontend/packages/core/src/features/endpoints/backup-restore/restore-endpoints.service.ts b/src/frontend/packages/core/src/features/endpoints/backup-restore/restore-endpoints.service.ts index 8fa35048c1..38dee43257 100644 --- a/src/frontend/packages/core/src/features/endpoints/backup-restore/restore-endpoints.service.ts +++ b/src/frontend/packages/core/src/features/endpoints/backup-restore/restore-endpoints.service.ts @@ -5,10 +5,10 @@ import { BehaviorSubject, combineLatest, Observable } from 'rxjs'; import { filter, map, switchMap } from 'rxjs/operators'; import { GeneralEntityAppState } from '../../../../../store/src/app-state'; +import { BrowserStandardEncoder } from '../../../../../store/src/browser-encoder'; import { selectSessionData } from '../../../../../store/src/reducers/auth.reducer'; import { SessionData } from '../../../../../store/src/types/auth.types'; import { LoggerService } from '../../../core/logger.service'; -import { BrowserStandardEncoder } from '../../../helper'; interface BackupContent { payload: string; diff --git a/src/frontend/packages/core/src/features/endpoints/backup-restore/restore-endpoints/restore-endpoints.component.ts b/src/frontend/packages/core/src/features/endpoints/backup-restore/restore-endpoints/restore-endpoints.component.ts index c3483dca50..3ddca26bd4 100644 --- a/src/frontend/packages/core/src/features/endpoints/backup-restore/restore-endpoints/restore-endpoints.component.ts +++ b/src/frontend/packages/core/src/features/endpoints/backup-restore/restore-endpoints/restore-endpoints.component.ts @@ -5,10 +5,10 @@ import { Store } from '@ngrx/store'; import { Observable, of, Subject } from 'rxjs'; import { first, map } from 'rxjs/operators'; -import { GetAllEndpoints } from '../../../../../../store/src/actions/endpoint.actions'; import { GeneralEntityAppState } from '../../../../../../store/src/app-state'; +import { httpErrorResponseToSafeString } from '../../../../../../store/src/jetstream'; +import { stratosEntityCatalog } from '../../../../../../store/src/stratos-entity-catalog'; import { getEventFiles } from '../../../../core/browser-helper'; -import { httpErrorResponseToSafeString } from '../../../../jetstream.helpers'; import { ConfirmationDialogConfig } from '../../../../shared/components/confirmation-dialog.config'; import { ConfirmationDialogService } from '../../../../shared/components/confirmation-dialog.service'; import { StepOnNextFunction, StepOnNextResult } from '../../../../shared/components/stepper/step/step.component'; @@ -79,7 +79,7 @@ export class RestoreEndpointsComponent { }; const restoreSuccess = () => { - this.store.dispatch(new GetAllEndpoints()); + stratosEntityCatalog.endpoint.api.getAll() result.next({ success: true, redirect: true, diff --git a/src/frontend/packages/core/src/features/endpoints/connect-endpoint-dialog/auth-forms/credentials-auth-form.component.ts b/src/frontend/packages/core/src/features/endpoints/connect-endpoint-dialog/auth-forms/credentials-auth-form.component.ts index cdf3c405d0..b585c0ab96 100644 --- a/src/frontend/packages/core/src/features/endpoints/connect-endpoint-dialog/auth-forms/credentials-auth-form.component.ts +++ b/src/frontend/packages/core/src/features/endpoints/connect-endpoint-dialog/auth-forms/credentials-auth-form.component.ts @@ -1,6 +1,7 @@ -import { FormGroup } from '@angular/forms'; import { Component, Input } from '@angular/core'; -import { IAuthForm } from '../../../../core/extension/extension-types'; +import { FormGroup } from '@angular/forms'; + +import { IAuthForm } from '../../../../../../store/src/extension-types'; @Component({ selector: 'app-credentials-auth-form', diff --git a/src/frontend/packages/core/src/features/endpoints/connect-endpoint-dialog/auth-forms/none-auth-form.component.ts b/src/frontend/packages/core/src/features/endpoints/connect-endpoint-dialog/auth-forms/none-auth-form.component.ts index c76f5a954c..3b6bb325ee 100644 --- a/src/frontend/packages/core/src/features/endpoints/connect-endpoint-dialog/auth-forms/none-auth-form.component.ts +++ b/src/frontend/packages/core/src/features/endpoints/connect-endpoint-dialog/auth-forms/none-auth-form.component.ts @@ -1,6 +1,7 @@ import { Component, Input } from '@angular/core'; import { FormGroup } from '@angular/forms'; -import { IAuthForm } from '../../../../core/extension/extension-types'; + +import { IAuthForm } from '../../../../../../store/src/extension-types'; @Component({ selector: 'app-none-auth-form', diff --git a/src/frontend/packages/core/src/features/endpoints/connect-endpoint-dialog/auth-forms/sso-auth-form.component.ts b/src/frontend/packages/core/src/features/endpoints/connect-endpoint-dialog/auth-forms/sso-auth-form.component.ts index bdac43f89e..83243a24ec 100644 --- a/src/frontend/packages/core/src/features/endpoints/connect-endpoint-dialog/auth-forms/sso-auth-form.component.ts +++ b/src/frontend/packages/core/src/features/endpoints/connect-endpoint-dialog/auth-forms/sso-auth-form.component.ts @@ -1,6 +1,7 @@ import { Component, Input } from '@angular/core'; import { FormGroup } from '@angular/forms'; -import { IAuthForm } from '../../../../core/extension/extension-types'; + +import { IAuthForm } from '../../../../../../store/src/extension-types'; @Component({ selector: 'app-sso-auth-form', diff --git a/src/frontend/packages/core/src/features/endpoints/connect-endpoint-dialog/connect-endpoint-dialog.component.ts b/src/frontend/packages/core/src/features/endpoints/connect-endpoint-dialog/connect-endpoint-dialog.component.ts index 3d0f72fa4c..3a56bdbc23 100644 --- a/src/frontend/packages/core/src/features/endpoints/connect-endpoint-dialog/connect-endpoint-dialog.component.ts +++ b/src/frontend/packages/core/src/features/endpoints/connect-endpoint-dialog/connect-endpoint-dialog.component.ts @@ -1,13 +1,11 @@ import { Component, Inject, OnDestroy } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { Store } from '@ngrx/store'; import { Subscription } from 'rxjs'; -import { ShowSnackBar } from '../../../../../store/src/actions/snackBar.actions'; -import { EndpointOnlyAppState } from '../../../../../store/src/app-state'; import { EndpointsService } from '../../../core/endpoints.service'; import { MarkdownPreviewComponent } from '../../../shared/components/markdown-preview/markdown-preview.component'; import { SidePanelService } from '../../../shared/services/side-panel.service'; +import { SnackBarService } from '../../../shared/services/snackbar.service'; import { ConnectEndpointConfig, ConnectEndpointService } from '../connect.service'; @@ -27,14 +25,14 @@ export class ConnectEndpointDialogComponent implements OnDestroy { constructor( public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: ConnectEndpointConfig, - private store: Store, endpointsService: EndpointsService, private sidePanelService: SidePanelService, + private snackBarService: SnackBarService, ) { - this.connectService = new ConnectEndpointService(store, endpointsService, data); + this.connectService = new ConnectEndpointService(endpointsService, data); this.hasConnected = this.connectService.hasConnected$.subscribe(() => { - this.store.dispatch(new ShowSnackBar(`Connected endpoint '${this.data.name}'`)); + this.snackBarService.show(`Connected endpoint '${this.data.name}'`); this.dialogRef.close(); }); } diff --git a/src/frontend/packages/core/src/features/endpoints/connect-endpoint/connect-endpoint.component.ts b/src/frontend/packages/core/src/features/endpoints/connect-endpoint/connect-endpoint.component.ts index fc355c4928..0f6bc94595 100644 --- a/src/frontend/packages/core/src/features/endpoints/connect-endpoint/connect-endpoint.component.ts +++ b/src/frontend/packages/core/src/features/endpoints/connect-endpoint/connect-endpoint.component.ts @@ -13,13 +13,12 @@ import { } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Subscription } from 'rxjs'; -import { map } from 'rxjs/operators'; import { entityCatalog } from '../../../../../store/src/entity-catalog/entity-catalog'; -import { EndpointAuthTypeConfig, IAuthForm, IEndpointAuthComponent } from '../../../core/extension/extension-types'; +import { EndpointAuthTypeConfig, IAuthForm, IEndpointAuthComponent } from '../../../../../store/src/extension-types'; +import { BaseEndpointAuth } from '../../../core/endpoint-auth'; import { safeUnsubscribe } from '../../../core/utils.service'; import { ConnectEndpointConfig, ConnectEndpointData, ConnectEndpointService } from '../connect.service'; -import { BaseEndpointAuth } from '../endpoint-auth'; @Component({ selector: 'app-connect-endpoint', diff --git a/src/frontend/packages/core/src/features/endpoints/connect.service.ts b/src/frontend/packages/core/src/features/endpoints/connect.service.ts index d4e9dac73d..2ad24a7196 100644 --- a/src/frontend/packages/core/src/features/endpoints/connect.service.ts +++ b/src/frontend/packages/core/src/features/endpoints/connect.service.ts @@ -1,4 +1,3 @@ -import { Store } from '@ngrx/store'; import { combineLatest, Observable, of, Subject, Subscription } from 'rxjs'; import { delay, @@ -13,18 +12,12 @@ import { } from 'rxjs/operators'; import { AuthParams, ConnectEndpoint } from '../../../../store/src/actions/endpoint.actions'; -import { GetSystemInfo } from '../../../../store/src/actions/system.actions'; -import { EndpointOnlyAppState } from '../../../../store/src/app-state'; -import { EndpointsEffect } from '../../../../store/src/effects/endpoint.effects'; -import { SystemEffects } from '../../../../store/src/effects/system.effects'; import { entityCatalog } from '../../../../store/src/entity-catalog/entity-catalog'; -import { endpointSchemaKey } from '../../../../store/src/helpers/entity-factory'; +import { EndpointType } from '../../../../store/src/extension-types'; import { ActionState } from '../../../../store/src/reducers/api-request-reducer/types'; -import { selectEntity, selectRequestInfo, selectUpdateInfo } from '../../../../store/src/selectors/api.selectors'; +import { stratosEntityCatalog } from '../../../../store/src/stratos-entity-catalog'; import { EndpointModel } from '../../../../store/src/types/endpoint.types'; -import { STRATOS_ENDPOINT_TYPE } from '../../base-entity-schemas'; import { EndpointsService } from '../../core/endpoints.service'; -import { EndpointType } from '../../core/extension/extension-types'; import { safeUnsubscribe } from '../../core/utils.service'; export interface ConnectEndpointConfig { @@ -65,15 +58,12 @@ export class ConnectEndpointService { private hasAttemptedConnect: boolean; private pData: ConnectEndpointData; - private endpointEntityKey = entityCatalog.getEntityKey(STRATOS_ENDPOINT_TYPE, endpointSchemaKey); - // We need a delay to ensure the BE has finished registering the endpoint. // If we don't do this and if we're quick enough, we can navigate to the application page // and end up with an empty list where we should have results. private connectDelay = 1000; constructor( - private store: Store, private endpointsService: EndpointsService, public config: ConnectEndpointConfig, ) { @@ -87,33 +77,29 @@ export class ConnectEndpointService { ).subscribe(([oldVal, newVal]) => { if (!newVal.error && (oldVal.busy && !newVal.busy)) { // Has finished fetching - this.store.dispatch(new GetSystemInfo()); + stratosEntityCatalog.endpoint.api.get(this.config.guid); } })); this.subs.push(this.connected$.pipe( - filter(([connected]) => connected), + filter(([isConnected]) => isConnected), delay(this.connectDelay), tap(() => this.hasConnected.next(true)), - distinctUntilChanged(([connected], [oldConnected]) => connected && oldConnected), - ).subscribe(([connected, endpoint]) => this.endpointsService.checkEndpoint(endpoint)) + distinctUntilChanged(([isConnected], [oldIsConnected]) => isConnected && oldIsConnected), + ).subscribe(([, endpoint]) => this.endpointsService.checkEndpoint(endpoint)) ); } private setupObservables() { - this.update$ = this.store.select( - this.getUpdateSelector() - ).pipe(filter(update => !!update)); + this.update$ = stratosEntityCatalog.endpoint.store.getEntityMonitor(this.config.guid).getUpdatingSection(ConnectEndpoint.UpdatingKey) + .pipe(filter(update => !!update)); - this.fetchingInfo$ = this.store.select( - this.getRequestSelector() - ).pipe( + this.fetchingInfo$ = stratosEntityCatalog.endpoint.store.getEntityMonitor(this.config.guid).entityRequest$.pipe( filter(request => !!request), - map(request => request.fetching)); + map(request => request.fetching) + ); - this.connected$ = this.store.select( - this.getEntitySelector() - ).pipe( + this.connected$ = stratosEntityCatalog.endpoint.store.getEntityMonitor(this.config.guid).entity$.pipe( map(endpoint => { const isConnected = !!(endpoint && endpoint.api_endpoint && endpoint.user); return [isConnected, endpoint] as [boolean, EndpointModel]; @@ -149,28 +135,6 @@ export class ConnectEndpointService { ); } - private getUpdateSelector() { - return selectUpdateInfo( - this.endpointEntityKey, - this.config.guid, - EndpointsEffect.connectingKey - ); - } - - private getRequestSelector() { - return selectRequestInfo( - this.endpointEntityKey, - SystemEffects.guid - ); - } - - private getEntitySelector() { - return selectEntity( - this.endpointEntityKey, - this.config.guid, - ); - } - public setData(data: ConnectEndpointData) { this.pData = data; } @@ -179,25 +143,21 @@ export class ConnectEndpointService { this.hasAttemptedConnect = true; const { authType, authVal, systemShared, bodyContent } = this.pData; - this.store.dispatch(new ConnectEndpoint( + return stratosEntityCatalog.endpoint.api.connect( this.config.guid, this.config.type, authType, authVal, systemShared, bodyContent, - )); - - return this.isBusy$.pipe( + ).pipe( pairwise(), - filter(([oldBusy, newBusy]) => { - return !(oldBusy === true && newBusy === false); - }), - withLatestFrom(this.update$), - map(([, updateSection]) => ({ + filter(([oldV, newV]) => oldV.busy && !newV.busy), + map(([, newV]) => newV), + map(updateSection => ({ success: !updateSection.error, errorMessage: updateSection.message - })) + })), ); } diff --git a/src/frontend/packages/core/src/features/endpoints/create-endpoint/create-endpoint-cf-step-1/create-endpoint-cf-step-1.component.ts b/src/frontend/packages/core/src/features/endpoints/create-endpoint/create-endpoint-cf-step-1/create-endpoint-cf-step-1.component.ts index a046dc6b62..96bca56f21 100644 --- a/src/frontend/packages/core/src/features/endpoints/create-endpoint/create-endpoint-cf-step-1/create-endpoint-cf-step-1.component.ts +++ b/src/frontend/packages/core/src/features/endpoints/create-endpoint/create-endpoint-cf-step-1/create-endpoint-cf-step-1.component.ts @@ -1,27 +1,21 @@ import { AfterContentInit, Component, Input, ViewChild } from '@angular/core'; import { NgForm, NgModel } from '@angular/forms'; import { ActivatedRoute } from '@angular/router'; -import { Store } from '@ngrx/store'; -import { denormalize } from 'normalizr'; import { Observable } from 'rxjs'; -import { filter, map, pairwise, withLatestFrom } from 'rxjs/operators'; +import { filter, map, pairwise } from 'rxjs/operators'; -import { GetAllEndpoints, RegisterEndpoint } from '../../../../../../store/src/actions/endpoint.actions'; -import { ShowSnackBar } from '../../../../../../store/src/actions/snackBar.actions'; -import { GeneralEntityAppState } from '../../../../../../store/src/app-state'; -import { EndpointsEffect } from '../../../../../../store/src/effects/endpoint.effects'; +import { getFullEndpointApiUrl } from '../../../../../../store/src/endpoint-utils'; import { entityCatalog } from '../../../../../../store/src/entity-catalog/entity-catalog'; import { StratosCatalogEndpointEntity, } from '../../../../../../store/src/entity-catalog/entity-catalog-entity/entity-catalog-entity'; -import { endpointSchemaKey } from '../../../../../../store/src/helpers/entity-factory'; -import { getAPIRequestDataState, selectUpdateInfo } from '../../../../../../store/src/selectors/api.selectors'; -import { selectPaginationState } from '../../../../../../store/src/selectors/pagination.selectors'; -import { endpointEntitySchema, STRATOS_ENDPOINT_TYPE } from '../../../../base-entity-schemas'; +import { ActionState } from '../../../../../../store/src/reducers/api-request-reducer/types'; +import { stratosEntityCatalog } from '../../../../../../store/src/stratos-entity-catalog'; import { getIdFromRoute } from '../../../../core/utils.service'; import { IStepperStep, StepOnNextFunction } from '../../../../shared/components/stepper/step/step.component'; +import { SnackBarService } from '../../../../shared/services/snackbar.service'; import { ConnectEndpointConfig } from '../../connect.service'; -import { getFullEndpointApiUrl, getSSOClientRedirectURI } from '../../endpoint-helpers'; +import { getSSOClientRedirectURI } from '../../endpoint-helpers'; /* tslint:disable:no-access-missing-member https://github.com/mgechev/codelyzer/issues/191*/ @Component({ @@ -58,23 +52,16 @@ export class CreateEndpointCfStep1Component implements IStepperStep, AfterConten endpointTypeSupportsSSO = false; endpoint: StratosCatalogEndpointEntity; - private endpointEntityKey = entityCatalog.getEntityKey(STRATOS_ENDPOINT_TYPE, endpointSchemaKey); - - constructor(private store: Store, activatedRoute: ActivatedRoute, ) { - - this.existingEndpoints = store.select(selectPaginationState(this.endpointEntityKey, GetAllEndpoints.storeKey)) - .pipe( - withLatestFrom(store.select(getAPIRequestDataState)), - map(([pagination, entities]) => { - const pages = Object.values(pagination.ids); - const page = [].concat.apply([], pages); - const endpoints = page.length ? denormalize(page, [endpointEntitySchema], entities) : []; - return { - names: endpoints.map(ep => ep.name), - urls: endpoints.map(ep => getFullEndpointApiUrl(ep)), - }; - }) - ); + constructor( + activatedRoute: ActivatedRoute, + private snackBarService: SnackBarService + ) { + this.existingEndpoints = stratosEntityCatalog.endpoint.store.getAll.getPaginationMonitor().currentPage$.pipe( + map(endpoints => ({ + names: endpoints.map(ep => ep.name), + urls: endpoints.map(ep => getFullEndpointApiUrl(ep)), + })) + ); const epType = getIdFromRoute(activatedRoute, 'type'); const epSubType = getIdFromRoute(activatedRoute, 'subtype'); @@ -87,7 +74,7 @@ export class CreateEndpointCfStep1Component implements IStepperStep, AfterConten onNext: StepOnNextFunction = () => { const { subType, type } = this.endpoint.getTypeAndSubtype(); - const action = new RegisterEndpoint( + return stratosEntityCatalog.endpoint.api.register( type, subType, this.nameField.value, @@ -96,15 +83,8 @@ export class CreateEndpointCfStep1Component implements IStepperStep, AfterConten this.clientIDField ? this.clientIDField.value : '', this.clientSecretField ? this.clientSecretField.value : '', this.ssoAllowedField ? !!this.ssoAllowedField.value : false, - ); - - this.store.dispatch(action); - - const update$ = this.store.select( - this.getUpdateSelector(action.guid()) - ).pipe(filter(update => !!update)); - - return update$.pipe(pairwise(), + ).pipe( + pairwise(), filter(([oldVal, newVal]) => (oldVal.busy && !newVal.busy)), map(([oldVal, newVal]) => newVal), map(result => { @@ -116,7 +96,7 @@ export class CreateEndpointCfStep1Component implements IStepperStep, AfterConten ssoAllowed: this.ssoAllowedField ? !!this.ssoAllowedField.value : false }; if (!result.error) { - this.store.dispatch(new ShowSnackBar(`Successfully registered '${this.nameField.value}'`)); + this.snackBarService.show(`Successfully registered '${this.nameField.value}'`); } const success = !result.error; return { @@ -129,13 +109,6 @@ export class CreateEndpointCfStep1Component implements IStepperStep, AfterConten ); } - private getUpdateSelector(guid) { - return selectUpdateInfo( - this.endpointEntityKey, - guid, - EndpointsEffect.registeringKey, - ); - } ngAfterContentInit() { this.validate = this.form.statusChanges.pipe( diff --git a/src/frontend/packages/core/src/features/endpoints/create-endpoint/create-endpoint-connect/create-endpoint-connect.component.ts b/src/frontend/packages/core/src/features/endpoints/create-endpoint/create-endpoint-connect/create-endpoint-connect.component.ts index 9fc5b74dee..7be71e52aa 100644 --- a/src/frontend/packages/core/src/features/endpoints/create-endpoint/create-endpoint-connect/create-endpoint-connect.component.ts +++ b/src/frontend/packages/core/src/features/endpoints/create-endpoint/create-endpoint-connect/create-endpoint-connect.component.ts @@ -1,9 +1,7 @@ import { Component, OnDestroy } from '@angular/core'; -import { Store } from '@ngrx/store'; import { Observable, of } from 'rxjs'; import { map } from 'rxjs/operators'; -import { EndpointOnlyAppState } from '../../../../../../store/src/app-state'; import { EndpointsService } from '../../../../core/endpoints.service'; import { MarkdownPreviewComponent } from '../../../../shared/components/markdown-preview/markdown-preview.component'; import { IStepperStep, StepOnNextResult } from '../../../../shared/components/stepper/step/step.component'; @@ -26,7 +24,6 @@ export class CreateEndpointConnectComponent implements OnDestroy, IStepperStep { public doConnect = false; constructor( - private store: Store, private endpointsService: EndpointsService, private sidePanelService: SidePanelService, ) { @@ -37,7 +34,7 @@ export class CreateEndpointConnectComponent implements OnDestroy, IStepperStep { } onEnter = (data: ConnectEndpointConfig) => { - this.connectService = new ConnectEndpointService(this.store, this.endpointsService, data); + this.connectService = new ConnectEndpointService(this.endpointsService, data); } onNext = (): Observable => this.doConnect ? this.connectService.submit().pipe( diff --git a/src/frontend/packages/core/src/features/endpoints/edit-endpoint/edit-endpoint-step/edit-endpoint-step.component.ts b/src/frontend/packages/core/src/features/endpoints/edit-endpoint/edit-endpoint-step/edit-endpoint-step.component.ts index 1376e3e6b7..cb6120b12e 100644 --- a/src/frontend/packages/core/src/features/endpoints/edit-endpoint/edit-endpoint-step/edit-endpoint-step.component.ts +++ b/src/frontend/packages/core/src/features/endpoints/edit-endpoint/edit-endpoint-step/edit-endpoint-step.component.ts @@ -1,21 +1,19 @@ import { Component, OnDestroy } from '@angular/core'; import { FormControl, FormGroup, Validators } from '@angular/forms'; import { ActivatedRoute } from '@angular/router'; -import { Store } from '@ngrx/store'; import { Observable, Subscription } from 'rxjs'; import { filter, first, map, pairwise, switchMap } from 'rxjs/operators'; -import { AppState } from '../../../../../../store/src/app-state'; +import { getFullEndpointApiUrl } from '../../../../../../store/src/endpoint-utils'; import { entityCatalog } from '../../../../../../store/src/entity-catalog/entity-catalog'; -import { selectUpdateInfo } from '../../../../../../store/src/selectors/api.selectors'; +import { ActionState } from '../../../../../../store/src/reducers/api-request-reducer/types'; +import { stratosEntityCatalog } from '../../../../../../store/src/stratos-entity-catalog'; import { StepOnNextFunction } from '../../../../shared/components/stepper/step/step.component'; -import { getFullEndpointApiUrl, getSSOClientRedirectURI } from '../../endpoint-helpers'; -import { UpdateEndpoint } from './../../../../../../store/src/actions/endpoint.actions'; +import { getSSOClientRedirectURI } from '../../endpoint-helpers'; import { EntityCatalogSchemas, IStratosEndpointDefinition, } from './../../../../../../store/src/entity-catalog/entity-catalog.types'; -import { endpointEntitiesSelector } from './../../../../../../store/src/selectors/endpoint.selectors'; import { EndpointModel } from './../../../../../../store/src/types/endpoint.types'; import { getIdFromRoute, safeUnsubscribe } from './../../../../core/utils.service'; import { IStepperStep } from './../../../../shared/components/stepper/step/step.component'; @@ -41,12 +39,11 @@ export class EditEndpointStepComponent implements OnDestroy, IStepperStep { existingEndpoints: Observable; endpoint$: Observable; definition$: Observable>; - existingEndpoinNames$: Observable; + existingEndpointNames$: Observable; formChangeSub: Subscription; setClientInfo = false; constructor( - private store: Store, activatedRoute: ActivatedRoute, ) { this.editEndpoint = new FormGroup({ @@ -65,9 +62,14 @@ export class EditEndpointStepComponent implements OnDestroy, IStepperStep { this.endpointID = getIdFromRoute(activatedRoute, 'id'); - this.existingEndpoints = this.store.select(endpointEntitiesSelector); + this.existingEndpoints = stratosEntityCatalog.endpoint.store.getAll.getPaginationMonitor().currentPage$.pipe( + map(endpoints => endpoints.reduce((res, endpoint) => { + res[endpoint.guid] = endpoint; + return res; + }, {})) + ); - this.existingEndpoinNames$ = this.existingEndpoints.pipe( + this.existingEndpointNames$ = this.existingEndpoints.pipe( map(endpoints => Object.values(endpoints).filter((ep: EndpointModel) => ep.guid !== this.endpointID)), map((endpoints: EndpointModel[]) => endpoints.map(ep => ep.name)) ); @@ -127,20 +129,19 @@ export class EditEndpointStepComponent implements OnDestroy, IStepperStep { return this.endpoint$.pipe( first(), switchMap(endpoint => { - const action = new UpdateEndpoint( - endpoint.cnsi_type, + return stratosEntityCatalog.endpoint.api.update( this.endpointID, - this.editEndpoint.value.name, - this.editEndpoint.value.skipSSL, - this.editEndpoint.value.setClientInfo, - this.editEndpoint.value.clientID, - this.editEndpoint.value.clientSecret, - this.editEndpoint.value.allowSSO, - ); - - this.store.dispatch(action); - - return this.store.select(selectUpdateInfo('stratosEndpoint', this.endpointID, 'updating')).pipe( + this.endpointID, { + endpointType: endpoint.cnsi_type, + id: this.endpointID, + name: this.editEndpoint.value.name, + skipSSL: this.editEndpoint.value.skipSSL, + setClientInfo: this.editEndpoint.value.setClientInfo, + clientID: this.editEndpoint.value.clientID, + clientSecret: this.editEndpoint.value.clientSecret, + allowSSO: this.editEndpoint.value.allowSSO, + } + ).pipe( pairwise(), filter(([oldV, newV]) => oldV.busy && !newV.busy), map(([, newV]) => newV), diff --git a/src/frontend/packages/core/src/features/endpoints/endpoint-helpers.ts b/src/frontend/packages/core/src/features/endpoints/endpoint-helpers.ts index 39d567fe8b..10b9a13fff 100644 --- a/src/frontend/packages/core/src/features/endpoints/endpoint-helpers.ts +++ b/src/frontend/packages/core/src/features/endpoints/endpoint-helpers.ts @@ -11,10 +11,6 @@ import { import { EndpointModel } from '../../../../store/src/types/endpoint.types'; import { EndpointListDetailsComponent } from '../../shared/components/list/list-types/endpoint/endpoint-list.helpers'; -export function getFullEndpointApiUrl(endpoint: EndpointModel) { - return endpoint && endpoint.api_endpoint ? - `${endpoint.api_endpoint.Scheme}://${endpoint.api_endpoint.Host}${endpoint.api_endpoint.Path}` : 'Unknown'; -} export function getEndpointUsername(endpoint: EndpointModel) { return endpoint && endpoint.user ? endpoint.user.name : '-'; @@ -27,12 +23,6 @@ export interface EndpointIcon { font: string; } -export enum EndpointAuthTypeNames { - CREDS = 'creds', - SSO = 'sso', - NONE = 'none' -} - // Any initial endpointTypes listDetailsComponent should be added here export const coreEndpointListDetailsComponents: Type[] = []; diff --git a/src/frontend/packages/core/src/features/endpoints/endpoints-page/endpoints-page.component.ts b/src/frontend/packages/core/src/features/endpoints/endpoints-page/endpoints-page.component.ts index 7992db8c39..9ecf211ded 100644 --- a/src/frontend/packages/core/src/features/endpoints/endpoints-page/endpoints-page.component.ts +++ b/src/frontend/packages/core/src/features/endpoints/endpoints-page/endpoints-page.component.ts @@ -10,7 +10,6 @@ import { ViewChild, ViewContainerRef, } from '@angular/core'; -import { MatSnackBar, MatSnackBarRef, SimpleSnackBar } from '@angular/material/snack-bar'; import { Store } from '@ngrx/store'; import { combineLatest, Subscription } from 'rxjs'; import { delay, first, map, tap } from 'rxjs/operators'; @@ -32,6 +31,7 @@ import { EndpointsListConfigService, } from '../../../shared/components/list/list-types/endpoint/endpoints-list-config.service'; import { ListConfig } from '../../../shared/components/list/list.component.types'; +import { SnackBarService } from '../../../shared/services/snackbar.service'; @Component({ selector: 'app-endpoints-page', @@ -49,7 +49,6 @@ export class EndpointsPageComponent implements AfterViewInit, OnDestroy, OnInit @ViewChild('customNoEndpoints', { read: ViewContainerRef, static: true }) customNoEndpointsContainer; customContentComponentRef: ComponentRef; - private snackBarRef: MatSnackBarRef; private snackBarText = { message: `There are no connected endpoints, connect with your personal credentials to get started.`, action: 'Got it' @@ -62,7 +61,7 @@ export class EndpointsPageComponent implements AfterViewInit, OnDestroy, OnInit public store: Store, private ngZone: NgZone, private resolver: ComponentFactoryResolver, - private snackBar: MatSnackBar, + private snackBarService: SnackBarService, cs: CustomizationService ) { this.customizations = cs.get(); @@ -103,10 +102,10 @@ export class EndpointsPageComponent implements AfterViewInit, OnDestroy, OnInit } private showSnackBar(show: boolean) { - if (!this.snackBarRef && show) { - this.snackBarRef = this.snackBar.open(this.snackBarText.message, this.snackBarText.action, { duration: 20000 }); - } else if (this.snackBarRef && !show) { - this.snackBarRef.dismiss(); + if (show) { + this.snackBarService.show(this.snackBarText.message, this.snackBarText.action, 20000); + } else { + this.snackBarService.hide(); } } diff --git a/src/frontend/packages/core/src/features/error-page/error-page/error-page.component.ts b/src/frontend/packages/core/src/features/error-page/error-page/error-page.component.ts index 9b6ab439b4..a404433a5e 100644 --- a/src/frontend/packages/core/src/features/error-page/error-page/error-page.component.ts +++ b/src/frontend/packages/core/src/features/error-page/error-page/error-page.component.ts @@ -7,14 +7,13 @@ import { first, map, withLatestFrom } from 'rxjs/operators'; import { SendClearEndpointEventsAction } from '../../../../../store/src/actions/internal-events.actions'; import { AppState } from '../../../../../store/src/app-state'; -import { endpointSchemaKey } from '../../../../../store/src/helpers/entity-factory'; -import { EntityMonitor } from '../../../../../store/src/monitors/entity-monitor'; +import { endpointEntityType } from '../../../../../store/src/helpers/stratos-entity-factory'; import { InternalEventMonitorFactory } from '../../../../../store/src/monitors/internal-event-monitor.factory'; +import { stratosEntityCatalog } from '../../../../../store/src/stratos-entity-catalog'; import { EndpointModel } from '../../../../../store/src/types/endpoint.types'; import { InternalEventState } from '../../../../../store/src/types/internal-events.types'; import { getPreviousRoutingState } from '../../../../../store/src/types/routing.type'; -import { endpointEntitySchema } from '../../../base-entity-schemas'; -import { StratosStatus } from '../../../shared/shared.types'; +import { StratosStatus } from '../../../../../store/src/types/shared.types'; import { eventReturnUrlParam } from '../../event-page/events-page/events-page.component'; @Component({ @@ -36,13 +35,8 @@ export class ErrorPageComponent implements OnInit { ngOnInit() { const endpointId = this.activatedRoute.snapshot.params.endpointId; if (endpointId) { - const endpointMonitor = new EntityMonitor( - this.store, - endpointId, - endpointEntitySchema.key, - endpointEntitySchema - ); - const cfEndpointEventMonitor = this.internalEventMonitorFactory.getMonitor(endpointSchemaKey, of([endpointId])); + const endpointMonitor = stratosEntityCatalog.endpoint.store.getEntityMonitor(endpointId); + const cfEndpointEventMonitor = this.internalEventMonitorFactory.getMonitor(endpointEntityType, of([endpointId])); this.errorDetails$ = cfEndpointEventMonitor.hasErroredOverTimeNoPoll(30).pipe( withLatestFrom(endpointMonitor.entity$), map(([errors, endpoint]) => { diff --git a/src/frontend/packages/core/src/features/home/home/home-page.component.ts b/src/frontend/packages/core/src/features/home/home/home-page.component.ts index 1c3a977d31..6700b83fa3 100644 --- a/src/frontend/packages/core/src/features/home/home/home-page.component.ts +++ b/src/frontend/packages/core/src/features/home/home/home-page.component.ts @@ -5,12 +5,12 @@ import { first, map } from 'rxjs/operators'; import { RouterNav } from '../../../../../store/src/actions/router.actions'; import { AppState, IRequestEntityTypeState } from '../../../../../store/src/app-state'; +import { EntityCatalogHelpers } from '../../../../../store/src/entity-catalog/entity-catalog.helper'; import { IUserFavoritesGroups } from '../../../../../store/src/types/favorite-groups.types'; import { UserFavorite } from '../../../../../store/src/types/user-favorites.types'; +import { UserFavoriteManager } from '../../../../../store/src/user-favorite-manager'; import { EndpointsService } from '../../../core/endpoints.service'; import { LoggerService } from '../../../core/logger.service'; -import { UserFavoriteManager } from '../../../core/user-favorite-manager'; -import { EntityCatalogHelpers } from '../../../../../store/src/entity-catalog/entity-catalog.helper'; @Component({ selector: 'app-home-page', diff --git a/src/frontend/packages/core/src/features/metrics/metrics.helpers.ts b/src/frontend/packages/core/src/features/metrics/metrics.helpers.ts index fc31d4b577..72dfa2d0c1 100644 --- a/src/frontend/packages/core/src/features/metrics/metrics.helpers.ts +++ b/src/frontend/packages/core/src/features/metrics/metrics.helpers.ts @@ -1,7 +1,8 @@ import { Observable, of as observableOf } from 'rxjs'; -import { StratosStatus } from '../../shared/shared.types'; -import { EndpointIcon, getFullEndpointApiUrl } from '../endpoints/endpoint-helpers'; +import { getFullEndpointApiUrl } from '../../../../store/src/endpoint-utils'; +import { StratosStatus } from '../../../../store/src/types/shared.types'; +import { EndpointIcon } from '../endpoints/endpoint-helpers'; import { entityCatalog } from './../../../../store/src/entity-catalog/entity-catalog'; import { MetricsEndpointProvider } from './services/metrics-service'; diff --git a/src/frontend/packages/core/src/features/metrics/services/metrics-service.ts b/src/frontend/packages/core/src/features/metrics/services/metrics-service.ts index 9e9076acea..e9391d7fae 100644 --- a/src/frontend/packages/core/src/features/metrics/services/metrics-service.ts +++ b/src/frontend/packages/core/src/features/metrics/services/metrics-service.ts @@ -2,12 +2,11 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { map, publishReplay, refCount } from 'rxjs/operators'; +import { getFullEndpointApiUrl } from '../../../../../store/src/endpoint-utils'; import { PaginationMonitor } from '../../../../../store/src/monitors/pagination-monitor'; -import { PaginationMonitorFactory } from '../../../../../store/src/monitors/pagination-monitor.factory'; +import { stratosEntityCatalog } from '../../../../../store/src/stratos-entity-catalog'; import { APIResource, EntityInfo } from '../../../../../store/src/types/api.types'; -import { endpointListKey, EndpointModel } from '../../../../../store/src/types/endpoint.types'; -import { endpointEntitySchema } from '../../../base-entity-schemas'; -import { getFullEndpointApiUrl } from '../../endpoints/endpoint-helpers'; +import { EndpointModel } from '../../../../../store/src/types/endpoint.types'; export interface MetricsEndpointProvider { provider: EndpointModel; @@ -22,14 +21,8 @@ export class MetricsService { haveNoMetricsEndpoints$: Observable; haveNoConnectedMetricsEndpoints$: Observable; - constructor( - private paginationMonitorFactory: PaginationMonitorFactory - ) { - this.endpointsMonitor = this.paginationMonitorFactory.create( - endpointListKey, - endpointEntitySchema, - true - ); + constructor() { + this.endpointsMonitor = stratosEntityCatalog.endpoint.store.getPaginationMonitor() this.setupObservables(); } diff --git a/src/frontend/packages/core/src/features/setup/setup.module.ts b/src/frontend/packages/core/src/features/setup/setup.module.ts index cd9593967a..c730116607 100644 --- a/src/frontend/packages/core/src/features/setup/setup.module.ts +++ b/src/frontend/packages/core/src/features/setup/setup.module.ts @@ -1,7 +1,7 @@ import { NgModule } from '@angular/core'; +import { ThemeService } from '../../../../store/src/theme.service'; import { CoreModule } from '../../core/core.module'; -import { ThemeService } from '../../core/theme.service'; import { SharedModule } from '../../shared/shared.module'; import { DomainMismatchComponent } from './domain-mismatch/domain-mismatch.component'; import { LocalAccountWizardComponent } from './local-account-wizard/local-account-wizard.component'; diff --git a/src/frontend/packages/core/src/features/user-profile/edit-profile-info/edit-profile-info.component.ts b/src/frontend/packages/core/src/features/user-profile/edit-profile-info/edit-profile-info.component.ts index 54194241ee..75aa2b69bf 100644 --- a/src/frontend/packages/core/src/features/user-profile/edit-profile-info/edit-profile-info.component.ts +++ b/src/frontend/packages/core/src/features/user-profile/edit-profile-info/edit-profile-info.component.ts @@ -2,7 +2,7 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { AbstractControl, FormBuilder, FormGroup, ValidatorFn, Validators } from '@angular/forms'; import { ErrorStateMatcher, ShowOnDirtyErrorStateMatcher } from '@angular/material/core'; import { Subscription } from 'rxjs'; -import { first, map, take, tap } from 'rxjs/operators'; +import { delay, first, map, take, tap } from 'rxjs/operators'; import { UserProfileInfo, UserProfileInfoUpdates } from '../../../../../store/src/types/user-profile.types'; import { CurrentUserPermissionsService } from '../../../core/permissions/current-user-permissions.service'; @@ -119,8 +119,7 @@ export class EditProfileInfoComponent implements OnInit, OnDestroy { updates[key] = this.editProfileForm.value[key]; } } - const obs$ = this.userProfileService.updateProfile(this.profile, updates); - return obs$.pipe( + return this.userProfileService.updateProfile(this.profile, updates).pipe( take(1), map(([profileResult, passwordResult]) => { const okay = !profileResult.error && !passwordResult.error; @@ -131,6 +130,7 @@ export class EditProfileInfoComponent implements OnInit, OnDestroy { message: okay ? '' : `An error occurred whilst updating your profile: ${message}` }; }), + delay(300), // Ensure that the profile is updated before fetching to refresh local copy tap(() => this.userProfileService.fetchUserProfile()) ); } diff --git a/src/frontend/packages/core/src/features/user-profile/profile-info/profile-info.component.ts b/src/frontend/packages/core/src/features/user-profile/profile-info/profile-info.component.ts index d5984a3886..915ecd6aea 100644 --- a/src/frontend/packages/core/src/features/user-profile/profile-info/profile-info.component.ts +++ b/src/frontend/packages/core/src/features/user-profile/profile-info/profile-info.component.ts @@ -6,8 +6,8 @@ import { map } from 'rxjs/operators'; import { SetPollingEnabledAction, SetSessionTimeoutAction } from '../../../../../store/src/actions/dashboard-actions'; import { DashboardOnlyAppState } from '../../../../../store/src/app-state'; import { selectDashboardState } from '../../../../../store/src/selectors/dashboard.selectors'; +import { ThemeService } from '../../../../../store/src/theme.service'; import { UserProfileInfo } from '../../../../../store/src/types/user-profile.types'; -import { ThemeService } from '../../../core/theme.service'; import { UserProfileService } from '../../../core/user-profile.service'; import { UserService } from '../../../core/user.service'; import { SetGravatarEnabledAction } from './../../../../../store/src/actions/dashboard-actions'; diff --git a/src/frontend/packages/core/misc/custom/index.html b/src/frontend/packages/core/src/index.html similarity index 95% rename from src/frontend/packages/core/misc/custom/index.html rename to src/frontend/packages/core/src/index.html index b6c415d27c..5756ba3e60 100644 --- a/src/frontend/packages/core/misc/custom/index.html +++ b/src/frontend/packages/core/src/index.html @@ -11,7 +11,7 @@ - +