diff --git a/packages/manager/apps/billing/.eslintrc.json b/packages/manager/apps/billing/.eslintrc.json new file mode 100644 index 000000000000..383e2831c19a --- /dev/null +++ b/packages/manager/apps/billing/.eslintrc.json @@ -0,0 +1,6 @@ +{ + "globals": { + "__VERSION__": true, + "__NG_APP_INJECTIONS__": true + } +} diff --git a/packages/manager/apps/billing/README.md b/packages/manager/apps/billing/README.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/manager/apps/billing/package.json b/packages/manager/apps/billing/package.json new file mode 100644 index 000000000000..dabedf703b83 --- /dev/null +++ b/packages/manager/apps/billing/package.json @@ -0,0 +1,72 @@ +{ + "name": "@ovh-ux/manager-billing-app", + "version": "0.0.0", + "private": true, + "description": "OVHcloud Billing app", + "repository": { + "type": "git", + "url": "git+https://github.com/ovh/manager.git", + "directory": "packages/manager/apps/billing" + }, + "license": "BSD-3-Clause", + "author": "OVH SAS", + "scripts": { + "build": "webpack --env production", + "dev": "webpack-dev-server", + "dev:watch": "yarn run dev", + "start": "lerna exec --stream --scope='@ovh-ux/manager-billing-app' --include-dependencies -- npm run build --if-present", + "start:dev": "lerna exec --stream --scope='@ovh-ux/manager-billing-app' --include-dependencies -- npm run dev --if-present", + "start:watch": "lerna exec --stream --parallel --scope='@ovh-ux/manager-billing-app' --include-dependencies -- npm run dev:watch --if-present" + }, + "dependencies": { + "@ovh-ux/manager-at-internet-configuration": "^1.5.0", + "@ovh-ux/manager-billing": "^0.20.0-alpha.45", + "@ovh-ux/manager-config": "^7.0.0", + "@ovh-ux/manager-core": "^12.0.0 || ^13.0.0", + "@ovh-ux/manager-error-page": "^2.3.1", + "@ovh-ux/manager-ng-layout-helpers": "^2.6.1", + "@ovh-ux/ng-at-internet": "^5.11.13", + "@ovh-ux/ng-at-internet-ui-router-plugin": "^3.5.0", + "@ovh-ux/ng-ovh-api-wrappers": "^5.0.0", + "@ovh-ux/ng-ovh-http": "^5.0.0", + "@ovh-ux/ng-ovh-request-tagger": "^1.1.7", + "@ovh-ux/ng-ovh-sso-auth": "^4.6.3", + "@ovh-ux/ng-ovh-swimming-poll": "^5.0.6", + "@ovh-ux/ng-shell-tracking": "^0.2.1", + "@ovh-ux/ng-translate-async-loader": "^2.1.5", + "@ovh-ux/ng-ui-router-breadcrumb": "^1.1.7", + "@ovh-ux/request-tagger": "^0.1.1", + "@ovh-ux/shell": "^2.0.0", + "@ovh-ux/ui-kit": "^6.5.1", + "@uirouter/angularjs": "^1.0.23", + "angular": "^1.7.5", + "angular-aria": "^1.7.8", + "angular-cookies": "^1.7.8", + "angular-dynamic-locale": "^0.1.37", + "angular-i18n": "^1.7.8", + "angular-resource": "^1.7.8", + "angular-sanitize": "^1.7.8", + "angular-translate": "^2.18.1", + "angular-translate-loader-pluggable": "^1.3.1", + "core-js": "^3.6.5", + "flatpickr": "~4.6.3", + "jquery": "^2.1.3", + "lodash-es": "^4.17.15", + "oclazyload": "^1.1.0", + "ovh-api-services": "^16.0.0", + "regenerator-runtime": "^0.13.7", + "whatwg-fetch": "^3.5.0" + }, + "devDependencies": { + "@ovh-ux/manager-webpack-config": "^6.1.1", + "glob": "^7.1.6", + "lodash": "^4.17.15", + "webpack": "^4.44.2", + "webpack-merge": "^4.2.2" + }, + "regions": [ + "CA", + "EU", + "US" + ] +} diff --git a/packages/manager/apps/billing/src/app.module.js b/packages/manager/apps/billing/src/app.module.js new file mode 100644 index 000000000000..1f04acdfee9a --- /dev/null +++ b/packages/manager/apps/billing/src/app.module.js @@ -0,0 +1,154 @@ +import angular from 'angular'; +import get from 'lodash/get'; +import has from 'lodash/has'; +import isString from 'lodash/isString'; +import uiRouter, { RejectType } from '@uirouter/angularjs'; +import '@ovh-ux/ui-kit'; +import '@ovh-ux/ng-at-internet'; +import { isTopLevelApplication } from '@ovh-ux/manager-config'; +import { registerCoreModule } from '@ovh-ux/manager-core'; +import ngOvhSsoAuth from '@ovh-ux/ng-ovh-sso-auth'; +import ngUiRouterBreadcrumb from '@ovh-ux/ng-ui-router-breadcrumb'; +import ovhManagerAtInternetConfiguration from '@ovh-ux/manager-at-internet-configuration'; +import { registerAtInternet } from '@ovh-ux/ng-shell-tracking'; +// TODO: Change to '@ovh-ux/manager-billing' when module is deployed +// import Billing from '@ovh-ux/manager-billing'; +import Billing from '../../../modules/billing/src'; +import errorPage from './error'; + +import TRACKING from './tracking/at-internet.constants'; +import '@ovh-ux/ui-kit/dist/css/oui.css'; + +export default async (containerEl, shellClient) => { + const moduleName = 'BillingApp'; + + const routingConfig = /* @ngInject */ ($urlRouterProvider) => { + $urlRouterProvider.otherwise('/billing'); + }; + + const trackingConfig = /* @ngInject */ (atInternetConfigurationProvider) => { + atInternetConfigurationProvider.setSkipInit(true); + atInternetConfigurationProvider.setPrefix('BillingApp'); + }; + + const [environment, locale] = await Promise.all([ + shellClient.environment.getEnvironment(), + shellClient.i18n.getLocale(), + ]); + + const coreCallbacks = { + onLocaleChange: (lang) => { + shellClient.i18n.setLocale(lang); + }, + }; + + const ssoAuthConfig = /* @ngInject */ (ssoAuthenticationProvider) => { + ssoAuthenticationProvider.setOnLogin(() => { + shellClient.auth.login(); + }); + ssoAuthenticationProvider.setOnLogout(() => { + shellClient.auth.logout(); + }); + }; + + const calendarConfigProvider = /* @ngInject */ ( + ouiCalendarConfigurationProvider, + ) => { + const [lang] = locale.split('_'); + return import(`flatpickr/dist/l10n/${lang}.js`) + .then((module) => { + ouiCalendarConfigurationProvider.setLocale(module.default[lang]); + }) + .catch(() => {}); + }; + + const broadcastAppStarted = /* @ngInject */ ($rootScope, $transitions) => { + const unregisterHook = $transitions.onSuccess({}, async () => { + if (!isTopLevelApplication()) { + await shellClient.ux.hidePreloader(); + } + $rootScope.$broadcast('app:started'); + unregisterHook(); + }); + }; + + const transitionsConfig = /* @ngInject */ ($transitions) => { + if (!isTopLevelApplication()) { + $transitions.onBefore({}, (transition) => { + if ( + !transition.ignored() && + transition.from().name !== '' && + transition.entering().length > 0 + ) { + shellClient.ux.startProgress(); + } + }); + + $transitions.onSuccess({}, () => { + shellClient.ux.stopProgress(); + }); + + $transitions.onError({}, (transition) => { + if (!transition.error().redirected) { + shellClient.ux.stopProgress(); + } + }); + } + }; + + const defaultErrorHandler = /* @ngInject */ ($state) => { + $state.defaultErrorHandler((error) => { + if (error.type === RejectType.ERROR) { + $state.go( + 'error', + { + detail: { + message: get(error.detail, 'data.message'), + code: has(error.detail, 'headers') + ? error.detail.headers('x-ovh-queryId') + : null, + }, + }, + { location: false }, + ); + } + }); + }; + + angular + .module( + moduleName, + [ + registerCoreModule(environment, coreCallbacks), + registerAtInternet(shellClient.tracking), + ovhManagerAtInternetConfiguration, + ngOvhSsoAuth, + ngUiRouterBreadcrumb, + 'oui', + uiRouter, + errorPage, + Billing, + ...get(__NG_APP_INJECTIONS__, environment.getRegion(), []), + ].filter(isString), + ) + .constant('shellClient', shellClient) + .config( + /* @ngInject */ ($locationProvider) => $locationProvider.hashPrefix(''), + ) + .config(routingConfig) + .config(ssoAuthConfig) + .config(async () => { + await shellClient.tracking.setConfig(environment.getRegion(), TRACKING); + }) + .config(trackingConfig) + .config(calendarConfigProvider) + .run(broadcastAppStarted) + .run(transitionsConfig) + .run(defaultErrorHandler); + + angular.bootstrap(containerEl, [moduleName], { + strictDi: true, + }); + + return moduleName; +}; diff --git a/packages/manager/apps/billing/src/error/error.module.js b/packages/manager/apps/billing/src/error/error.module.js new file mode 100644 index 000000000000..acc727b16dd4 --- /dev/null +++ b/packages/manager/apps/billing/src/error/error.module.js @@ -0,0 +1,9 @@ +import managerErrorPage from '@ovh-ux/manager-error-page'; + +import routing from './error.routing'; + +const moduleName = 'ovhManagerBillingError'; + +angular.module(moduleName, [managerErrorPage]).config(routing); + +export default moduleName; diff --git a/packages/manager/apps/billing/src/error/error.routing.js b/packages/manager/apps/billing/src/error/error.routing.js new file mode 100644 index 000000000000..45bb318d8ac9 --- /dev/null +++ b/packages/manager/apps/billing/src/error/error.routing.js @@ -0,0 +1,17 @@ +export default /* @ngInject */ ($stateProvider) => { + $stateProvider.state('error', { + params: { + detail: null, + }, + url: '/error', + component: 'managerErrorPage', + resolve: { + cancelLink: /* @ngInject */ ($state) => $state.href('app'), + error: /* @ngInject */ ($transition$) => $transition$.params(), + submitAction: /* @ngInject */ ($window) => () => + $window.location.reload(), + translationsRefresh: /* @ngInject */ ($translate) => $translate.refresh(), + breadcrumb: () => null, + }, + }); +}; diff --git a/packages/manager/apps/billing/src/error/index.js b/packages/manager/apps/billing/src/error/index.js new file mode 100644 index 000000000000..331942589301 --- /dev/null +++ b/packages/manager/apps/billing/src/error/index.js @@ -0,0 +1,22 @@ +import angular from 'angular'; +import '@uirouter/angularjs'; +import 'oclazyload'; + +const moduleName = 'ovhManagerBillingErrorPageLazyLoading'; + +angular.module(moduleName, ['ui.router', 'oc.lazyLoad']).config( + /* @ngInject */ ($stateProvider) => { + $stateProvider.state('error.**', { + url: '/error', + lazyLoad: ($transition$) => { + const $ocLazyLoad = $transition$.injector().get('$ocLazyLoad'); + + return import('./error.module').then((mod) => + $ocLazyLoad.inject(mod.default || mod), + ); + }, + }); + }, +); + +export default moduleName; diff --git a/packages/manager/apps/billing/src/index.html b/packages/manager/apps/billing/src/index.html new file mode 100644 index 000000000000..d4ba5a63fae9 --- /dev/null +++ b/packages/manager/apps/billing/src/index.html @@ -0,0 +1,16 @@ + + +
+ +