summaryrefslogtreecommitdiffstats
path: root/web_src/js/features/repo-home.js
diff options
context:
space:
mode:
Diffstat (limited to 'web_src/js/features/repo-home.js')
-rw-r--r--web_src/js/features/repo-home.js180
1 files changed, 180 insertions, 0 deletions
diff --git a/web_src/js/features/repo-home.js b/web_src/js/features/repo-home.js
new file mode 100644
index 0000000000..142698f074
--- /dev/null
+++ b/web_src/js/features/repo-home.js
@@ -0,0 +1,180 @@
+import {stripTags} from '../utils.js';
+
+const {AppSubUrl, csrf} = window.config;
+
+export function initRepoTopicBar() {
+ const mgrBtn = $('#manage_topic');
+ const editDiv = $('#topic_edit');
+ const viewDiv = $('#repo-topics');
+ const saveBtn = $('#save_topic');
+ const topicDropdown = $('#topic_edit .dropdown');
+ const topicForm = $('#topic_edit.ui.form');
+ const topicPrompts = getPrompts();
+
+ mgrBtn.on('click', () => {
+ viewDiv.hide();
+ editDiv.css('display', ''); // show Semantic UI Grid
+ });
+
+ function getPrompts() {
+ const hidePrompt = $('div.hide#validate_prompt');
+ const prompts = {
+ countPrompt: hidePrompt.children('#count_prompt').text(),
+ formatPrompt: hidePrompt.children('#format_prompt').text()
+ };
+ hidePrompt.remove();
+ return prompts;
+ }
+
+ saveBtn.on('click', () => {
+ const topics = $('input[name=topics]').val();
+
+ $.post(saveBtn.data('link'), {
+ _csrf: csrf,
+ topics
+ }, (_data, _textStatus, xhr) => {
+ if (xhr.responseJSON.status === 'ok') {
+ viewDiv.children('.topic').remove();
+ if (topics.length) {
+ const topicArray = topics.split(',');
+
+ const last = viewDiv.children('a').last();
+ for (let i = 0; i < topicArray.length; i++) {
+ const link = $('<a class="ui repo-topic large label topic"></a>');
+ link.attr('href', `${AppSubUrl}/explore/repos?q=${encodeURIComponent(topicArray[i])}&topic=1`);
+ link.text(topicArray[i]);
+ link.insertBefore(last);
+ }
+ }
+ editDiv.css('display', 'none');
+ viewDiv.show();
+ }
+ }).fail((xhr) => {
+ if (xhr.status === 422) {
+ if (xhr.responseJSON.invalidTopics.length > 0) {
+ topicPrompts.formatPrompt = xhr.responseJSON.message;
+
+ const {invalidTopics} = xhr.responseJSON;
+ const topicLables = topicDropdown.children('a.ui.label');
+
+ topics.split(',').forEach((value, index) => {
+ for (let i = 0; i < invalidTopics.length; i++) {
+ if (invalidTopics[i] === value) {
+ topicLables.eq(index).removeClass('green').addClass('red');
+ }
+ }
+ });
+ } else {
+ topicPrompts.countPrompt = xhr.responseJSON.message;
+ }
+ }
+ }).always(() => {
+ topicForm.form('validate form');
+ });
+ });
+
+ topicDropdown.dropdown({
+ allowAdditions: true,
+ forceSelection: false,
+ fullTextSearch: 'exact',
+ fields: {name: 'description', value: 'data-value'},
+ saveRemoteData: false,
+ label: {
+ transition: 'horizontal flip',
+ duration: 200,
+ variation: false,
+ blue: true,
+ basic: true,
+ },
+ className: {
+ label: 'ui small label'
+ },
+ apiSettings: {
+ url: `${AppSubUrl}/api/v1/topics/search?q={query}`,
+ throttle: 500,
+ cache: false,
+ onResponse(res) {
+ const formattedResponse = {
+ success: false,
+ results: [],
+ };
+ const query = stripTags(this.urlData.query.trim());
+ let found_query = false;
+ const current_topics = [];
+ topicDropdown.find('div.label.visible.topic,a.label.visible').each((_, e) => { current_topics.push(e.dataset.value) });
+
+ if (res.topics) {
+ let found = false;
+ for (let i = 0; i < res.topics.length; i++) {
+ // skip currently added tags
+ if (current_topics.includes(res.topics[i].topic_name)) {
+ continue;
+ }
+
+ if (res.topics[i].topic_name.toLowerCase() === query.toLowerCase()) {
+ found_query = true;
+ }
+ formattedResponse.results.push({description: res.topics[i].topic_name, 'data-value': res.topics[i].topic_name});
+ found = true;
+ }
+ formattedResponse.success = found;
+ }
+
+ if (query.length > 0 && !found_query) {
+ formattedResponse.success = true;
+ formattedResponse.results.unshift({description: query, 'data-value': query});
+ } else if (query.length > 0 && found_query) {
+ formattedResponse.results.sort((a, b) => {
+ if (a.description.toLowerCase() === query.toLowerCase()) return -1;
+ if (b.description.toLowerCase() === query.toLowerCase()) return 1;
+ if (a.description > b.description) return -1;
+ if (a.description < b.description) return 1;
+ return 0;
+ });
+ }
+
+ return formattedResponse;
+ },
+ },
+ onLabelCreate(value) {
+ value = value.toLowerCase().trim();
+ this.attr('data-value', value).contents().first().replaceWith(value);
+ return $(this);
+ },
+ onAdd(addedValue, _addedText, $addedChoice) {
+ addedValue = addedValue.toLowerCase().trim();
+ $($addedChoice).attr('data-value', addedValue);
+ $($addedChoice).attr('data-text', addedValue);
+ }
+ });
+
+ $.fn.form.settings.rules.validateTopic = function (_values, regExp) {
+ const topics = topicDropdown.children('a.ui.label');
+ const status = topics.length === 0 || topics.last().attr('data-value').match(regExp);
+ if (!status) {
+ topics.last().removeClass('green').addClass('red');
+ }
+ return status && topicDropdown.children('a.ui.label.red').length === 0;
+ };
+
+ topicForm.form({
+ on: 'change',
+ inline: true,
+ fields: {
+ topics: {
+ identifier: 'topics',
+ rules: [
+ {
+ type: 'validateTopic',
+ value: /^[a-z0-9][a-z0-9-]{0,35}$/,
+ prompt: topicPrompts.formatPrompt
+ },
+ {
+ type: 'maxCount[25]',
+ prompt: topicPrompts.countPrompt
+ }
+ ]
+ },
+ }
+ });
+}