@vixoniccom/menu-daily 0.1.2-dev.0 → 0.2.0-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +31 -0
- package/.vscode/settings.json +3 -0
- package/CHANGELOG.md +21 -0
- package/build/index.html +1 -0
- package/build/main.js +2 -0
- package/build/main.js.LICENSE.txt +39 -0
- package/build/test/downloads/1234.ttf +0 -0
- package/build/test/downloads/background.jpg +0 -0
- package/build/test/downloads/futura-font.ttf +0 -0
- package/build/test/parameters.json +38 -0
- package/build/test/services.json +871 -0
- package/build.zip +0 -0
- package/configuration/appearanceGroup/AppearanceInputs.ts +94 -0
- package/configuration/appearanceGroup/index.ts +8 -0
- package/configuration/dataGroup/DataInputs.ts +21 -0
- package/configuration/dataGroup/index.ts +8 -0
- package/configuration/index.ts +7 -0
- package/configuration.json +43 -78
- package/package.json +13 -12
- package/src/global.d.ts +15 -51
- package/src/main.ts +0 -5
- package/src/parameters.d.ts +31 -0
- package/src/scenes/App.tsx +25 -38
- package/src/scenes/components/FontLoader.tsx +3 -16
- package/src/scenes/components/FormattedText.tsx +3 -4
- package/src/scenes/components/Grid/Grid.tsx +8 -8
- package/src/scenes/components/Grid/GridItem.tsx +1 -0
- package/src/scenes/components/Grid/animation.ts +69 -55
- package/src/scenes/components/MealContainer/components/OptionItem.tsx +1 -2
- package/src/scenes/components/MealContainer/components/Title/index.tsx +17 -20
- package/src/scenes/components/MealContainer/components/Title/styles/Framed.tsx +19 -28
- package/src/scenes/components/MealContainer/components/Title/styles/Modern.tsx +15 -24
- package/src/scenes/components/MealContainer/components/Title/styles/index.tsx +25 -1
- package/src/scenes/components/MealContainer/index.tsx +31 -31
- package/src/test/parameters.json +7 -5
- package/src/test/services.json +871 -0
- package/tsconfig.json +9 -17
- package/src/dataLoader.ts +0 -169
package/tsconfig.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
|
-
"target": "
|
|
4
|
-
"module": "
|
|
3
|
+
"target": "es6",
|
|
4
|
+
"module": "esnext",
|
|
5
5
|
"moduleResolution": "node",
|
|
6
|
-
"jsx": "
|
|
6
|
+
"jsx": "react-jsx",
|
|
7
7
|
"allowJs": true,
|
|
8
8
|
"checkJs": true,
|
|
9
9
|
"allowSyntheticDefaultImports": true,
|
|
@@ -19,18 +19,10 @@
|
|
|
19
19
|
"noUnusedLocals": true,
|
|
20
20
|
"noUnusedParameters": true,
|
|
21
21
|
"sourceMap": true,
|
|
22
|
-
"
|
|
23
|
-
|
|
24
|
-
]
|
|
25
|
-
"typeRoots": [
|
|
26
|
-
"./node_modules/@types",
|
|
27
|
-
"./src"
|
|
28
|
-
]
|
|
22
|
+
"skipLibCheck": true,
|
|
23
|
+
"types": ["node"],
|
|
24
|
+
"typeRoots": ["./node_modules/@types", "./src"]
|
|
29
25
|
},
|
|
30
|
-
"include": [
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"exclude": [
|
|
34
|
-
"./node_modules/**/*"
|
|
35
|
-
]
|
|
36
|
-
}
|
|
26
|
+
"include": ["./src/**/*"],
|
|
27
|
+
"exclude": ["./node_modules/**/*"]
|
|
28
|
+
}
|
package/src/dataLoader.ts
DELETED
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
import xlsx from 'xlsx'
|
|
2
|
-
import localforage from 'localforage'
|
|
3
|
-
import { logger } from './logger'
|
|
4
|
-
|
|
5
|
-
const getStoreKey = (id: string) => (`urlrequest-menu:${id}`)
|
|
6
|
-
|
|
7
|
-
export class DataLoader {
|
|
8
|
-
onUpdate?: (data: MenuData) => void
|
|
9
|
-
onError?: (e: Error) => void
|
|
10
|
-
|
|
11
|
-
private _url: string | undefined
|
|
12
|
-
get url (): string | undefined { return this._url }
|
|
13
|
-
|
|
14
|
-
private _data: MenuData | undefined
|
|
15
|
-
get data (): MenuData | undefined { return this._data }
|
|
16
|
-
|
|
17
|
-
private _mealType?: string
|
|
18
|
-
private _pollingInterval: number = 60000
|
|
19
|
-
private _pollingTimer: number | undefined
|
|
20
|
-
|
|
21
|
-
private _req: XMLHttpRequest | undefined
|
|
22
|
-
|
|
23
|
-
private _started: boolean = false
|
|
24
|
-
|
|
25
|
-
constructor (url?: string, interval?: number, mealType?: string) {
|
|
26
|
-
this.setup(url, interval, mealType)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
setup (url?: string, interval: number = 300000, mealType?: string) {
|
|
30
|
-
if (!url) {
|
|
31
|
-
this.stop()
|
|
32
|
-
return
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
this._pollingInterval = interval >= 60000 ? interval : 60000
|
|
36
|
-
this._mealType = mealType
|
|
37
|
-
if (this._url !== url) {
|
|
38
|
-
this.stop()
|
|
39
|
-
this._url = url
|
|
40
|
-
// Get cache data
|
|
41
|
-
if (!this._data) {
|
|
42
|
-
localforage.getItem<CacheData>(getStoreKey(this._url)).then(
|
|
43
|
-
(data) => {
|
|
44
|
-
if (!data || !data.updateTime || !data.menuData) {
|
|
45
|
-
this.startPolling()
|
|
46
|
-
} else {
|
|
47
|
-
logger.log('Got cached data!', data.updateTime)
|
|
48
|
-
this.onUpdate && this.onUpdate(data.menuData)
|
|
49
|
-
let timeDiff = Date.now() - data.updateTime
|
|
50
|
-
if (timeDiff >= this._pollingInterval) {
|
|
51
|
-
this.startPolling()
|
|
52
|
-
} else {
|
|
53
|
-
this.startPollingTimer(this._pollingInterval - timeDiff)
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
|
-
(_e) => {
|
|
58
|
-
this.startPolling()
|
|
59
|
-
}
|
|
60
|
-
)
|
|
61
|
-
} else {
|
|
62
|
-
this.startPolling()
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
private startPolling () {
|
|
68
|
-
if (this._started) return
|
|
69
|
-
if (!this._url) return
|
|
70
|
-
this._started = true
|
|
71
|
-
this.load()
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
private stop (): void {
|
|
75
|
-
window.clearTimeout(this._pollingTimer)
|
|
76
|
-
this._started = false
|
|
77
|
-
if (this._req) this._req.abort()
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
private load (): void {
|
|
81
|
-
if (!this._url) return
|
|
82
|
-
|
|
83
|
-
this._req = new XMLHttpRequest()
|
|
84
|
-
this._req.open('GET', this._url, true)
|
|
85
|
-
this._req.responseType = 'arraybuffer'
|
|
86
|
-
|
|
87
|
-
this._req.onload = this.onLoad.bind(this)
|
|
88
|
-
|
|
89
|
-
this._req.onerror = (e) => {
|
|
90
|
-
if (e) {
|
|
91
|
-
this.onError && this.onError(e as any)
|
|
92
|
-
this.startPollingTimer(30000)
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
this._req.send()
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
private onLoad (_ev: Event) {
|
|
100
|
-
if (!(this._req && this._url)) return
|
|
101
|
-
|
|
102
|
-
logger.log('Data loaded', Date.now())
|
|
103
|
-
let arraybuffer = this._req.response
|
|
104
|
-
|
|
105
|
-
/* convert data to binary string */
|
|
106
|
-
let data = new Uint8Array(arraybuffer)
|
|
107
|
-
let arr = new Array()
|
|
108
|
-
for (let i = 0; i !== data.length; ++i) arr[i] = String.fromCharCode(data[i])
|
|
109
|
-
let bstr = arr.join('')
|
|
110
|
-
|
|
111
|
-
/* Call XLSX */
|
|
112
|
-
let workbook = xlsx?.read(bstr, { type: 'binary' })
|
|
113
|
-
this._pollingTimer = window.setTimeout(() => { this.load() }, this._pollingInterval)
|
|
114
|
-
|
|
115
|
-
let menuData = this.parseData(workbook)
|
|
116
|
-
if (menuData) {
|
|
117
|
-
this._data = menuData
|
|
118
|
-
// Save cache
|
|
119
|
-
localforage.setItem<CacheData>(getStoreKey(this._url), {
|
|
120
|
-
updateTime: Date.now(),
|
|
121
|
-
menuData: this._data
|
|
122
|
-
})
|
|
123
|
-
// Dispatch update
|
|
124
|
-
this.onUpdate && this.onUpdate(this._data)
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
private startPollingTimer (interval?: number) {
|
|
129
|
-
if (this._pollingTimer) window.clearTimeout(this._pollingInterval)
|
|
130
|
-
this._pollingTimer = window.setTimeout(() => { this.load() }, interval || this._pollingInterval)
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
private parseData (workbook: xlsx.WorkBook): MenuData | undefined {
|
|
134
|
-
try {
|
|
135
|
-
if (!workbook) return undefined
|
|
136
|
-
if (this._mealType) workbook.SheetNames.find((name) => name.toUpperCase() === this._mealType!.toUpperCase())
|
|
137
|
-
let menuData: MenuData = workbook.SheetNames.reduce((menu: MenuData, name) => {
|
|
138
|
-
let newMenu = {...menu}
|
|
139
|
-
let dailyMenu = this.parseSheet(workbook.Sheets[name])
|
|
140
|
-
if (dailyMenu) newMenu[name.toUpperCase()] = dailyMenu
|
|
141
|
-
return newMenu
|
|
142
|
-
}, {})
|
|
143
|
-
logger.log(menuData)
|
|
144
|
-
return menuData
|
|
145
|
-
} catch (e: any) {
|
|
146
|
-
this.onError && this.onError(e)
|
|
147
|
-
return undefined
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
private parseSheet (sheet: xlsx.WorkSheet): MenuByDate | undefined {
|
|
152
|
-
if (!sheet) return undefined
|
|
153
|
-
let meals: MenuByDate | {} = xlsx?.utils.sheet_to_json(sheet, {raw: true}).reduce((menu: MenuByDate, row: any) => {
|
|
154
|
-
let newMenu = {...menu}
|
|
155
|
-
let keys = Object.keys(row)
|
|
156
|
-
let date: {d: number, m: number, y: number} = xlsx?.SSF.parse_date_code(row[keys[0]] as any)
|
|
157
|
-
if (date.d && date.m && date.y) {
|
|
158
|
-
newMenu[new Date(date.y,date.m - 1,date.d).getTime()] = keys.slice(1).map((key) => {
|
|
159
|
-
return {
|
|
160
|
-
type: key,
|
|
161
|
-
options: row[key] && row[key].split(';') || []
|
|
162
|
-
} as Meal
|
|
163
|
-
})
|
|
164
|
-
}
|
|
165
|
-
return newMenu
|
|
166
|
-
}, {})
|
|
167
|
-
return meals
|
|
168
|
-
}
|
|
169
|
-
}
|