fix pubilsh job posting
This commit is contained in:
@@ -967,9 +967,14 @@ const positionsNeedingAttention = (f) => {
|
|||||||
*
|
*
|
||||||
* A draft is a real record with real values on it and no way for anyone to
|
* A draft is a real record with real values on it and no way for anyone to
|
||||||
* apply to it, which makes it the one thing on this page that is genuinely
|
* apply to it, which makes it the one thing on this page that is genuinely
|
||||||
* unfinished. Each one is offered with the control that finishes it: the same
|
* unfinished. Each one is named, with what it already holds.
|
||||||
* authoring form, told which draft it is continuing, with everything already
|
*
|
||||||
* entered still in place.
|
* It reports, it does not reopen. This used to attach "Continue to save" to
|
||||||
|
* every draft, routing to the authoring form — so a question asked in the panel
|
||||||
|
* could end with the reader back inside Create Position, and a position that
|
||||||
|
* had been saved minutes earlier was presented as still needing saving. The
|
||||||
|
* draft is on the Positions list marked Draft and its own card opens the form;
|
||||||
|
* the panel says where it is rather than taking anyone there.
|
||||||
*
|
*
|
||||||
* Read from `postings` by status — no list of drafts is kept anywhere, and a
|
* Read from `postings` by status — no list of drafts is kept anywhere, and a
|
||||||
* position stops appearing here the moment it is published.
|
* position stops appearing here the moment it is published.
|
||||||
@@ -991,9 +996,8 @@ const positionDrafts = (f) => {
|
|||||||
p.location,
|
p.location,
|
||||||
'Not published yet, so nobody can apply and no screening runs.',
|
'Not published yet, so nobody can apply and no screening runs.',
|
||||||
].filter(Boolean).join(' · '),
|
].filter(Boolean).join(' · '),
|
||||||
action: { label: 'Continue to save', to: `/admin/positions/new?draft=${encodeURIComponent(p.id)}` },
|
|
||||||
}))),
|
}))),
|
||||||
note('Continuing reopens the same form with everything already entered — the vetting weights included. Publishing it there is what makes it an active position.')
|
note('Each one is on the Positions list marked Draft. Opening its card reopens the form with everything already entered — the vetting weights included — and publishing it there is what makes it an active position.')
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -110,6 +110,50 @@ async function streamDocument({ document, signal, onFrame, onDone }) {
|
|||||||
else if (latest.length) onDone(latest);
|
else if (latest.length) onDone(latest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Create Position form, as an address.
|
||||||
|
*
|
||||||
|
* Named once because two things have to agree about it: nothing stored may
|
||||||
|
* offer a way back into the authoring form after a position has been saved.
|
||||||
|
*/
|
||||||
|
const AUTHORING_ROUTE = '/admin/positions/new';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A stored thread, with any completed-then-reopen action stripped out.
|
||||||
|
*
|
||||||
|
* A reply is persisted as the blocks it rendered, so a thread written before
|
||||||
|
* this was fixed still carries the old "Continue to save" — a live control
|
||||||
|
* routing back into Create Position, offered on a position that was saved long
|
||||||
|
* ago. Removing it in code was not enough; the ones already written down had to
|
||||||
|
* stop working too.
|
||||||
|
*
|
||||||
|
* Deliberately narrow: only actions pointing at the authoring form are dropped,
|
||||||
|
* and only from stored threads. Every other block, chip and link is left as it
|
||||||
|
* was written, so a thread reads exactly as it did apart from the one control
|
||||||
|
* that should never have been there.
|
||||||
|
*/
|
||||||
|
function withoutAuthoringActions(messages = []) {
|
||||||
|
const leadsToForm = (target) => String(target || '').includes(AUTHORING_ROUTE);
|
||||||
|
|
||||||
|
return messages.map((message) => {
|
||||||
|
if (message.role !== 'assistant') return message;
|
||||||
|
|
||||||
|
const followUp = message.followUp?.filter((chip) => !leadsToForm(chip.route));
|
||||||
|
const blocks = message.blocks?.map((block) => (
|
||||||
|
block?.type === 'insights'
|
||||||
|
? {
|
||||||
|
...block,
|
||||||
|
items: block.items.map(({ action, ...item }) => (
|
||||||
|
leadsToForm(action?.to) ? item : { ...item, ...(action ? { action } : null) }
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
: block
|
||||||
|
));
|
||||||
|
|
||||||
|
return { ...message, ...(followUp ? { followUp } : null), ...(blocks ? { blocks } : null) };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Conversation state for one page context.
|
* Conversation state for one page context.
|
||||||
*
|
*
|
||||||
@@ -174,7 +218,7 @@ export function useConversation({
|
|||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
try {
|
try {
|
||||||
const raw = sessionStorage.getItem(storageKey);
|
const raw = sessionStorage.getItem(storageKey);
|
||||||
setMessages(raw ? JSON.parse(raw) : []);
|
setMessages(raw ? withoutAuthoringActions(JSON.parse(raw)) : []);
|
||||||
} catch {
|
} catch {
|
||||||
setMessages([]);
|
setMessages([]);
|
||||||
}
|
}
|
||||||
@@ -491,12 +535,17 @@ export function useConversation({
|
|||||||
setError(null);
|
setError(null);
|
||||||
setFlow(null);
|
setFlow(null);
|
||||||
|
|
||||||
messagesRef.current = record.messages;
|
/* Same rule as loading a stored thread: a conversation kept in History was
|
||||||
setMessages(record.messages);
|
written before this was fixed too, and reopening it must not hand back a
|
||||||
|
route into the authoring form. */
|
||||||
|
const messages = withoutAuthoringActions(record.messages);
|
||||||
|
|
||||||
|
messagesRef.current = messages;
|
||||||
|
setMessages(messages);
|
||||||
conversationRef.current = record.id;
|
conversationRef.current = record.id;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
sessionStorage.setItem(storageKey, JSON.stringify(record.messages));
|
sessionStorage.setItem(storageKey, JSON.stringify(messages));
|
||||||
sessionStorage.setItem(idKey, record.id);
|
sessionStorage.setItem(idKey, record.id);
|
||||||
} catch {
|
} catch {
|
||||||
// The reopened thread stays in memory only.
|
// The reopened thread stays in memory only.
|
||||||
|
|||||||
@@ -462,7 +462,9 @@ export function positionCreatedReply(position) {
|
|||||||
const isDraft = position.status === 'draft';
|
const isDraft = position.status === 'draft';
|
||||||
|
|
||||||
return doc(
|
return doc(
|
||||||
text(isDraft ? 'Saved as a draft.' : 'Position created successfully.'),
|
/* Draft and published are different outcomes, so they are named
|
||||||
|
differently: one was saved, the other went live. */
|
||||||
|
text(isDraft ? 'Saved as a draft.' : 'Position published successfully.'),
|
||||||
list([
|
list([
|
||||||
position.company,
|
position.company,
|
||||||
position.title,
|
position.title,
|
||||||
@@ -493,9 +495,17 @@ export function positionFailedReply() {
|
|||||||
* no navigation, and the same answer as asking it by hand.
|
* no navigation, and the same answer as asking it by hand.
|
||||||
*/
|
*/
|
||||||
export const createdFollowUp = (position) => (position.status === 'draft'
|
export const createdFollowUp = (position) => (position.status === 'draft'
|
||||||
/* A draft is unfinished, so the way on is the form that finishes it — the
|
/**
|
||||||
same route the Positions card's Continue uses. */
|
* A saved draft offers no action, and that is the fix.
|
||||||
? [{ label: 'Continue to save', route: `/admin/positions/new?draft=${encodeURIComponent(position.id)}` }]
|
*
|
||||||
|
* This used to offer "Continue to save", routing back to the Create Position
|
||||||
|
* form. It made the completed state look unfinished: the reader had just been
|
||||||
|
* told the position was saved, and was immediately asked to save it again —
|
||||||
|
* by a button that put them back in the form they had just left. The write
|
||||||
|
* has happened, the record exists with `status: draft`, and the way to finish
|
||||||
|
* a draft later is its own card on the Positions list.
|
||||||
|
*/
|
||||||
|
? []
|
||||||
: [
|
: [
|
||||||
{ label: 'View position', route: `/admin/positions/${position.id}` },
|
{ label: 'View position', route: `/admin/positions/${position.id}` },
|
||||||
{ label: 'Match candidates', prompt: `Who matches ${position.title}?` },
|
{ label: 'Match candidates', prompt: `Who matches ${position.title}?` },
|
||||||
|
|||||||
Reference in New Issue
Block a user