feat(frontend): navigation refractor
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">
|
||||
<style type="text/css">
|
||||
body {
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
<template>
|
||||
<v-breadcrumbs
|
||||
v-if="!$apollo.loading"
|
||||
class="display-1"
|
||||
:items="breadcrumbs"
|
||||
divider="/"
|
||||
></v-breadcrumbs>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import gql from 'graphql-tag'
|
||||
export default {
|
||||
name: 'BreadcrumbTitle',
|
||||
apollo: {
|
||||
stream: {
|
||||
query: gql`
|
||||
query Stream($id: String!) {
|
||||
stream(id: $id) {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables() {
|
||||
return {
|
||||
id: this.$route.params.streamId
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
branch: {
|
||||
query: gql`
|
||||
query Stream($streamId: String!, $branchName: String!) {
|
||||
stream(id: $streamId) {
|
||||
id
|
||||
name
|
||||
branch(name: $branchName) {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables() {
|
||||
return {
|
||||
streamId: this.$route.params.streamId,
|
||||
branchName: this.$route.params.branchName
|
||||
}
|
||||
},
|
||||
skip() {
|
||||
return !this.$route.params.branchName
|
||||
},
|
||||
update: (data) => {
|
||||
return data.stream.branch
|
||||
}
|
||||
},
|
||||
commit: {
|
||||
query: gql`
|
||||
query Stream($streamId: String!, $commitId: String!) {
|
||||
stream(id: $streamId) {
|
||||
id
|
||||
name
|
||||
commit(id: $commitId) {
|
||||
id
|
||||
branchName
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables() {
|
||||
return {
|
||||
streamId: this.$route.params.streamId,
|
||||
commitId: this.$route.params.commitId
|
||||
}
|
||||
},
|
||||
skip() {
|
||||
return !this.$route.params.commitId
|
||||
},
|
||||
update: (data) => {
|
||||
return data.stream.commit
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
breadcrumbs() {
|
||||
let items = [
|
||||
{
|
||||
text: this.stream.name,
|
||||
disabled: false,
|
||||
exact: true,
|
||||
to: '/streams/' + this.stream.id
|
||||
}
|
||||
]
|
||||
|
||||
if (this.branch) {
|
||||
items.push({
|
||||
text: 'branches',
|
||||
disabled: false,
|
||||
exact: true,
|
||||
to: '/streams/' + this.stream.id + '/branches/'
|
||||
})
|
||||
items.push({
|
||||
text: this.branch.name,
|
||||
disabled: true,
|
||||
exact: true,
|
||||
to: '/streams/' + this.stream.id + '/branches/' + encodeURIComponent(this.branch.name)
|
||||
})
|
||||
} else if (this.commit) {
|
||||
items.push({
|
||||
text: 'branches',
|
||||
disabled: false,
|
||||
exact: true,
|
||||
to: '/streams/' + this.stream.id + '/branches/'
|
||||
})
|
||||
items.push({
|
||||
text: this.commit.branchName,
|
||||
disabled: false,
|
||||
exact: true,
|
||||
to:
|
||||
'/streams/' + this.stream.id + '/branches/' + encodeURIComponent(this.commit.branchName)
|
||||
})
|
||||
items.push({
|
||||
text: this.commit.id,
|
||||
disabled: true
|
||||
})
|
||||
} else {
|
||||
items.push({
|
||||
text: this.$route.name,
|
||||
disabled: true
|
||||
})
|
||||
}
|
||||
|
||||
return items
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -8,8 +8,8 @@
|
||||
@close="closeSaveDialog"
|
||||
/>
|
||||
</v-dialog>
|
||||
<v-card-title>Globals</v-card-title>
|
||||
<v-card-subtitle v-if="commitMessage">
|
||||
<b>Selected commit:</b>
|
||||
<v-icon dense class="text-subtitle-1">mdi-source-commit</v-icon>
|
||||
{{ commitMessage }}
|
||||
</v-card-subtitle>
|
||||
|
||||
@@ -8,7 +8,7 @@ const routes = [
|
||||
path: '/authn',
|
||||
name: 'Auth',
|
||||
redirect: '/authn/login',
|
||||
component: () => import('../views/Auth.vue'),
|
||||
component: () => import('@/views/Auth.vue'),
|
||||
children: [
|
||||
{
|
||||
path: 'login',
|
||||
@@ -16,7 +16,7 @@ const routes = [
|
||||
meta: {
|
||||
title: 'Login | Speckle'
|
||||
},
|
||||
component: () => import('../views/auth/Login.vue')
|
||||
component: () => import('@/views/auth/Login.vue')
|
||||
},
|
||||
{
|
||||
path: 'register',
|
||||
@@ -24,7 +24,7 @@ const routes = [
|
||||
meta: {
|
||||
title: 'Register | Speckle'
|
||||
},
|
||||
component: () => import('../views/auth/Registration.vue')
|
||||
component: () => import('@/views/auth/Registration.vue')
|
||||
},
|
||||
{
|
||||
path: 'resetpassword',
|
||||
@@ -32,7 +32,7 @@ const routes = [
|
||||
meta: {
|
||||
title: 'Register | Speckle'
|
||||
},
|
||||
component: () => import('../views/auth/ResetPasswordRequest.vue')
|
||||
component: () => import('@/views/auth/ResetPasswordRequest.vue')
|
||||
},
|
||||
{
|
||||
path: 'resetpassword/finalize',
|
||||
@@ -40,7 +40,7 @@ const routes = [
|
||||
meta: {
|
||||
title: 'Register | Speckle'
|
||||
},
|
||||
component: () => import('../views/auth/ResetPasswordFinalization.vue')
|
||||
component: () => import('@/views/auth/ResetPasswordFinalization.vue')
|
||||
},
|
||||
{
|
||||
path: 'verify/:appId/:challenge',
|
||||
@@ -48,7 +48,7 @@ const routes = [
|
||||
meta: {
|
||||
title: 'Authorizing App | Speckle'
|
||||
},
|
||||
component: () => import('../views/auth/AuthorizeApp.vue')
|
||||
component: () => import('@/views/auth/AuthorizeApp.vue')
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -57,7 +57,7 @@ const routes = [
|
||||
meta: {
|
||||
title: 'Home | Speckle'
|
||||
},
|
||||
component: () => import('../views/Frontend.vue'),
|
||||
component: () => import('@/views/Frontend.vue'),
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
@@ -65,7 +65,7 @@ const routes = [
|
||||
meta: {
|
||||
title: 'Home | Speckle'
|
||||
},
|
||||
component: () => import('../views/Timeline.vue')
|
||||
component: () => import('@/views/Timeline.vue')
|
||||
},
|
||||
{
|
||||
path: 'streams',
|
||||
@@ -73,14 +73,14 @@ const routes = [
|
||||
meta: {
|
||||
title: 'Streams | Speckle'
|
||||
},
|
||||
component: () => import('../views/Streams.vue')
|
||||
component: () => import('@/views/Streams.vue')
|
||||
},
|
||||
{
|
||||
path: 'streams/:streamId',
|
||||
meta: {
|
||||
title: 'Stream | Speckle'
|
||||
},
|
||||
component: () => import('../views/Stream.vue'),
|
||||
component: () => import('@/views/stream/Stream.vue'),
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
@@ -88,31 +88,16 @@ const routes = [
|
||||
meta: {
|
||||
title: 'Stream | Speckle'
|
||||
},
|
||||
component: () => import('../views/StreamMain.vue')
|
||||
},
|
||||
// {
|
||||
// path: 'globals/',
|
||||
// name: 'globals',
|
||||
// meta: {
|
||||
// title: 'Globals | Speckle'
|
||||
// },
|
||||
// component: () => import('../views/Globals.vue')
|
||||
// },
|
||||
{
|
||||
path: 'globals/:commitId',
|
||||
name: 'previous globals',
|
||||
meta: {
|
||||
title: 'Globals | Speckle'
|
||||
},
|
||||
component: () => import('../views/Globals.vue')
|
||||
component: () => import('@/views/stream/Activity.vue')
|
||||
},
|
||||
|
||||
{
|
||||
path: 'branches/',
|
||||
name: 'branches',
|
||||
meta: {
|
||||
title: 'Branches | Speckle'
|
||||
},
|
||||
component: () => import('../views/Branches.vue')
|
||||
component: () => import('@/views/stream/Branches.vue')
|
||||
},
|
||||
{
|
||||
path: 'branches/:branchName',
|
||||
@@ -120,15 +105,7 @@ const routes = [
|
||||
meta: {
|
||||
title: 'Branch | Speckle'
|
||||
},
|
||||
component: () => import('../views/StreamMain.vue')
|
||||
},
|
||||
{
|
||||
path: 'branches/:branchName/commits',
|
||||
name: 'commits',
|
||||
meta: {
|
||||
title: 'Commits | Speckle'
|
||||
},
|
||||
component: () => import('../views/Commits.vue')
|
||||
component: () => import('@/views/stream/Branch.vue')
|
||||
},
|
||||
{
|
||||
path: 'commits/:commitId',
|
||||
@@ -136,7 +113,7 @@ const routes = [
|
||||
meta: {
|
||||
title: 'Commit | Speckle'
|
||||
},
|
||||
component: () => import('../views/Commit.vue')
|
||||
component: () => import('@/views/stream/Commit.vue')
|
||||
},
|
||||
{
|
||||
path: 'objects/:objectId',
|
||||
@@ -144,55 +121,55 @@ const routes = [
|
||||
meta: {
|
||||
title: 'Object | Speckle'
|
||||
},
|
||||
component: () => import('../views/Object.vue')
|
||||
component: () => import('@/views/stream/Object.vue')
|
||||
},
|
||||
{
|
||||
path: 'settings/',
|
||||
name: 'settings',
|
||||
meta: {
|
||||
title: 'Stream Settings | Speckle'
|
||||
},
|
||||
props: true,
|
||||
component: () => import('../views/settings/StreamSettings.vue'),
|
||||
component: () => import('@/views/stream/Settings.vue')
|
||||
},
|
||||
{
|
||||
path: 'webhooks/',
|
||||
name: 'webhooks',
|
||||
meta: {
|
||||
title: 'Webhooks | Speckle'
|
||||
},
|
||||
props: true,
|
||||
component: () => import('@/views/stream/Webhooks.vue'),
|
||||
children: [
|
||||
{
|
||||
path: 'general/',
|
||||
name: 'general',
|
||||
meta: {
|
||||
title: 'Stream Settings | Speckle'
|
||||
},
|
||||
props: true,
|
||||
component: () => import('../views/settings/SettingsGeneral.vue')
|
||||
},
|
||||
{
|
||||
path: 'webhooks/',
|
||||
name: 'webhooks',
|
||||
meta: {
|
||||
title: 'Webhooks | Speckle'
|
||||
},
|
||||
props: true,
|
||||
component: () => import('../views/settings/SettingsWebhooks.vue'),
|
||||
children: [
|
||||
{
|
||||
path: 'edit/:webhookId/',
|
||||
name: 'edit webhook',
|
||||
props: true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'webhooks/new/',
|
||||
name: 'add webhook',
|
||||
props: true,
|
||||
component: () => import('../views/settings/SettingsWebhooks.vue')
|
||||
},
|
||||
{
|
||||
path: 'globals/',
|
||||
name: 'globals',
|
||||
meta: {
|
||||
title: 'Globals | Speckle'
|
||||
},
|
||||
props: true,
|
||||
component: () => import('../views/Globals.vue')
|
||||
path: 'edit/:webhookId/',
|
||||
name: 'edit webhook',
|
||||
props: true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'webhooks/new/',
|
||||
name: 'add webhook',
|
||||
props: true,
|
||||
component: () => import('@/views/stream/Webhooks.vue')
|
||||
},
|
||||
{
|
||||
path: 'globals/',
|
||||
name: 'globals',
|
||||
meta: {
|
||||
title: 'Globals | Speckle'
|
||||
},
|
||||
props: true,
|
||||
component: () => import('@/views/stream/Globals.vue')
|
||||
},
|
||||
{
|
||||
path: 'globals/:commitId',
|
||||
name: 'previous globals',
|
||||
meta: {
|
||||
title: 'Globals | Speckle'
|
||||
},
|
||||
component: () => import('@/views/stream/Globals.vue')
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -203,7 +180,7 @@ const routes = [
|
||||
meta: {
|
||||
title: 'Your Profile | Speckle'
|
||||
},
|
||||
component: () => import('../views/Profile.vue')
|
||||
component: () => import('@/views/Profile.vue')
|
||||
},
|
||||
{
|
||||
path: 'profile/:userId',
|
||||
@@ -211,7 +188,7 @@ const routes = [
|
||||
meta: {
|
||||
title: 'User Profile | Speckle'
|
||||
},
|
||||
component: () => import('../views/ProfileUser.vue')
|
||||
component: () => import('@/views/ProfileUser.vue')
|
||||
},
|
||||
{
|
||||
path: 'admin',
|
||||
@@ -222,25 +199,25 @@ const routes = [
|
||||
{
|
||||
name: 'Admin | Overview',
|
||||
path: '',
|
||||
component: () => import('../views/admin/AdminOverview.vue')
|
||||
component: () => import('@/views/admin/AdminOverview.vue')
|
||||
},
|
||||
{
|
||||
name: 'Admin | Users',
|
||||
path: 'users',
|
||||
component: () => import('../views/admin/AdminUsers.vue')
|
||||
component: () => import('@/views/admin/AdminUsers.vue')
|
||||
},
|
||||
{
|
||||
name: 'Admin | Streams',
|
||||
path: 'streams',
|
||||
component: () => import('../views/admin/AdminStreams.vue')
|
||||
component: () => import('@/views/admin/AdminStreams.vue')
|
||||
},
|
||||
{
|
||||
name: 'Admin | Settings',
|
||||
path: 'settings',
|
||||
component: () => import('../views/admin/AdminSettings.vue')
|
||||
component: () => import('@/views/admin/AdminSettings.vue')
|
||||
}
|
||||
],
|
||||
component: () => import('../views/admin/AdminPanel.vue')
|
||||
component: () => import('@/views/admin/AdminPanel.vue')
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -250,7 +227,7 @@ const routes = [
|
||||
meta: {
|
||||
title: 'Error | Speckle'
|
||||
},
|
||||
component: () => import('../views/Error.vue')
|
||||
component: () => import('@/views/Error.vue')
|
||||
},
|
||||
{
|
||||
path: '/onboarding',
|
||||
@@ -258,12 +235,12 @@ const routes = [
|
||||
meta: {
|
||||
title: 'Getting Started | Speckle'
|
||||
},
|
||||
component: () => import('../views/GettingStartedView.vue')
|
||||
component: () => import('@/views/GettingStartedView.vue')
|
||||
},
|
||||
{
|
||||
path: '/embed',
|
||||
name: 'Embeded Viewer',
|
||||
component: () => import('../views/EmbedViewer.vue')
|
||||
component: () => import('@/views/EmbedViewer.vue')
|
||||
},
|
||||
{
|
||||
path: '*',
|
||||
@@ -271,7 +248,7 @@ const routes = [
|
||||
meta: {
|
||||
title: 'Not Found | Speckle'
|
||||
},
|
||||
component: () => import('../views/NotFound.vue')
|
||||
component: () => import('@/views/NotFound.vue')
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
<template>
|
||||
<v-container>
|
||||
<div v-if="!objectId && !$apollo.loading && !revealBuilder">
|
||||
<v-card :loading="loading">
|
||||
<template slot="progress">
|
||||
<v-progress-linear indeterminate></v-progress-linear>
|
||||
</template>
|
||||
<v-card-title>You don't have any globals on this stream!</v-card-title>
|
||||
<v-card-text
|
||||
v-if="$attrs['user-role'] === 'contributor' || $attrs['user-role'] === 'owner'"
|
||||
class="subtitle-1"
|
||||
>
|
||||
Globals are useful for storing design values, project requirements, notes, or any info you
|
||||
want to keep track of alongside your geometry. Would you like to create some now?
|
||||
</v-card-text>
|
||||
<v-card-text
|
||||
v-if="!($attrs['user-role'] === 'contributor') && !($attrs['user-role'] === 'owner')"
|
||||
class="subtitle-1"
|
||||
>
|
||||
Globals are useful for storing design values, project requirements, notes, or any info you
|
||||
want to keep track of alongside your geometry. You don't have permission to create and
|
||||
edit globals on this stream, but you can create your own stream to try them out!
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer />
|
||||
<v-btn
|
||||
v-if="$attrs['user-role'] === 'contributor' || $attrs['user-role'] === 'owner'"
|
||||
color="primary"
|
||||
@click="createClicked"
|
||||
>
|
||||
create globals
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</div>
|
||||
<div v-if="objectId || revealBuilder">
|
||||
<globals-builder
|
||||
:branch-name="branchName"
|
||||
:stream-id="streamId"
|
||||
:object-id="objectId"
|
||||
:commit-message="commit ? commit.message : null"
|
||||
:user-role="$attrs['user-role']"
|
||||
@new-commit="newCommit"
|
||||
/>
|
||||
<v-card v-if="!$apollo.loading && branch.commits.items.length">
|
||||
<v-card-title>History</v-card-title>
|
||||
<v-card-text>
|
||||
<list-item-commit
|
||||
v-for="item in branch.commits.items"
|
||||
:key="item.id"
|
||||
:route="`/streams/${streamId}/globals/${item.id}`"
|
||||
:commit="item"
|
||||
:stream-id="streamId"
|
||||
/>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</div>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import gql from 'graphql-tag'
|
||||
import branchQuery from '../graphql/branch.gql'
|
||||
|
||||
export default {
|
||||
name: 'Globals',
|
||||
components: {
|
||||
GlobalsBuilder: () => import('../components/GlobalsBuilder'),
|
||||
ListItemCommit: () => import('../components/ListItemCommit')
|
||||
},
|
||||
apollo: {
|
||||
branch: {
|
||||
query: branchQuery,
|
||||
variables() {
|
||||
return {
|
||||
streamId: this.streamId,
|
||||
branchName: this.branchName
|
||||
}
|
||||
},
|
||||
update(data) {
|
||||
return data.stream.branch
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
branchName: 'globals', //TODO: handle multipile globals branches,
|
||||
|
||||
revealBuilder: false,
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
streamId() {
|
||||
return this.$route.params.streamId
|
||||
},
|
||||
commit() {
|
||||
return this.$route.params.commitId
|
||||
? this.branch?.commits?.items?.filter((c) => c.id == this.$route.params.commitId)[0]
|
||||
: this.branch?.commits?.items[0]
|
||||
},
|
||||
objectId() {
|
||||
return this.commit?.referencedObject
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async createClicked() {
|
||||
if (!this.branch) {
|
||||
this.loading = true
|
||||
this.$matomo && this.$matomo.trackPageView('globals/branch/create')
|
||||
await this.$apollo.mutate({
|
||||
mutation: gql`
|
||||
mutation branchCreate($params: BranchCreateInput!) {
|
||||
branchCreate(branch: $params)
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
params: {
|
||||
streamId: this.streamId,
|
||||
name: 'globals',
|
||||
description: 'Stream globals'
|
||||
}
|
||||
}
|
||||
})
|
||||
this.$apollo.queries.branch.refetch()
|
||||
this.loading = false
|
||||
}
|
||||
|
||||
this.revealBuilder = true
|
||||
},
|
||||
newCommit() {
|
||||
this.$apollo.queries.branch.refetch()
|
||||
if (this.$route.params.commitId) this.$router.push(`/streams/${this.streamId}/globals`)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -1,154 +0,0 @@
|
||||
<template>
|
||||
<v-container :fluid="$vuetify.breakpoint.mdAndDown">
|
||||
<!-- <v-navigation-drawer app clipped left>
|
||||
<v-list>
|
||||
<v-list-item v-for="n in 5" :key="n" link>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>Item {{ n }}</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-navigation-drawer> -->
|
||||
<v-row v-if="stream">
|
||||
<v-col cols="12" sm="12" md="4" lg="3" xl="3">
|
||||
<sidebar-stream :user-role="userRole"></sidebar-stream>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="8" lg="9" xl="9" class="pt-10">
|
||||
<router-view :user-role="userRole"></router-view>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row v-else-if="error" justify="center">
|
||||
<v-col cols="12" sm="12" md="8" lg="9" xl="8" class="pt-10">
|
||||
<error-block :message="error" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-snackbar
|
||||
v-if="commitSnackbarInfo"
|
||||
v-model="commitSnackbar"
|
||||
:timeout="5000"
|
||||
color="primary"
|
||||
absolute
|
||||
right
|
||||
top
|
||||
>
|
||||
New commit
|
||||
<i>{{ commitSnackbarInfo.message }}</i>
|
||||
on
|
||||
<i>{{ commitSnackbarInfo.branchName }}</i>
|
||||
<template #action="{ attrs }">
|
||||
<v-btn
|
||||
text
|
||||
v-bind="attrs"
|
||||
:to="'/streams/' + $route.params.streamId + '/commits/' + commitSnackbarInfo.id"
|
||||
@click="commitSnackbar = false"
|
||||
>
|
||||
see
|
||||
</v-btn>
|
||||
<v-btn icon v-bind="attrs" @click="commitSnackbar = false">
|
||||
<v-icon>mdi-close</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-snackbar>
|
||||
<stream-invite-dialog v-if="stream" ref="streamInviteDialog" :stream-id="stream.id" />
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SidebarStream from '../components/SidebarStream'
|
||||
import ErrorBlock from '../components/ErrorBlock'
|
||||
import streamQuery from '../graphql/stream.gql'
|
||||
import gql from 'graphql-tag'
|
||||
import StreamInviteDialog from '../components/dialogs/StreamInviteDialog'
|
||||
|
||||
export default {
|
||||
name: 'Stream',
|
||||
components: {
|
||||
SidebarStream,
|
||||
ErrorBlock,
|
||||
StreamInviteDialog
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
error: '',
|
||||
commitSnackbar: false,
|
||||
commitSnackbarInfo: {}
|
||||
}
|
||||
},
|
||||
apollo: {
|
||||
stream: {
|
||||
query: streamQuery,
|
||||
variables() {
|
||||
return {
|
||||
id: this.$route.params.streamId
|
||||
}
|
||||
},
|
||||
error(err) {
|
||||
if (err.message) this.error = err.message.replace('GraphQL error: ', '')
|
||||
else this.error = err
|
||||
}
|
||||
},
|
||||
$subscribe: {
|
||||
streamUpdated: {
|
||||
query: gql`
|
||||
subscription($id: String!) {
|
||||
streamUpdated(streamId: $id)
|
||||
}
|
||||
`,
|
||||
variables() {
|
||||
return {
|
||||
id: this.$route.params.streamId
|
||||
}
|
||||
},
|
||||
result(info) {
|
||||
this.$apollo.queries.stream.refetch()
|
||||
},
|
||||
skip() {
|
||||
return !this.loggedIn
|
||||
}
|
||||
},
|
||||
commitCreated: {
|
||||
query: gql`
|
||||
subscription($streamId: String!) {
|
||||
commitCreated(streamId: $streamId)
|
||||
}
|
||||
`,
|
||||
variables() {
|
||||
return {
|
||||
streamId: this.$route.params.streamId
|
||||
}
|
||||
},
|
||||
result(commitInfo) {
|
||||
if (!commitInfo.data.commitCreated) return
|
||||
this.commitSnackbar = true
|
||||
this.commitSnackbarInfo = commitInfo.data.commitCreated
|
||||
},
|
||||
skip() {
|
||||
return !this.loggedIn
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
userRole() {
|
||||
let uuid = localStorage.getItem('uuid')
|
||||
if (!uuid) return null
|
||||
if (this.$apollo.loading) return null
|
||||
let contrib = this.stream.collaborators.find((u) => u.id === uuid)
|
||||
if (contrib) return contrib.role.split(':')[1]
|
||||
else return null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
//open stream invite dialog if ?invite=true
|
||||
//used by desktop connectors
|
||||
if (this.$route.query.invite && this.$route.query.invite === 'true') {
|
||||
setTimeout(() => {
|
||||
this.$refs.streamInviteDialog.show()
|
||||
}, 500)
|
||||
}
|
||||
},
|
||||
loggedIn() {
|
||||
return localStorage.getItem('uuid') !== null
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,149 +0,0 @@
|
||||
<template>
|
||||
<admin-card v-if="selectedWebhook != undefined" :loading="loading" title="Edit Webhook">
|
||||
<template #subtitle>
|
||||
<v-icon dense class="text-subtitle-1 pr-1">mdi-webhook</v-icon>
|
||||
<code>{{ selectedWebhook.id }}</code>
|
||||
</template>
|
||||
<webhook-form
|
||||
:loading.sync="loading"
|
||||
:stream-id="$attrs.streamId"
|
||||
:webhook-id="selectedWebhook.id"
|
||||
@refetch-webhooks="refetchWebhooks"
|
||||
/>
|
||||
</admin-card>
|
||||
|
||||
<admin-card v-else-if="$route.name === 'add webhook'" :loading="loading" title="Add Webhook">
|
||||
<webhook-form
|
||||
:loading.sync="loading"
|
||||
:stream-id="$attrs.streamId"
|
||||
@refetch-webhooks="refetchWebhooks"
|
||||
/>
|
||||
</admin-card>
|
||||
|
||||
<admin-card v-else title="Webhooks">
|
||||
<template #menu>
|
||||
<v-btn
|
||||
small
|
||||
outlined
|
||||
color="primary"
|
||||
:to="`/settings/streams/${$attrs.streamId}/webhooks/new`"
|
||||
>
|
||||
Add Webhook
|
||||
</v-btn>
|
||||
</template>
|
||||
|
||||
<v-card-text v-if="webhooks.length == 0">
|
||||
You don't have any webhooks on this stream yet. Click the blue "Add Webhook" button in the top
|
||||
right to add one.
|
||||
</v-card-text>
|
||||
|
||||
<v-list subheader two-line>
|
||||
<v-list-item
|
||||
v-for="wh in webhooks"
|
||||
:key="wh.id"
|
||||
:to="`/settings/streams/${$attrs.streamId}/webhooks/edit/${wh.id}`"
|
||||
>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>
|
||||
<v-tooltip left>
|
||||
<template #activator="{ on }" class="ml-1">
|
||||
<v-icon class="pb-2 pr-1" small :color="wh.statusIcon.color" v-on="on">
|
||||
{{ wh.statusIcon.icon }}
|
||||
</v-icon>
|
||||
</template>
|
||||
<span>{{ getStatusInfo(wh) }}</span>
|
||||
</v-tooltip>
|
||||
<span id="description">
|
||||
{{ wh.description ? wh.description : `webhook ${wh.id}` }}
|
||||
</span>
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle>{{ wh.url }}</v-list-item-subtitle>
|
||||
<v-list-item-subtitle>{{ `( ${wh.triggers.join(', ')} )` }}</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</admin-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import webhooksQuery from '../../graphql/webhooks.gql'
|
||||
export default {
|
||||
name: 'SettingsWebhooks',
|
||||
components: {
|
||||
AdminCard: () => import('@/components/admin/AdminCard'),
|
||||
WebhookForm: () => import('@/components/settings/WebhookForm')
|
||||
},
|
||||
props: {
|
||||
userRole: {
|
||||
type: String,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
apollo: {
|
||||
webhooks: {
|
||||
query: webhooksQuery,
|
||||
variables() {
|
||||
return {
|
||||
streamId: this.$attrs.streamId
|
||||
}
|
||||
},
|
||||
update(data) {
|
||||
let webhooks = data.stream.webhooks.items
|
||||
webhooks.forEach((wh) => {
|
||||
wh.statusIcon = this.getStatusIcon(wh)
|
||||
})
|
||||
return webhooks
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
selectedWebhook() {
|
||||
if (this.$apollo.loading || !this.$attrs.webhookId) return
|
||||
|
||||
return this.webhooks.find(({ id }) => id === this.$attrs.webhookId)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getStatusIcon(webhook) {
|
||||
let status = 5 // default 5 if no events
|
||||
if (webhook.history.items.length) status = webhook.history.items[0].status
|
||||
switch (status) {
|
||||
case 0:
|
||||
case 1:
|
||||
return { color: 'amber', icon: 'mdi-alert-outline' }
|
||||
case 2:
|
||||
return { color: 'green', icon: 'mdi-check' }
|
||||
case 3:
|
||||
return { color: 'red', icon: 'mdi-close' }
|
||||
|
||||
default:
|
||||
return { color: 'blue-grey', icon: 'mdi-alert-circle-outline' }
|
||||
}
|
||||
},
|
||||
getStatusInfo(webhook) {
|
||||
if (!webhook.history.items.length) return 'No events yet'
|
||||
let msg = webhook.history.items[0].statusInfo
|
||||
|
||||
return msg
|
||||
},
|
||||
refetchWebhooks() {
|
||||
this.$apollo.queries.webhooks.refetch()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#description {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 300px;
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
@@ -1,136 +0,0 @@
|
||||
<template>
|
||||
<v-container v-if="isOwner">
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="4" lg="3" xl="3" class="pt-md-10">
|
||||
<v-card id="sideMenu" elevation="1" class="rounded-lg overflow-hidden">
|
||||
<v-card-title class="tmr-8 display-1 text--secondary">
|
||||
{{ stream.name }}
|
||||
<br />
|
||||
<v-btn block plain small class="justify-start mt-3 pa-0" :to="'/streams/' + stream.id">
|
||||
<v-icon small>mdi-chevron-left</v-icon>
|
||||
back to stream
|
||||
</v-btn>
|
||||
</v-card-title>
|
||||
<div v-for="child in childRoutes" :key="child.to">
|
||||
<router-link v-slot="{ isActive, navigate }" :to="child.to">
|
||||
<v-hover v-slot="{ hover }">
|
||||
<span
|
||||
:class="{ 'active-border primary--text': isActive, 'primary--text': hover }"
|
||||
class="pa-2 pl-6 text-left d-flex menu-item bold"
|
||||
@click="navigate"
|
||||
>
|
||||
{{ child.name }}
|
||||
</span>
|
||||
</v-hover>
|
||||
</router-link>
|
||||
</div>
|
||||
</v-card>
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" sm="12" md="8" lg="9" xl="9" class="pt-md-10">
|
||||
<v-fade-transition mode="out-in">
|
||||
<router-view :user-role="userRole" />
|
||||
</v-fade-transition>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
<v-container v-else-if="!isOwner && !$apollo.loading">
|
||||
<v-card>
|
||||
<v-card-text class="text-center">
|
||||
<v-icon size="50" color="error">mdi-alert</v-icon>
|
||||
<h3>Sorry...but maybe you shouldn't be here!</h3>
|
||||
<p>
|
||||
Either this stream does not exist or you do not have the required permissions to edit this
|
||||
stream's settings.
|
||||
</p>
|
||||
<v-btn @click="$router.back()">Go back</v-btn>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import streamQuery from '../../graphql/stream.gql'
|
||||
|
||||
export default {
|
||||
name: 'Settings',
|
||||
components: {},
|
||||
apollo: {
|
||||
stream: {
|
||||
query: streamQuery,
|
||||
variables() {
|
||||
return {
|
||||
id: this.$attrs.streamId
|
||||
}
|
||||
},
|
||||
error(err) {
|
||||
if (err.message) this.error = err.message.replace('GraphQL error: ', '')
|
||||
else this.error = err
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
childRoutes: [
|
||||
{
|
||||
name: 'General',
|
||||
to: `/settings/streams/${this.$attrs.streamId}/general`
|
||||
},
|
||||
{
|
||||
name: 'Webhooks',
|
||||
to: `/settings/streams/${this.$attrs.streamId}/webhooks`
|
||||
},
|
||||
{
|
||||
name: 'Globals',
|
||||
to: `/settings/streams/${this.$attrs.streamId}/globals`
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
userRole() {
|
||||
let uuid = localStorage.getItem('uuid')
|
||||
if (!uuid) return null
|
||||
if (this.$apollo.loading) return null
|
||||
if (!this.stream) return null
|
||||
let contrib = this.stream.collaborators.find((u) => u.id === uuid)
|
||||
if (contrib) return contrib.role.split(':')[1]
|
||||
else return null
|
||||
},
|
||||
isOwner() {
|
||||
return this.userRole === 'owner'
|
||||
}
|
||||
},
|
||||
methods: {}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.gray-border {
|
||||
border-top: 1pt solid var(--v-background-base) !important;
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
border-top: 1pt solid var(--v-background-base) !important;
|
||||
cursor: pointer;
|
||||
transition: 0.1s all ease-out, border-top-color 0s;
|
||||
|
||||
&::before {
|
||||
@include speckle-gradient-bg;
|
||||
|
||||
position: absolute;
|
||||
content: '';
|
||||
width: 0;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
transition: all 0.1s ease-in-out, border-top-color 0s;
|
||||
}
|
||||
|
||||
&.active-border::before {
|
||||
width: 4pt;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+65
-31
@@ -1,5 +1,43 @@
|
||||
<template>
|
||||
<v-row v-if="!error">
|
||||
<v-col v-if="stream">
|
||||
<v-breadcrumbs class="display-1" :items="breadcrumbs" divider="/"></v-breadcrumbs>
|
||||
<h3 class="title font-italic font-weight-thin my-5">
|
||||
{{ truncate(stream.description) }}
|
||||
</h3>
|
||||
<div>
|
||||
<v-chip>
|
||||
<v-icon small>mdi-source-branch</v-icon>
|
||||
|
||||
{{ stream.branches.totalCount }}
|
||||
branch{{ stream.branches.totalCount === 1 ? '' : 'es' }}
|
||||
</v-chip>
|
||||
<v-chip class="ml-3">
|
||||
<v-icon small>mdi-source-commit</v-icon>
|
||||
|
||||
|
||||
{{ stream.commits.totalCount }}
|
||||
commit{{ stream.commits.totalCount === 1 ? '' : 's' }}
|
||||
</v-chip>
|
||||
<v-chip class="ml-3">
|
||||
<span
|
||||
v-if="stream.isPublic"
|
||||
v-tooltip="`Anyone can view this stream. Only you and collaborators can edit it.`"
|
||||
>
|
||||
<v-icon small>mdi-lock-open-variant-outline</v-icon>
|
||||
public
|
||||
</span>
|
||||
<span v-else v-tooltip="`Only collaborators can access this stream.`">
|
||||
<v-icon small>mdi-lock-outline</v-icon>
|
||||
private
|
||||
</span>
|
||||
</v-chip>
|
||||
<span class="ml-3 caption">
|
||||
Created
|
||||
<timeago v-tooltip="formatDate(stream.createdAt)" :datetime="stream.createdAt"></timeago>
|
||||
</span>
|
||||
</div>
|
||||
</v-col>
|
||||
<v-col sm="12">
|
||||
<v-card v-if="$apollo.queries.branches.loading">
|
||||
<v-skeleton-loader type="card-heading, card-avatar, article"></v-skeleton-loader>
|
||||
@@ -208,7 +246,7 @@
|
||||
</v-card>
|
||||
|
||||
<v-card
|
||||
v-if="$apollo.queries.description.loading || $apollo.queries.branches.loading"
|
||||
v-if="$apollo.queries.stream.loading || $apollo.queries.branches.loading"
|
||||
class="mt-5"
|
||||
>
|
||||
<v-skeleton-loader type="article"></v-skeleton-loader>
|
||||
@@ -222,17 +260,16 @@
|
||||
</v-row>
|
||||
</template>
|
||||
<script>
|
||||
import marked from 'marked'
|
||||
import DOMPurify from 'dompurify'
|
||||
import streamQuery from '@/graphql/stream.gql'
|
||||
import gql from 'graphql-tag'
|
||||
import NoDataPlaceholder from '../components/NoDataPlaceholder'
|
||||
import SourceAppAvatar from '../components/SourceAppAvatar'
|
||||
import streamBranchesQuery from '../graphql/streamBranches.gql'
|
||||
import Renderer from '../components/Renderer'
|
||||
import UserAvatar from '../components/UserAvatar'
|
||||
import ErrorBlock from '../components/ErrorBlock'
|
||||
import BranchNewDialog from '../components/dialogs/BranchNewDialog'
|
||||
import BranchEditDialog from '../components/dialogs/BranchEditDialog'
|
||||
import NoDataPlaceholder from '@/components/NoDataPlaceholder'
|
||||
import SourceAppAvatar from '@/components/SourceAppAvatar'
|
||||
import streamBranchesQuery from '@/graphql/streamBranches.gql'
|
||||
import Renderer from '@/components/Renderer'
|
||||
import UserAvatar from '@/components/UserAvatar'
|
||||
import ErrorBlock from '@/components/ErrorBlock'
|
||||
import BranchNewDialog from '@/components/dialogs/BranchNewDialog'
|
||||
import BranchEditDialog from '@/components/dialogs/BranchEditDialog'
|
||||
|
||||
export default {
|
||||
name: 'StreamMain',
|
||||
@@ -273,21 +310,13 @@ export default {
|
||||
return data.stream.branches.items.filter((b) => !b.name.startsWith('globals'))
|
||||
}
|
||||
},
|
||||
description: {
|
||||
query: gql`
|
||||
query($id: String!) {
|
||||
stream(id: $id) {
|
||||
id
|
||||
description
|
||||
}
|
||||
}
|
||||
`,
|
||||
stream: {
|
||||
query: streamQuery,
|
||||
variables() {
|
||||
return {
|
||||
id: this.$route.params.streamId
|
||||
}
|
||||
},
|
||||
update: (data) => data.stream.description
|
||||
}
|
||||
},
|
||||
commitNotif: {
|
||||
query: gql`
|
||||
@@ -365,11 +394,6 @@ export default {
|
||||
if (!this.branches) return []
|
||||
return this.branches.map((b) => b.name)
|
||||
},
|
||||
compiledStreamDescription() {
|
||||
if (!this.description) return ''
|
||||
let md = marked(this.description)
|
||||
return DOMPurify.sanitize(md)
|
||||
},
|
||||
latestCommit() {
|
||||
if (!this.selectedBranch) return null
|
||||
return this.selectedBranch.commits.items[0]
|
||||
@@ -396,12 +420,22 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.$apollo.queries.branches.refetch()
|
||||
this.$apollo.queries.description.refetch()
|
||||
this.$apollo.queries.stream.refetch()
|
||||
},
|
||||
methods: {
|
||||
closeDescription() {
|
||||
this.dialogDescription = false
|
||||
this.$apollo.queries.description.refetch()
|
||||
truncate(input, length = 250) {
|
||||
if (!input) return ''
|
||||
if (input.length > length) {
|
||||
return input.substring(0, length) + '...'
|
||||
}
|
||||
return input
|
||||
},
|
||||
formatDate(d) {
|
||||
if (!this.stream) return null
|
||||
let date = new Date(d)
|
||||
let options = { year: 'numeric', month: 'short', day: 'numeric' }
|
||||
|
||||
return date.toLocaleString(undefined, options)
|
||||
},
|
||||
editBranch() {
|
||||
this.$refs.editBranchDialog.open(this.selectedBranch).then((dialog) => {
|
||||
+10
-34
@@ -5,6 +5,7 @@
|
||||
<v-skeleton-loader type="article, article"></v-skeleton-loader>
|
||||
</v-col>
|
||||
<v-col v-else-if="stream.branch" cols="12">
|
||||
<breadcrumb-title />
|
||||
<v-card class="pa-4" elevation="0" rounded="lg">
|
||||
<branch-edit-dialog ref="editBranchDialog" />
|
||||
|
||||
@@ -15,7 +16,6 @@
|
||||
<v-btn
|
||||
v-if="userRole === 'contributor' || userRole === 'owner'"
|
||||
small
|
||||
plain
|
||||
color="primary"
|
||||
text
|
||||
class="px-0"
|
||||
@@ -25,7 +25,7 @@
|
||||
Edit branch
|
||||
</v-btn>
|
||||
</v-card-title>
|
||||
<v-breadcrumbs :items="breadcrumbs" divider="/"></v-breadcrumbs>
|
||||
|
||||
<v-card-text v-if="stream.branch.description">
|
||||
{{ stream.branch.description }}
|
||||
</v-card-text>
|
||||
@@ -63,15 +63,17 @@
|
||||
</template>
|
||||
<script>
|
||||
import gql from 'graphql-tag'
|
||||
import branchQuery from '../graphql/branch.gql'
|
||||
import ListItemCommit from '../components/ListItemCommit'
|
||||
import BranchEditDialog from '../components/dialogs/BranchEditDialog'
|
||||
import NoDataPlaceholder from '../components/NoDataPlaceholder'
|
||||
import ErrorBlock from '../components/ErrorBlock'
|
||||
import branchQuery from '@/graphql/branch.gql'
|
||||
|
||||
export default {
|
||||
name: 'Branch',
|
||||
components: { ListItemCommit, BranchEditDialog, NoDataPlaceholder, ErrorBlock },
|
||||
components: {
|
||||
ListItemCommit: () => import('@/components/ListItemCommit'),
|
||||
BranchEditDialog: () => import('@/components/dialogs/BranchEditDialog'),
|
||||
NoDataPlaceholder: () => import('@/components/NoDataPlaceholder'),
|
||||
ErrorBlock: () => import('@/components/ErrorBlock'),
|
||||
BreadcrumbTitle: () => import('@/components/BreadcrumbTitle')
|
||||
},
|
||||
props: {
|
||||
userRole: {
|
||||
type: String,
|
||||
@@ -114,32 +116,6 @@ export default {
|
||||
computed: {
|
||||
streamId() {
|
||||
return this.$route.params.streamId
|
||||
},
|
||||
breadcrumbs() {
|
||||
return [
|
||||
{
|
||||
text: this.stream.name,
|
||||
disabled: false,
|
||||
exact: true,
|
||||
to: '/streams/' + this.stream.id
|
||||
},
|
||||
{
|
||||
text: 'branches',
|
||||
disabled: false,
|
||||
exact: true,
|
||||
to: '/streams/' + this.stream.id + '/branches/'
|
||||
},
|
||||
{
|
||||
text: this.stream.branch.name,
|
||||
disabled: true,
|
||||
exact: true,
|
||||
to:
|
||||
'/streams/' +
|
||||
this.stream.id +
|
||||
'/branches/' +
|
||||
encodeURIComponent(this.stream.branch.name)
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
+10
-26
@@ -1,10 +1,11 @@
|
||||
<template>
|
||||
<v-row>
|
||||
<v-col sm="12">
|
||||
<v-card v-if="$apollo.queries.stream.loading">
|
||||
<v-skeleton-loader type="article"></v-skeleton-loader>
|
||||
</v-card>
|
||||
<v-card v-else rounded="lg" class="pa-4 mb-4" elevation="0">
|
||||
<v-col v-if="$apollo.queries.stream.loading">
|
||||
<v-skeleton-loader type="article"></v-skeleton-loader>
|
||||
</v-col>
|
||||
<v-col v-else-if="branches" cols="12">
|
||||
<breadcrumb-title />
|
||||
<v-card rounded="lg" class="pa-4 mb-4" elevation="0">
|
||||
<branch-new-dialog ref="newBranchDialog" />
|
||||
|
||||
<v-card-title>
|
||||
@@ -14,7 +15,6 @@
|
||||
<v-spacer />
|
||||
<v-btn
|
||||
v-if="userRole === 'contributor' || userRole === 'owner'"
|
||||
plain
|
||||
color="primary"
|
||||
text
|
||||
class="px-0"
|
||||
@@ -25,7 +25,6 @@
|
||||
New branch
|
||||
</v-btn>
|
||||
</v-card-title>
|
||||
<v-breadcrumbs :items="breadcrumbs" divider="/"></v-breadcrumbs>
|
||||
<v-card-text>
|
||||
<i>
|
||||
A branch represents an independent line of data. You can think of them as an independent
|
||||
@@ -66,14 +65,14 @@
|
||||
</v-row>
|
||||
</template>
|
||||
<script>
|
||||
import BranchNewDialog from '../components/dialogs/BranchNewDialog'
|
||||
import streamBranchesQuery from '../graphql/streamBranches.gql'
|
||||
import streamBranchesQuery from '@/graphql/streamBranches.gql'
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export default {
|
||||
name: 'StreamMain',
|
||||
components: {
|
||||
BranchNewDialog
|
||||
BranchNewDialog: () => import('@/components/dialogs/BranchNewDialog'),
|
||||
BreadcrumbTitle: () => import('@/components/BreadcrumbTitle')
|
||||
},
|
||||
props: {
|
||||
userRole: {
|
||||
@@ -139,22 +138,7 @@ export default {
|
||||
branches() {
|
||||
return this.stream.branches.items.filter((b) => !b.name.startsWith('globals'))
|
||||
},
|
||||
breadcrumbs() {
|
||||
return [
|
||||
{
|
||||
text: this.stream.name,
|
||||
disabled: false,
|
||||
exact: true,
|
||||
to: '/streams/' + this.stream.id
|
||||
},
|
||||
{
|
||||
text: 'branches',
|
||||
disabled: true,
|
||||
exact: true,
|
||||
to: '/streams/' + this.stream.id + '/branches/'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
loggedIn() {
|
||||
return localStorage.getItem('uuid') !== null
|
||||
}
|
||||
+15
-50
@@ -7,6 +7,8 @@
|
||||
</v-card>
|
||||
</v-col>
|
||||
<v-col v-else-if="stream.commit" cols="12">
|
||||
<breadcrumb-title />
|
||||
|
||||
<v-card elevation="0" rounded="lg">
|
||||
<v-sheet class="pa-4" color="transparent">
|
||||
<commit-edit-dialog ref="commitDialog"></commit-edit-dialog>
|
||||
@@ -18,17 +20,16 @@
|
||||
v-if="userRole === 'contributor' || userRole === 'owner'"
|
||||
v-tooltip="'Edit commit details'"
|
||||
small
|
||||
plain
|
||||
color="primary"
|
||||
text
|
||||
class="px-0"
|
||||
@click="editCommit"
|
||||
>
|
||||
<v-icon small class="mr-2 float-left">mdi-cog-outline</v-icon>
|
||||
Edit
|
||||
Edit commit
|
||||
</v-btn>
|
||||
</v-card-title>
|
||||
<v-breadcrumbs :items="breadcrumbs" divider="/"></v-breadcrumbs>
|
||||
|
||||
<v-list-item dense>
|
||||
<v-list-item-icon class="mr-2 mt-1">
|
||||
<user-avatar
|
||||
@@ -107,25 +108,20 @@
|
||||
</template>
|
||||
<script>
|
||||
import gql from 'graphql-tag'
|
||||
import UserAvatar from '../components/UserAvatar'
|
||||
import ObjectSpeckleViewer from '../components/ObjectSpeckleViewer'
|
||||
import ObjectSimpleViewer from '../components/ObjectSimpleViewer'
|
||||
import Renderer from '../components/Renderer'
|
||||
import streamCommitQuery from '../graphql/commit.gql'
|
||||
import CommitEditDialog from '../components/dialogs/CommitEditDialog'
|
||||
import SourceAppAvatar from '../components/SourceAppAvatar'
|
||||
import ErrorBlock from '../components/ErrorBlock'
|
||||
|
||||
import streamCommitQuery from '@/graphql/commit.gql'
|
||||
|
||||
export default {
|
||||
name: 'Commit',
|
||||
name: 'Branch',
|
||||
components: {
|
||||
CommitEditDialog,
|
||||
UserAvatar,
|
||||
ObjectSpeckleViewer,
|
||||
ObjectSimpleViewer,
|
||||
Renderer,
|
||||
SourceAppAvatar,
|
||||
ErrorBlock
|
||||
CommitEditDialog: () => import('@/components/dialogs/CommitEditDialog'),
|
||||
UserAvatar: () => import('@/components/UserAvatar'),
|
||||
ObjectSpeckleViewer: () => import('@/components/ObjectSpeckleViewer'),
|
||||
ObjectSimpleViewer: () => import('@/components/ObjectSimpleViewer'),
|
||||
Renderer: () => import('@/components/Renderer'),
|
||||
SourceAppAvatar: () => import('@/components/SourceAppAvatar'),
|
||||
ErrorBlock: () => import('@/components/ErrorBlock'),
|
||||
BreadcrumbTitle: () => import('@/components/BreadcrumbTitle')
|
||||
},
|
||||
props: {
|
||||
userRole: {
|
||||
@@ -166,37 +162,6 @@ export default {
|
||||
},
|
||||
commitObjectUrl() {
|
||||
return `${window.location.origin}/streams/${this.stream.id}/objects/${this.commitObject.referencedId}`
|
||||
},
|
||||
breadcrumbs() {
|
||||
return [
|
||||
{
|
||||
text: this.stream.name,
|
||||
disabled: false,
|
||||
exact: true,
|
||||
to: '/streams/' + this.stream.id
|
||||
},
|
||||
{
|
||||
text: 'branches',
|
||||
disabled: false,
|
||||
exact: true,
|
||||
to: '/streams/' + this.stream.id + '/branches/'
|
||||
},
|
||||
{
|
||||
text: this.stream.commit.branchName,
|
||||
disabled: false,
|
||||
exact: true,
|
||||
to:
|
||||
'/streams/' +
|
||||
this.stream.id +
|
||||
'/branches/' +
|
||||
encodeURIComponent(this.stream.commit.branchName) +
|
||||
'/commits'
|
||||
},
|
||||
{
|
||||
text: this.stream.commit.message,
|
||||
disabled: true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -0,0 +1,172 @@
|
||||
<template>
|
||||
<v-row>
|
||||
<v-col>
|
||||
<breadcrumb-title />
|
||||
<div v-if="!objectId && !$apollo.loading && !revealBuilder">
|
||||
<v-card :loading="loading">
|
||||
<template slot="progress">
|
||||
<v-progress-linear indeterminate></v-progress-linear>
|
||||
</template>
|
||||
<v-card-title>You don't have any globals on this stream!</v-card-title>
|
||||
<v-card-text
|
||||
v-if="$attrs['user-role'] === 'contributor' || $attrs['user-role'] === 'owner'"
|
||||
class="subtitle-1"
|
||||
>
|
||||
Globals are useful for storing design values, project requirements, notes, or any info
|
||||
you want to keep track of alongside your geometry. Would you like to create some now?
|
||||
</v-card-text>
|
||||
<v-card-text
|
||||
v-if="!($attrs['user-role'] === 'contributor') && !($attrs['user-role'] === 'owner')"
|
||||
class="subtitle-1"
|
||||
>
|
||||
Globals are useful for storing design values, project requirements, notes, or any info
|
||||
you want to keep track of alongside your geometry. You don't have permission to create
|
||||
and edit globals on this stream, but you can create your own stream to try them out!
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer />
|
||||
<v-btn
|
||||
v-if="$attrs['user-role'] === 'contributor' || $attrs['user-role'] === 'owner'"
|
||||
color="primary"
|
||||
@click="createClicked"
|
||||
>
|
||||
create globals
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</div>
|
||||
<div v-if="objectId || revealBuilder">
|
||||
<globals-builder
|
||||
:branch-name="branchName"
|
||||
:stream-id="streamId"
|
||||
:object-id="objectId"
|
||||
:commit-message="commit ? commit.message : null"
|
||||
:user-role="$attrs['user-role']"
|
||||
@new-commit="newCommit"
|
||||
/>
|
||||
<v-card v-if="!$apollo.loading && branch.commits.items.length">
|
||||
<v-card-title>History</v-card-title>
|
||||
<v-card-text>
|
||||
<list-item-commit
|
||||
v-for="item in branch.commits.items"
|
||||
:key="item.id"
|
||||
:route="`/streams/${streamId}/globals/${item.id}`"
|
||||
:commit="item"
|
||||
:stream-id="streamId"
|
||||
/>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</div>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import gql from 'graphql-tag'
|
||||
import branchQuery from '@/graphql/branch.gql'
|
||||
|
||||
export default {
|
||||
name: 'Globals',
|
||||
components: {
|
||||
GlobalsBuilder: () => import('@/components/GlobalsBuilder'),
|
||||
ListItemCommit: () => import('@/components/ListItemCommit'),
|
||||
BreadcrumbTitle: () => import('@/components/BreadcrumbTitle')
|
||||
},
|
||||
apollo: {
|
||||
stream: {
|
||||
query: gql`
|
||||
query Stream($id: String!) {
|
||||
stream(id: $id) {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables() {
|
||||
return {
|
||||
id: this.$route.params.streamId
|
||||
}
|
||||
}
|
||||
},
|
||||
branch: {
|
||||
query: branchQuery,
|
||||
variables() {
|
||||
return {
|
||||
streamId: this.streamId,
|
||||
branchName: this.branchName
|
||||
}
|
||||
},
|
||||
update(data) {
|
||||
return data.stream.branch
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
branchName: 'globals', //TODO: handle multipile globals branches,
|
||||
|
||||
revealBuilder: false,
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
breadcrumbs() {
|
||||
return [
|
||||
{
|
||||
text: this.stream.name,
|
||||
disabled: false,
|
||||
exact: true,
|
||||
to: '/streams/' + this.stream.id
|
||||
},
|
||||
{
|
||||
text: 'globals',
|
||||
disabled: true
|
||||
}
|
||||
]
|
||||
},
|
||||
streamId() {
|
||||
return this.$route.params.streamId
|
||||
},
|
||||
commit() {
|
||||
return this.$route.params.commitId
|
||||
? this.branch?.commits?.items?.filter((c) => c.id == this.$route.params.commitId)[0]
|
||||
: this.branch?.commits?.items[0]
|
||||
},
|
||||
objectId() {
|
||||
return this.commit?.referencedObject
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async createClicked() {
|
||||
if (!this.branch) {
|
||||
this.loading = true
|
||||
this.$matomo && this.$matomo.trackPageView('globals/branch/create')
|
||||
await this.$apollo.mutate({
|
||||
mutation: gql`
|
||||
mutation branchCreate($params: BranchCreateInput!) {
|
||||
branchCreate(branch: $params)
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
params: {
|
||||
streamId: this.streamId,
|
||||
name: 'globals',
|
||||
description: 'Stream globals'
|
||||
}
|
||||
}
|
||||
})
|
||||
this.$apollo.queries.branch.refetch()
|
||||
this.loading = false
|
||||
}
|
||||
|
||||
this.revealBuilder = true
|
||||
},
|
||||
newCommit() {
|
||||
this.$apollo.queries.branch.refetch()
|
||||
if (this.$route.params.commitId) this.$router.push(`/streams/${this.streamId}/globals`)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
+3
-3
@@ -43,9 +43,9 @@
|
||||
</v-row>
|
||||
</template>
|
||||
<script>
|
||||
import ObjectSpeckleViewer from '../components/ObjectSpeckleViewer'
|
||||
import ObjectSimpleViewer from '../components/ObjectSimpleViewer'
|
||||
import Renderer from '../components/Renderer'
|
||||
import ObjectSpeckleViewer from '@/components/ObjectSpeckleViewer'
|
||||
import ObjectSimpleViewer from '@/components/ObjectSimpleViewer'
|
||||
import Renderer from '@/components/Renderer'
|
||||
|
||||
export default {
|
||||
name: 'ObjectViewer',
|
||||
@@ -0,0 +1,354 @@
|
||||
<template>
|
||||
<v-container :fluid="$vuetify.breakpoint.mdAndDown">
|
||||
<v-navigation-drawer app clipped left>
|
||||
<v-card-text v-if="stream">
|
||||
<!-- <div v-if="isHomeRoute">
|
||||
<v-btn
|
||||
v-if="userRole === 'owner'"
|
||||
small
|
||||
color="primary"
|
||||
text
|
||||
class="px-0"
|
||||
@click="editStreamDialog = true"
|
||||
>
|
||||
<v-icon small class="mr-2 float-left">mdi-pencil-outline</v-icon>
|
||||
Edit details
|
||||
</v-btn>
|
||||
<v-btn
|
||||
v-if="userRole === 'owner'"
|
||||
small
|
||||
color="primary"
|
||||
text
|
||||
class="px-0 d-block"
|
||||
@click="dialogShare = true"
|
||||
>
|
||||
<v-icon small class="mr-2">mdi-account-multiple</v-icon>
|
||||
Manage collaboratos
|
||||
</v-btn> -->
|
||||
|
||||
<!-- <v-btn
|
||||
v-tooltip="'Edit stream global variables!'"
|
||||
small
|
||||
plain
|
||||
color="primary"
|
||||
text
|
||||
class="px-0 d-block justify-start"
|
||||
:to="`/streams/${stream.id}/globals`"
|
||||
>
|
||||
Manage Globals
|
||||
</v-btn> -->
|
||||
|
||||
<!-- <v-btn
|
||||
v-if="userRole === 'owner'"
|
||||
small
|
||||
color="primary"
|
||||
text
|
||||
left
|
||||
class="px-0"
|
||||
:to="`/streams/${stream.id}/settings/general`"
|
||||
@click.prevent=""
|
||||
>
|
||||
<v-icon small class="mr-2">mdi-cog-outline</v-icon>
|
||||
Settings
|
||||
</v-btn>
|
||||
|
||||
<v-btn
|
||||
v-if="userRole === 'owner'"
|
||||
small
|
||||
plain
|
||||
color="primary"
|
||||
text
|
||||
class="px-0 d-block"
|
||||
@click="showStreamInviteDialog"
|
||||
>
|
||||
<v-icon small class="mr-2">mdi-email-send-outline</v-icon>
|
||||
Invite to this stream
|
||||
</v-btn>
|
||||
|
||||
<v-dialog v-model="editStreamDialog" max-width="500">
|
||||
<stream-edit-dialog
|
||||
:stream-id="stream.id"
|
||||
:name="stream.name"
|
||||
:description="stream.description"
|
||||
:is-public="stream.isPublic"
|
||||
:open="editStreamDialog"
|
||||
@close="editClosed"
|
||||
/>
|
||||
</v-dialog>
|
||||
|
||||
<v-card-title><h5>Collaborators</h5></v-card-title>
|
||||
|
||||
<v-row no-gutters>
|
||||
<template v-for="(collab, i) in stream.collaborators">
|
||||
<v-col :key="i" cols="3" class="mb-2">
|
||||
<user-avatar
|
||||
:id="collab.id"
|
||||
:size="40"
|
||||
:avatar="collab.avatar"
|
||||
:name="collab.name"
|
||||
></user-avatar>
|
||||
</v-col>
|
||||
<v-col :key="collab.id" cols="9" class="mb-2 hidden-sm-and-down">
|
||||
<span class="text-body-2">{{ collab.name }}</span>
|
||||
<br />
|
||||
<span class="caption">{{ collab.role.split(':')[1] }}</span>
|
||||
</v-col>
|
||||
</template>
|
||||
</v-row>
|
||||
|
||||
<stream-invite-dialog ref="streamInviteDialog" :stream-id="stream.id" />
|
||||
<v-dialog v-if="userId" v-model="dialogShare" max-width="500">
|
||||
<stream-share-dialog
|
||||
:users="stream.collaborators"
|
||||
:stream-id="stream.id"
|
||||
:user-id="userId"
|
||||
@close="dialogShare = false"
|
||||
></stream-share-dialog>
|
||||
</v-dialog> -->
|
||||
<!-- </div> -->
|
||||
</v-card-text>
|
||||
|
||||
<v-list>
|
||||
<v-list-item
|
||||
v-for="menu in menues"
|
||||
:key="menu.name"
|
||||
:to="menu.to"
|
||||
exact
|
||||
@click="handleFunction(menu.click)"
|
||||
>
|
||||
<v-list-item-icon>
|
||||
<v-icon>{{ menu.icon }}</v-icon>
|
||||
</v-list-item-icon>
|
||||
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>{{ menu.name }}</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-navigation-drawer>
|
||||
<v-row v-if="stream">
|
||||
<!-- <v-col cols="12" sm="12" md="4" lg="3" xl="3">
|
||||
<sidebar-stream :user-role="userRole"></sidebar-stream>
|
||||
</v-col> -->
|
||||
|
||||
<v-col cols="12" class="pt-10">
|
||||
<router-view :user-role="userRole"></router-view>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row v-else-if="error" justify="center">
|
||||
<v-col cols="12" class="pt-10">
|
||||
<error-block :message="error" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-snackbar
|
||||
v-if="commitSnackbarInfo"
|
||||
v-model="commitSnackbar"
|
||||
:timeout="5000"
|
||||
color="primary"
|
||||
absolute
|
||||
right
|
||||
top
|
||||
>
|
||||
New commit
|
||||
<i>{{ commitSnackbarInfo.message }}</i>
|
||||
on
|
||||
<i>{{ commitSnackbarInfo.branchName }}</i>
|
||||
<template #action="{ attrs }">
|
||||
<v-btn
|
||||
text
|
||||
v-bind="attrs"
|
||||
:to="'/streams/' + $route.params.streamId + '/commits/' + commitSnackbarInfo.id"
|
||||
@click="commitSnackbar = false"
|
||||
>
|
||||
see
|
||||
</v-btn>
|
||||
<v-btn icon v-bind="attrs" @click="commitSnackbar = false">
|
||||
<v-icon>mdi-close</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-snackbar>
|
||||
<stream-invite-dialog v-if="stream" ref="streamInviteDialog" :stream-id="stream.id" />
|
||||
<v-dialog v-if="userId && stream" v-model="dialogShare" max-width="500">
|
||||
<stream-share-dialog
|
||||
:users="stream.collaborators"
|
||||
:stream-id="stream.id"
|
||||
:user-id="userId"
|
||||
@close="dialogShare = false"
|
||||
></stream-share-dialog>
|
||||
</v-dialog>
|
||||
<v-dialog v-model="editStreamDialog" max-width="500">
|
||||
<stream-edit-dialog
|
||||
v-if="stream"
|
||||
:stream-id="stream.id"
|
||||
:name="stream.name"
|
||||
:description="stream.description"
|
||||
:is-public="stream.isPublic"
|
||||
:open="editStreamDialog"
|
||||
@close="editClosed"
|
||||
/>
|
||||
</v-dialog>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ErrorBlock from '@/components/ErrorBlock'
|
||||
import streamQuery from '@/graphql/stream.gql'
|
||||
import gql from 'graphql-tag'
|
||||
import StreamInviteDialog from '@/components/dialogs/StreamInviteDialog'
|
||||
import StreamEditDialog from '@/components/dialogs/StreamEditDialog'
|
||||
import StreamShareDialog from '@/components/dialogs/StreamShareDialog'
|
||||
|
||||
export default {
|
||||
name: 'Stream',
|
||||
components: {
|
||||
ErrorBlock,
|
||||
StreamInviteDialog,
|
||||
StreamShareDialog,
|
||||
StreamEditDialog
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
error: '',
|
||||
commitSnackbar: false,
|
||||
commitSnackbarInfo: {},
|
||||
editStreamDialog: false,
|
||||
dialogShare: false,
|
||||
menues: [
|
||||
{ name: 'Activity', icon: 'mdi-history', to: '/streams/' + this.$route.params.streamId },
|
||||
{
|
||||
name: 'Branches',
|
||||
icon: 'mdi-source-branch',
|
||||
to: '/streams/' + this.$route.params.streamId + '/branches'
|
||||
},
|
||||
{
|
||||
name: 'Collaborators',
|
||||
icon: 'mdi-account-group-outline',
|
||||
click: 'manageCollabrators'
|
||||
},
|
||||
{
|
||||
name: 'Globals',
|
||||
icon: 'mdi-earth',
|
||||
to: '/streams/' + this.$route.params.streamId + '/globals'
|
||||
},
|
||||
{
|
||||
name: 'Webhooks',
|
||||
icon: 'mdi-webhook',
|
||||
to: '/streams/' + this.$route.params.streamId + '/webhooks'
|
||||
},
|
||||
{
|
||||
name: 'Settings',
|
||||
icon: 'mdi-cog-outline',
|
||||
click: 'editStream'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
apollo: {
|
||||
stream: {
|
||||
query: streamQuery,
|
||||
variables() {
|
||||
return {
|
||||
id: this.$route.params.streamId
|
||||
}
|
||||
},
|
||||
error(err) {
|
||||
if (err.message) this.error = err.message.replace('GraphQL error: ', '')
|
||||
else this.error = err
|
||||
}
|
||||
},
|
||||
$subscribe: {
|
||||
streamUpdated: {
|
||||
query: gql`
|
||||
subscription($id: String!) {
|
||||
streamUpdated(streamId: $id)
|
||||
}
|
||||
`,
|
||||
variables() {
|
||||
return {
|
||||
id: this.$route.params.streamId
|
||||
}
|
||||
},
|
||||
result(info) {
|
||||
this.$apollo.queries.stream.refetch()
|
||||
},
|
||||
skip() {
|
||||
return !this.loggedIn
|
||||
}
|
||||
},
|
||||
commitCreated: {
|
||||
query: gql`
|
||||
subscription($streamId: String!) {
|
||||
commitCreated(streamId: $streamId)
|
||||
}
|
||||
`,
|
||||
variables() {
|
||||
return {
|
||||
streamId: this.$route.params.streamId
|
||||
}
|
||||
},
|
||||
result(commitInfo) {
|
||||
if (!commitInfo.data.commitCreated) return
|
||||
this.commitSnackbar = true
|
||||
this.commitSnackbarInfo = commitInfo.data.commitCreated
|
||||
},
|
||||
skip() {
|
||||
return !this.loggedIn
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
userId() {
|
||||
return localStorage.getItem('uuid')
|
||||
},
|
||||
userRole() {
|
||||
let uuid = localStorage.getItem('uuid')
|
||||
if (!uuid) return null
|
||||
if (this.$apollo.loading) return null
|
||||
let contrib = this.stream.collaborators.find((u) => u.id === uuid)
|
||||
if (contrib) return contrib.role.split(':')[1]
|
||||
else return null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
//open stream invite dialog if ?invite=true
|
||||
//used by desktop connectors
|
||||
if (this.$route.query.invite && this.$route.query.invite === 'true') {
|
||||
setTimeout(() => {
|
||||
this.$refs.streamInviteDialog.show()
|
||||
}, 500)
|
||||
}
|
||||
},
|
||||
loggedIn() {
|
||||
return localStorage.getItem('uuid') !== null
|
||||
},
|
||||
methods: {
|
||||
handleFunction(f) {
|
||||
if (this[f]) this[f]()
|
||||
},
|
||||
editStream() {
|
||||
this.editStreamDialog = true
|
||||
},
|
||||
manageCollabrators() {
|
||||
this.dialogShare = true
|
||||
},
|
||||
showStreamInviteDialog() {
|
||||
this.$refs.streamInviteDialog.show()
|
||||
},
|
||||
editClosed() {
|
||||
this.editStreamDialog = false
|
||||
this.$apollo.queries.stream.refetch()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.v-breadcrumbs {
|
||||
padding: 0 !important;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
.v-breadcrumbs li {
|
||||
font-size: inherit !important;
|
||||
font-weight: inherit !important;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,150 @@
|
||||
<template>
|
||||
<v-row>
|
||||
<v-col>
|
||||
<breadcrumb-title />
|
||||
<admin-card v-if="selectedWebhook != undefined" :loading="loading" title="Edit Webhook">
|
||||
<template #subtitle>
|
||||
<v-icon dense class="text-subtitle-1 pr-1">mdi-webhook</v-icon>
|
||||
<code>{{ selectedWebhook.id }}</code>
|
||||
</template>
|
||||
<webhook-form
|
||||
:loading.sync="loading"
|
||||
:stream-id="$attrs.streamId"
|
||||
:webhook-id="selectedWebhook.id"
|
||||
@refetch-webhooks="refetchWebhooks"
|
||||
/>
|
||||
</admin-card>
|
||||
|
||||
<admin-card v-else-if="$route.name === 'add webhook'" :loading="loading" title="Add Webhook">
|
||||
<webhook-form
|
||||
:loading.sync="loading"
|
||||
:stream-id="$attrs.streamId"
|
||||
@refetch-webhooks="refetchWebhooks"
|
||||
/>
|
||||
</admin-card>
|
||||
|
||||
<admin-card v-else>
|
||||
<template #menu>
|
||||
<v-btn small outlined color="primary" :to="`/streams/${$attrs.streamId}/webhooks/new`">
|
||||
Add Webhook
|
||||
</v-btn>
|
||||
</template>
|
||||
|
||||
<v-card-text v-if="webhooks.length == 0">
|
||||
You don't have any webhooks on this stream yet. Click the blue "Add Webhook" button in the
|
||||
top right to add one.
|
||||
</v-card-text>
|
||||
|
||||
<v-list subheader two-line>
|
||||
<v-list-item
|
||||
v-for="wh in webhooks"
|
||||
:key="wh.id"
|
||||
:to="`/settings/streams/${$attrs.streamId}/webhooks/edit/${wh.id}`"
|
||||
>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>
|
||||
<v-tooltip left>
|
||||
<template #activator="{ on }" class="ml-1">
|
||||
<v-icon class="pb-2 pr-1" small :color="wh.statusIcon.color" v-on="on">
|
||||
{{ wh.statusIcon.icon }}
|
||||
</v-icon>
|
||||
</template>
|
||||
<span>{{ getStatusInfo(wh) }}</span>
|
||||
</v-tooltip>
|
||||
<span id="description">
|
||||
{{ wh.description ? wh.description : `webhook ${wh.id}` }}
|
||||
</span>
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle>{{ wh.url }}</v-list-item-subtitle>
|
||||
<v-list-item-subtitle>{{ `( ${wh.triggers.join(', ')} )` }}</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</admin-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import webhooksQuery from '@/graphql/webhooks.gql'
|
||||
export default {
|
||||
name: 'SettingsWebhooks',
|
||||
components: {
|
||||
AdminCard: () => import('@/components/admin/AdminCard'),
|
||||
WebhookForm: () => import('@/components/settings/WebhookForm'),
|
||||
BreadcrumbTitle: () => import('@/components/BreadcrumbTitle')
|
||||
},
|
||||
props: {
|
||||
userRole: {
|
||||
type: String,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
apollo: {
|
||||
webhooks: {
|
||||
query: webhooksQuery,
|
||||
variables() {
|
||||
return {
|
||||
streamId: this.$attrs.streamId
|
||||
}
|
||||
},
|
||||
update(data) {
|
||||
let webhooks = data.stream.webhooks.items
|
||||
webhooks.forEach((wh) => {
|
||||
wh.statusIcon = this.getStatusIcon(wh)
|
||||
})
|
||||
return webhooks
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
selectedWebhook() {
|
||||
if (this.$apollo.loading || !this.$attrs.webhookId) return
|
||||
|
||||
return this.webhooks.find(({ id }) => id === this.$attrs.webhookId)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getStatusIcon(webhook) {
|
||||
let status = 5 // default 5 if no events
|
||||
if (webhook.history.items.length) status = webhook.history.items[0].status
|
||||
switch (status) {
|
||||
case 0:
|
||||
case 1:
|
||||
return { color: 'amber', icon: 'mdi-alert-outline' }
|
||||
case 2:
|
||||
return { color: 'green', icon: 'mdi-check' }
|
||||
case 3:
|
||||
return { color: 'red', icon: 'mdi-close' }
|
||||
|
||||
default:
|
||||
return { color: 'blue-grey', icon: 'mdi-alert-circle-outline' }
|
||||
}
|
||||
},
|
||||
getStatusInfo(webhook) {
|
||||
if (!webhook.history.items.length) return 'No events yet'
|
||||
let msg = webhook.history.items[0].statusInfo
|
||||
|
||||
return msg
|
||||
},
|
||||
refetchWebhooks() {
|
||||
this.$apollo.queries.webhooks.refetch()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#description {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 300px;
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
@@ -15,7 +15,7 @@ module.exports = {
|
||||
let stream = {
|
||||
id: crs( { length: 10 } ),
|
||||
name: name || 'Random Stream',
|
||||
description: description || 'No description provided.',
|
||||
description: description || '',
|
||||
isPublic: isPublic !== false,
|
||||
updatedAt: knex.fn.now( )
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user