Why .eslintrc may don't see aliases from .babelrc.js? - babeljs

I have some aliases inside .babelrc.js
And .eslintrc with eslint-import-resolver-babel-module plugin to get aliases from babel config.
But eslint anyway can't resolve aliases.
.babelrc.js, .eslintrc, package.json in the gist: https://gist.github.com/SilentImp/4d005064063701faa04c29b02114d0df
.babelrc.js
const fs = require('fs');
const path = require('path');
const projectPath = path.resolve(__dirname, './');
const pathToSrc = path.resolve(projectPath, 'src');
const stats = fs.statSync(pathToSrc);
const env = process.env.NODE_ENV || 'dev';
const envAppConfigURL = path.resolve(__dirname, `../app/${env}.js`);
const devAppConfigURL = path.resolve(__dirname, 'dev.js');
const localAppConfigURL = path.resolve(__dirname, 'local.js');
const sampleAppConfigURL = path.resolve(__dirname, 'local.sample.js');
const isEnvConfig = fs.existsSync(envAppConfigURL);
const isDevConfig = fs.existsSync(devAppConfigURL);
const isLocalConfig = fs.existsSync(localAppConfigURL);
const isSampleConfig = fs.existsSync(sampleAppConfigURL);
let ConfigURL;
if (isEnvConfig) {
ConfigURL = envAppConfigURL;
} else if (isLocalConfig) {
ConfigURL = localAppConfigURL;
} else if (isSampleConfig) {
ConfigURL = sampleAppConfigURL;
} else {
ConfigURL = devAppConfigURL;
}
module.exports = {
"presets": [
["#babel/preset-env", {
"targets": {
"uglify": true,
"node": "current",
"browsers": ["> 3%", "ie 11"]
},
"debug": false,
}],
"#babel/preset-react",
["#babel/preset-stage-0", {
"decoratorsLegacy": true,
}]
],
"plugins": [
["module-resolver", {
"root": ["/"],
"alias": {
Config$: ConfigURL,
Utils: path.resolve(projectPath, 'src/shared/utils/'),
Components: path.resolve(projectPath, 'src/shared/components/'),
Reducers: path.resolve(projectPath, 'src/shared/reducers/'),
Images: path.resolve(projectPath, 'src/shared/assets/images/'),
Icons: path.resolve(projectPath, 'src/shared/assets/icons/'),
Styles: path.resolve(projectPath, 'src/shared/assets/styles/'),
Shared: path.resolve(projectPath, 'src/shared/'),
}
}],
"react-css-modules",
"#babel/plugin-proposal-export-default-from",
["#babel/plugin-proposal-decorators", {
"legacy": true
}],
["#babel/plugin-proposal-class-properties", {
"loose" : true
}]
],
};
.eslintrc
{
"env": {
"browser": true,
"node": true,
"jest": true,
"worker": true,
"serviceworker": true,
"es6": true
},
"extends": "airbnb",
"parser": "babel-eslint",
"globals": {
"FontFaceObserver": true,
"fontFaceSet": true,
},
"plugins": [
"react",
"jsx-a11y",
"import",
"jest"
],
"rules": {
"jsx-a11y/anchor-is-valid": [ "error", { "components": [ "Link" ], "specialLink": [ "to" ] } ],
"no-underscore-dangle": ["error", { "allow": ["_id", "_insertCss", "_getCss","__REDUX_STATE__", "_meta"] }],
"no-restricted-syntax": ["error", "WithStatement", "BinaryExpression[operator='in']"]
},
"settings": {
"import/resolver": {
"babel-module": {}
}
}
}

Well it seems that I need to duplicate all aliases in both configs.
I have rewrite .eslintrc as .eslintrc.js:
const fs = require('fs');
const path = require('path');
const projectPath = path.resolve(__dirname, './');
const pathToSrc = path.resolve(projectPath, 'src');
const configPath = path.resolve(projectPath, 'config/app');
const stats = fs.statSync(pathToSrc);
const env = process.env.NODE_ENV || 'dev';
const envAppConfigURL = path.resolve(configPath, `${env}.js`);
const devAppConfigURL = path.resolve(configPath, 'dev.js');
const localAppConfigURL = path.resolve(configPath, 'local.js');
const sampleAppConfigURL = path.resolve(configPath, 'local.sample.js');
const isEnvConfig = fs.existsSync(envAppConfigURL);
const isDevConfig = fs.existsSync(devAppConfigURL);
const isLocalConfig = fs.existsSync(localAppConfigURL);
const isSampleConfig = fs.existsSync(sampleAppConfigURL);
let ConfigURL;
if (isEnvConfig) {
ConfigURL = envAppConfigURL;
} else if (isLocalConfig) {
ConfigURL = localAppConfigURL;
} else if (isSampleConfig) {
ConfigURL = sampleAppConfigURL;
} else {
ConfigURL = devAppConfigURL;
}
module.exports = {
"env": {
"browser": true,
"node": true,
"jest": true,
"worker": true,
"serviceworker": true,
"es6": true
},
"extends": "airbnb",
"parser": "babel-eslint",
"globals": {
"FontFaceObserver": true,
"fontFaceSet": true,
},
"plugins": [
"react",
"jsx-a11y",
"import",
"jest"
],
"rules": {
"jsx-a11y/anchor-is-valid": [ "error", { "components": [ "Link" ], "specialLink": [ "to" ] } ],
"no-underscore-dangle": ["error", { "allow": ["_id", "_insertCss", "_getCss","__REDUX_STATE__", "_meta"] }],
"no-restricted-syntax": ["error", "WithStatement", "BinaryExpression[operator='in']"]
},
"settings": {
"import/resolver": {
"babel-module": {
"alias": {
Config$: ConfigURL,
Utils: path.resolve(projectPath, 'src/shared/utils/'),
Components: path.resolve(projectPath, 'src/shared/components/'),
Reducers: path.resolve(projectPath, 'src/shared/reducers/'),
Images: path.resolve(projectPath, 'src/shared/assets/images/'),
Icons: path.resolve(projectPath, 'src/shared/assets/icons/'),
Styles: path.resolve(projectPath, 'src/shared/assets/styles/'),
Shared: path.resolve(projectPath, 'src/shared/'),
}
}
}
}
};

