Skip to content

Commit

Permalink
feat(ui-devkit): Allow custom global styles to be specified
Browse files Browse the repository at this point in the history
Relates to #391
  • Loading branch information
michaelbromley committed Jan 7, 2021
1 parent c0ec8d9 commit 2081a15
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 10 deletions.
2 changes: 1 addition & 1 deletion packages/ui-devkit/scaffold/angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"src/i18n-messages"
],
"styles": [
"src/styles/styles.scss"
"src/global-styles.scss"
],
"stylePreprocessorOptions": {
"includePaths": [
Expand Down
1 change: 1 addition & 0 deletions packages/ui-devkit/scaffold/src/global-styles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@import "./styles/styles";
31 changes: 29 additions & 2 deletions packages/ui-devkit/src/compiler/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ import * as fs from 'fs-extra';
import * as path from 'path';

import { DEFAULT_BASE_HREF, MODULES_OUTPUT_DIR } from './constants';
import { setupScaffold } from './scaffold';
import { copyGlobalStyleFile, setupScaffold } from './scaffold';
import { getAllTranslationFiles, mergeExtensionTranslations } from './translations';
import { Extension, StaticAssetDefinition, UiExtensionCompilerOptions } from './types';
import {
copyStaticAsset,
copyUiDevkit,
getStaticAssetPath,
isAdminUiExtension,
isGlobalStylesExtension,
isStaticAssetExtension,
isTranslationExtension,
normalizeExtensions,
Expand Down Expand Up @@ -89,6 +90,7 @@ function runWatchMode(
await setupScaffold(outputPath, extensions);
const adminUiExtensions = extensions.filter(isAdminUiExtension);
const normalizedExtensions = normalizeExtensions(adminUiExtensions);
const globalStylesExtensions = extensions.filter(isGlobalStylesExtension);
const staticAssetExtensions = extensions.filter(isStaticAssetExtension);
const allTranslationFiles = getAllTranslationFiles(extensions.filter(isTranslationExtension));
buildProcess = spawn(cmd, ['run', 'start', `--port=${port}`, `--base-href=${baseHref}`], {
Expand Down Expand Up @@ -126,6 +128,18 @@ function runWatchMode(
}
}
}
for (const extension of globalStylesExtensions) {
const globalStylePaths = Array.isArray(extension.globalStyles)
? extension.globalStyles
: [extension.globalStyles];
for (const stylePath of globalStylePaths) {
if (!watcher) {
watcher = chokidarWatch(stylePath);
} else {
watcher.add(stylePath);
}
}
}
for (const translationFiles of Object.values(allTranslationFiles)) {
if (!translationFiles) {
continue;
Expand All @@ -145,10 +159,17 @@ function runWatchMode(
}

if (watcher) {
const allStaticAssetDefs = adminUiExtensions.reduce(
const allStaticAssetDefs = staticAssetExtensions.reduce(
(defs, e) => [...defs, ...(e.staticAssets || [])],
[] as StaticAssetDefinition[],
);
const allGlobalStyles = globalStylesExtensions.reduce(
(defs, e) => [
...defs,
...(Array.isArray(e.globalStyles) ? e.globalStyles : [e.globalStyles]),
],
[] as string[],
);

watcher.on('change', async filePath => {
const extension = normalizedExtensions.find(e => filePath.includes(e.extensionPath));
Expand All @@ -168,6 +189,12 @@ function runWatchMode(
return;
}
}
for (const stylePath of allGlobalStyles) {
if (filePath.includes(stylePath)) {
await copyGlobalStyleFile(outputPath, stylePath);
return;
}
}
for (const languageCode of Object.keys(allTranslationFiles)) {
// tslint:disable-next-line:no-non-null-assertion
const translationFiles = allTranslationFiles[languageCode as LanguageCode]!;
Expand Down
1 change: 1 addition & 0 deletions packages/ui-devkit/src/compiler/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export const STATIC_ASSETS_OUTPUT_DIR = 'static-assets';
export const GLOBAL_STYLES_OUTPUT_DIR = 'global-styles';
export const EXTENSION_ROUTES_FILE = 'src/extension.routes.ts';
export const SHARED_EXTENSIONS_FILE = 'src/shared-extensions.module.ts';
export const MODULES_OUTPUT_DIR = 'src/extensions';
Expand Down
46 changes: 43 additions & 3 deletions packages/ui-devkit/src/compiler/scaffold.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,27 @@ import { spawn } from 'child_process';
import * as fs from 'fs-extra';
import * as path from 'path';

import { EXTENSION_ROUTES_FILE, MODULES_OUTPUT_DIR, SHARED_EXTENSIONS_FILE } from './constants';
import {
EXTENSION_ROUTES_FILE,
GLOBAL_STYLES_OUTPUT_DIR,
MODULES_OUTPUT_DIR,
SHARED_EXTENSIONS_FILE,
STATIC_ASSETS_OUTPUT_DIR,
} from './constants';
import { getAllTranslationFiles, mergeExtensionTranslations } from './translations';
import {
AdminUiExtension,
AdminUiExtensionLazyModule,
AdminUiExtensionSharedModule,
Extension,
GlobalStylesExtension,
StaticAssetExtension,
} from './types';
import {
copyStaticAsset,
copyUiDevkit,
isAdminUiExtension,
isGlobalStylesExtension,
isStaticAssetExtension,
isTranslationExtension,
logger,
Expand All @@ -25,7 +33,7 @@ import {

export async function setupScaffold(outputPath: string, extensions: Extension[]) {
deleteExistingExtensionModules(outputPath);
copySourceIfNotExists(outputPath);
copyAdminUiSource(outputPath);

const adminUiExtensions = extensions.filter(isAdminUiExtension);
const normalizedExtensions = normalizeExtensions(adminUiExtensions);
Expand All @@ -34,6 +42,9 @@ export async function setupScaffold(outputPath: string, extensions: Extension[])
const staticAssetExtensions = extensions.filter(isStaticAssetExtension);
await copyStaticAssets(outputPath, staticAssetExtensions);

const globalStyleExtensions = extensions.filter(isGlobalStylesExtension);
await addGlobalStyles(outputPath, globalStyleExtensions);

const allTranslationFiles = getAllTranslationFiles(extensions.filter(isTranslationExtension));
await mergeExtensionTranslations(outputPath, allTranslationFiles);

Expand Down Expand Up @@ -82,6 +93,35 @@ async function copyStaticAssets(outputPath: string, extensions: Array<Partial<St
}
}

async function addGlobalStyles(outputPath: string, extensions: GlobalStylesExtension[]) {
const globalStylesDir = path.join(outputPath, 'src', GLOBAL_STYLES_OUTPUT_DIR);
await fs.remove(globalStylesDir);
await fs.ensureDir(globalStylesDir);
const imports: string[] = [];
for (const extension of extensions) {
const styleFiles = Array.isArray(extension.globalStyles)
? extension.globalStyles
: [extension.globalStyles];
for (const styleFile of styleFiles) {
await copyGlobalStyleFile(outputPath, styleFile);
imports.push(path.basename(styleFile, path.extname(styleFile)));
}
}
const globalStylesSource =
`@import "./styles/styles";\n` +
imports.map(file => `@import "./${GLOBAL_STYLES_OUTPUT_DIR}/${file}";`).join('\n');

const globalStylesFile = path.join(outputPath, 'src', 'global-styles.scss');
await fs.writeFile(globalStylesFile, globalStylesSource, 'utf-8');
}

export async function copyGlobalStyleFile(outputPath: string, stylePath: string) {
const globalStylesDir = path.join(outputPath, 'src', GLOBAL_STYLES_OUTPUT_DIR);
const fileBasename = path.basename(stylePath);
const styleOutputPath = path.join(globalStylesDir, fileBasename);
await fs.copyFile(stylePath, styleOutputPath);
}

function generateLazyExtensionRoutes(extensions: Array<Required<AdminUiExtension>>): string {
const routes: string[] = [];
for (const extension of extensions as Array<Required<AdminUiExtension>>) {
Expand Down Expand Up @@ -136,7 +176,7 @@ function getModuleFilePath(
* Copy the Admin UI sources & static assets to the outputPath if it does not already
* exists there.
*/
function copySourceIfNotExists(outputPath: string) {
function copyAdminUiSource(outputPath: string) {
const angularJsonFile = path.join(outputPath, 'angular.json');
const indexFile = path.join(outputPath, '/src/index.html');
if (fs.existsSync(angularJsonFile) && fs.existsSync(indexFile)) {
Expand Down
32 changes: 29 additions & 3 deletions packages/ui-devkit/src/compiler/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { LanguageCode } from '@vendure/common/lib/generated-types';

export type Extension = AdminUiExtension | TranslationExtension | StaticAssetExtension;
export type Extension =
| AdminUiExtension
| TranslationExtension
| StaticAssetExtension
| GlobalStylesExtension;

/**
* @description
Expand Down Expand Up @@ -32,6 +36,9 @@ export interface TranslationExtension {
/**
* @description
* Defines extensions which copy static assets to the custom Admin UI application source asset directory.
*
* @docsCategory UiDevkit
* @docsPage AdminUiExtension
*/
export interface StaticAssetExtension {
/**
Expand All @@ -42,6 +49,22 @@ export interface StaticAssetExtension {
staticAssets: StaticAssetDefinition[];
}

/**
* @description
* Defines extensions which add global styles to the custom Admin UI application.
*
* @docsCategory UiDevkit
* @docsPage AdminUiExtension
*/
export interface GlobalStylesExtension {
/**
* @description
* Specifies a path (or array of paths) to global style files (css or Sass) which will be
* incorporated into the Admin UI app global stylesheet.
*/
globalStyles: string[] | string;
}

/**
* @description
* Defines extensions to the Admin UI application by specifying additional
Expand All @@ -55,7 +78,10 @@ export interface StaticAssetExtension {
* @docsPage AdminUiExtension
* @docsWeight 0
*/
export interface AdminUiExtension extends Partial<TranslationExtension>, Partial<StaticAssetExtension> {
export interface AdminUiExtension
extends Partial<TranslationExtension>,
Partial<StaticAssetExtension>,
Partial<GlobalStylesExtension> {
/**
* @description
* An optional ID for the extension module. Only used internally for generating
Expand Down Expand Up @@ -164,7 +190,7 @@ export interface UiExtensionCompilerOptions {
* An array of objects which configure Angular modules and/or
* translations with which to extend the Admin UI.
*/
extensions: Array<AdminUiExtension | TranslationExtension | StaticAssetExtension>;
extensions: Extension[];
/**
* @description
* Set to `true` in order to compile the Admin UI in development mode (using the Angular CLI
Expand Down
7 changes: 6 additions & 1 deletion packages/ui-devkit/src/compiler/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { STATIC_ASSETS_OUTPUT_DIR } from './constants';
import {
AdminUiExtension,
Extension,
GlobalStylesExtension,
StaticAssetDefinition,
StaticAssetExtension,
TranslationExtension,
Expand Down Expand Up @@ -86,7 +87,7 @@ export function normalizeExtensions(extensions?: AdminUiExtension[]): Array<Requ
id = hash.digest('hex');
}

return { staticAssets: [], translations: {}, ...e, id };
return { staticAssets: [], translations: {}, globalStyles: [], ...e, id };
});
}

Expand All @@ -101,3 +102,7 @@ export function isTranslationExtension(input: Extension): input is TranslationEx
export function isStaticAssetExtension(input: Extension): input is StaticAssetExtension {
return input.hasOwnProperty('staticAssets');
}

export function isGlobalStylesExtension(input: Extension): input is GlobalStylesExtension {
return input.hasOwnProperty('globalStyles');
}

1 comment on commit 2081a15

@jeancx
Copy link
Contributor

@jeancx jeancx commented on 2081a15 Jan 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's getting cool, a lot of personalizations, nice clean code, thanks for the good work!

Please sign in to comment.