Renaming a tiddler break links, the user should be warned at least #196

Open
mildred opened this Issue Nov 4, 2013 · 39 comments

Projects

None yet

8 participants

@mildred
mildred commented Nov 4, 2013

Renaming a tiddler break links. However, no hint about that is shown to the user when the title is modified.

Possible solutions in increasing order of complexity:

  • explain what happens if the tiddler name is modified (links will be broken), discourage renaming tiddlers.
  • display the list of backlinks that will be broken
  • modify the linking tiddlers so the links are not brokens, take care of sub-tiddlers as well if there is any.
@Jermolene
Owner

Thanks @mildred.

There will be full search and replace in due course. The plan would be to automatically offer to update links when renaming a tiddler.

@tobibeer
Contributor
tobibeer commented Nov 7, 2013

Maybe this approach is of interest / a good solution for tw5?

http://renametiddlers.tiddlyspace.com

@Jermolene
Owner

Thanks @tobibeer I hadn't considered the idea of the renamed field for storing the previous title of a tiddler.

@pmario
Contributor
pmario commented Nov 8, 2013

hmmm,
-1 for storing outdated content. use a VCS.

My first reaction is: "I wouldn't want to cary outdated information with any tiddler". Keep the history is part of a version control system.

eg: When do you remove the "renamed" field. -> To check this you'd need a "keep renamed" date field :/

@tobibeer
Contributor
tobibeer commented Nov 8, 2013

For me, TW is first and foremost a straight forward, all-in-one system, no full-blown serverside.

If I needed a serverside wiki with version control, I might just be looking for something else. Sure, in TiddlyWeb or a node.js based host, there might be a tiddler history which might at some point even be exposed / utilised / accessed via appropriate APIs which would then be prioritized over a simplisitic implementation such as a renamed field.

But the point is, in a simple, single-file wiki, I need a straight forward way to keep track of what has changed without forcing the user to walk through a full-blown (non-existing) Renaming Wizard every time a tiddler title is being changed.

Thus, the renamed field is surely never removed, unless I manually chose to do so. It is updated when the title is changed — and that is quite a straight forward process, if you ask me. I don't see why I would need a "keep renamed" date (?) field when I am working in an encapsulated wiki as a single user.

@pmario
Contributor
pmario commented Nov 8, 2013

I'm in favor of a "Renaming Wizard", that creates a clean document state, with no outdated artefacts.

IMO most of the time a "renamed" field will contain "typo fixes" and "New Tiddler" which isn't valuable data for me.

If I download a 3rd party TW, that contains "renamed" fields, these fields don't have any value for me. They are just there for the creator, because this info may have value for her/him, for a short period of time.

What about tiddlers, that are copied from one TW to an other? ... In the new context it is just confusing.

@tobibeer
Contributor
tobibeer commented Nov 8, 2013

I'm in favor of a "Renaming Wizard", that creates a clean document state, with no outdated artefacts.

Sure, a Renaming Wizard would be a desirable thing in terms of data quality / maintenance, but not necessarily in terms of simple, distraction-free editing. I can already hear people expressing ideas of how it could work so that you don't have to manually do that all the time you want to change a tiddler title.

IMO most of the time a "renamed" field will contain "typo fixes" and "New Tiddler" which isn't valuable data for me.

http://renametiddlers.tiddlyspace.com does ignore "New Tiddler". As for typos, I don't see a problem in keeping them, you might just as well have typos in tiddlyLinks.

If I download a 3rd party TW, that contains "renamed" fields, these fields don't have any value for me. They are just there for the creator, because this info may have value for her/him, for a short period of time.

Nope, not if the same wiki still contains links to the outdated titles, which are still working since they are pointing to the right, renamed tiddler.

What about tiddlers, that are copied from one TW to an other? ... In the new context it is just confusing.

Seems irrelevant, because you will have to manually create new links to that tiddler in your wiki anyways.

In fact, there actually are use-cases where renamed tiddlerish components would keep on working simply because the history is being kept rather than discarded. It would open up abilities to rename distributed contents without breaking things.

@Spangenhelm
Contributor

What about using a uniqid field ?

Exemple:

