web: moderate accounts, accept 12MB uploads, put SAVE under CREATE
- /admin User account rows gain BLOCK/UNBLOCK, REMOVE/RESTORE and DELETE. Blocked = cannot sign in (sessions swept), removed = hidden from the strip and cannot sign in, both reversible; DELETE drops the account with its photos and recipes and unlinks the files. An allowlisted account is never a target, so an admin cannot moderate or delete itself. - Photo uploads move from a 3MB API cap / 4m nginx cap to 12MB / 16m, and the browser shrinks an oversized still before sending it (2048px JPEG, avatars 512px) so the declared type still matches the sniffed bytes. - The studio SAVE leaves the top bar and sits under the CREATE RECIPES tab, labelled SAVE RECIPES.
This commit is contained in:
+24
-11
@@ -1023,8 +1023,9 @@ export function Workspace() {
|
||||
setShowRecipes((v) => !v);
|
||||
},
|
||||
},
|
||||
// ponytail: no CREATE chip — saving goes through the top bar. IMPORT
|
||||
// is a chip inside the RECIPES strip.
|
||||
// ponytail: no CREATE chip — the save button lives under the CREATE
|
||||
// RECIPES tab (see the create column). IMPORT is a chip inside the
|
||||
// RECIPES strip.
|
||||
];
|
||||
case 'favorited':
|
||||
return saved.length === 0
|
||||
@@ -1114,7 +1115,6 @@ export function Workspace() {
|
||||
onUndo={undoLast}
|
||||
onReset={reset}
|
||||
onExport={exportPhoto}
|
||||
onSave={saveRecipe}
|
||||
onAuth={() => setAuthMode('login')}
|
||||
onSignup={() => setAuthMode('signup')}
|
||||
onLogout={async () => {
|
||||
@@ -1131,14 +1131,27 @@ export function Workspace() {
|
||||
<div className={`col col-main${tab === 'create' ? ' col-create' : ''}`} data-col="main">
|
||||
<ChipRow chips={[resetChip()]} />
|
||||
{tab === 'create' ? (
|
||||
<RecipeCreatePanel
|
||||
currentBase={recipe.baseFilter}
|
||||
current={recipe.adjustments}
|
||||
signedIn={!!user}
|
||||
onPreview={previewCreatedRecipe}
|
||||
onSave={(draft) => void addCreatedRecipe(draft)}
|
||||
onExport={exportRecipeFile}
|
||||
/>
|
||||
<>
|
||||
<RecipeCreatePanel
|
||||
currentBase={recipe.baseFilter}
|
||||
current={recipe.adjustments}
|
||||
signedIn={!!user}
|
||||
onPreview={previewCreatedRecipe}
|
||||
onSave={(draft) => void addCreatedRecipe(draft)}
|
||||
onExport={exportRecipeFile}
|
||||
/>
|
||||
{/* The studio's own save lives here now, under the CREATE tab:
|
||||
it stores the recipe standing on the stage, where the panel
|
||||
above stores the draft being built. */}
|
||||
<button
|
||||
type="button"
|
||||
className="btn"
|
||||
data-key="save-recipes"
|
||||
onClick={() => void saveRecipe()}
|
||||
>
|
||||
{t('save.recipes')}
|
||||
</button>
|
||||
</>
|
||||
) : (
|
||||
<ChipRow chips={chips} />
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user