-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ability to add models from the deployed site (#407)
- Loading branch information
1 parent
f2d3332
commit d3b7860
Showing
8 changed files
with
273 additions
and
82 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
export const createMapFromSessionStorage = <Id, Value>(key: string, map = new Map<Id, Value>()): Map<Id, Value> => { | ||
const cachedItem = sessionStorage.getItem(key); | ||
if (cachedItem) { | ||
const cachedMap = new Map<Id, Value>(JSON.parse(cachedItem || '[]') as []); | ||
for (const id of cachedMap.keys()) { | ||
// Only add the value if it doesn't already exist | ||
// AKA only add user-made data, update everything else from api | ||
if (!map.has(id)) { | ||
const value = cachedMap.get(id); | ||
if (value) { | ||
map.set(id, value); | ||
} | ||
} | ||
} | ||
} | ||
window.addEventListener('beforeunload', () => { | ||
sessionStorage.setItem(key, JSON.stringify([...map])); | ||
}); | ||
return map; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import { DBApi } from './data-api'; | ||
import { MODEL_PROPS, validateType } from './model-props'; | ||
import { Arch, ArchId, Model, ModelId, Tag, TagId, User, UserId } from './schema'; | ||
import { canonicalizeModelId } from './schema-util'; | ||
import { typedEntries } from './util'; | ||
|
||
export interface Report { | ||
message: string; | ||
fix?: () => Promise<void>; | ||
} | ||
|
||
export const validateModel = ( | ||
model: Model, | ||
modelId: ModelId, | ||
modelData: ReadonlyMap<ModelId, Model>, | ||
architectureData: ReadonlyMap<ArchId, Arch>, | ||
tagData: ReadonlyMap<TagId, Tag>, | ||
userData: ReadonlyMap<UserId, User>, | ||
api: DBApi | ||
): Report[] => { | ||
const errors: Report[] = []; | ||
const report = (message: string, fix?: () => Promise<void>) => | ||
errors.push({ message: `Model ${modelId}: ${message}`, fix }); | ||
|
||
if (modelId.startsWith(`${model.scale}x`)) { | ||
const expected = canonicalizeModelId(modelId); | ||
if (expected !== modelId) { | ||
report(`Model ID should be ${expected}`, () => api.models.changeId(modelId, expected)); | ||
} | ||
} else { | ||
report(`Model ID must start with scale`, () => | ||
api.models.changeId(modelId, `${model.scale}x-${modelId.replace(/^\d+x-?/, '')}` as ModelId) | ||
); | ||
} | ||
|
||
if (model.thumbnail || model.images.some((image) => image.thumbnail)) { | ||
report(`Thumbnails are automatically generated and should not appear in the database`, async () => { | ||
const model = await api.models.get(modelId); | ||
delete model.thumbnail; | ||
for (const image of model.images) { | ||
delete image.thumbnail; | ||
} | ||
await api.models.update([[modelId, model]]); | ||
}); | ||
} | ||
|
||
for (const [key, prop] of typedEntries(MODEL_PROPS)) { | ||
const value = model[key]; | ||
|
||
if (value === null || value === undefined) { | ||
if (!prop.optional) report(`Missing required property '${key}'`); | ||
continue; | ||
} | ||
|
||
const error = validateType(value, prop, `'${key}'`, { | ||
isValidModelId: (id) => modelData.has(id as ModelId), | ||
isValidUserId: (id) => userData.has(id as UserId), | ||
isValidTagId: (id) => tagData.has(id as TagId), | ||
isValidArchitectureId: (id) => architectureData.has(id as ArchId), | ||
}); | ||
if (error) { | ||
const { message, fix } = error; | ||
report( | ||
message, | ||
fix && | ||
(async () => { | ||
const model = await api.models.get(modelId); | ||
const newValue = fix(); | ||
if (newValue === undefined) { | ||
delete model[key]; | ||
} else { | ||
model[key] = newValue as never; | ||
} | ||
await api.models.update([[modelId, model]]); | ||
}) | ||
); | ||
} | ||
} | ||
return errors; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { GetStaticProps } from 'next'; | ||
import { useEffect, useState } from 'react'; | ||
import { Model, ModelId } from '../../lib/schema'; | ||
import ModelsPage from './[id]'; | ||
|
||
const modelId = 'OMDB_ADDMODEL_DUMMY' as ModelId; | ||
|
||
export default function Page() { | ||
const [model, setModel] = useState<Model | null>(null); | ||
|
||
useEffect(() => { | ||
const model = JSON.parse(sessionStorage.getItem('dummy-model') ?? '{}') as Model; | ||
setModel(model); | ||
}, []); | ||
|
||
if (!model) return null; | ||
|
||
return ( | ||
<div> | ||
<ModelsPage | ||
editModeOverride | ||
modelData={{ [modelId]: model }} | ||
modelId={modelId} | ||
similar={[]} | ||
/> | ||
</div> | ||
); | ||
} | ||
|
||
export const getStaticProps: GetStaticProps = () => { | ||
return { props: {} }; | ||
}; |
Oops, something went wrong.