mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2025-07-05 19:42:51 +00:00
MWS - added DELETE functionality to both Recipes and Bags
This commit is contained in:
parent
060bea89ae
commit
1758a9ce12
@ -30,6 +30,33 @@ exports.useACL = true;
|
|||||||
exports.entityName = "bag"
|
exports.entityName = "bag"
|
||||||
|
|
||||||
exports.handler = function(request,response,state) {
|
exports.handler = function(request,response,state) {
|
||||||
|
var server = state.server,
|
||||||
|
sqlTiddlerDatabase = server.sqlTiddlerDatabase;
|
||||||
|
|
||||||
|
// Handle DELETE request
|
||||||
|
if(state.data._method === "DELETE") {
|
||||||
|
if(state.data.bag_name) {
|
||||||
|
const result = $tw.mws.store.deleteBag(state.data.bag_name);
|
||||||
|
if(!result) {
|
||||||
|
state.sendResponse(302,{
|
||||||
|
"Content-Type": "text/plain",
|
||||||
|
"Location": "/"
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
state.sendResponse(400,{
|
||||||
|
"Content-Type": "text/plain"
|
||||||
|
},
|
||||||
|
result.message,
|
||||||
|
"utf8");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
state.sendResponse(400,{
|
||||||
|
"Content-Type": "text/plain"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(state.data.bag_name) {
|
if(state.data.bag_name) {
|
||||||
const result = $tw.mws.store.createBag(state.data.bag_name,state.data.description);
|
const result = $tw.mws.store.createBag(state.data.bag_name,state.data.description);
|
||||||
if(!result) {
|
if(!result) {
|
||||||
@ -52,3 +79,4 @@ exports.handler = function(request,response,state) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
}());
|
}());
|
||||||
|
|
@ -4,9 +4,9 @@ type: application/javascript
|
|||||||
module-type: mws-route
|
module-type: mws-route
|
||||||
|
|
||||||
POST /recipes
|
POST /recipes
|
||||||
|
DELETE /recipes (via _method=DELETE)
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
|
|
||||||
recipe_name
|
recipe_name
|
||||||
description
|
description
|
||||||
bag_names: space separated list of bags
|
bag_names: space separated list of bags
|
||||||
@ -32,7 +32,33 @@ exports.entityName = "recipe"
|
|||||||
|
|
||||||
exports.handler = function(request,response,state) {
|
exports.handler = function(request,response,state) {
|
||||||
var server = state.server,
|
var server = state.server,
|
||||||
sqlTiddlerDatabase = server.sqlTiddlerDatabase
|
sqlTiddlerDatabase = server.sqlTiddlerDatabase;
|
||||||
|
|
||||||
|
// Check and handle if this is a DELETE request
|
||||||
|
if(state.data._method === "DELETE") {
|
||||||
|
if(state.data.recipe_name && state.data.bag_names) {
|
||||||
|
const result = sqlTiddlerDatabase.deleteRecipe(state.data.recipe_name);
|
||||||
|
if(!result) {
|
||||||
|
state.sendResponse(302,{
|
||||||
|
"Content-Type": "text/plain",
|
||||||
|
"Location": "/"
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
state.sendResponse(400,{
|
||||||
|
"Content-Type": "text/plain"
|
||||||
|
},
|
||||||
|
result.message,
|
||||||
|
"utf8");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
state.sendResponse(400,{
|
||||||
|
"Content-Type": "text/plain"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle POST request (original code)
|
||||||
if(state.data.recipe_name && state.data.bag_names) {
|
if(state.data.recipe_name && state.data.bag_names) {
|
||||||
const result = $tw.mws.store.createRecipe(state.data.recipe_name,$tw.utils.parseStringArray(state.data.bag_names),state.data.description);
|
const result = $tw.mws.store.createRecipe(state.data.recipe_name,$tw.utils.parseStringArray(state.data.bag_names),state.data.description);
|
||||||
if(!result) {
|
if(!result) {
|
||||||
|
@ -203,6 +203,31 @@ SqlTiddlerDatabase.prototype.listBags = function() {
|
|||||||
return rows;
|
return rows;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Delete a recipe and its bag associations
|
||||||
|
*/
|
||||||
|
SqlTiddlerDatabase.prototype.deleteRecipe = function(recipe_name) {
|
||||||
|
// Delete recipe_bags entries first (due to foreign key constraints)
|
||||||
|
this.engine.runStatement(`
|
||||||
|
DELETE FROM recipe_bags
|
||||||
|
WHERE recipe_id = (
|
||||||
|
SELECT recipe_id
|
||||||
|
FROM recipes
|
||||||
|
WHERE recipe_name = $recipe_name
|
||||||
|
)
|
||||||
|
`, {
|
||||||
|
$recipe_name: recipe_name
|
||||||
|
});
|
||||||
|
|
||||||
|
// Then delete the recipe itself
|
||||||
|
this.engine.runStatement(`
|
||||||
|
DELETE FROM recipes
|
||||||
|
WHERE recipe_name = $recipe_name
|
||||||
|
`, {
|
||||||
|
$recipe_name: recipe_name
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Create or update a bag
|
Create or update a bag
|
||||||
Returns the bag_id of the bag
|
Returns the bag_id of the bag
|
||||||
@ -229,6 +254,19 @@ SqlTiddlerDatabase.prototype.createBag = function(bag_name,description,accesscon
|
|||||||
return updateBags.lastInsertRowid;
|
return updateBags.lastInsertRowid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Delete a bag and all its associated data
|
||||||
|
*/
|
||||||
|
SqlTiddlerDatabase.prototype.deleteBag = function(bag_name) {
|
||||||
|
// Delete the bag (cascade will handle related records)
|
||||||
|
this.engine.runStatement(`
|
||||||
|
DELETE FROM bags
|
||||||
|
WHERE bag_name = $bag_name
|
||||||
|
`, {
|
||||||
|
$bag_name: bag_name
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Returns array of {recipe_name:,recipe_id:,description:,bag_names: []}
|
Returns array of {recipe_name:,recipe_id:,description:,bag_names: []}
|
||||||
*/
|
*/
|
||||||
@ -1446,3 +1484,4 @@ SqlTiddlerDatabase.prototype.getRoleById = function(roleId) {
|
|||||||
exports.SqlTiddlerDatabase = SqlTiddlerDatabase;
|
exports.SqlTiddlerDatabase = SqlTiddlerDatabase;
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
@ -95,6 +95,46 @@ SqlTiddlerStore.prototype.validateItemName = function(name,allowPrivilegedCharac
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Delete a recipe. Returns null on success, or {message:} on error
|
||||||
|
*/
|
||||||
|
SqlTiddlerStore.prototype.deleteRecipe = function(recipe_name) {
|
||||||
|
var self = this;
|
||||||
|
return this.sqlTiddlerDatabase.transaction(function() {
|
||||||
|
// Check if recipe exists
|
||||||
|
const recipes = self.sqlTiddlerDatabase.listRecipes();
|
||||||
|
const recipeExists = recipes.some(recipe => recipe.recipe_name === recipe_name);
|
||||||
|
if(!recipeExists) {
|
||||||
|
return {message: "Recipe does not exist"};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the recipe
|
||||||
|
self.sqlTiddlerDatabase.deleteRecipe(recipe_name);
|
||||||
|
self.dispatchEvent("change");
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Delete a bag. Returns null on success, or {message:} on error
|
||||||
|
*/
|
||||||
|
SqlTiddlerStore.prototype.deleteBag = function(bag_name) {
|
||||||
|
var self = this;
|
||||||
|
return this.sqlTiddlerDatabase.transaction(function() {
|
||||||
|
// Check if bag exists
|
||||||
|
const bags = self.sqlTiddlerDatabase.listBags();
|
||||||
|
const bagExists = bags.some(bag => bag.bag_name === bag_name);
|
||||||
|
if(!bagExists) {
|
||||||
|
return {message: "Bag does not exist"};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the bag
|
||||||
|
self.sqlTiddlerDatabase.deleteBag(bag_name);
|
||||||
|
self.dispatchEvent("change");
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Returns null if the argument is an array of valid bag/recipe names, or a string error message if not
|
Returns null if the argument is an array of valid bag/recipe names, or a string error message if not
|
||||||
*/
|
*/
|
||||||
|
@ -86,6 +86,14 @@ title: $:/plugins/tiddlywiki/multiwikiserver/templates/get-index
|
|||||||
</div>
|
</div>
|
||||||
<div class="mws-wiki-card-description">
|
<div class="mws-wiki-card-description">
|
||||||
<$text text={{{ [<recipe-info>jsonget[description]] }}}/>
|
<$text text={{{ [<recipe-info>jsonget[description]] }}}/>
|
||||||
|
</div>
|
||||||
|
<div class="mws-wiki-card-actions">
|
||||||
|
<form action="/recipes" method="post">
|
||||||
|
<input type="hidden" name="_method" value="DELETE"/>
|
||||||
|
<input type="hidden" name="recipe_name" value={{{ [<recipe-info>jsonget[recipe_name]] }}}/>
|
||||||
|
<input type="hidden" name="bag_names" value={{{ [<recipe-info>jsonget[bag_names]join[ ]] }}}/>
|
||||||
|
<button type="submit" class="mws-delete-button">Delete Recipe</button>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -133,6 +141,13 @@ title: $:/plugins/tiddlywiki/multiwikiserver/templates/get-index
|
|||||||
>
|
>
|
||||||
<$transclude $variable="bagPill"/>
|
<$transclude $variable="bagPill"/>
|
||||||
<$text text={{{ [<bag-info>jsonget[description]] }}}/>
|
<$text text={{{ [<bag-info>jsonget[description]] }}}/>
|
||||||
|
<div class="mws-wiki-card-actions">
|
||||||
|
<form action="/bags" method="post" onsubmit="return confirmBagDelete(this)">
|
||||||
|
<input type="hidden" name="_method" value="DELETE"/>
|
||||||
|
<input type="hidden" name="bag_name" value={{{ [<bag-info>jsonget[bag_name]] }}}/>
|
||||||
|
<button type="submit" class="mws-delete-button">Delete Bag</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</$let>
|
</$let>
|
||||||
</li>
|
</li>
|
||||||
</$list>
|
</$list>
|
||||||
@ -241,6 +256,27 @@ title: $:/plugins/tiddlywiki/multiwikiserver/templates/get-index
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mws-delete-button {
|
||||||
|
background-color: #f44336;
|
||||||
|
color: white;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mws-delete-button:hover {
|
||||||
|
background-color: #d32f2f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mws-wiki-card-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
.mws-admin-dropdown-content a:hover {background-color: #ddd;}
|
.mws-admin-dropdown-content a:hover {background-color: #ddd;}
|
||||||
|
|
||||||
.mws-admin-dropdown:hover .mws-admin-dropdown-content {display: block;}
|
.mws-admin-dropdown:hover .mws-admin-dropdown-content {display: block;}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user