11import { Injectable } from '@angular/core' ;
22import { perfNow } from 'src/app/util/util' ;
3- import { YamlService } from '../yaml-loader/yaml-loader.service' ;
3+ import { FileNotFoundError , YamlService } from '../yaml-loader/yaml-loader.service' ;
4+ import { GithubService } from '../settings/github.service' ;
45import { MetaStore } from 'src/app/model/meta-store' ;
56import { TeamProgressFile , Uuid } from 'src/app/model/types' ;
67import {
@@ -11,20 +12,36 @@ import {
1112 Data ,
1213} from 'src/app/model/activity-store' ;
1314import { DataStore } from 'src/app/model/data-store' ;
15+ import { NotificationService } from '../notification.service' ;
1416
1517export class DataValidationError extends Error {
1618 constructor ( message : string ) {
1719 super ( message ) ;
1820 }
1921}
2022
23+ export class MissingModelError extends Error {
24+ filename : string | null ;
25+ constructor ( message : string , filename : string | null = null ) {
26+ super ( message ) ;
27+ this . filename = filename ;
28+ }
29+ }
30+
2131@Injectable ( { providedIn : 'root' } )
2232export class LoaderService {
2333 private META_FILE : string = 'assets/YAML/meta.yaml' ;
34+ private DSOMM_MODEL_URL : string ;
2435 private debug : boolean = false ;
2536 private dataStore : DataStore | null = null ;
2637
27- constructor ( private yamlService : YamlService ) { }
38+ constructor (
39+ private yamlService : YamlService ,
40+ private githubService : GithubService ,
41+ private notificationService : NotificationService
42+ ) {
43+ this . DSOMM_MODEL_URL = this . githubService . getDsommModelUrl ( ) ;
44+ }
2845
2946 get datastore ( ) : DataStore | null {
3047 return this . dataStore ;
@@ -70,8 +87,18 @@ export class LoaderService {
7087 console . log ( `${ perfNow ( ) } : YAML: All YAML files loaded` ) ;
7188
7289 return this . dataStore ;
73- } catch ( err ) {
74- throw err ;
90+ } catch ( err : any ) {
91+ if ( err instanceof FileNotFoundError ) {
92+ console . error ( `${ perfNow ( ) } : Missing model file: ${ err ?. filename || err } ` ) ;
93+ if ( err . filename && err . filename . endsWith ( 'default/model.yaml' ) ) {
94+ this . notificationService . notify ( 'Loading error' , `No DSOMM model found.\n\nPlease download \`model.yaml\` from [GitHub](${ this . DSOMM_MODEL_URL } ).` ) ; // eslint-disable-line
95+ } else {
96+ this . notificationService . notify ( 'Loading error' , err . message + ': ' + err . filename ) ;
97+ }
98+ } else {
99+ this . notificationService . notify ( 'Error' , 'Failed to load data: \n\n' + err ) ;
100+ }
101+ return this . dataStore ;
75102 }
76103 }
77104
@@ -117,11 +144,14 @@ export class LoaderService {
117144 private async loadActivities ( meta : MetaStore ) : Promise < ActivityStore > {
118145 const activityStore = new ActivityStore ( ) ;
119146 const errors : string [ ] = [ ] ;
120- let usingHistoricYamlFile = false ;
147+ let usingLegacyYamlFile = false ;
121148
149+ if ( meta . activityFiles . length == 0 ) {
150+ throw new MissingModelError ( 'No `activityFiles` are specified in `meta.yaml`.' ) ;
151+ }
122152 for ( let filename of meta . activityFiles ) {
123153 if ( this . debug ) console . log ( `${ perfNow ( ) } s: Loading activity file: ${ filename } ` ) ;
124- usingHistoricYamlFile ||= filename . endsWith ( 'generated/generated.yaml' ) ;
154+ usingLegacyYamlFile ||= filename . endsWith ( 'generated/generated.yaml' ) ;
125155
126156 const response : ActivityFile = await this . loadActivityFile ( filename ) ;
127157
@@ -140,8 +170,8 @@ export class LoaderService {
140170 if ( errors . length > 0 ) {
141171 errors . forEach ( error => console . error ( error ) ) ;
142172
143- // Only throw for non-generated files (backwards compatibility)
144- if ( ! usingHistoricYamlFile ) {
173+ // Legacy generated.yaml has several data validation problems. Do not report these
174+ if ( ! usingLegacyYamlFile ) {
145175 throw new DataValidationError (
146176 'Data validation error after loading: ' +
147177 filename +
0 commit comments