From f6d647894486defb7ab856da0ce1901fc0ed8750 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Tue, 23 Jan 2024 14:29:50 +0000 Subject: [PATCH] Add support for recipe descriptions --- .../MultiWikiServer Administration.tid | 35 ++++++++++--------- .../multiwikiserver/admin-ui/Styles.tid | 19 ++++++---- .../multiwikiserver/modules/init.js | 8 ++--- .../modules/route-put-recipe-tiddler.js | 12 ++++--- .../modules/sql-tiddler-database.js | 22 ++++++++---- .../modules/sql-tiddler-store.js | 28 +++++++++------ 6 files changed, 76 insertions(+), 48 deletions(-) diff --git a/plugins/tiddlywiki/multiwikiserver/admin-ui/MultiWikiServer Administration.tid b/plugins/tiddlywiki/multiwikiserver/admin-ui/MultiWikiServer Administration.tid index 9352ffa74..46a603907 100644 --- a/plugins/tiddlywiki/multiwikiserver/admin-ui/MultiWikiServer Administration.tid +++ b/plugins/tiddlywiki/multiwikiserver/admin-ui/MultiWikiServer Administration.tid @@ -50,10 +50,12 @@ title: MultiWikiServer Administration \procedure bagPill(element-tag:"span",is-topmost:"no") \whitespace trim <$genesis $type=<> class={{{ mws-bag-pill [match[yes]then[mws-bag-pill-topmost]] +[join[ ]] }}}> - <$image source=`/wiki/${ [{!!bag-name}encodeuricomponent[]] }$/bags/${ [{!!bag-name}encodeuricomponent[]] }$/tiddlers/%24%3A%2Ffavicon.ico` class="mws-favicon-small"/> - - <$text text={{!!bag-name}}/> - + + <$image source=`/wiki/${ [{!!bag-name}encodeuricomponent[]] }$/bags/${ [{!!bag-name}encodeuricomponent[]] }$/tiddlers/%24%3A%2Ffavicon.ico` class="mws-favicon-small"/> + + <$text text={{!!bag-name}}/> + + \end @@ -62,24 +64,25 @@ title: MultiWikiServer Administration \whitespace trim
- + <$image source=`/wiki/${ [{!!recipe-name}encodeuricomponent[]] }$/recipes/${ [{!!recipe-name}encodeuricomponent[]] }$/tiddlers/%24%3A%2Ffavicon.ico` class="mws-favicon"/>
<$text text={{!!recipe-name}}/>
-
    - <$list filter="[list]" counter="counter"> - <$transclude $variable="bagPill" is-topmost={{{ [match[yes]] }}} element-tag="li"/> - -
+ <%if [list] %> +
    + <$list filter="[list]" counter="counter"> + <$transclude $variable="bagPill" is-topmost={{{ [match[yes]] }}} element-tag="li"/> + +
