Skip to content

Commit c08ec05

Browse files
authoredJun 6, 2022
Add views tab (#392)
* add views tab * update views tab * update view * Add kind * Add parameters type * use parameter and change env to development * remove metadata * fix offChainViews * change text position * use another color
1 parent 455f4f6 commit c08ec05

File tree

8 files changed

+236
-176
lines changed

8 files changed

+236
-176
lines changed
 

‎.env.development

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
NODE_ENV=development
2-
VUE_APP_API_URI=https://api.better-call.dev/v1
2+
VUE_APP_API_URI=https://sharm.better-call.dev/v1

‎src/index.css

+4
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,8 @@
5454

5555
.cursor-pointer {
5656
cursor: pointer;
57+
}
58+
59+
.disabled-gray {
60+
color: #9E9E9E;
5761
}

‎src/router/index.js

+7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import Contract from '@/views/contract/Contract.vue'
1616
import OperationsTab from '@/views/contract/OperationsTab.vue'
1717
import CodeTab from '@/views/contract/CodeTab.vue'
1818
import InteractTab from '@/views/contract/InteractTab.vue'
19+
import ViewsTab from '@/views/contract/ViewsTab/ViewsTab.vue'
1920
import StorageTab from '@/views/contract/StorageTab.vue'
2021
import ContractTokensTab from '@/views/contract/TokensTab/TokensTab.vue'
2122
import TransfersTab from '@/views/contract/TransfersTab/TransfersTab.vue'
@@ -199,6 +200,12 @@ const router = new Router({
199200
component: InteractTab,
200201
props: true
201202
},
203+
{
204+
path: 'views/:view?',
205+
name: 'views',
206+
component: ViewsTab,
207+
props: true
208+
},
202209
{
203210
path: 'storage',
204211
name: 'storage',

‎src/views/contract/Contract.vue

+24-1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
:is-anything-loading="isLoadingDataForTabs"
7171
:same-contracts="sameContracts"
7272
:migrations="migrations"
73+
:offchain-views="offChainViews"
7374
/>
7475

7576
<VContainer fluid>
@@ -83,6 +84,7 @@
8384
:same-contracts="sameContracts"
8485
:same-count="sameCount"
8586
:migrations="migrations"
87+
:off-chain-views="offChainViews"
8688
></router-view>
8789
</VContainer>
8890
</div>
@@ -97,6 +99,7 @@ import MenuToolbar from "./MenuToolbar";
9799
import Tags from "../../components/Tags";
98100
import {openTzktContract} from "../../utils/tzkt";
99101
import {DATA_LOADING_STATUSES} from "../../utils/network";
102+
import {applyStyles} from "../../utils/styles";
100103
101104
const MIN_SEARCHBOX_WIDTH = 240;
102105
@@ -125,6 +128,8 @@ export default {
125128
sameCount: 0,
126129
migrationsLoading: DATA_LOADING_STATUSES.NOTHING,
127130
migrations: [],
131+
offChainViews: [],
132+
offChainViewsLoadingStatus: DATA_LOADING_STATUSES.NOTHING,
128133
}),
129134
computed: {
130135
alias() {
@@ -157,7 +162,10 @@ export default {
157162
return this.sameContractsLoadingStatus === DATA_LOADING_STATUSES.PROGRESS;
158163
},
159164
isLoadingDataForTabs() {
160-
return this.isSameContractsLoading;
165+
return this.isSameContractsLoading || this.isOffChainsLoading;
166+
},
167+
isOffChainsLoading() {
168+
return this.offChainViewsLoadingStatus === DATA_LOADING_STATUSES.PROGRESS;
161169
},
162170
isContract() {
163171
return this.address.startsWith("KT");
@@ -189,6 +197,20 @@ export default {
189197
hideError: "hideError",
190198
showClipboardOK: "showClipboardOK",
191199
}),
200+
async loadViewsSchema() {
201+
this.offChainViewsLoadingStatus = DATA_LOADING_STATUSES.PROGRESS;
202+
this.offChainViews = [];
203+
if (this.network && this.address) {
204+
try {
205+
let views = await this.api.getMetadataViewsSchema(this.network, this.address);
206+
this.offChainViewsLoadingStatus = DATA_LOADING_STATUSES.NOTHING;
207+
views.forEach(view => applyStyles(view.schema));
208+
this.offChainViews = views;
209+
} catch (err) {
210+
this.showError("Error while fetching off-chain views");
211+
}
212+
}
213+
},
192214
openInTzkt() {
193215
openTzktContract(this.contract);
194216
},
@@ -246,6 +268,7 @@ export default {
246268
this.getContract();
247269
this.getTokensTotal();
248270
this.getMigrations();
271+
this.loadViewsSchema()
249272
}
250273
this.getInfo();
251274
this.getTokenBalancesTotal();

‎src/views/contract/MenuToolbar.vue

+8-1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@
4444
<v-tab :to="pushTo({ name: 'fork' })" replace v-if="isContract">
4545
<v-icon left small>mdi-source-fork</v-icon>Fork
4646
</v-tab>
47+
<v-tab v-show="isOffChainViews" :to="pushTo({name: 'views'})" replace>
48+
<v-icon left small>mdi-adjust</v-icon>Views
49+
</v-tab>
4750
<v-tab v-show="isSameContracts || isMigrations" :to="pushTo({name: 'details'})" replace>
4851
<v-icon left small>mdi-alert-circle-outline</v-icon>Details
4952
</v-tab>
@@ -67,6 +70,7 @@ export default {
6770
sameContracts: Array,
6871
isAnythingLoading: Boolean,
6972
migrations: Array,
73+
offchainViews: Array,
7074
},
7175
computed: {
7276
isContract() {
@@ -77,7 +81,10 @@ export default {
7781
},
7882
isMigrations() {
7983
return this.migrations.length > 0;
80-
}
84+
},
85+
isOffChainViews() {
86+
return this.offchainViews.length > 0;
87+
},
8188
},
8289
methods: {
8390
pushTo(obj) {

‎src/views/contract/MetadataTab/MetadataTab.vue

+1-11
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,6 @@
1818
:metadata="reservedMetadata"
1919
class="pr-8 pl-2"
2020
/>
21-
<template v-if="metadata.views && metadata.views.length > 0">
22-
<v-divider></v-divider>
23-
<OffchainViews
24-
:views="views"
25-
:network="network"
26-
:address="address"
27-
class="pr-8 py-8"
28-
/>
29-
</template>
3021
<template v-if="unknownFields && unknownFields.length > 0">
3122
<v-divider></v-divider>
3223
<FieldsWrapper
@@ -48,14 +39,13 @@
4839
<script>
4940
import FieldsWrapper from "@/views/contract/MetadataTab/CustomFields/FieldsWrapper";
5041
import ReservedFields from "@/views/contract/MetadataTab/ReservedFields";
51-
import OffchainViews from "@/views/contract/MetadataTab/OffchainViews";
5242
import { mapActions } from "vuex";
5343
import { applyStyles } from '@/utils/styles.js';
5444
import RawJsonViewer from "@/components/Dialogs/RawJsonViewer";
5545
5646
export default {
5747
name: "Metadata",
58-
components: {OffchainViews, ReservedFields, FieldsWrapper, RawJsonViewer},
48+
components: { ReservedFields, FieldsWrapper, RawJsonViewer},
5949
props: {
6050
metadata: Object,
6151
network: String,

‎src/views/contract/MetadataTab/OffchainViews.vue

-162
This file was deleted.
+191
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
<template>
2+
<v-container fluid class="pa-8 canvas fill-canvas">
3+
<v-row no-gutters>
4+
<v-col cols="3">
5+
<h3 class="mb-3 text--secondary font-weight-medium">Views</h3>
6+
<v-list-item-group
7+
class="themed-border radius-1"
8+
active-class="token-card-selected"
9+
:value="selected"
10+
mandatory
11+
>
12+
<template v-for="(item, i) in offChainViews">
13+
<v-list-item @click="selected = i" class="token-card" :key="'entrypoint-' + i">
14+
<v-list-item-content>
15+
<v-list-item-title class="d-flex justify-space-between align-center">
16+
<span v-if="item.name">{{ item.name }}</span>
17+
<span v-else class="text--disabled">NO NAME</span>
18+
<span class="disabled-gray text-small">
19+
{{ item.kind }}
20+
</span>
21+
</v-list-item-title>
22+
</v-list-item-content>
23+
</v-list-item>
24+
</template>
25+
</v-list-item-group>
26+
</v-col>
27+
<v-col cols="6" class="px-8">
28+
<template v-if="selectedItem">
29+
<v-card flat outlined>
30+
<v-card-text class="pa-0 pt-6 data">
31+
<SchemaHeader
32+
title="View"
33+
:is-storage="true"
34+
:storage-html="selectedItem.name"
35+
:storage-name="selectedItem.name"
36+
/>
37+
<SchemaForm
38+
header="Parameters"
39+
fallback-text="This implementation doesn't have parameters"
40+
:schema="selectedItem.schema"
41+
:show="true"
42+
:is-deploy="true"
43+
:is-optional-settings="false"
44+
@executeClick="callOffchainView"
45+
@modelChange="setModel"
46+
/>
47+
</v-card-text>
48+
</v-card>
49+
</template>
50+
<v-dialog
51+
v-model="showSuccess"
52+
max-width="525"
53+
persistent
54+
dark
55+
@click:outside="showSuccess = false"
56+
@keydown.esc="showSuccess = false"
57+
>
58+
<v-card flat outlined>
59+
<v-card-title class="sidebar d-flex justify-center pa-4">
60+
<span class="body-1 font-weight-medium text-uppercase text--secondary">View result</span>
61+
<v-spacer></v-spacer>
62+
<v-btn icon small @click="showSuccess = false">
63+
<v-icon>mdi-close</v-icon>
64+
</v-btn>
65+
</v-card-title>
66+
<v-card-text class="pa-8">
67+
<MiguelTreeView :miguel="successResponse" />
68+
</v-card-text>
69+
</v-card>
70+
</v-dialog>
71+
</v-col>
72+
<v-col cols="3">
73+
<h3 class="mb-3 text--secondary font-weight-medium">Parameters type</h3>
74+
<v-card flat outlined style="max-width: 500px;">
75+
<v-navigation-drawer floating permanent style="max-height: 80vh; width: 100%;">
76+
<div class="pa-3">
77+
<TypeDef
78+
v-if="selectedItem.typedef"
79+
:typedef="selectedItem.typedef"
80+
first="parameter"
81+
class="pt-3 pb-1 px-6"
82+
style="opacity: 0.8"
83+
/>
84+
<p v-else class="mb-0">
85+
No parameters for this view.
86+
</p>
87+
</div>
88+
</v-navigation-drawer>
89+
</v-card>
90+
</v-col>
91+
<TreeNodeDetails
92+
prim="string"
93+
:data="fullErrorValue"
94+
:value="isErrorShown"
95+
is-error-info
96+
/>
97+
</v-row>
98+
</v-container>
99+
</template>
100+
101+
<script>
102+
import SchemaHeader from "../../../components/schema/schemaComponents/SchemaHeader";
103+
import SchemaForm from "../../../components/schema/schemaForm/SchemaForm";
104+
import TreeNodeDetails from "../../../components/Dialogs/TreeNodeDetails";
105+
import MiguelTreeView from "../../../components/MiguelTreeView";
106+
import TypeDef from "../TypeDef";
107+
108+
export default {
109+
name: "ViewsTab",
110+
props: {
111+
address: String,
112+
network: String,
113+
offChainViews: Array,
114+
},
115+
components: {
116+
TypeDef,
117+
MiguelTreeView,
118+
TreeNodeDetails,
119+
SchemaForm,
120+
SchemaHeader,
121+
},
122+
computed: {
123+
selectedItem() {
124+
if (this.selected < 0 || this.offChainViews.length < this.selected) {
125+
return null;
126+
}
127+
if (typeof this.selected === "number") {
128+
return this.offChainViews[this.selected];
129+
}
130+
return null;
131+
},
132+
},
133+
methods: {
134+
setModel(val) {
135+
this.model = val;
136+
},
137+
callOffchainView() {
138+
this.api
139+
.executeMetadataView(this.network, this.address, {
140+
name: this.selectedItem.name,
141+
implementation: this.selectedItem.implementation,
142+
data: this.model,
143+
kind: this.selectedItem.kind,
144+
})
145+
.then((res) => {
146+
if (!res) return;
147+
this.showSuccess = true;
148+
this.successResponse = res;
149+
})
150+
.catch((err) => {
151+
this.isErrorShown = false;
152+
this.fullErrorValue = {
153+
name: `${err.response.statusText}${err.response.status}`,
154+
val: err.response.data.message,
155+
realPrim: 'string',
156+
label: err.response.data.message,
157+
};
158+
this.$nextTick(() => {
159+
this.isErrorShown = true;
160+
});
161+
})
162+
}
163+
},
164+
data() {
165+
return {
166+
model: {},
167+
selected: 0,
168+
isErrorShown: false,
169+
successText: '',
170+
showSuccess: false,
171+
successResponse: null,
172+
fullErrorValue: null,
173+
}
174+
}
175+
};
176+
</script>
177+
178+
179+
180+
<style lang="scss" scoped>
181+
.entrypoint-panel > .v-expansion-panel-header {
182+
background-color: var(--v-sidebar-base);
183+
}
184+
185+
.v-expansion-panel.entrypoint-selected {
186+
background-color: var(--v-data-base);
187+
& > .v-expansion-panel-header {
188+
background-color: var(--v-data-base);
189+
}
190+
}
191+
</style>

0 commit comments

Comments
 (0)
Please sign in to comment.