Tiddler's title: Test1
Uniqid tiddler's hidden/system field: 12345678

  1. Link to: Test1 works everywhere because it is modified automatically by the system to point to the uniqid and use the title associated. (here Test1)
  2. Changing tiddler's title for Test2
  3. Link is still good because the uniqid didnt change and is automatically renamed with the new tiddler's title.
@Spangenhelm
Contributor

Up!

@felixhayashi
Contributor

I already brought this topic up for discussion in the forum. @Jermolene extensively answered some of my questions there:

https://groups.google.com/d/msg/tiddlywiki/Y1V7oyBLpSs/9ZZFF0IGG8MJ

Nonetheless, I use ids in my tiddlywikis and refer to them via the mechanism described here :
https://groups.google.com/d/msg/tiddlywiki/Y1V7oyBLpSs/hgn4ZAlTC5cJ
which then looks like this {{ 24235434453 | id }}

Hope this helps.

edit: and I agree with @pmario that keeping obsolete data is not the key.

@Spangenhelm
Contributor

We might just use the timestamp which is already created with the new tiddler anyway and surely unique ! And this solution would not impact shadows or system tiddlers since they do not use timestamp and do not allow renaming anyway.

As a bonus there is nothing "old/deprecated" to keep since that:

  1. we already have it, it is automatically created with the tiddler
  2. it will never change, even after upgrade
  3. it will always be needed (to sort tiddlers by date for example) so no chance to have it deleted
  4. no name versions to track
  5. no need for complicated renaming wizard !

If i don't miss anything this would solve the whole problem at once ! (Yes i'm pretty proud ;-)

@felixhayashi
Contributor

@Spangenhelm true :) . but consider that timestamps are only "unique" if tiddlers are manually created. Automatic creation of two or more tiddlers might yield duplicates.

@pmario
Contributor
pmario commented Nov 2, 2014

Not only automatically created tiddlers will have duplicate timestamps. If I manually create new tiddlers (nodejs version) I use the same created timestamp, because of lazyness :) Export / Import may duplicate them too. So using timestamps as UUIDs will not really solve the problem.

@Spangenhelm
Contributor

@pmario

If I manually create new tiddlers (nodejs version) I use the same created timestamp, because of lazyness :)

So you would do the same with uniqid unless it is automatically handled ;)

Basically we need the same function in any case:

  1. Generate a uniqid
  2. Make sure it is really unique by checking against all other existing ids
  3. If not generate a new one until it is

Two difference between this and timestamps:

  1. We already have timestamps
  2. In case of automatic creation of tiddler -> make sure timestamp are unique by adding one second between each (you can create 59 tiddlers with maximum one minute between the first and the last, not so bad i think)
@pmario
Contributor
pmario commented Nov 3, 2014

TL;DR
I'd vote against a UUID that is only based on a timestamp, because it's not unique in any sense.

Unique for me is universal unique, so you can export / import any tiddler in the universe, without having the same ID. Creating it is relatively simple.


@Spangenhelm

So you would do the same with uniqid unless it is automatically handled ;)

no. An UUID is designed to be unique, a timestamp is not. So I can safely duplicate a timestamp and I will. IMO adding a second to a timestamp, just because, this timestamp already exists is a bug

I'd delete a UUID, if I clone a tiddler on the file system. So the core or a plugin, would need to check if an UUID is there and if not create one.

Creating a UUID is about 20 lines of js code. If you want to use RFC4122, version 4 ID you get a string like this: 0F60A953-C615-46C7-9001-3D7CB79218EB.

No matter how fast all TW users click new tiddler button, they'll not manage to create the same string again in a hundred++ years. So there is no need to check, if it already exists. It's unique by design.

Misusing the timestamp will easily create the same timestamp, if you have enough users creating them. Even if you go down to the millisecond.


I did some experiments with human readable UUIDs some time ago. See: TiddlyWeb_ID_generator

It uses the timestamp, the URL address and a hash function to create uniqueness. ... Just some experiments.

At the moment I use this function to create UUIDs http://chat-plugins.tiddlyspace.com/#UUIDPlugin
If you go to the page, enter the developer console (F12) and type: Math.uuid() and you'll get a RFC4122 UUID which has 5.3x10^36 possibilities.

