revisions complete

This commit is contained in:
2023-10-15 19:14:07 +03:00
parent 1faac31372
commit 8d3e8373c0
16 changed files with 288 additions and 218 deletions
+1 -1
View File
@@ -221,7 +221,7 @@
{:else if activeContentTab === "_graph"}
<Graph {graph} {record}/>
{:else if activeContentTab === "_info"}
<Info bind:record {users} {schema}/>
<Info {record} {graph} {users} {schema}/>
{/if}
</div>
</div>
+140 -96
View File
@@ -2,23 +2,26 @@
import {friendlyDate} from "../../helpers";
import Avatar from "../account/Avatar.svelte";
import {usernameById} from "../account/users";
import {isEqual} from "lodash";
import Status from "./Status.svelte";
import {isEqual, sortBy} from "lodash";
import Icon from "../common/Icon.svelte";
import RevisionCell from "./revisions/RevisionCell.svelte";
import {getContext} from "svelte";
import RevisionEdgeRow from "./revisions/RevisionEdgeRow.svelte";
const channel = getContext("channel");
export let record;
export let graph;
export let users;
export let schema;
let revisionSection;
let rollbackError = "";
$: revisions = [];
$: fieldsWithDiff = [];
$: selectedRevision = null;
$: recordEdges = {};
$: selectedRevisionEdges = {};
$: edgeFieldsDiff = {};
axios
.get(`/records/${record.id}/revisions`)
.get(`${channel.lucentUrl}/records/${record.id}/revisions`)
.then((response) => {
revisions = response.data;
})
@@ -26,19 +29,30 @@
console.log(error);
});
function getEdgesByField(edges) {
return schema.fields
.filter((f) => ["file", "reference"].includes(f.ui))
.reduce((c, f) => {
let fieldEdges = edges
.filter((e) => e.field === f.name)
.map((e) =>
record._children.find((child) => child.id === e.to)
);
function getEdgesByField(fieldsWithDiff, revision) {
c[f.name] = fieldEdges;
return c;
}, {});
edgeFieldsDiff = graph.edges.filter((e) => e.depth === 1).reduce((c, e) => {
if (!c[e.field]) {
c[e.field] = {
record: [],
revision: [],
}
}
c[e.field]["record"].push(e)
return c;
}, {});
edgeFieldsDiff = revision._edges.reduce((c, e) => {
if (!c[e.field]) {
c[e.field] = {
record: [],
revision: [],
}
}
c[e.field]["revision"].push(e)
return c;
}, edgeFieldsDiff);
}
function compare(e, revision) {
@@ -48,6 +62,8 @@
fieldsWithDiff = schema.fields.filter((f) => {
return !isEqual(selectedRevision.data[f.name], record.data[f.name]);
});
getEdgesByField(fieldsWithDiff, revision)
revisionSection.scrollIntoView();
}
function rollback(e) {
@@ -55,7 +71,7 @@
rollbackError = "";
axios
.post(
`/records/${record.id}/rollback/${selectedRevision._sys.version}`
`${channel.lucentUrl}/records/${record.id}/rollback/${selectedRevision._sys.version}`
)
.then((response) => {
window.location.reload();
@@ -82,16 +98,16 @@
<div>
<span class="label text-end text-muted"> created </span>
<Avatar
name={usernameById(users, record._sys.createdBy)}
side={24}
name={usernameById(users, record._sys.createdBy)}
side={24}
/>
{friendlyDate(record._sys.createdAt)}
</div>
<div>
<span class="label text-end text-muted">updated </span>
<Avatar
name={usernameById(users, record._sys.updatedBy)}
side={24}
name={usernameById(users, record._sys.updatedBy)}
side={24}
/>
{friendlyDate(record._sys.updatedAt)}
</div>
@@ -101,42 +117,38 @@
>Rules for this schema
</span>
<small>
Revisions are retained for {schema.revisionRetentionDays} days
<br/>
Each record maintains the last {schema.revisionRetentionNumber}
Each record maintains the last {schema.revisions}
versions
</small>
</div>
</div>
</div>
<div class="lx-card mt-4">
{#if schema.revisionRetentionDays > 0}
{#if schema.revisions > 0}
<div class="header-small mb-3">Revisions</div>
{#each revisions as revision}
{#if revision._sys.version != record._sys.version}
<div
class="row p-2 rounded"
class:active={revision._sys.version ===
class="row p-2 rounded"
class:active={revision._sys.version ===
selectedRevision?._sys.version}
>
<div class="col-2">
<Status status={revision.status}/>
</div>
<div class="col-2">version {revision._sys.version}</div>
<div class="col-5">
<Avatar
name={usernameById(users, revision._sys.updatedBy)}
side={24}
name={usernameById(users, revision._sys.updatedBy)}
side={24}
/>
{friendlyDate(revision._sys.updatedAt)}
</div>
<div class="col-3 text-center">
<button
disabled={revision._sys.version ===
disabled={revision._sys.version ===
selectedRevision?._sys.version}
class="btn btn-sm btn-outline-primary"
on:click={(e) => compare(e, revision)}
class="btn btn-sm btn-outline-primary"
on:click={(e) => compare(e, revision)}
>Compare
</button
>
@@ -150,74 +162,106 @@
</div>
{/if}
</div>
{#if selectedRevision}
<div class="mt-4">
{#if fieldsWithDiff.length > 0}
<p class="text-center fw-bold mb-3 mt-5">
If you choose to rollback to this revision
</p>
<button
on:click={rollback}
class="btn btn-primary mb-5 d-block mx-auto"
>
Rollback to version {selectedRevision._sys.version}
</button>
<div bind:this={revisionSection}>
{#if selectedRevision}
<div class="mt-4">
{#if fieldsWithDiff.length > 0}
<p class="text-center fw-bold mb-3 mt-5">
If you choose to rollback to this revision
</p>
<button
on:click={rollback}
class="btn btn-primary mb-5 d-block mx-auto"
>
Rollback to version {selectedRevision._sys.version}
</button>
{#if rollbackError}
<span class="d-block text-danger mt-3">{rollbackError}</span>
{/if}
<div class="mt-3">
{#each fieldsWithDiff as field}
<!-- <div
class=" lx-card d-flex p-4 mb-4"
style="overflow:hidden"
> -->
<!-- <div class="d-block" style="width:200px;">
{field.label}
</div> -->
<div
class="lx-card row p-4 mb-4 w-100"
style="overflow:hidden"
>
<div class="col-5">
<RevisionCell
edges={recordEdges}
{field}
side={record.data[field.name]}
colorClass="text-danger"
/>
</div>
<div class="col-2">
<div
class="h-100 d-flex align-items-center justify-content-center text-secondary"
>
<span class="me-1">{field.label}</span>
<Icon
icon="angle-right"
width="12"
height="12"
{#if rollbackError}
<span class="d-block text-danger mt-3">{rollbackError}</span>
{/if}
<div class="mt-3">
{#each fieldsWithDiff as field}
<!-- <div
class=" lx-card d-flex p-4 mb-4"
style="overflow:hidden"
> -->
<!-- <div class="d-block" style="width:200px;">
{field.label}
</div> -->
<div
class="lx-card row p-4 mb-4 w-100"
style="overflow:hidden"
>
<div class="col-5">
<RevisionCell
{field}
side={record.data[field.name]}
colorClass="text-danger"
/>
</div>
<div class="col-2">
<div
class="h-100 d-flex align-items-center justify-content-center text-secondary"
>
<span class="me-1">{field.label}</span>
<Icon
icon="angle-right"
width="12"
height="12"
/>
</div>
</div>
<div class="col-5">
<RevisionCell
edges={selectedRevision._edges}
{field}
side={selectedRevision.data[field.name]}
colorClass="text-success"
/>
</div>
</div>
<div class="col-5">
<RevisionCell
edges={selectedRevisionEdges}
{field}
side={selectedRevision.data[field.name]}
colorClass="text-success"
/>
<!-- </div> -->
{/each}
</div>
{:else}
<div class=" lx-card text-center">
<span>Nothing will change</span>
</div>
{/if}
<div class="mt-3">
<p class="text-center fw-bold mb-3 mt-5">
Record References
</p>
{#each Object.entries(edgeFieldsDiff) as [field, edges]}
<div
class="lx-card row p-4 mb-4 w-100"
style="overflow:hidden"
>
<div class="col-4">
{field}:
</div>
<div class="col-8">
<p class="mb-2 text-danger">Record</p>
{#each edges.record as edge}
<RevisionEdgeRow {edge} />
{:else}
<p>No references</p>
{/each}
<p class="mt-4 mb-2 text-success">Revision</p>
{#each edges.revision as edge}
<RevisionEdgeRow {edge} />
{:else}
<p>No references</p>
{/each}
</div>
</div>
<!-- </div> -->
{/each}
</div>
{:else}
<div class=" lx-card text-center">
<span>Nothing will change</span>
</div>
{/if}
</div>
{/if}
</div>
{/if}
</div>
<style>
.label {
@@ -8,7 +8,7 @@
export let colorClass;
</script>
{#if ["reference", "file"].includes(field.ui)}
{#if ["reference", "file"].includes(field.info.name)}
<div class="{colorClass} field-content">
<div class="d-flex align-items-center text-center flex-wrap">
{#each edges[field.name] as edgeRecord}
@@ -31,11 +31,11 @@
{/each}
</div>
</div>
{:else if field.ui === "json"}
{:else if ["json", "block"].includes(field.info.name)}
<div class="{colorClass} field-content" style="white-space: break-spaces;">
{JSON.stringify(side, null, 2) ?? ""}
</div>
{:else if field.ui === "rich"}
{:else if field.info.name === "rich"}
<div class="{colorClass} field-content">{@html side ?? ""}</div>
{:else}
<div class="{colorClass} field-content">{JSON.stringify(side) ?? ""}</div>
@@ -0,0 +1,15 @@
<script>
import Preview from "../../files/Preview.svelte";
import PreviewCardSmall from "../PreviewCardSmall.svelte";
import {getContext} from "svelte";
const channel = getContext("channel")
export let edge;
</script>
<div>
<span class="me-3">Rank: {edge.rank}</span>
<span>id: </span> <a href="{channel.lucentUrl}/records/{edge.target}" target="_blank">{edge.target}</a>
</div>