1+ <script >
2+ import _ from " lodash" ;
3+ import {dataTypeStore } from " ../../../svelte-stores/data-type-store" ;
4+ import {buildHierarchies , reduceToSelectedNodesOnly } from " ../../../common/hierarchy-utils" ;
5+ import DataTypeTreeNode from " ../../../common/svelte/DataTypeTreeNode.svelte" ;
6+ import DataTypeTreeSelector from " ../../../common/svelte/DataTypeTreeSelector.svelte" ;
7+ import {entityRelationshipStore } from " ../../../svelte-stores/entity-relationship-store" ;
8+ import {mkRel } from " ../../../common/relationship-utils" ;
9+ import {toEntityRef } from " ../../../common/entity-utils" ;
10+ import {onMount } from " svelte" ;
11+ import toasts from " ../../../svelte-stores/toast-store" ;
12+ import {displayError } from " ../../../common/error-utils" ;
13+ import NoData from " ../../../common/svelte/NoData.svelte" ;
14+ import Markdown from " ../../../common/svelte/Markdown.svelte" ;
15+ import EntityLink from " ../../../common/svelte/EntityLink.svelte" ;
16+ import SubSection from " ../../../common/svelte/SubSection.svelte" ;
17+ import {userStore } from " ../../../svelte-stores/user-store" ;
18+ import {getEditRoleForEntityKind } from " ../../../common/role-utils" ;
19+ import {entity } from " ../../../common/services/enums/entity" ;
20+
21+
22+ const Modes = {
23+ EDIT : " EDIT" ,
24+ VIEW : " VIEW"
25+ };
26+
27+ const root = {};
28+
29+ export let primaryEntityReference;
30+
31+ let dataTypesCall = dataTypeStore .findAll ();
32+ let selected = [];
33+ let mode = Modes .VIEW ;
34+ let viewHierarchy = [];
35+ let focusedType = null ;
36+ let canEdit = false ;
37+
38+ let currentDataTypesCall = null ;
39+ let userCall = null ;
40+
41+ let restrictedEntities = [entity .MEASURABLE .key ]; // Determines which parent pages the permissions check applies to
42+
43+ function reload () {
44+ currentDataTypesCall = entityRelationshipStore .findForEntity (
45+ primaryEntityReference,
46+ " SOURCE" ,
47+ [" RELATES_TO" ],
48+ true );
49+ }
50+
51+ onMount (() => {
52+ reload ();
53+ userCall = userStore .load ();
54+ });
55+
56+ function onFocus (evt ) {
57+ focusedType = evt .detail ;
58+ }
59+
60+ function onSelect (evt ) {
61+ const dt = evt .detail ;
62+ const alreadySelected = _ .includes (selected, dt .id );
63+
64+ const remoteCall = alreadySelected
65+ ? entityRelationshipStore .remove
66+ : entityRelationshipStore .create ;
67+
68+ const rel = mkRel (
69+ primaryEntityReference,
70+ " RELATES_TO" ,
71+ toEntityRef (evt .detail ));
72+
73+ const msgAction = alreadySelected
74+ ? " removed"
75+ : " added" ;
76+
77+ remoteCall (rel)
78+ .then (() => {
79+ toasts .success (` Successfully ${ msgAction} data type: ${ dt .name } ` );
80+ })
81+ .catch (err => {
82+ displayError (` Failed ${ msgAction} data type: ${ dt .name } ` , err);
83+ })
84+ .finally (reload);
85+ }
86+
87+ $: selected = _
88+ .chain ($currentDataTypesCall? .data )
89+ .filter (d => d .b .kind === " DATA_TYPE" )
90+ .map (d => d .b .id )
91+ .value ();
92+
93+ $: viewHierarchy = buildHierarchies (reduceToSelectedNodesOnly (dataTypes, selected));
94+
95+ $: selectionFilter = (d ) => ! _ .includes (selected, d .id );
96+ $: dataTypes = $dataTypesCall .data ;
97+
98+ $: user = $userCall? .data ;
99+
100+ $: requiredRole = getEditRoleForEntityKind (primaryEntityReference .kind , entity .DATA_TYPE .key );
101+ $: hasEditRoleForKind = _ .includes (user? .roles , requiredRole);
102+
103+ $: canEdit = ! _ .includes (restrictedEntities, primaryEntityReference .kind ) || hasEditRoleForKind;
104+
105+ < / script>
106+
107+ {#if mode === Modes .VIEW }
108+
109+ < h4> Associated Data Types < small> View< / small>< / h4>
110+ < div class = " help-block" >
111+ The tree below shows the set of data types which have been related to this entity.
112+ < / div>
113+
114+ {#if viewHierarchy .length === 0 }
115+ < NoData>
116+ There are < strong> no data types< / strong> associated with this entity
117+ < / NoData>
118+ {: else }
119+ < div class = " row" >
120+ < div class = " col-md-7" >
121+ < DataTypeTreeNode isRoot= {true }
122+ node= {root}
123+ childNodes= {viewHierarchy}
124+ expanded= {selected}
125+ on: select= {onFocus}/ >
126+ < / div>
127+ < div class = " col-md-5" >
128+ {#if focusedType}
129+ < SubSection>
130+ < div slot= " header" >
131+ < span> {focusedType .name }< / span>
132+ < / div>
133+ < div slot= " content" >
134+ < div class = " focused-type-content" >
135+ < Markdown text= {focusedType .description }/ >
136+ < / div>
137+ < / div>
138+ < div slot= " controls" >
139+ < div class = " focused-type-controls" >
140+ More about: < EntityLink ref= {focusedType}/ >
141+ < / div>
142+ < / div>
143+ < / SubSection>
144+ {/ if }
145+ < / div>
146+ < / div>
147+
148+ {/ if }
149+
150+ {#if canEdit}
151+ < div class = " actions" >
152+ < button class = " btn btn-primary btn-sm"
153+ on: click= {() => mode = Modes .EDIT }>
154+ Edit
155+ < / button>
156+ < / div>
157+ {/ if }
158+
159+ {: else if mode === Modes .EDIT }
160+
161+ < h4> Associated Data Types < small> Edit< / small>< / h4>
162+
163+ < div class = " help-block" >
164+ Use the tree below to edit the set of data types which have been related to this entity.
165+ As you toggle, the data will be automatically saved.
166+ < / div>
167+
168+ < DataTypeTreeSelector multiSelect= {true }
169+ nonConcreteSelectable= {false }
170+ selectionFilter= {selectionFilter}
171+ on: select= {onSelect}/ >
172+
173+ < div class = " actions" >
174+ < button class = " btn-skinny"
175+ on: click= {() => mode = Modes .VIEW }>
176+ & laquo; Back to view
177+ < / button>
178+ < / div>
179+ {/ if }
180+
181+
182+ < style>
183+ .actions {
184+ padding- top: 1em ;
185+ }
186+
187+ .focused - type- content {
188+ padding- left: 1em ;
189+ }
190+
191+ .focused - type- controls {
192+ float: right;
193+ padding- right: 1em ;
194+ }
195+ < / style>
0 commit comments