streams icon indicating copy to clipboard operation
streams copied to clipboard

Make it easier to manipulate tags when editing nodes using the inline editor

Open zhangxiubo opened this issue 3 years ago • 4 comments

Use case: a user might want to add tags (e.g. todo) to a node when editing them in-place; currently the user needs to open the tiddler to manipulate the tags. Perhaps there can be a built-in way to add/remove tags when the inline node editor is active?

zhangxiubo avatar Jul 06 '21 13:07 zhangxiubo

This is something I've had on my mind for a while. The challenge here is figuring out what a good approach for implementing this would be. What makes it a bit complex is that rather than just think about manipulating tags, it is necessary to think about other ways that an end users might want to interact with a node and consider them together, such as manipulating other fields.

Also, the thinking was eventually to allow defining different types of stream nodes, where each type has a separate template. So care has to be taken to not add too much complexity to the template for each node which may make it difficult to implement different node types in the future.

In terms of adding tags, I have considered all of the following at some point:

  • parsing the last line of a node as tags if it starts with a marker like tags:. The problem with such an approach is that it would be one way only, allowing you to add tags.
  • adding custom shortcuts to the context menu for manipulating tags. This is already doable today, especially if you want to toggle or add a small group of tags. Adding a keyboard shortcut that toggles the todo tag is pretty easy. You can also style nodes with the todo tag differently.
    • See FAQ for details on these things.
  • another idea that I think has a lot of potential to offer a user configurable and extensible way to interact with nodes is a popup menu that is triggered by a keyboard shortcut, as shown in this demo.

I welcome thoughts on these proposals or any alternative ideas for how to go about this.

saqimtiaz avatar Jul 10 '21 17:07 saqimtiaz

PS @zhangxiubo there are a couple of people interested in how you set up your backlinks with Streams macros. If you are able to talk them through it, I can also add that information to the documentation. Thank you.

saqimtiaz avatar Jul 10 '21 17:07 saqimtiaz

My personal feeling is that it is a bit cumbersome to use the context menu (exit editing - right click menu - select tag item - edit tag), I would be more inclined to trigger a popup menu (like rename tid) via shortcut keys (very direct). At present, my method is customize TW to allow edit tags directly in the displayed state, so that it is barely convenient to manipulating tags through keyboard.

huruka avatar Aug 07 '21 17:08 huruka

I have a solution that works and that may be satisfactory to some of the users. At the same time, it has some shortcomings and may not be satisfactory for all users. It consists of a few components modified to work together.

  1. defines a trigger pattern (##) that brings up a popup menu listing tags, filtering with the user input (what follows the trigger pattern) (using the edit-comptext plugin) (config extract follows)
      "pattern": "##",
      "filter": "[tags[]!is[system]]",
      "start": "<<tag \"",
      "end": "\">>"
  1. upon selection in the popup menu, the tag is wrapped in a wikitext tag macro, which renders a tag pillbox (visual cue)
  2. the node itself becomes tagged using a modified autotag plugin functionality. Modified plugin code extract follows:
var newTags=[];
	for(var i=0,x=allTags.length;i<x;i++){
		var trimmedtag=allTags[i].replace(/<<tag "|">>/g,"");
		//console.log("trimmed tag="+trimmedtag);
		//console.log("value truefalse="+tagsresolved.includes(trimmedtag));
		if( tiddler.text.indexOf(allTags[i]) !==-1 && !tagsresolved.includes(trimmedtag)  && ( tiddler.tags === undefined || tiddler.tags.indexOf(trimmedtag) ==-1 )){
			newTags.push(trimmedtag);
		}
	}
//console.log(newTags);
cache[title]=true; // save the processed tiddler on the cache to avoid edit loops
taggedTiddlers.push(new $tw.Tiddler(tiddler,{tags: tiddler.tags ? newTags.concat(tiddler.tags) : newTags })); //only concatenate if the source tiddler has tagsS
//console.log("stringyfied: "+$tw.utils.stringifyList(oldtags));
//$tw.wiki.setText(roottiddler,"tags",undefined,$tw.utils.stringifyList(newTags));

This solution supports tag names that include spaces. Visually, it is quite easy to infer the node has been tagged (pillbox); however it could be misleading... read below.

In terms for shortcomings:

  1. it is only useful to add tags; removing the wikitext is not sufficient to remove the tag, but is a necessary first step (otherwise it would be added back automagically when the node is rendered again) (the code could be modified to strip all tags that are not included as tag macros in the text, but I didn't not want that behaviour)
  2. actually removing the node tag is painful in the regular Streams UI; you need to open the node and remove the tag from there

So very much a hack, unsustainable, probably awful for performance, etc... but works well for me. I also tried but did not succeed to have the root tiddler tagged this way instead of the node. I worked around it.

https://user-images.githubusercontent.com/17093421/138003076-0c5967fb-4d27-4550-8a4c-6c078b18445b.mp4

bepuzzled avatar Oct 19 '21 23:10 bepuzzled