Related

AWS Api Gateway VTL Merge Json Object

Trying to merge the principalId from Lambda Authorizer into the payload that will be sent to Event Bridge.
So far I've gotten close by transforming to map and re-creating the Json object. The problem is that this Json object is printed out as a key:value pair with no quotes, So there's an error thrown.
According to the docs, there's non $util.toJson($map) available, this seems to be only available for AppSync.
const eventsAPI = new RestApi(this, 'eventsAPI', apigwOps);
const LambdaAuth0Authorizer = new LambdaAuth0Authorizer(this, 'LambdaAuth0Authorizer', {
env: {
auth0Audience: '',
auth0Domain: '',
},
});
const eventTypeResource = eventsAPI.root.addResource('event');
const options: IntegrationOptions = {
credentialsRole: apigwRole,
passthroughBehavior: PassthroughBehavior.NEVER,
requestParameters: {
'integration.request.header.X-Amz-Target': "'AWSEvents.PutEvents'",
'integration.request.header.Content-Type': "'application/x-amz-json-1.1'",
},
requestTemplates: {
'application/json': `
#set ( $map = $util.parseJson($input.body) )
#set ( $j = {
"eventType": "$map['eventType']",
"action": "$map['action']",
"subject": "$map['subject']",
"eventTime": $map['eventTime'],
"actor": "$context.authorizer.principalId"
}
)
{"Entries":
[
{
"Source": "com.xyz",
"Detail": "$util.escapeJavascript($j)",
"Resources": [],
"DetailType": "event",
"EventBusName": "${eventBus.eventBusName}"
}
]
}
`,
},
integrationResponses: [
{
statusCode: '200',
responseTemplates: {
'application/json': '',
},
},
],
};
eventTypeResource.addMethod('POST', new Integration({
type: IntegrationType.AWS,
uri: `arn:aws:apigateway:${env.region}:events:path//`,
integrationHttpMethod: 'POST',
options: options,
}), {
authorizer: LambdaAuth0Authorizer.authorizer,
methodResponses: [{ statusCode: '200' }],
requestModels: { 'application/json': getEventModel(this, eventsAPI) },
requestValidator: new RequestValidator(this, 'eventValidator', {
restApi: eventsAPI,
validateRequestBody: true,
}),
});
This generates:
{"Entries":
[
{
"Source": "com.uproarapi",
"Detail": "{eventType=FOLLOW, action=CREATE, subject=USER_777POIUY, eventTime=51644444444, actor=}",
"Resources": [],
"DetailType": "UpRoarEvent",
"EventBusName": "UpRoarEventBus"
}
]
}
With an error:
{"Entries":[{"ErrorCode":"MalformedDetail","ErrorMessage":"Detail is malformed."}],"FailedEntryCount":1}

503 The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later. nuxt js

