Skip to content

Commit

Permalink
JSDoc and improved mods description block.
Browse files Browse the repository at this point in the history
  • Loading branch information
Crystal-Spider committed May 19, 2024
1 parent fb05c4a commit 1db2939
Show file tree
Hide file tree
Showing 26 changed files with 576 additions and 104 deletions.
114 changes: 57 additions & 57 deletions docs/chunk-NIP2FQJK.js → docs/chunk-OZD44EQJ.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/chunk-2IXMRQSH.js → docs/chunk-V3ZU3IA3.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/index.html

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions docs/main-ECV3BVZI.js → docs/main-572EXXT3.js

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ import {FrameComponent} from '~cn/feature/frame/frame.component';
styleUrl: './app.component.scss'
})
export class AppComponent {
/**
* @constructor
* @public
* @param {MatIconRegistry} matIconRegistry
* @param {DomSanitizer} sanitizer
*/
public constructor(private readonly matIconRegistry: MatIconRegistry, private readonly sanitizer: DomSanitizer) {
this.registerSvgIcon('client');
this.registerSvgIcon('server');
Expand All @@ -29,6 +35,12 @@ export class AppComponent {
this.registerSvgIcon('neoforge');
}

/**
* Registers the specified SVG icon.
*
* @private
* @param {string} icon
*/
private registerSvgIcon(icon: string) {
this.matIconRegistry.addSvgIcon(icon, this.sanitizer.bypassSecurityTrustResourceUrl(`assets/svg/${icon}.svg`));
}
Expand Down
5 changes: 5 additions & 0 deletions src/app/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ import {MARKED_OPTIONS, provideMarkdown} from 'ngx-markdown';

import {ROOT_ROUTES} from './app.routes';

/**
* Application configuration.
*
* @type {ApplicationConfig}
*/
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(ROOT_ROUTES),
Expand Down
5 changes: 5 additions & 0 deletions src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ import {ModsEffects} from './feature/mods/redux/effects';
import {modsFeature} from './feature/mods/redux/feature';
import {ModsService} from './feature/mods/service/mods.service';

/**
* Application routes.
*
* @type {Routes}
*/
export const ROOT_ROUTES: Routes = [
{
path: ROUTE.HOME,
Expand Down
2 changes: 2 additions & 0 deletions src/app/core/abstract/form-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ export abstract class FormComponent<T> extends SubscriberComponent implements On

/**
* @inheritdoc
*
* @public
*/
public ngOnChanges(changes: TypedChanges<FormComponent<T>>): void {
if (changes.formData && this.formData) {
Expand Down
2 changes: 2 additions & 0 deletions src/app/core/abstract/subscriber.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export abstract class SubscriberComponent implements OnDestroy {

/**
* @inheritdoc
*
* @public
*/
public ngOnDestroy(): void {
this.subject$.next();
Expand Down
22 changes: 22 additions & 0 deletions src/app/feature/frame/component/header/header.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,37 @@ import {SeparatorComponent} from '~cn/shared/component/separator/separator.compo
styleUrl: './header.component.scss'
})
export class HeaderComponent {
/**
* Active route.
*
* @public
* @type {!ROUTE}
*/
@Input({required: true})
public activeRoute!: ROUTE;

/**
* Whether the navigation floating menu is open.
*
* @public
* @type {boolean}
*/
public menuOpen = false;

/**
* Update the tracking of the floating menu's open state.
*
* @public
*/
public onMenuOpen() {
this.menuOpen = true;
}

/**
* Update the tracking of the floating menu's open state.
*
* @public
*/
public onMenuClose() {
this.menuOpen = false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ export class GeneratorFormComponent extends FormComponent<SkeletonForm> implemen

/**
* @inheritdoc
*
* @public
*/
public ngOnInit(): void {
this.valueChanges('autogenModId', value => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import {InputComponent} from '~cn/shared/component/form/input/input.component';
export class ModsFormComponent extends FormComponent<ModsForm> implements OnInit {
/**
* @inheritdoc
*
* @public
*/
public ngOnInit(): void {
this.valueChanges('query', () => this.emitSubmit(), (_, index) => index > 0 && this.validity);
Expand Down
102 changes: 102 additions & 0 deletions src/app/feature/mods/model/mods-query.interface.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,137 @@
import {MinecraftVersion} from '~cn/core/model/minecraft-version.type';
import {ModVersion} from '~cn/core/model/mod-version.type';

/**
* GitHub GraphQL result of a query with nodes.
*
* @export
* @interface QueryNodes
* @typedef {QueryNodes}
* @template T
*/
export interface QueryNodes<T> {
/**
* Total amount of nodes.
* Can differ from the amount of nodes retrieved as the latter is limited.
*
* @type {number}
*/
totalCount: number;
/**
* Nodes.
*
* @type {T[]}
*/
nodes: T[];
}

/**
* GitHub GraphQL result of the query to retrieve a topic name.
*
* @export
* @interface TopicQuery
* @typedef {TopicQuery}
*/
export interface TopicQuery {
/**
* Topic wrapper with name.
*
* @type {{name: string}}
*/
topic: {
name: string;
};
}

/**
* GitHub GraphQL result of the query to retrieve a release name.
*
* @export
* @interface ReleaseQuery
* @typedef {ReleaseQuery}
*/
export interface ReleaseQuery {
/**
* Name.
*
* @type {`v${MinecraftVersion}-${ModVersion}`}
*/
name: `v${MinecraftVersion}-${ModVersion}`;
}

/**
* GitHub GraphQL result of the query to retrieve a Crystal Nest mod.
*
* @export
* @interface RepositoryQuery
* @typedef {RepositoryQuery}
*/
export interface RepositoryQuery {
/**
* Name.
*
* @type {string}
*/
name: string;
/**
* Description field.
*
* @type {string}
*/
description: string;
/**
* Whether the wiki is enabled.
*
* @type {boolean}
*/
hasWikiEnabled: boolean;
/**
* Whether it's a template.
*
* @type {boolean}
*/
isTemplate: boolean;
/**
* Topics.
*
* @type {QueryNodes<TopicQuery>}
*/
repositoryTopics: QueryNodes<TopicQuery>;
/**
* Optional latest stable release name.
*
* @type {ReleaseQuery | null}
*/
latestRelease: ReleaseQuery | null;
/**
* List with the latest release, regardless of whether it's stable or prerelease.
*
* @type {QueryNodes<ReleaseQuery>}
*/
releases: QueryNodes<ReleaseQuery>;
/**
* Readme object.
*
* @type {{text: string}}
*/
object: {
text: string;
};
}

/**
* GitHub GraphQL result of the query to retrieve Crystal Nest mods.
*
* @export
* @interface ModsQuery
* @typedef {ModsQuery}
*/
export interface ModsQuery {
/**
* Root data object.
*
* @type {{organization: {repositories: QueryNodes<RepositoryQuery>}}}
*/
data: {
organization: {
repositories: QueryNodes<RepositoryQuery>;
Expand Down
2 changes: 1 addition & 1 deletion src/app/feature/mods/mods.component.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<cn-mods-form (onSubmit)="search($event)"></cn-mods-form>
<cn-mods-form (onSubmit)="filter($event)"></cn-mods-form>
<section>
@for (mod of mods$ | async; track mod.name) {
<cn-card [mod]="mod" />
Expand Down
8 changes: 7 additions & 1 deletion src/app/feature/mods/mods.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,13 @@ export class ModsComponent {
this.store$.dispatch(retrieveMods());
}

public search(form: ModsForm) {
/**
* Starts the flow to filter the list of mods.
*
* @public
* @param {ModsForm} form
*/
public filter(form: ModsForm) {
this.store$.dispatch(filterMods(form));
}
}
12 changes: 12 additions & 0 deletions src/app/feature/mods/redux/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,22 @@ import {createAction, props} from '@ngrx/store';
import {Mod} from '../model/mod.interface';
import {ModsForm} from '../model/mods-form.interface';

/**
* Retrieves Crystal Nest mods.
*/
export const retrieveMods = createAction('[Mods] Retrieve mods');

/**
* Saves the given mods in the store.
*/
export const saveMods = createAction('[Mods] Save mods', props<{mods: Mod[]}>());

/**
* Filters the mods.
*/
export const filterMods = createAction('[Mods] Filter mods', props<ModsForm>());

/**
* Saves the filtered mods.
*/
export const saveFilteredMods = createAction('[Mods] Save filtered mods', props<{filteredMods: Mod[]}>());
52 changes: 50 additions & 2 deletions src/app/feature/mods/redux/effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,32 @@ import {MinecraftVersion} from '~cn/core/model/minecraft-version.type';
import {ModLoader} from '~cn/core/model/mod-loader.type';
import {ModVersion} from '~cn/core/model/mod-version.type';

/**
* Mods effects.
*
* @export
* @class ModsEffects
* @typedef {ModsEffects}
*/
@Injectable()
export class ModsEffects {
/**
* List of topics related to each mod loader.
*
* @private
* @readonly
* @type {string[]}
*/
private readonly loaderTopics = ['fabric', 'forge', 'neoforge'].map(loader => `minecraft-${loader}-mod`);

/**
* Intercepts the action {@link retrieveMods} to retrieve the list of mods and,
* if mods weren't retireved already, calls {@link ModsService.getMods getMods} to retrieve the GitHub GraphQL query result for Crystal Nest mods,
* then emits the action {@link saveMods} to save the list of mods resulted from parsing the query result.
*
* @public
* @type {TypedAction<"[Mods] Save mods">}
*/
public retrieveMods$ = createEffect(() => this.actions$.pipe(
ofType(retrieveMods),
withLatestFrom(this.store$.select(modsFeature.selectMods)),
Expand All @@ -43,11 +65,18 @@ export class ModsEffects {
))
));

/**
* Intercepts the action {@link filteredMods} to filter the list of mods,
* emits the action {@link saveFilteredMods} to save the filtered list of mods.
*
* @public
* @type {Observable<TypedAction<"[Mods] Save filtered mods">>}
*/
public filterMods$ = createEffect(() => this.actions$.pipe(
ofType(filterMods),
withLatestFrom(this.store$.select(modsFeature.selectMods)),
filter(([, mods]) => !!mods),
map(([filters, mods]) => saveFilteredMods({filteredMods: this.search(mods || [], filters)}))
map(([filters, mods]) => saveFilteredMods({filteredMods: this.filter(mods || [], filters)}))
));

/**
Expand All @@ -59,7 +88,18 @@ export class ModsEffects {
*/
public constructor(private readonly actions$: Actions, private readonly store$: Store<State>, private readonly modsService: ModsService) {}

private search(mods: Mod[], {query, client, server}: ModsForm): Mod[] {
/**
* Filters the list of mods based on the provided filters.
*
* @private
* @param {Mod[]} mods
* @param {ModsForm} filters
* @param {ModsForm} filters.query
* @param {ModsForm} filters.client
* @param {ModsForm} filters.server
* @returns {Mod[]}
*/
private filter(mods: Mod[], {query, client, server}: ModsForm): Mod[] {
return query ? new Fuse(mods.map(mod => ({
...mod,
shorthand: mod.title.split(' ').map(word => word[0]).join('')
Expand All @@ -74,6 +114,14 @@ export class ModsEffects {
}).search(query).map(result => result.item) : mods;
}

/**
* Checks whether the specified side is required.
*
* @private
* @param {string} readme
* @param {'client' | 'server'} side
* @returns {boolean}
*/
private checkSide(readme: string, side: 'client' | 'server'): boolean {
return readme.match(/!\[Overlay\]\(.*\/(.*?)\.svg\)/)?.[0].includes(side) || false;
}
Expand Down
Loading

0 comments on commit 1db2939

Please sign in to comment.