$(document).ready(() => {
  const SettingSection = {
    template: '#vue-setting-section',
    props: ['id', 'content', 'type', 'name', 'arg'],
    data: function() {
      return {
        mode: 'default',
        processing: false,
        editContent: null
      };
    },
    created: function() {
      this.initialState();
    },
    computed: {
      endpoint: function() {
        return '/api/settings/' + this.id;
      }
    },
    methods: {
      onCancel: function(event) {
        this.initialState();
      },
      onEdit: function(ev) {
        this.mode = "edit";
      },
      onDelete: function(ev) {
        if (!confirm("really?")) {
          return;
        }
        this.destroy();
      },
      onSubmit: function(ev) {
        this.processing = true;
        $.ajax({
          url: this.endpoint,
          method: "POST",
          data: {
            _method: "PATCH",
            id: this.id,
            content: this.editContent
          }
        }).then((data)=> {
          _.each(data, function(v,k){
            this[k] = v;
          });
          this.initialState();
        }).always(()=> {
          this.processing = false;
        });
      },
      initialState: function(){
        this.processing = false;
        this.mode = 'default';
        this.editContent = this.content;
      },
      destroy: function(){
        $.ajax({
          url: this.endpoint,
          method: "POST",
          data: {
            _method: "DELETE",
            id: this.id
          }
        }).then(()=> {
          this.$parent.update();
        });
      }
    }
  };

  new Vue({
    el: "#vue-setting",
    data: function(){
      return {
        loaded: false,
        loading: false,
        sections: {
          sources: [],
          matches: []
        }
      };
    },
    mounted: function() {
      this.$nextTick(() => {
        this.update();
      })
    },
    components: {
      'setting-section': SettingSection
    },
    methods: {
      update: function() {
        this.loading = true;
        $.getJSON("/api/settings", (data)=> {
          var sources = [];
          var matches = [];
          data.forEach((v)=> {
            if(v.name === "source"){
              sources.push(v);
            }else{
              matches.push(v);
            }
          });
          this.sections.sources = sources;
          this.sections.matches = matches;
          this.loaded = true;
          setTimeout(()=> {
            this.loading = false;
          }, 500);
        });
      }
    }
  });
})

@@ -735,32 +735,123 @@
  function(ev) %7B%0A
+        const token = document.getElementsByName(%22csrf-token%22)%5B0%5D.getAttribute('content');%0A
         this.pro
@@ -858,32 +858,32 @@
 cessing = true;%0A
-
         $.ajax(%7B
@@ -1050,16 +1050,84 @@
 Content%0A
+          %7D,%0A          headers: %7B%0A            'X-CSRF-Token': token%0A
         
@@ -1511,32 +1511,123 @@
 oy: function()%7B%0A
+        const token = document.getElementsByName(%22csrf-token%22)%5B0%5D.getAttribute('content');%0A
         $.ajax(%7B
@@ -1732,16 +1732,16 @@
 ELETE%22,%0A
-
         
@@ -1756,16 +1756,84 @@
 this.id%0A
+          %7D,%0A          headers: %7B%0A            'X-CSRF-Token': token%0A
         

Set CSRF token