Skip to content

Commit c4ee0a8

Browse files
authored
Add packagist requirement suggestions (#53)
Added requirement suggestions from Packagist.org
1 parent 5e1584e commit c4ee0a8

File tree

3 files changed

+98
-16
lines changed

3 files changed

+98
-16
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ All notable changes to `cybercog/laravel-paket` will be documented in this file.
99
- ([#48]) Added repositories tab
1010
- ([#51]) Added refetch data button in top menu
1111
- ([#52]) Added polling to get realtime job output
12+
- ([#53]) Added requirement suggestions from Packagist.org
1213

1314
## [1.4.0]
1415

@@ -59,6 +60,7 @@ All notable changes to `cybercog/laravel-paket` will be documented in this file.
5960
[1.2.0]: https://github.com/cybercog/laravel-paket/compare/1.1.0...1.2.0
6061
[1.1.0]: https://github.com/cybercog/laravel-paket/compare/1.0.0...1.1.0
6162

63+
[#53]: https://github.com/cybercog/laravel-paket/pull/53
6264
[#52]: https://github.com/cybercog/laravel-paket/pull/52
6365
[#51]: https://github.com/cybercog/laravel-paket/pull/51
6466
[#48]: https://github.com/cybercog/laravel-paket/pull/48

resources/js/components/Requirement/InstallForm.vue

Lines changed: 85 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,40 @@
11
<template>
2-
<div class="flex">
3-
<input
4-
type="text"
5-
:class="getInputClass()"
6-
:readonly="isDisabled()"
7-
v-model="command"
8-
v-on:keyup.enter="install()"
9-
placeholder="Type in vendor/package OR composer require vendor/package"
10-
/>
11-
<button
12-
type="submit"
13-
:class="getButtonClass()"
14-
:disabled="isDisabled()"
15-
v-text="getButtonText()"
16-
v-on:click="install()"
17-
></button>
2+
<div class="relative">
3+
<div class="flex">
4+
<input
5+
type="text"
6+
:class="getInputClass()"
7+
:readonly="isDisabled()"
8+
v-model="command"
9+
v-on:keyup.enter="install()"
10+
placeholder="Type in vendor/package OR composer require vendor/package"
11+
/>
12+
<button
13+
type="submit"
14+
:class="getButtonClass()"
15+
:disabled="isDisabled()"
16+
v-text="getButtonText()"
17+
v-on:click="install()"
18+
></button>
19+
</div>
20+
<div class="border absolute w-full" v-if="getSuggestions().length > 0">
21+
<div v-for="suggestion in getSuggestions()" class="bg-white hover:bg-gray-200 p-2 cursor-pointer" v-on:click="suggestionSelect(suggestion)">
22+
<div v-text="suggestion.name"></div>
23+
<div v-text="suggestion.description" class="text-xs text-gray-600"></div>
24+
</div>
25+
</div>
1826
</div>
1927
</template>
2028

2129
<script>
30+
import debounce from 'lodash/debounce';
31+
2232
export default {
2333
data() {
2434
return {
2535
buttonText: 'Install',
2636
command: '',
37+
selectedSuggestion: null,
2738
requirement: {
2839
name: '',
2940
version: null,
@@ -34,6 +45,23 @@
3445
};
3546
},
3647
48+
watch: {
49+
command(value, oldValue) {
50+
if (this.selectedSuggestion !== null) {
51+
this.selectedSuggestion = null;
52+
return;
53+
}
54+
55+
if (oldValue.trim() !== value.trim()) {
56+
this.debouncedSearchSuggestions(value);
57+
}
58+
},
59+
},
60+
61+
created() {
62+
this.debouncedSearchSuggestions = debounce(this.searchSuggestions, 500);
63+
},
64+
3765
methods: {
3866
async install() {
3967
this.sanitizeInput();
@@ -60,6 +88,47 @@
6088
this.forgetInput();
6189
},
6290
91+
async searchSuggestions(query) {
92+
if (query === '') {
93+
await this.$store.dispatch('clearRequirementSuggestions');
94+
return;
95+
}
96+
97+
// Ignore search if fully qualified console command
98+
if (query.includes('composer require')) {
99+
return;
100+
}
101+
102+
// Ignore search if version already specified
103+
if (query.includes(':')) {
104+
return;
105+
}
106+
107+
// Ignore search if adding flags like --dev
108+
if (query.includes('--')) {
109+
return;
110+
}
111+
112+
await this.$store.dispatch('collectRequirementSuggestions', {
113+
query: query,
114+
});
115+
},
116+
117+
suggestionSelect(suggestion) {
118+
this.selectedSuggestion = suggestion;
119+
this.command = suggestion.name;
120+
this.$store.dispatch('clearRequirementSuggestions');
121+
},
122+
123+
getSuggestions() {
124+
// Need to avoid bug with quick full delete command with holding backspace button
125+
if (this.command === '') {
126+
return [];
127+
}
128+
129+
return this.$store.state.requirementSuggestions;
130+
},
131+
63132
isDisabled() {
64133
return this.$store.state.isInstallerLocked
65134
|| this.$store.getters.getActiveJobs().length > 0;

resources/js/store.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const state = {
99
isInstallerLocked: false,
1010
installerCurrentJob: null,
1111
requirements: [],
12+
requirementSuggestions: [],
1213
repositories: [],
1314
jobs: [],
1415
protectedRequirements: [
@@ -103,6 +104,16 @@ const actions = {
103104
}
104105
}, 1000);
105106
},
107+
108+
async collectRequirementSuggestions(context, payload) {
109+
const response = await Axios.get(`https://packagist.org/search.json?q=${payload.query}`);
110+
111+
context.state.requirementSuggestions = response.data.results;
112+
},
113+
114+
clearRequirementSuggestions(context) {
115+
context.state.requirementSuggestions = [];
116+
},
106117
};
107118

108119
const getters = {

0 commit comments

Comments
 (0)