If you type: Math.uuid(21) you'll get a string like this: p5KyJzd1LuGsItnnalZf0 which has 4.4x10^37 possibilities. It has slightly more possibilities as RFC4122 (which is considered practically unique). So we are fine.


If you don't trust the browser built in random number generator, we could use the TW built in generator: http://bitwiseshiftleft.github.io/sjcl/doc/symbols/sjcl.prng.html. But imo this is not needed, as we don't use the UUID for cryptography.

@tobibeer
Contributor
tobibeer commented Nov 3, 2014

I'd vote against a UUID that is only based on a timestamp, because it's not unique in any sense.

Unique for me is universal unique, so you can export / import any tiddler in the universe, without having the same ID. Creating it is relatively simple.

+1

therefore...

  1. Make sure it is really unique by checking against all other existing ids

does not apply and...

+1 thinking of IDs in a context beyond the local wiki, even beyond any server-side, meaning: global, www ...that is, if they shall ever become a tiddly-thing

@Spangenhelm
Contributor

@pmario

Creating a UUID is about 20 lines of js code.

Right it is no big deal but what bothers me is the need of creating something instead of using what we already have.

@pmario
Contributor
pmario commented Nov 3, 2014

Right it is no big deal but what bothers me is the need of creating something instead of using what we already have.

Yes but we can't use it, because a timestamp is not designed to be unique. There will be a really big "blowback" if we would misuse it in the core. And as I wrote. If I create a timestamp, I expect it, to be as exact as possible. So If I click a journal button and it shows me something different I'd file a "bug issue"

@edrex
Contributor
edrex commented Jan 14, 2016

@Jermolene, $:/core/modules/widgets/navigator.js handles tm-rename-tiddler events by calling $tw.wiki.renameTiddler which updates tags and other references immediately, but it's not triggered when the title is changed in tiddler edit mode. Is that planned?

I ask because I want to port mGSD's RenameTagsPlugin UX (trigger reference updates on any rename, after prompting user) to gsd5 [1], and if that were in core it would at least give me a pattern to follow.

