Give each sync connection a page to pair its items with records by hand, and show each pairing on its record (#327) #1174
No reviewers
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo!1174
Loading…
Reference in a new issue
No description provided.
Delete branch "327-pairing-page"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What a sync plugin could not pair by UID had nowhere to be paired: a card
could not be said to be that company, an event the second interview.
SyncLink appeared only in the Django admin, no record page showed a pairing,
and a plugin may add no page of its own (#228).
key) lists the items a person may pair, or the one item a (collection,
uid) key names. fill_record(connection, config, item, kind, into=None)
makes or fills a record through the surface's services, as the plugin.
RemoteItem and RECORD_KINDS (contact, company, department, you,
interview, reminder, application) are on postulo.plugins.api. A plugin
without remote_items gets no page.
removed on the other side, read from SyncLink alone. Search and Show
unpaired ask the plugin live, under a new per-account allowance
(POSTULO_CONNECTION_PAIRING_RATE, 120/h) and a 15-second deadline, and
draw a captioned table in a live region. An item's page offers the
person's own records of a kind: Pair, Fill and pair, or Fill once without
pairing. Unpair keeps both sides (#326); for a twin gone, Pair again, or
let the plugin make a new one. The plugin is asked outside any
transaction through the helper Test uses.
again and the link's address comes from that answer, never the form.
Written with no etag, so the next run makes the first comparison. Only
the owner's own connections, records and links are reached; everything
else is 404. Labels from the server are escaped text, never links.
synced ..." or "Removed on the other side", with Unpair and Pair with an
item..., on the company page (and its departments), the application
page, the contact, interview and reminder edit pages and Your details,
from SyncLink only.
create_by_hand, doing what the page does.
No migration and no archive change. Tests: tests/test_pairing.py (pair,
unpair, pair again and create each seen by a fake plugin's next run), the
isolation sweep, page coverage and the browser walk, the plugin surface,
and an accessibility test of the page after Show unpaired.
Closes #327
Notes for review
Closes #327.SyncPlugin:remote_items(config, search="", kind="", key=None) -> list[RemoteItem];keyis(collection, uid).fill_record(connection, config, item, kind, into=None)returns the record; it writes through the surface's services with the plugin asvia/actor.remote_itemsgets no page (404, no button on the list) and no Pair with an item… link.RemoteItem(collection, uid, label, collection_label, href, detail, kinds, slot;.key) andRECORD_KINDS(contact, company, department, you, interview, reminder, application).connections/<pk>/pairing/:pairing(GET): paired and gone rows fromSyncLinkalone; Search / Show unpaired asks the plugin and swaps the results into anaria-liveregion (htmxhx-select, a plain GET without scripts). A?for=kind-pknames the record being paired, from a record's line.pairing_item(GET): one item, asked again by key, with a table of the person's own records of a kind (radios) and Pair / Fill … and pair / Fill once, without pairing.pairing_apply,pairing_unpair,pairing_renew(POST).remote_href,collection,uidandslotcome from that answer; the form carries only the key. Written with no etag, no local hash, no last-synced time.unpaired_at), as #326.owner=user), not a group's or a share's; a shared record's page shows no line.youis theUser; it can be paired, never filled (nothing on the surface writes a person).intoitself when given; otherwise refused and not paired. Fill and pair is refused up front if another record holds the item.http.until). At most 100 items drawn, 50 records offered._too_oftengainedpairing=True, spendingPOSTULO_CONNECTION_PAIRING_RATE(120/h, new, in settings and.env.example) under the scopeconnection-pairing, so Test is not spent by pairing.linkredirect with a message (so the isolation sweep's owner check reaches the view); a link not the person's on that connection is 404.cotton/pairing_line.html, fed by a new tag libraryplugins/templatetags/pairings.py(pairings_of). It is on the company page (plus each department,quiet), the application page, the contact, interview and reminder edit pages, and Your details.pair_by_hand,unpair_by_hand,create_by_handinpostulo.plugins.testing, tested intests/test_pairing.py.furnishednow registers a pairable stand-in plugin (and is a yield fixture) so the walk visits the page, the page after Show unpaired, and an item page; plus an axe test of the page after Show unpaired.scratchpad/batch/wiki-327.md(Writing-a-plugin, Configuration, Tracking-applications). Until it is applied,tests/test_wiki_surface.pyfails onRemoteItem,RECORD_KINDSandPOSTULO_CONNECTION_PAIRING_RATE.🤖 Generated with Claude Code
aff43c6903e1949b4a3ce1949b4a3c4fc8db0a73