My site was running fine and then I updated nuxt.config.js. Then after that, the site starts to show Service Unavailable.
I am using pm2 to start / deploy the app. Its vps server with apache in it.
Its showing:
Service Unavailable
The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later.
But, if I run npm run dev the site loads fine without any issue. Also, I checked the status with pm2 list, it showing the app is online.
My package.json
{
"name": "nuxtjs",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "nuxt --hostname domain.link --port 49000",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate",
"deploy": "pm2 start npm --name nuxtjs -- start"
},
"dependencies": {
"#nuxtjs/axios": "^5.13.6",
"#yeger/vue-masonry-wall": "^3.0.16",
"core-js": "^3.19.3",
"nuxt": "^2.15.8",
"pm2": "^5.1.2",
"vue": "^2.6.14",
"vue-server-renderer": "^2.6.14",
"vue-template-compiler": "^2.6.14",
"webpack": "^4.46.0"
},
"devDependencies": {},
"config": {
"nuxt": {
"host": "0.0.0.0",
"port": "49000"
}
}
}
My nuxt.config:
import { join } from "path";
export default {
target: "static",
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
title: "Project Title",
htmlAttrs: {
lang: "en",
},
meta: [
{ charset: "utf-8" },
{ name: "viewport", content: "width=device-width, initial-scale=1" },
{ hid: "description", name: "description", content: "" },
{ name: "format-detection", content: "telephone=no" },
{ property: "og:title", content: "Project Title" },
{
property: "og:image",
content: "https://lovealabradoodle.com/images/two.jpg",
},
{
property: "og:description",
content:
"Content here",
},
],
link: [
{ rel: "icon", type: "image/x-icon", href: "/favicon.ico" },
{
rel: "stylesheet",
href: "https://fonts.googleapis.com/css?family=Roboto:400,600,700%7CMontserrat:400,500,600,700",
},
{
rel: "stylesheet",
href: "https://use.fontawesome.com/releases/v5.15.4/css/all.css",
},
{
rel: "stylesheet",
href: join("/", `fonts/flaticon/flaticon.css`),
},
{
rel: "stylesheet",
href: join("/", `css/bootstrap.min.css`),
},
{
rel: "stylesheet",
href: join("/", `css/plugins.css`),
},
{
rel: "stylesheet",
href: join("/", `css/magnific-popup.css`),
},
{
rel: "stylesheet",
href: join("/", `css/aos.css`),
},
{
rel: "stylesheet",
href: join("/", `css/style.css`),
},
{
rel: "stylesheet",
href: join("/", `css/styles/maincolors.css`),
},
],
script: [
// {
// src: "js/jquery.min.js",
// body: true,
// },
{
src: join("/", `js/bootstrap.bundle.min.js`),
body: true,
},
{
src: join("/", `js/imagesloaded.pkgd.min.js`),
body: true,
},
{
src: join("/", `js/isotope.pkgd.min.js`),
body: true,
},
{
src: join("/", `js/jquery.magnific-popup.min.js`),
body: true,
},
{
src: join("/", `js/easing.min.js`),
body: true,
},
{
src: join("/", `js/aos.js`),
body: true,
},
{
src: join("/", `js/custom-nuxt.js`),
body: true,
},
],
bodyAttrs: {
id: "top",
},
},
// Global CSS: https://go.nuxtjs.dev/config-css
css: [
// "~/static/css/bootstrap.min.css",
// "~/static/css/plugins.css",
// "~/static/css/magnific-popup.css",
// "~/static/css/aos.css",
// "~/static/css/style.css",
// "~/static/css/styles/maincolors.css",
],
//Global JS
// script: [
// "~assets/js/custom.js"
// ],
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [],
// Auto import components: https://go.nuxtjs.dev/config-components
components: {
path: "~/components", // will get any components nested in let's say /components/test too
pathPrefix: false,
},
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
buildModules: [],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
// https://go.nuxtjs.dev/axios
"#nuxtjs/axios",
],
// Axios module configuration: https://go.nuxtjs.dev/config-axios
axios: {
// Workaround to avoid enforcing hard-coded localhost:3000: https://github.com/nuxt-community/axios-module/issues/308
baseURL: "http://api.domain.link/api",
retry: { retries: 3 },
},
publicRuntimeConfig: {
axios: {
baseURL: "http://api.domain.link/api",
},
},
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
extractCSS: true,
},
};
I ran yarn/npm install and it worked for me

#babel/plugin-transform-runtime is allowing esm imports in cjs files

I'm using Rollup.js, and babel to bundle my js library. I noticed that my dist cjs files are referencing esm core-js helpers in addition to the correct cjs helpers.
For instance, in my final cjs file, I see a reference to both var _extends$2 = require('#babel/runtime-corejs3/helpers/esm/extends'); and var _extends$3 = require('#babel/runtime-corejs3/helpers/extends'); when I run yarn build:lib.
Has anyone seen this before? Been racking my brain and haven't been able to find what is the cause of this.
For reference,
package.json (condensed for brevity)
{
"name": "my-platform",
"version": "0.1.0",
"description": "",
"main": "dist/index.cjs",
"module": "dist/my-platform.esm.js",
"types": "dist/index.d.ts",
"engines": {
"node": ">=10.18.0"
},
"scripts": {
"build:lib": "rollup -c",
"build:docs": "build-storybook",
"build": "concurrently \"yarn build:lib\" \"yarn build:docs\"",
},
"sideEffects": false,
"peerDependencies": {
"#emotion/core": "^10.0.22",
"react": "^16.12.0 || 17"
},
"resolutions": {
"git-raw-commits": "2.0.8"
},
"devDependencies": {
"#babel/cli": "^7.12.7",
"#babel/core": "^7.12.7",
"#babel/plugin-transform-runtime": "^7.12.10",
"#babel/preset-env": "^7.12.7",
"#babel/preset-react": "^7.12.7",
"#babel/preset-typescript": "^7.12.7",
"#commitlint/cli": "^11.0.0",
"#commitlint/config-conventional": "^11.0.0",
"#emotion/babel-preset-css-prop": "^10.0.23",
"#emotion/core": "^10.0.22",
"#jest/globals": "^26.6.2",
"#rollup/plugin-babel": "^5.2.2",
"#rollup/plugin-commonjs": "^17.1.0",
"#rollup/plugin-json": "^4.1.0",
"#rollup/plugin-node-resolve": "^11.1.0",
"#rollup/plugin-replace": "^2.3.4",
"#typescript-eslint/eslint-plugin": "^4.14.0",
"#typescript-eslint/parser": "^4.14.0",
"babel-jest": "^26.6.3",
"babel-loader": "^8.0.6",
"babel-plugin-annotate-pure-calls": "^0.4.0",
"babel-plugin-dev-expression": "^0.2.2",
"babel-plugin-macros": "^3.0.1",
"concurrently": "^5.0.1",
"fs-extra": "^9.1.0",
"husky": ">=4.3.8",
"jest": "^26.6.3",
"jest-emotion": "^10.0.26",
"jest-junit": "^12.0.0",
"path": "^0.12.7",
"prettier": "^2.2.1",
"react": "^17.0.1",
"react-docgen-typescript-loader": "^3.4.0",
"react-dom": "^17.0.1",
"react-test-renderer": "^17.0.1",
"regenerator-runtime": "^0.13.3",
"rollup": "^2.38.1",
"rollup-plugin-delete": "^2.0.0",
"rollup-plugin-terser": "^7.0.2",
"rollup-plugin-typescript2": "^0.29.0",
"stylelint": "^13.9.0",
"stylelint-config-prettier": "^8.0.0",
"stylelint-config-standard": "^20.0.0",
"tsdx": "^0.14.1",
"tslib": "^2.1.0",
"typescript": "^4.1.3"
},
"dependencies": {
"#babel/runtime-corejs3": "~7.12.18"
}
}
babel.config
module.exports = (api) => {
const isTest = api.env('test');
api.cache.forever();
return {
presets: [
[
'#babel/preset-env',
isTest ? { targets: { node: 'current' } } : { modules: false },
],
'#babel/preset-react',
'#babel/preset-typescript',
'#emotion/babel-preset-css-prop',
],
plugins: [
'annotate-pure-calls',
'dev-expression',
'macros',
[
'#babel/plugin-transform-runtime',
{
corejs: 3,
version: '^7.12.5',
},
],
],
comments: false,
};
};
rollup.config.js
import fs from 'fs-extra';
import path from 'path';
import resolve from '#rollup/plugin-node-resolve';
import babel from '#rollup/plugin-babel';
import typescript from 'rollup-plugin-typescript2';
import json from '#rollup/plugin-json';
import commonjs from '#rollup/plugin-commonjs';
import replace from '#rollup/plugin-replace';
import del from 'rollup-plugin-delete';
import { terser } from 'rollup-plugin-terser';
import { DEFAULT_EXTENSIONS } from '#babel/core';
import pkg from './package.json';
const external = [
...Object.keys(pkg.peerDependencies || {}),
...Object.keys(pkg.dependencies || {}),
];
const makeExternalPredicate = (externalArr) => {
if (externalArr.length === 0) {
return () => false;
}
const pattern = new RegExp(`^(${externalArr.join('|')})($|/)`);
return (id) => pattern.test(id);
};
const configTerser = () =>
terser({
output: { comments: false },
compress: {
keep_infinity: true,
pure_getters: true,
passes: 10,
},
ecma: 5,
toplevel: true,
warnings: true,
});
function writeCjsEntryFile() {
const baseLine = `module.exports = require('./my-platform`;
const contents = `
'use strict'
if (process.env.NODE_ENV === 'production') {
${baseLine}.cjs.production.min.js')
} else {
${baseLine}.cjs.development.js')
}
`;
return fs.outputFile(path.join(__dirname, './dist', 'index.js'), contents);
}
const getEnv = (format, minify) => {
switch (format) {
case 'cjs':
return minify ? 'production.' : 'development.';
default:
return '';
}
};
const makeOutput = (format, minify) => ({
file: `dist/my-platform.${format}.${getEnv(format, minify)}${
minify ? 'min.' : ''
}js`,
esModule: true,
exports: 'named',
format,
freeze: false,
sourcemap: true,
plugins: [
minify && configTerser(),
format === 'cjs' && {
writeBundle: writeCjsEntryFile,
},
],
});
let currentBundleIndex = 0;
const makeRollupConfig = (minify, format) => {
return {
input: './src/index.ts',
output: makeOutput(format, minify),
plugins: [
currentBundleIndex === 1 && del({ targets: 'dist/**' }),
minify &&
replace({
'process.env.NODE_ENV': JSON.stringify('production'),
}),
resolve({
extensions: ['.js', '.jsx', '.ts', '.tsx'],
}),
json(),
typescript({
typescript: require('typescript'),
tsconfigOverride: {
exclude: [
'**/*.spec.ts',
'**/*.test.ts',
'**/*.stories.ts',
'**/*.spec.tsx',
'**/*.test.tsx',
'**/*.stories.tsx',
'node_modules',
'test',
],
compilerOptions: {
target: 'esnext',
rootDir: 'src',
},
},
}),
commonjs(),
babel({
babelHelpers: 'runtime',
exclude: 'node_modules/**',
extensions: [...DEFAULT_EXTENSIONS, '.ts', '.tsx'],
presets: [
[
'#babel/preset-env',
{
modules: false,
},
],
],
plugins: [
[
'#babel/plugin-transform-runtime',
{
useESModules: format === 'esm',
corejs: 3,
version: '^7.12.5',
},
],
],
}),
],
external: makeExternalPredicate(external),
};
};
export default [
makeRollupConfig(false, 'cjs'),
makeRollupConfig(false, 'esm'),
makeRollupConfig(true, 'cjs'),
];
Any help would be appreciated. Thanks!