The major difficulty is getting code to run when a rename happens. I can see a few possibilities:

  • $tw.hooks.addHook("th-saving-tiddler",function(tiddler) {... This is what I tried first, but the old title isn't available here.
  • Replace $tw.Wiki.addTiddler with a wrapped version that detects renames and fires an event, I guess via a wikimethod module.
  • Do something at the widget level with the title field on the edit form. I'm guessing this is more idiomatic TW5, although I'm not sure (and I don't know how to go about it).

IDK TW5 at all, just fumbling around in the dark here. Any advice greatly appreciated. Generally it seems like there should be more tiddler lifecycle hooks, but probably I'm missing something.

[1] gsd5 references aren't tags like mGSD's but regular fields, so $tw.wiki.renameTiddlers wouldn't work verbatim, but it would make a fine template.

cc @roma0104 @simonbaird

@roma0104
Contributor

Thanks for the feedback both here and on GSD5.
This is an issue that I have appear from time to time. In fact just yesterday I had this issue with a project.

I haven't delved deep to work on this issue but my initial thought is how I can capture the title of the Project prior to the hook, th-saving-tiddler, being called. It appears that the draft.of field is removed prior to the hook being called. Not certain of the ramifications of passing these fields to any hooked plugins, but then we could have cleanup mechanism that does a sanity check before saving it to the store.

@edrex edrex added a commit to edrex/TiddlyWiki5 that referenced this issue Jan 14, 2016
@edrex edrex navigator: update tag and list references on rename, and introduce th…
…-renaming-tiddler\

\
Addresses issue #196
3d8b589
@edrex
Contributor
edrex commented Jan 16, 2016

I'd like to propose the following to address dangling tag and list references when renaming a tiddler. It's the spec for #2223. Please provide feedback.

When a user modifies the title of an existing tiddler on the edit form, after checking for rename conflict and if so confirming overwrite,

  • Fire a hook th-renaming-tiddler, with the old name and the new name
  • Search the store for any tiddlers with tags or lists referencing the old name for the current tiddler, and update them to reference the new name.

If there are already tag/list references to the new name (whether on not a tiddler was overwritten), they will remain. This is considered "by design", but could be added by a plugin using the hook.

What do people think? I am hoping we can get by without a prompt, but am not taking a hard line on it. Are there real examples where a prompt would be needed?

@felixhayashi
Contributor

Fire a hook th-renaming-tiddler, modeled after th-saving-tiddler, but with from_title set to the old name.

👍 That is nice.

Search the store for any tiddlers with tags or lists referencing the old name for the current tiddler

…and replace them.

Note that if there are existing tag/list references to the new name (regardless of whether an existing tiddler was overwritten), these will remain.

👍 I agree!


In addition: As said in #1614 (comment), and in corrspondence to the OP, I would also highly welcome if not only the tags and list fields were updated but a redirect of links (using a regex-based replacement).*

@edrex
Contributor
edrex commented Jan 16, 2016

Thanks for the feedback, updated above. It hadn't occurred to me that wikitext links need to be updated as well. How about we do that as a follow-on patch, using the hook?

@felixhayashi
Contributor

Hi @edrex

How about we do that as a follow-on patch, using the hook?

that would be nice.

Since retargetReferences is already called when a renaming event occurs (thanks to the new hook ;), I'd highly favor to implement a link rename operation directly in the function retargetReferences, which you introduced in your existing patch. However, I don't have the time to do that at the moment :(

@tobibeer
Contributor

I think it needs to be a modal (wizard), especially so that there is an awareness of all the tidbits that are affected. If a user wants to, they can configure it to do its thIng silently. I would not want that.

@edrex
Contributor
edrex commented Jan 16, 2016

Informing the user of updates outside of the current tiddler seems like a good practice/policy, I agree.

I think a modal is only needed if we can't update references safely, which is why I'm interested in specific cases where automatic updates might be harmful.

If we can update safely, and just want to let the user know changes were made, we can use a notification.

@felixhayashi
Contributor

In my opinion a rename operation should never invoke any modal. At most a notify() but that is already too much.

I think a modal is only needed if we can't update references safely, which is why I'm interested in specific cases where automatic updates might be harmful.

@edrex I would not say a rename can be harmful, even if it only replaces a subset of links, it is better than nothing. The real challenge is to consider the million ways a user might reference / link to a tiddler from another tiddler. No way a rename can detect all of these and even if it could, what should it do about it? I think this is the reason why @Jermolene hasn't picked up this issue yet, because it is not really clear what to rename and how. A simple regex search an replace over tiddler fields doesn't work :(

It is ease to replace title here:

  • <$link to="NAME" …
  • [[NAME]]

but what about <$vars foo="NAME"> <$link to=<<foo>> … </$vars>?

In any case, I hope we manage to workout a solution that at least succeeds in replacing the most significant occurences.

@tobibeer
Contributor

The function of a modal / wizard would NOT be to inform a user as to what has been automagically replaced … but to allow a user to (de)select the ones he or she would (not) want modified.

@pmario
Contributor
pmario commented Jan 17, 2016

-1 for a modal. I'd like a summary tiddler similar to the import tiddler, where I can select content and even have a look.

The import mechanism seems to be good here. I can manually change the content on a per tiddler basis. when I'm done I can impot it.

@tobibeer
Contributor

I'm fine with it not being a modal. That's not the crucial bit. The crucial bit would be that I get to review and decide and an awareness of what gets updated …beforehand.

It better be a modal because we're in the context of an operation being interrupted… it's not some optional import / accidental drag and drop.

@edrex
Contributor
edrex commented Jan 21, 2016

I've put up a smaller pull request #2247 with just the hook, so editions can start experimenting and as a step toward reference updating in core.

Rather than add a new renaming hook as in the previous pull request, this just adds a field tiddler.renaming to th-saving-tiddler in case of a rename.

@tobibeer and @felixhayashi, I appreciate both your perspectives and like that you have strong views about the UX. I think since Tiddlywiki is a multi-purpose environment, different users are inevitably going to want different workflows. The above change can support either so go review it! :)

Back on topic, I'd like to distinguish atomic field updating from body text updating, since I see the first as lower risk (agree?). I think conflating the two is part of why this issue hasn't gotten much traction. I could see wanting automatic updates for atomic fields (or a single all-or-nothing prompt, with a user pref to skip the prompt) along with a wizard for find and replace updates, for example.

@felixhayashi
Contributor

Hi @edrex

sorry for the criticism but I think the hook in #2223 is far more reasonable, especially because it is temporary, doesn't leave traces and is backwards compatible. Many people highly dislike to have logging data in their wiki about what was renamed into what. Also this solution is not backwards compatible since many people may already use a renaming field for other purposes :(

I appreciate your work very much, but I would suggest to stick with a hook, which is great.

Back on topic, I'd like to distinguish atomic field updating from body text updating, since I see the first as lower risk (agree?).

Not quite sure if I understood you correctly, but I even favor a solution where the user doesn't even have to say yes/no but the task is just executed (in an atomic way) and only if the atomic transaction fails (unlikely, why should it fail?) the user is informed.

@edrex
Contributor
edrex commented Jan 21, 2016

@felixhayashi, if the criticism is meant to move the issue forward, I welcome it so don't apologize.

If you'll read the latest patch closely you'll see that it sets a temporary property tiddler.renaming, not a property of tiddler.fields, so it won't conflict with a field named renaming and it won't persist. If you could provide further feedback on the PR issue that would be preferred.

@felixhayashi
Contributor

If you'll read the latest patch closely you'll see that it sets a temporary property tiddler.renaming

Ah, so it gets added to the changedtiddlers refresh object, then its ok of course! reminds me of my own quest: #1550: "ChangedTiddlers: append previous state (tiddler object) to change object" ;)

@Jermolene
Owner

In terms of the UI for handling tiddler renames, I'm not wildly keen on modals. The trouble is that it is hard to refer to the rest of the wiki to check things in order to be able to respond to the modal. I prefer something inline and modeless. For example, we could detect that the title has been changed in edit mode and display a special panel underneath the title that explains what's going on and provides checkboxes for whether to rename references as tags, lists, etc.

@felixhayashi
Contributor

I agree, I also would not want modals, not even reports/summaries of what has happened.

For example, we could detect that the title has been changed in edit mode and display a special panel underneath the title that explains what's going on and provides checkboxes for whether to rename references as tags, lists, etc.

A problem that I see with this method is that when a tiddler has been renamed from "outside". E.g. TiddlyMap can be used to rename tiddlers from within the map. In my opinion, TW should just do its best to rename references everywhere where it is obvious that things should be renamed. I really like how the renameTiddler bulkops behaves.

In addition, it should cleary state in the docs what is happening when a user renames a tiddler.

What would be great if the renameTiddler function could be enhanced by also replacing explicitly stated links and transcludes i.e. [[ … ]] and {{…}}.

@Jermolene
Owner

TiddlyMap can be used to rename tiddlers from within the map

Do multiple tiddlers get renamed in one operation, or just a single tiddler? If the logic I referred to above was easily transcludable, could you just include it in your dialogue?

What would be great if the renameTiddler function could be enhanced by also replacing explicitly stated links and transcludes i.e. [[ … ]] and {{…}}.

There's some significant complexity to that. We could use a regexp but there would be false positives. Perhaps we could use the parse tree to find the links and transclusions, as we do for computing backlinks.

Anyhow, one way to treat these things is as a bulk operation that needs confirmation: that's the idea of the $:/Import tiddler: it's the beginnings of a general purpose way of displaying the differences between a set of incoming tiddlers and the current state of the store, and then accepting or rejecting the changes. My plan is to use the same thing for displaying the results of a find and replace operation.

@edrex
Contributor
edrex commented Feb 6, 2016

I had been thinking about an API for responding to renames that would support all the various UX possibilities.

It would be a hook respondToRename(oldName, newName, targetTiddler), where targetTiddler is the tiddler to be considered for update. Implementers would return a sparse object with just the fields to be changed set. This would allow hook invoker to display a list of changes to the user and then apply them in a separate step. It would also allow an alternate invoker which would apply changes without prompting. I like the idea of keeping the API and the UX decoupled like this, since it increases the flexibility of the system.

@edrex
Contributor
edrex commented Feb 6, 2016

I missed the last part of Jeremy's last comment, and I hadn't had a look at $:Import. It sounds like object diffing, and somewhat related to the idea of an API for proposing automatic updates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment