feat(v4.0): wire Share/Publish modal with real API calls
- publishPage() → POST /api/pages/{id}/publish
- unpublishPage() → DELETE /api/pages/{id}/publish
- shareInvite() → POST /api/pages/{id}/share
- loadShares() → GET /api/pages/{id}/shares
- removeShare() → DELETE /api/pages/{id}/share/{sid}
- All buttons now call real API instead of local state toggle
This commit is contained in:
@@ -75,9 +75,9 @@ page_title %}{{ page.title }}{% endblock %} {% block topbar %}
|
|||||||
class="sd-input"
|
class="sd-input"
|
||||||
placeholder="Add people, groups or emails..."
|
placeholder="Add people, groups or emails..."
|
||||||
x-model="inviteEmail"
|
x-model="inviteEmail"
|
||||||
@keydown.enter="invitePerson"
|
@keydown.enter="shareInvite()"
|
||||||
/>
|
/>
|
||||||
<button class="sd-btn-primary" @click="invitePerson">
|
<button class="sd-btn-primary" @click="shareInvite()">
|
||||||
Invite
|
Invite
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -268,7 +268,7 @@ page_title %}{{ page.title }}{% endblock %} {% block topbar %}
|
|||||||
</p>
|
</p>
|
||||||
<button
|
<button
|
||||||
class="sd-btn-primary sd-btn-full"
|
class="sd-btn-primary sd-btn-full"
|
||||||
@click="pagePublished = true"
|
@click="publishPage()"
|
||||||
>
|
>
|
||||||
Publish
|
Publish
|
||||||
</button>
|
</button>
|
||||||
@@ -354,7 +354,7 @@ page_title %}{{ page.title }}{% endblock %} {% block topbar %}
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
class="sd-danger-btn"
|
class="sd-danger-btn"
|
||||||
@click="pagePublished = false"
|
@click="unpublishPage()"
|
||||||
>
|
>
|
||||||
Unpublish
|
Unpublish
|
||||||
</button>
|
</button>
|
||||||
@@ -657,6 +657,58 @@ page_title %}{{ page.title }}{% endblock %} {% block topbar %}
|
|||||||
clearTimeout(this._toastTimer);
|
clearTimeout(this._toastTimer);
|
||||||
this._toastTimer = setTimeout(() => { this.toastVisible = false; }, 2500);
|
this._toastTimer = setTimeout(() => { this.toastVisible = false; }, 2500);
|
||||||
},
|
},
|
||||||
|
publishPage() {
|
||||||
|
var self = this;
|
||||||
|
var csrf = document.cookie.match(/csrf_token=([^;]+)/);
|
||||||
|
fetch('/api/pages/' + this.pid + '/publish', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': csrf ? csrf[1] : '' }
|
||||||
|
}).then(function(r){ return r.json(); }).then(function(d){
|
||||||
|
if (d.status === 'ok') { self.pagePublished = true; self.publishedUrl = d.url || self.publishedUrl; self.showToast('Published to web'); }
|
||||||
|
else { self.showToast(d.detail || 'Publish failed'); }
|
||||||
|
}).catch(function(){ self.showToast('Publish failed'); });
|
||||||
|
},
|
||||||
|
unpublishPage() {
|
||||||
|
var self = this;
|
||||||
|
var csrf = document.cookie.match(/csrf_token=([^;]+)/);
|
||||||
|
fetch('/api/pages/' + this.pid + '/publish', {
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: { 'X-CSRF-Token': csrf ? csrf[1] : '' }
|
||||||
|
}).then(function(r){ return r.json(); }).then(function(d){
|
||||||
|
if (d.status === 'ok') { self.pagePublished = false; self.publishedUrl = ''; self.showToast('Unpublished'); }
|
||||||
|
else { self.showToast(d.detail || 'Unpublish failed'); }
|
||||||
|
}).catch(function(){ self.showToast('Unpublish failed'); });
|
||||||
|
},
|
||||||
|
shareInvite() {
|
||||||
|
var self = this;
|
||||||
|
if (!this.inviteEmail.trim()) return;
|
||||||
|
var csrf = document.cookie.match(/csrf_token=([^;]+)/);
|
||||||
|
fetch('/api/pages/' + this.pid + '/share', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': csrf ? csrf[1] : '' },
|
||||||
|
body: JSON.stringify({ email: this.inviteEmail.trim(), permission: this.invitePermission })
|
||||||
|
}).then(function(r){ return r.json(); }).then(function(d){
|
||||||
|
if (d.status === 'ok') { self.inviteEmail = ''; self.showToast('Invitation sent'); self.loadShares(); }
|
||||||
|
else { self.showToast(d.detail || 'Share failed'); }
|
||||||
|
}).catch(function(){ self.showToast('Share failed'); });
|
||||||
|
},
|
||||||
|
loadShares() {
|
||||||
|
var self = this;
|
||||||
|
fetch('/api/pages/' + this.pid + '/shares').then(function(r){ return r.json(); }).then(function(d){
|
||||||
|
self.accessList = d.shares || [];
|
||||||
|
}).catch(function(){ self.accessList = []; });
|
||||||
|
},
|
||||||
|
removeShare(sid) {
|
||||||
|
var self = this;
|
||||||
|
var csrf = document.cookie.match(/csrf_token=([^;]+)/);
|
||||||
|
fetch('/api/pages/' + this.pid + '/share/' + sid, {
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: { 'X-CSRF-Token': csrf ? csrf[1] : '' }
|
||||||
|
}).then(function(r){ return r.json(); }).then(function(d){
|
||||||
|
if (d.status === 'ok') { self.showToast('Share removed'); self.loadShares(); }
|
||||||
|
else { self.showToast(d.detail || 'Remove failed'); }
|
||||||
|
}).catch(function(){ self.showToast('Remove failed'); });
|
||||||
|
},
|
||||||
invitePerson(){if(!this.inviteEmail.trim())return;this.accessList.push({email:this.inviteEmail,permission:this.invitePermission,permOpen:false});this.inviteEmail='';},
|
invitePerson(){if(!this.inviteEmail.trim())return;this.accessList.push({email:this.inviteEmail,permission:this.invitePermission,permOpen:false});this.inviteEmail='';},
|
||||||
removeAccess(email){this.accessList=this.accessList.filter(a=>a.email!==email);},
|
removeAccess(email){this.accessList=this.accessList.filter(a=>a.email!==email);},
|
||||||
exportPage(){this.moreOpen=false;},
|
exportPage(){this.moreOpen=false;},
|
||||||
|
|||||||
Reference in New Issue
Block a user