Why the controller does not get loaded sometimes?

I have a problem, that sometimes the controller does not get loaded:
and you can see the error message. It should load the following controller(marked with red border):
Why it is not getting loaded sometimes?
When the controller gets loaded, it looks like:
UPDATE:
I am using flexible column layout.
The App.view.xml looks like:
<mvc:View controllerName="ch.mindustrie.ZMM_CLASSIFICATION.controller.App" xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m" xmlns:f="sap.f">
<App id="root">
<f:FlexibleColumnLayout id="idClassLayout"/>
</App>
</mvc:View>
the manifest.json file:
{
"_version": "1.9.0",
"sap.app": {
"id": "ch.mindustrie.ZMM_CLASSIFICATION",
"type": "application",
"i18n": "i18n/i18n.properties",
"applicationVersion": {
"version": "0.1.0"
},
"title": "{{appTitle}}",
"description": "{{appDescription}}",
"sourceTemplate": {
"id": "servicecatalog.connectivityComponentForManifest",
"version": "0.0.0"
},
"dataSources": {
"ZMM_CLASSIFICATION_SRV": {
"uri": "/sap/opu/odata/sap/ZMM_CLASSIFICATION_SRV/",
"type": "OData",
"settings": {
"odataVersion": "2.0",
"localUri": "localService/ZMM_CLASSIFICATION_SRV/metadata.xml"
}
}
}
},
"sap.ui": {
"technology": "UI5",
"icons": {
"icon": "",
"favIcon": "",
"phone": "",
"phone#2": "",
"tablet": "",
"tablet#2": ""
},
"deviceTypes": {
"desktop": true,
"tablet": true,
"phone": true
},
"supportedThemes": [
"sap_hcb",
"sap_belize"
]
},
"sap.ui5": {
"handleValidation": true,
"rootView": {
"viewName": "ch.mindustrie.ZMM_CLASSIFICATION.view.App",
"type": "XML",
"async": true,
"id": "app"
},
"dependencies": {
"minUI5Version": "1.50.0",
"libs": {
"sap.ui.layout": {},
"sap.ui.core": {},
"sap.m": {},
"sap.f": {},
"sap.collaboration": {
"lazy": true
}
}
},
"contentDensities": {
"compact": true,
"cozy": true
},
"models": {
"i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"settings": {
"bundleName": "ch.mindustrie.ZMM_CLASSIFICATION.i18n.i18n"
}
},
"Classification": {
"uri": "/sap/opu/odata/sap/ZMM_CLASSIFICATION_SRV/",
"type": "sap.ui.model.odata.v2.ODataModel",
"settings": {
"defaultOperationMode": "Server",
"defaultBindingMode": "OneWay",
"defaultCountMode": "Request"
},
"dataSource": "ZMM_CLASSIFICATION_SRV",
"preload": true
}
},
"resources": {
"css": [
{
"uri": "css/style.css"
}
]
},
"routing": {
"config": {
"routerClass": "sap.f.routing.Router",
"viewType": "XML",
"viewPath": "ch.mindustrie.ZMM_CLASSIFICATION.view",
"controlId": "idClassLayout",
"bypassed": {
"target": [
"search",
"characteristic"
]
},
"async": true
},
"routes": [
{
"pattern": "",
"name": "search",
"target": [
"characteristic",
"search"
],
"layout": "TwoColumnsBeginExpanded"
},
{
"pattern": "search/{internalclassnum}",
"name": "characteristic",
"target": [
"search",
"characteristic"
],
"layout": "TwoColumnsMidExpanded"
}
],
"targets": {
"search": {
"viewName": "Search",
"viewLevel": 1,
"viewId": "search",
"controlAggregation": "beginColumnPages"
},
"characteristic": {
"viewName": "Characteristic",
"viewLevel": 2,
"viewId": "characteristic",
"controlAggregation": "endColumnPages"
}
}
}
},
"sap.platform.abap": {
"uri": "/sap/bc/ui5_ui5/sap/zmm_classifi/webapp",
"_version": "1.1.0"
}
}
the Search.view.xml:
<mvc:View xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" xmlns:l="sap.ui.layout" xmlns:uxap="sap.uxap"
xmlns:f="sap.ui.layout.form" xmlns:smartFilterBar="sap.ui.comp.smartfilterbar"
controllerName="ch.mindustrie.ZMM_CLASSIFICATION.controller.Search" xmlns:html="http://www.w3.org/1999/xhtml">
<smartFilterBar:SmartFilterBar id="SelectionFilterBar" entitySet="ZMM_C_CLASSIFICATION" search="onSearchClass">
<smartFilterBar:controlConfiguration>
<smartFilterBar:ControlConfiguration key="ClassType" visibleInAdvancedArea="true" preventInitialDataFetchInValueHelpDialog="false"></smartFilterBar:ControlConfiguration>
<smartFilterBar:ControlConfiguration key="ClassNum" visibleInAdvancedArea="true" preventInitialDataFetchInValueHelpDialog="false"></smartFilterBar:ControlConfiguration>
</smartFilterBar:controlConfiguration>
</smartFilterBar:SmartFilterBar>
<Tree id="ClassTree" items="{path: 'Tree>/'}" toggleOpenState="onOpenAnItemOnTree">
<CustomTreeItem>
<FlexBox width="100%" alignItems="Center" justifyContent="SpaceBetween">
<items>
<Label text="{Tree>text}" wrapping="true"/>
<Button icon="sap-icon://display" type="Transparent" press="onClassPressed"/>
</items>
</FlexBox>
</CustomTreeItem>
</Tree>
</mvc:View>
And the Search.Controller
sap.ui.define([
"ch/mindustrie/ZMM_CLASSIFICATION/controller/BaseController"
], function (BaseController) {
"use strict";
return BaseController.extend("ch.mindustrie.ZMM_CLASSIFICATION.controller.Search", {
/**
* Called when a controller is instantiated and its View controls (if available) are already created.
* #memberOf ch.mindustrie.ZMM_CLASSIFICATION.view.Search
*/
onInit: function () {
//Set model for smart filter bar
const oModel = this.getModel("Classification");
this.setModel(oModel);
//Model for classification tree
this.setModel(new sap.ui.model.json.JSONModel(), "Tree");
},
onSearchClass: function () {
const aFilter = this.byId("SelectionFilterBar").getFilters();
const self = this;
//Build the first node
this._readClassification(aFilter)
.then(aData => self.getModel("Tree").setProperty("/", aData));
},
/*
* Read classification from server.
*/
_readClassification: function (aFilter) {
const self = this;
//Build entry node
const oModel = this.getModel("Classification");
const oDateFrom = new sap.ui.model.Filter({
path: "ValidFrom",
operator: sap.ui.model.FilterOperator.LE,
value1: new Date()
});
const oDateUntil = new sap.ui.model.Filter({
path: "ValidFrom",
operator: sap.ui.model.FilterOperator.GE,
value1: new Date()
});
return new Promise((resolve, reject) => {
oModel
.read("/ZMM_C_CLASSIFICATION", {
filters: aFilter.concat([oDateFrom, oDateUntil]),
success: function (oData) {
let aTreeWithNodes = [];
const aTree = oData.results.map(self._buildEntryTree);
aTree.forEach((oNode, index) => {
self._readSubClasses(oNode.internalClass)
.then(aData => {
const oWithNodes = aTree[index];
if (aData.length > 0) {
oWithNodes.nodes = aData;
}
aTreeWithNodes.push(oWithNodes);
if (aTreeWithNodes.length === aTree.length) {
resolve(aTreeWithNodes);
}
});
});
},
error: function (oError) {
reject(oError);
}
});
});
},
_readSubClasses: function (sSubInternalClass) {
const oModel = this.getModel("Classification");
const self = this;
const oUpInteralClass = new sap.ui.model.Filter({
path: "UpInternalClass",
operator: sap.ui.model.FilterOperator.EQ,
value1: sSubInternalClass
});
return new Promise((resolve) => {
oModel
.read("/ZMM_C_CLASSSUB_REL", {
filters: [oUpInteralClass],
success: function (oData) {
const aNewNodes = (oData.results.length > 0 ? oData.results.map(self._prepareDescEntryNodes) : []);
resolve(aNewNodes);
},
error: function () {
resolve([]);
}
});
});
},
/*
* Build the entry node.
*/
_buildEntryTree: function (oData) {
return {
text: oData.ClassType + " " + oData.ClassNum + " " + oData.ClassNumDescr,
classType: oData.ClassType,
classNum: oData.ClassNum,
internalClass: oData.InternalClass,
nodes: []
};
},
onOpenAnItemOnTree: function (oEvent) {
const bExpanded = oEvent.getParameter("expanded");
if (!bExpanded) {
return;
}
const iItemIndex = oEvent.getParameter("itemIndex");
const oItemContext = oEvent.getParameter("itemContext");
const oTree = this.byId("ClassTree");
const oModel = this.getView().getModel("Tree");
const sPath = oItemContext.getPath();
const oCurrentNode = oModel.getProperty(sPath);
this._loadOnDemand(oModel, oCurrentNode, sPath, oTree.getItems()[iItemIndex].getLevel());
},
/*
* Load descendants asynchronously.
*/
_loadOnDemand: function (oModel, oCurrentNode, sPath) {
const aChildNodes = oCurrentNode.nodes.map(oClass => {
return new sap.ui.model.Filter({
path: "InternalClass",
operator: sap.ui.model.FilterOperator.EQ,
value1: oClass.internalClass
});
});
this._readClassification(aChildNodes)
.then(aNewNodes => oModel.setProperty(sPath + "/nodes", aNewNodes));
},
/*
* When the item in the tree is getting pressed.
*/
onClassPressed: function (oEvent) {
const oRow = oEvent.getSource().getBindingContext("Tree").getObject();
this.getRouter().navTo("characteristic", {
internalclassnum: oRow.internalClass
});
}
});
});
I believe the flexibility services only work in the Fiori launchpad, not in the webide sandbox launchpad. Do you get the same issue if you deploy?