+ <%else%> + (no bags defined) + <%endif%>
- DDDDDD -
-
- Additional Details + <$transclude $tiddler=<> $mode="inline"/>
@@ -91,7 +94,7 @@ title: MultiWikiServer Administration These are the wikis available on this server. Click on a wiki to visit it in a new browser tab.

    - <$list filter="[prefix[$:/state/multiwikiserver/recipes/]]"> + <$list filter="[prefix[_multiwikiserver/recipes/]]">
  • <>
  • @@ -105,7 +108,7 @@ title: MultiWikiServer Administration

    Bags

      - <$list filter="[prefix[$:/state/multiwikiserver/bags/]]"> + <$list filter="[prefix[_multiwikiserver/bags/]]">
    • <>
    • diff --git a/plugins/tiddlywiki/multiwikiserver/admin-ui/Styles.tid b/plugins/tiddlywiki/multiwikiserver/admin-ui/Styles.tid index 11a5bab09..0a9013b84 100644 --- a/plugins/tiddlywiki/multiwikiserver/admin-ui/Styles.tid +++ b/plugins/tiddlywiki/multiwikiserver/admin-ui/Styles.tid @@ -53,10 +53,6 @@ Styles specific to the full screen layout } -.mws-wiki-card-extra { - -} - .mws-vertical-list { list-style: none; padding: 0; @@ -79,6 +75,11 @@ Styles specific to the full screen layout padding: 0 0.25em; } +.mws-bag-pill:hover { + background: <>; + foreground: <>; +} + .mws-bag-pill-topmost { background: <>; } @@ -87,17 +88,23 @@ Styles specific to the full screen layout margin-left: 0.5em; } +.mws-bag-pill-link { + text-decoration: none; + color: currentcolor; +} + +.mws-favicon.tc-image-loading, .mws-favicon-small.tc-image-loading, .mws-favicon.tc-image-error, .mws-favicon-small.tc-image-error { visibility: hidden; } .mws-favicon { - max-width: 4em; + width: 4em; max-height: 4em; } .mws-favicon-small { vertical-align: text-bottom; - max-width: 1em; + width: 1em; max-height: 1em; } \ No newline at end of file diff --git a/plugins/tiddlywiki/multiwikiserver/modules/init.js b/plugins/tiddlywiki/multiwikiserver/modules/init.js index 4e747336f..75a520a3c 100644 --- a/plugins/tiddlywiki/multiwikiserver/modules/init.js +++ b/plugins/tiddlywiki/multiwikiserver/modules/init.js @@ -45,10 +45,10 @@ exports.startup = function() { $tw.sqlTiddlerStore.createBag("bag-alpha"); $tw.sqlTiddlerStore.createBag("bag-beta"); $tw.sqlTiddlerStore.createBag("bag-gamma"); - $tw.sqlTiddlerStore.createRecipe("recipe-rho",["bag-alpha","bag-beta"]); - $tw.sqlTiddlerStore.createRecipe("recipe-sigma",["bag-alpha","bag-gamma"]); - $tw.sqlTiddlerStore.createRecipe("recipe-tau",["bag-alpha"]); - $tw.sqlTiddlerStore.createRecipe("recipe-upsilon",["bag-alpha","bag-gamma","bag-beta"]); + $tw.sqlTiddlerStore.createRecipe("recipe-rho",["bag-alpha","bag-beta"],"First wiki"); + $tw.sqlTiddlerStore.createRecipe("recipe-sigma",["bag-alpha","bag-gamma"],"Second Wiki"); + $tw.sqlTiddlerStore.createRecipe("recipe-tau",["bag-alpha"],"Third Wiki"); + $tw.sqlTiddlerStore.createRecipe("recipe-upsilon",["bag-alpha","bag-gamma","bag-beta"],"Fourth Wiki"); // Save tiddlers $tw.sqlTiddlerStore.saveBagTiddler({title: "$:/SiteTitle",text: "Bag Alpha"},"bag-alpha"); $tw.sqlTiddlerStore.saveBagTiddler({title: "$:/SiteTitle",text: "Bag Beta"},"bag-beta"); diff --git a/plugins/tiddlywiki/multiwikiserver/modules/route-put-recipe-tiddler.js b/plugins/tiddlywiki/multiwikiserver/modules/route-put-recipe-tiddler.js index c5ca2dd52..1e04d3094 100644 --- a/plugins/tiddlywiki/multiwikiserver/modules/route-put-recipe-tiddler.js +++ b/plugins/tiddlywiki/multiwikiserver/modules/route-put-recipe-tiddler.js @@ -40,10 +40,14 @@ exports.handler = function(request,response,state) { // Require the recipe names to match if(recipe_name === recipe_name_2) { var result = $tw.sqlTiddlerStore.saveRecipeTiddler(fields,recipe_name); - response.writeHead(204, "OK",{ - Etag: "\"" + result.bag_name + "/" + encodeURIComponent(title) + "/" + result.tiddler_id + ":\"", - "Content-Type": "text/plain" - }); + if(result) { + response.writeHead(204, "OK",{ + Etag: "\"" + result.bag_name + "/" + encodeURIComponent(title) + "/" + result.tiddler_id + ":\"", + "Content-Type": "text/plain" + }); + } else { + response.writeHead(400); + } response.end(); return; } diff --git a/plugins/tiddlywiki/multiwikiserver/modules/sql-tiddler-database.js b/plugins/tiddlywiki/multiwikiserver/modules/sql-tiddler-database.js index 2a658cced..c6dca3aac 100644 --- a/plugins/tiddlywiki/multiwikiserver/modules/sql-tiddler-database.js +++ b/plugins/tiddlywiki/multiwikiserver/modules/sql-tiddler-database.js @@ -64,7 +64,8 @@ SqlTiddlerDatabase.prototype.createTables = function() { -- Recipes have names... CREATE TABLE IF NOT EXISTS recipes ( recipe_id INTEGER PRIMARY KEY AUTOINCREMENT, - recipe_name TEXT UNIQUE + recipe_name TEXT UNIQUE, + description TEXT ) `,` -- ...and recipes also have an ordered list of bags @@ -139,23 +140,27 @@ SqlTiddlerDatabase.prototype.createBag = function(bagname) { }); }; +/* +Returns array of {recipe_name:,description:} +*/ SqlTiddlerDatabase.prototype.listRecipes = function() { const rows = this.runStatementGetAll(` - SELECT recipe_name + SELECT recipe_name, description FROM recipes ORDER BY recipe_name `); return rows; }; -SqlTiddlerDatabase.prototype.createRecipe = function(recipename,bagnames) { +SqlTiddlerDatabase.prototype.createRecipe = function(recipename,bagnames,description) { // Run the queries this.runStatement(` -- Create the entry in the recipes table if required - INSERT OR IGNORE INTO recipes (recipe_name) - VALUES ($recipe_name) + INSERT OR IGNORE INTO recipes (recipe_name, description) + VALUES ($recipe_name, $description) `,{ - recipe_name: recipename + recipe_name: recipename, + description: description }); this.runStatement(` -- Delete existing recipe_bags entries for this recipe @@ -219,7 +224,7 @@ SqlTiddlerDatabase.prototype.saveBagTiddler = function(tiddlerFields,bagname) { }; /* -Returns {tiddler_id:,bag_name:} +Returns {tiddler_id:,bag_name:} or null if the recipe is empty */ SqlTiddlerDatabase.prototype.saveRecipeTiddler = function(tiddlerFields,recipename) { // Find the topmost bag in the recipe @@ -241,6 +246,9 @@ SqlTiddlerDatabase.prototype.saveRecipeTiddler = function(tiddlerFields,recipena `,{ recipe_name: recipename }); + if(!row) { + return null; + } // Save the tiddler to the topmost bag var info = this.saveBagTiddler(tiddlerFields,row.bag_name); return { diff --git a/plugins/tiddlywiki/multiwikiserver/modules/sql-tiddler-store.js b/plugins/tiddlywiki/multiwikiserver/modules/sql-tiddler-store.js index 22c207dc6..f24eb5cea 100644 --- a/plugins/tiddlywiki/multiwikiserver/modules/sql-tiddler-store.js +++ b/plugins/tiddlywiki/multiwikiserver/modules/sql-tiddler-store.js @@ -23,7 +23,7 @@ adminWiki - reference to $tw.Wiki object into which entity state tiddlers should function SqlTiddlerStore(options) { options = options || {}; this.adminWiki = options.adminWiki || $tw.wiki; - this.entityStateTiddlerPrefix = "$:/state/multiwikiserver/"; + this.entityStateTiddlerPrefix = "_multiwikiserver/"; // Create the database this.databasePath = options.databasePath || ":memory:"; var SqlTiddlerDatabase = require("$:/plugins/tiddlywiki/multiwikiserver/sql-tiddler-database.js").SqlTiddlerDatabase; @@ -57,7 +57,7 @@ SqlTiddlerStore.prototype.updateAdminWiki = function() { this.saveEntityStateTiddler({ title: "recipes/" + recipeInfo.recipe_name, "recipe-name": recipeInfo.recipe_name, - text: "", + text: recipeInfo.description, list: $tw.utils.stringifyList(this.getRecipeBags(recipeInfo.recipe_name).map(bag_name => { return this.entityStateTiddlerPrefix + "bags/" + bag_name; })) @@ -110,12 +110,14 @@ SqlTiddlerStore.prototype.listRecipes = function() { return this.sqlTiddlerDatabase.listRecipes(); }; -SqlTiddlerStore.prototype.createRecipe = function(recipename,bagnames) { - this.sqlTiddlerDatabase.createRecipe(recipename,bagnames); +SqlTiddlerStore.prototype.createRecipe = function(recipename,bagnames,description) { + bagnames = bagnames || []; + description = description || ""; + this.sqlTiddlerDatabase.createRecipe(recipename,bagnames,description); this.saveEntityStateTiddler({ title: "recipes/" + recipename, "recipe-name": recipename, - text: "", + text: description, list: $tw.utils.stringifyList(bagnames.map(bag_name => { return this.entityStateTiddlerPrefix + "bags/" + bag_name; })) @@ -162,12 +164,16 @@ Returns {bag_name:, tiddler: {fields}, tiddler_id:} */ SqlTiddlerStore.prototype.getRecipeTiddler = function(title,recipename) { var tiddlerInfo = this.sqlTiddlerDatabase.getRecipeTiddler(title,recipename); - return Object.assign( - {}, - tiddlerInfo, - { - tiddler: this.processOutgoingTiddler(tiddlerInfo.tiddler,tiddlerInfo.tiddler_id,tiddlerInfo.bag_name,recipename) - }); + if(tiddlerInfo) { + return Object.assign( + {}, + tiddlerInfo, + { + tiddler: this.processOutgoingTiddler(tiddlerInfo.tiddler,tiddlerInfo.tiddler_id,tiddlerInfo.bag_name,recipename) + }); + } else { + return null; + } }; /*