Skip to content
This repository has been archived by the owner on Jan 28, 2022. It is now read-only.

Commit

Permalink
feat: Auto Discovery
Browse files Browse the repository at this point in the history
  • Loading branch information
Shepless committed May 18, 2020
1 parent 466ba56 commit 6e472f6
Show file tree
Hide file tree
Showing 14 changed files with 314 additions and 59 deletions.
Binary file added assets/images/loader.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 6 additions & 1 deletion src/components/drop-down/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
}

.selected-tick {
position: relative;
float: right;
width: 12px;
height: 12px;
Expand All @@ -88,7 +89,11 @@
line-height: 1.5;

&:after {
content: ''
content: '';
transform: translate(-50%, -50%);
top: 50%;
left: 50%;
position: absolute;
}
}
}
29 changes: 27 additions & 2 deletions src/components/sub-menus/add-integration/script.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import Vue from 'vue';
import { Component } from 'vue-property-decorator';
import { Component, Prop } from 'vue-property-decorator';
import { map } from 'rxjs/operators';
import { Guid } from 'guid-typescript';
import { Inject } from '../../../utilities/dependency-injection';
import { YioStore } from '../../../store';
import { ServerConnection } from '../../../server';
import { IKeyValuePair, IDropDownItem, IIntegrationSchema } from '../../../types';
import { IKeyValuePair, IDropDownItem, IIntegrationSchema, IDiscoveredIntegration } from '../../../types';
import { SpotifyAuthentication } from '../../../utilities/spotify-authentication';
import ActionButton from '../../action-button/index.vue';
import ActionIconButton from '../../action-icon-button/index.vue';
Expand Down Expand Up @@ -42,6 +42,12 @@ export default class AddIntegration extends Vue {
@Inject(() => SpotifyAuthentication)
public spotifyAuthentication: SpotifyAuthentication;

@Prop({
type: Object,
required: false
})
public discoveredIntegration: IDiscoveredIntegration;

public isAddingNewIntegration: boolean = this.spotifyAuthentication.isInAuthenticationCycle;
public supportedIntegrations: IKeyValuePair<IIntegrationSchema>;
public integrationTypeSelected: boolean = false;
Expand All @@ -55,6 +61,25 @@ export default class AddIntegration extends Vue {
public newDataValue: string = '';
public selectedValue: string = this.isIntegrationTypeSelectedSpotify ? 'spotify' : '';

public mounted() {
if (this.discoveredIntegration) {
this.isAddingNewIntegration = true;
const matchingItem = this.typeOptions.find((type) => type.value === this.discoveredIntegration.type);

if (matchingItem) {
this.selectedValue = matchingItem.value;
this.onIntegrationTypeChanged(matchingItem);
this.propertyValues.friendly_name = this.discoveredIntegration.friendly_name;

this.$nextTick().then(() => {
if (Object.keys(this.propertyValues).includes('ip')) {
this.propertyValues.ip = this.discoveredIntegration.ip;
}
});
}
}
}

public onIntegrationTypeChanged(item: IDropDownItem) {
const selectedIntegration = this.supportedIntegrations[item.value];
const properties = selectedIntegration.properties || {};
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@
"configuredIntegrations": "Configured Integrations",
"discoveredIntegrations": "Discovered Integrations",
"addIntegration": "Add Integration",
"newIntegration": "New Integration"
"newIntegration": "New Integration",
"searchForIntegrations": "Search For Integrations On Your Network"
},
"entities": {
"title": "Entities Controlled By YIO Remote",
Expand Down
28 changes: 25 additions & 3 deletions src/pages/integrations/script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Vue from 'vue';
import { Component } from 'vue-property-decorator';
import { Inject } from '../../utilities/dependency-injection';
import { YioStore } from '../../store';
import { IIntegrationInstance, IKeyValuePair, IYioTableComponent } from '../../types';
import { IIntegrationInstance, IKeyValuePair, IYioTableComponent, IDiscoveredIntegration } from '../../types';
import { ServerConnection } from '../../server';
import YioTable from '../../components/table/index.vue';
import ActionIconButton from '../../components/action-icon-button/index.vue';
Expand All @@ -18,7 +18,9 @@ import AddIntegration from '../../components/sub-menus/add-integration/index.vue
subscriptions(this: IntegrationsPage) {
return {
integrations: this.store.integrations.configured$,
supportedIntegrations: this.store.integrations.supported$
supportedIntegrations: this.store.integrations.supported$,
discoveredIntegrations: this.store.integrations.discovered$,
isSearching: this.store.select('integrations', 'isSearchingForIntegrations')
};
}
})
Expand All @@ -29,13 +31,33 @@ export default class IntegrationsPage extends Vue {
@Inject(() => ServerConnection)
public server: ServerConnection;
public integrations: IKeyValuePair<IIntegrationInstance>;
public discoveredIntegrations: IDiscoveredIntegration[];
public supportedIntegrations: IKeyValuePair<object>;
public isSearching: boolean = false;

public mounted() {
this.$menu.show(AddIntegration, {});
}

public onItemSelected(index: number) {
public onSearchForIntegrations() {
if (this.isSearching) {
return;
}

this.isSearching = true;
this.server.discoverIntegrations().then(() => this.isSearching = false);
}

public onItemSelected(index: number, isNew: boolean) {
if (isNew) {
this.$menu.hide();
this.$menu.show(AddIntegration, {
discoveredIntegration: this.discoveredIntegrations[index],
onCancel: this.onItemDeselected
});
return;
}

const integration = this.integrations[index];
const schema = this.supportedIntegrations[integration.type];

Expand Down
42 changes: 41 additions & 1 deletion src/pages/integrations/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,48 @@
height: 100%;
}

.title {
.configured, .discovered {
display: flex;
flex-direction: column;
height: 50%;
}

.discovered-container {
display: flex;
flex-direction: row;
}

.title-container {
font-family: OpenSans;
position: relative;
}

.title {
line-height: 40px;
}

.search-container {
display: flex;
flex-direction: row;
}

.icon-search {
cursor: pointer;
}

.search-message {
font-size: 10px;
opacity: 0.5;
line-height: 40px;
}

.spinner {
margin: 12px 10px;
width: 15px;
height: 15px;
background: url('../../../assets/images/loader.gif');
background-size: contain;
background-repeat: no-repeat;
}

td {
Expand Down
89 changes: 61 additions & 28 deletions src/pages/integrations/template.html
Original file line number Diff line number Diff line change
@@ -1,30 +1,63 @@
<div class="integrations">
<h1 class="title">
{{$t('pages.integrations.configuredIntegrations')}}
</h1>
<yio-table ref="table" :items="integrations" max-height="525px" @onItemSelected="onItemSelected" @onItemsDeselected="onItemDeselected">
<template v-slot:header>
<th>
{{$t('common.name')}}
</th>
<th>
{{$t('common.type')}}
</th>
<th :style="{ width: '80px' }"></th>
</template>
<template v-slot:item="{ item }">
<td>
{{item.friendly_name}}
</td>
<td>
{{item.type}}
</td>
<td :style="{ width: '80px' }">
<action-icon-button @onClick="onItemDeleted(item)" type="delete"></action-icon-button>
</td>
</template>
</yio-table>
<h1 class="title">
{{$t('pages.integrations.discoveredIntegrations')}}
</h1>
<div class="configured">
<h1 class="title">
{{$t('pages.integrations.configuredIntegrations')}}
</h1>
<yio-table ref="table" :items="integrations" max-height="525px" @onItemSelected="(index) => onItemSelected(index, false)" @onItemsDeselected="onItemDeselected">
<template v-slot:header>
<th>
{{$t('common.name')}}
</th>
<th>
{{$t('common.type')}}
</th>
<th :style="{ width: '80px' }"></th>
</template>
<template v-slot:item="{ item }">
<td>
{{item.friendly_name}}
</td>
<td>
{{item.type}}
</td>
<td :style="{ width: '80px' }">
<action-icon-button @onClick="onItemDeleted(item)" type="delete"></action-icon-button>
</td>
</template>
</yio-table>
</div>
<div class="discovered">
<div class="discovered-container">
<div class="title-container">
<div class="title">
{{$t('pages.integrations.discoveredIntegrations')}}
</div>
</div>
<div v-if="isSearching" class="spinner"></div>
<div v-else class="search-container">
<i class="icon icon-search" @click="onSearchForIntegrations"></i>
<div class="search-message">{{$t('pages.integrations.searchForIntegrations')}}</div>
</div>
</div>
<yio-table ref="table" :items="discoveredIntegrations" max-height="525px" @onItemSelected="(index) => onItemSelected(index, true)" @onItemsDeselected="onItemDeselected">
<template v-slot:header>
<th>
{{$t('common.name')}}
</th>
<th>
{{$t('common.type')}}
</th>
<th :style="{ width: '80px' }"></th>
</template>
<template v-slot:item="{ item }">
<td>
{{item.friendly_name}}
</td>
<td>
{{item.type}}
</td>
<td :style="{ width: '80px' }"></td>
</template>
</yio-table>
</div>
</div>
8 changes: 6 additions & 2 deletions src/pages/software-update/script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,14 @@ export default class SoftwareUpdatePage extends Vue {
this.$t('pages.softwareUpdate.upToDate');
}

public updateAutoSoftwareUpdate(value: boolean) {
this.server.setAutoUpdate(value);
}

public checkForUpdate() {
this.isNewVersionAvailable = !this.isNewVersionAvailable;
console.log('TODO: API ENDPOINT NEEDED');
this.server.checkForUpdate();
}

public update() {
console.log('TODO: API ENDPOINT NEEDED');
}
Expand Down
Loading

0 comments on commit 6e472f6

Please sign in to comment.