Promises do not work (for me)

Probably I'm missing something basic here. Scenario goes like this:
Within the root view controller of my application (App.controller.js, onInit function) I'm performing a series of read operations on a named model in order to have additional data ready mainly for use by formatters in subsequent views. What I have done is using promises to make sure that data will be ready.
Problem is that application occasionally crashes when the initial view with pattern "" (Worklist.view.xml in my case) is loaded after the root view (App.view.xml) because the formatter function can't find the data expected. Added a few break-points and observed the debugger:
stopping at the first read function
stopping at the promises condition at the end
stopping (and throwing error) at the formatter function at the subsequent view
stopping in the success function of oData read (resolve)
page freezes afterwards as result of the exception thrown above
"Normal" flow, when application doesn't crash goes like this:
stopping at the first read function
stopping at the promises condition at the end
stopping in the success function of oData read (resolve)
stopping at the readyToGo function (it's there just for temporary debugging)
stopping at the formatter function at the subsequent view
page display, everything in order
Judging by the above, I have reached the conclusion that my promises do not work. Any ideas?
sap.ui.define([
"kristal/apps/agreements/controller/BaseController",
"sap/ui/model/json/JSONModel"
], function (BaseController, JSONModel) {
"use strict";
/* PROMISE VARIABLES */
var oModelTypeDataDeferred = jQuery.Deferred();
var oModelStatusDataDeferred = jQuery.Deferred();
var oModelRoleDataDeferred = jQuery.Deferred();
var oModelRefDataDeferred = jQuery.Deferred();
var oModelExtOrgDataDeferred = jQuery.Deferred();
var oModelInvolvementDataDeferred = jQuery.Deferred();
return BaseController.extend("kristal.apps.agreements.controller.App", {
onInit: function () {
/* CALLED AFTER PROMISES HAVE BEEN FULFILLED */
var readyToGo = function() {
jQuery.sap.log.error("Ready!");
};
var oViewModel;
var fnSetAppNotBusy;
var iOriginalBusyDelay = this.getView().getBusyIndicatorDelay();
var oViewModel = new JSONModel({
busy: true,
delay: 0
});
this.setModel(oViewModel, "appView");
fnSetAppNotBusy = function() {
oViewModel.setProperty("/busy", false);
oViewModel.setProperty("/delay", iOriginalBusyDelay);
};
this.getOwnerComponent().getModel().metadataLoaded().then(fnSetAppNotBusy);
var oModel = this.getOwnerComponent().getModel("f4");
/* oData READ OPS */
oModel.metadataLoaded().then(function(){
// Initialize additional data
var sPath = "/Agreement_TypesSet";
oModel.read(sPath, {
success: function(oData, oResponse) {
oModelTypeDataDeferred.resolve();
},
error: function(oError) {
jQuery.sap.log.error("Error", oError);
}
});
sPath = "/Agreement_StatusesSet";
oModel.read(sPath, {
success: function(oData, oResponse) {
oModelStatusDataDeferred.resolve();
},
error: function(oError) {
jQuery.sap.log.error("Error", oError);
}
});
sPath = "/Role_TypesSet";
oModel.read(sPath, {
success: function(oData, oResponse) {
oModelRoleDataDeferred.resolve();
},
error: function(oError) {
jQuery.sap.log.error("Error", oError);
}
});
sPath = "/Reference_TypesSet";
oModel.read(sPath, {
success: function(oData, oResponse) {
oModelRefDataDeferred.resolve();
},
error: function(oError) {
jQuery.sap.log.error("Error", oError);
}
});
sPath = "/External_OrganizationsSet";
oModel.read(sPath, {
success: function(oData, oResponse) {
oModelRefDataDeferred.resolve();
},
error: function(oError) {
jQuery.sap.log.error("Error", oError);
}
});
sPath = "/Involvement_TypesSet";
oModel.read(sPath, {
success: function(oData, oResponse) {
oModelInvolvementDataDeferred.resolve();
},
error: function(oError) {
jQuery.sap.log.error("Error", oError);
}
});
/* IF ALL PROMISES FULFILLED, PROCEED */
jQuery.when(oModelTypeDataDeferred, oModelStatusDataDeferred, oModelRoleDataDeferred, oModelRefDataDeferred, oModelExtOrgDataDeferred, oModelInvolvementDataDeferred)
.done().then(jQuery.proxy(readyToGo, this));
},
// ...
});
});
manifest.json:
{
"_version": "1.4.0",
"sap.app": {
"id": "kristal.apps.agreements",
"type": "application",
"i18n": "i18n/i18n.properties",
"title": "{{appTitle}}",
"description": "{{appDescription}}",
"applicationVersion": {
"version": "1.0.0"
},
"dataSources": {
"mainService": {
"uri": "/DEV/sap/opu/odata/SAP/ZCONTRACTS_SRV/",
"type": "OData",
"settings": {
"odataVersion": "2.0",
"localUri": "localService/metadata.xml"
}
}
},
"sourceTemplate": {
"id": "sap.ui.ui5-template-plugin.1worklist",
"version": "1.38.3"
}
},
"sap.ui": {
"technology": "UI5",
"icons": {
"icon": "sap-icon://task",
"favIcon": "",
"phone": "",
"phone#2": "",
"tablet": "",
"tablet#2": ""
},
"deviceTypes": {
"desktop": true,
"tablet": true,
"phone": true
},
"supportedThemes": [
"sap_hcb",
"sap_bluecrystal"
]
},
"sap.ui5": {
"rootView": {
"viewName": "kristal.apps.agreements.view.App",
"type": "XML",
"id": "app",
"async": true
},
"dependencies": {
"minUI5Version": "1.38.0",
"libs": {
"sap.ui.core": {
"minVersion": "1.38.0"
},
"sap.m": {
"minVersion": "1.38.0"
},
"sap.ushell": {
"minVersion": "1.38.0"
},
"sap.collaboration": {
"minVersion": "1.38",
"lazy": true
}
}
},
"contentDensities": {
"compact": true,
"cozy": true
},
"models": {
"i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"settings": {
"bundleName": "kristal.apps.agreements.i18n.i18n"
}
},
"": {
"dataSource": "mainService",
"preload": true,
"settings": {
"defaultBindingMode": "TwoWay"
}
},
"f4": {
"dataSource": "mainService",
"preload": true,
"settings": {
"metadataUrlParams": {
"sap-documentation": "heading"
},
"defaultBindingMode": "TwoWay"
}
}
},
"routing": {
"config": {
"routerClass": "sap.m.routing.Router",
"viewType": "XML",
"viewPath": "kristal.apps.agreements.view",
"controlId": "app",
"controlAggregation": "pages",
"bypassed": {
"target": [
"notFound"
]
},
"async": true
},
"routes": [{
"pattern": "",
"name": "worklist",
"target": [
"worklist"
]
}, {
"pattern": "AgreementsSet/{objectId}",
"name": "object",
"target": [
"object"
]
}],
"targets": {
"worklist": {
"viewName": "Worklist",
"viewId": "worklist",
"viewLevel": 1
},
"object": {
"viewName": "Object",
"viewId": "object",
"viewLevel": 2
},
"objectNotFound": {
"viewName": "ObjectNotFound",
"viewId": "objectNotFound"
},
"notFound": {
"viewName": "NotFound",
"viewId": "notFound"
}
}
}
},
"sap.platform.abap": {
"uri": "/sap/bc/ui5_ui5/sap/zctr_contr_mnt/webapp",
"_version": "1.1.0"
}
}
Component.js
sap.ui.define([
"sap/ui/core/UIComponent",
"sap/ui/Device",
"kristal/apps/agreements/model/models",
"kristal/apps/agreements/controller/ErrorHandler"
], function(UIComponent, Device, models, ErrorHandler) {
"use strict";
return UIComponent.extend("kristal.apps.agreements.Component", {
metadata: {
manifest: "json"
},
init: function() {
UIComponent.prototype.init.apply(this, arguments);
this._oErrorHandler = new ErrorHandler(this);
this.setModel(models.createDeviceModel(), "device");
this.setModel(models.createFLPModel(), "FLP");
this.getRouter().initialize();
},
destroy: function() {
this._oErrorHandler.destroy();
// call the base component's destroy function
UIComponent.prototype.destroy.apply(this, arguments);
},
getContentDensityClass: function() {
if (this._sContentDensityClass === undefined) {
// check whether FLP has already set the content density class; do nothing in this case
if (jQuery(document.body).hasClass("sapUiSizeCozy") || jQuery(document.body).hasClass("sapUiSizeCompact")) {
this._sContentDensityClass = "";
} else if (!Device.support.touch) { // apply "compact" mode if touch is not supported
this._sContentDensityClass = "sapUiSizeCompact";
} else {
// "cozy" in case of touch support; default for most sap.m controls, but needed for desktop-first controls like sap.ui.table.Table
this._sContentDensityClass = "sapUiSizeCozy";
}
}
return this._sContentDensityClass;
}
});
});
It was all about moving functionality from the root view to component.js and putting the router initialization into the promise conditions, thank you experts