Better UI, better admin
This commit is contained in:
parent
bbf774d8d9
commit
b9569229fb
@ -8,3 +8,4 @@ import "./admin/businesses/admin-businesses";
|
||||
import "./admin/businesses/admin-edit-business";
|
||||
|
||||
import "./admin/offers/admin-edit-offer";
|
||||
import "./admin/offers/ow-admin-offers";
|
||||
|
@ -1,12 +1,66 @@
|
||||
import { Component } from "../../shared";
|
||||
import { Component, FORM_STYLE } from "../../shared";
|
||||
|
||||
customElements.define('admin-businesses', class extends Component {
|
||||
static get observedAttributes() {
|
||||
return ['state-filter'];
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super(`
|
||||
<style>
|
||||
:host { display: block; }
|
||||
::slotted([state]) {
|
||||
display: none;
|
||||
}
|
||||
:host([state-filter="Pending"]) ::slotted([state="Pending"]) {
|
||||
display: block;
|
||||
}
|
||||
:host([state-filter="Approved"]) ::slotted([state="Approved"]) {
|
||||
display: block;
|
||||
}
|
||||
:host([state-filter="Banned"]) ::slotted([state="Banned"]) {
|
||||
display: block;
|
||||
}
|
||||
:host([state-filter="Pinned"]) ::slotted([state="Pinned"]) {
|
||||
display: block;
|
||||
}
|
||||
:host([state-filter="Internal"]) ::slotted([state="Internal"]) {
|
||||
display: block;
|
||||
}
|
||||
${ FORM_STYLE }
|
||||
</style>
|
||||
<slot></slot>
|
||||
<article>
|
||||
<section>
|
||||
<select id="state">
|
||||
<option value="Pending">Pending</option>
|
||||
<option value="Approved">Approved</option>
|
||||
<option value="Banned">Banned</option>
|
||||
<option value="Pinned">Pinned</option>
|
||||
<option value="Internal">Internal</option>
|
||||
</select>
|
||||
</section>
|
||||
<section>
|
||||
<slot></slot>
|
||||
</section>
|
||||
</article>
|
||||
`);
|
||||
this.shadowRoot.querySelector('#state').addEventListener('change', ev => {
|
||||
ev.stopPropagation();
|
||||
this.state_filter = ev.target.value;
|
||||
});
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this.state_filter = 'Pending';
|
||||
}
|
||||
|
||||
get state_filter() {
|
||||
return this.getAttribute('state-filter');
|
||||
}
|
||||
|
||||
set state_filter(v) {
|
||||
this.setAttribute('state-filter', v);
|
||||
this.shadowRoot.querySelector('#state').value = v;
|
||||
}
|
||||
});
|
||||
|
@ -16,13 +16,19 @@ customElements.define('admin-edit-business', class extends Component {
|
||||
:host(:first-child) {
|
||||
border-top: 2px solid var(--border-slim-color);
|
||||
}
|
||||
section {
|
||||
article {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
#state {
|
||||
min-width: 200px;
|
||||
}
|
||||
#view {
|
||||
width: calc(100% - 220px);
|
||||
}
|
||||
#actions {
|
||||
width: 200px
|
||||
}
|
||||
#actions > input:not(:last-child) {
|
||||
margin-right: .5rem;
|
||||
}
|
||||
@ -38,9 +44,11 @@ customElements.define('admin-edit-business', class extends Component {
|
||||
}
|
||||
${ BUTTON_STYLE }${ INPUT_STYLE }
|
||||
</style>
|
||||
<section>
|
||||
<slot></slot>
|
||||
<div id="actions">
|
||||
<article>
|
||||
<section id="view">
|
||||
<slot></slot>
|
||||
</section>
|
||||
<section id="actions">
|
||||
<input value="Usuń" type="button" />
|
||||
<form id="change-state" action="/admin/businesses/set-state" method="post">
|
||||
<input name="id" id="id" type="hidden" />
|
||||
@ -52,8 +60,8 @@ customElements.define('admin-edit-business', class extends Component {
|
||||
<option value="Internal">Internal</option>
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
</article>
|
||||
`);
|
||||
|
||||
const form = this.shadowRoot.querySelector('#change-state');
|
||||
|
64
client/src/admin/offers/ow-admin-offers.js
Normal file
64
client/src/admin/offers/ow-admin-offers.js
Normal file
@ -0,0 +1,64 @@
|
||||
import { Component, FORM_STYLE } from "../../shared.js";
|
||||
|
||||
customElements.define('ow-admin-offers', class extends Component {
|
||||
static get observedAttributes() {
|
||||
return ['state-filter'];
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super(`
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
::slotted([state]) {
|
||||
display: none;
|
||||
}
|
||||
:host([state-filter='Pending']) ::slotted([state="Pending"]) {
|
||||
display: block;
|
||||
}
|
||||
:host([state-filter='Approved']) ::slotted([state="Approved"]) {
|
||||
display: block;
|
||||
}
|
||||
:host([state-filter='Banned']) ::slotted([state="Banned"]) {
|
||||
display: block;
|
||||
}
|
||||
:host([state-filter='Finished']) ::slotted([state="Finished"]) {
|
||||
display: block;
|
||||
}
|
||||
${ FORM_STYLE }
|
||||
</style>
|
||||
<article>
|
||||
<section>
|
||||
<select id="state">
|
||||
<option value="Pending">Pending</option>
|
||||
<option value="Approved">Approved</option>
|
||||
<option value="Banned">Banned</option>
|
||||
<option value="Finished">Finished</option>
|
||||
</select>
|
||||
</section>
|
||||
<section>
|
||||
<slot></slot>
|
||||
</section>
|
||||
</article>
|
||||
`);
|
||||
this.shadowRoot.querySelector('#state').addEventListener('change', ev => {
|
||||
ev.stopPropagation();
|
||||
this.state_filter = ev.target.value;
|
||||
});
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this.state_filter = 'Pending';
|
||||
}
|
||||
|
||||
get state_filter() {
|
||||
return this.getAttribute('state-filter');
|
||||
}
|
||||
|
||||
set state_filter(v) {
|
||||
this.setAttribute('state-filter', v);
|
||||
this.shadowRoot.querySelector('#state').value = v;
|
||||
}
|
||||
});
|
@ -18,8 +18,10 @@ import "./ow-account/account-view.js";
|
||||
import "./local-businesses/local-businesses.js";
|
||||
import "./local-businesses/local-business-item.js";
|
||||
import "./local-businesses/local-business.js";
|
||||
import "./local-businesses/single-local-business.js";
|
||||
|
||||
import "./login-form.js";
|
||||
|
||||
import "./register-form.js";
|
||||
import "./register-form/register-business-account-form";
|
||||
import "./register-form/register-business-item-form.js";
|
||||
|
7
client/src/local-businesses/single-local-business.js
Normal file
7
client/src/local-businesses/single-local-business.js
Normal file
@ -0,0 +1,7 @@
|
||||
import { Component } from '../shared.js';
|
||||
|
||||
customElements.define('single-local-business', class extends Component {
|
||||
constructor() {
|
||||
super(`<style>:host{display:block;margin:0 8px;}@media only screen and (min-device-width: 100px){:host{margin:0;}}</style><article><slot></slot></article>`);
|
||||
}
|
||||
});
|
@ -1,7 +1,7 @@
|
||||
{% extends "../layout.html" %}
|
||||
{% block content %}
|
||||
<ow-admin>
|
||||
<ow-offers>
|
||||
<ow-admin-offers>
|
||||
<h1>Admin - Sprzedaż niepotrzebnych rzeczy</h1>
|
||||
|
||||
{% for offer in offers %}
|
||||
@ -27,6 +27,6 @@
|
||||
></marketplace-offer>
|
||||
</admin-edit-offer>
|
||||
{% endfor %}
|
||||
</ow-offers>
|
||||
</ow-admin-offers>
|
||||
</ow-admin>
|
||||
{% endblock %}
|
||||
|
@ -1,34 +1,34 @@
|
||||
{% extends "../base.html" %}
|
||||
{% block content %}
|
||||
<local-business
|
||||
slot="business"
|
||||
business-id="{{business.id}}"
|
||||
name="{{business.name}}"
|
||||
state="{{business.state.as_str()}}"
|
||||
>
|
||||
{% for line in business.description.lines() %}
|
||||
<p slot="description">{{line}}</p>
|
||||
{% endfor %}
|
||||
|
||||
{% for item in business.items %}
|
||||
<local-business-item
|
||||
slot="item"
|
||||
name="{{item.name}}"
|
||||
price="{{item.price}}"
|
||||
picture-url="{{item.picture_url}}"
|
||||
<single-local-business {{h.account_id_tag(account)}}>
|
||||
<local-business
|
||||
business-id="{{business.id}}"
|
||||
name="{{business.name}}"
|
||||
state="{{business.state.as_str()}}"
|
||||
>
|
||||
</local-business-item>
|
||||
{% endfor %}
|
||||
<contact-info-list slot="contacts">
|
||||
{% for contact in business.contacts %}
|
||||
<contact-info
|
||||
mode="icon"
|
||||
contact-id="{{contact.id}}"
|
||||
content="{{h.render_contact(contact.contact_type.as_str(), contact.content.as_str())}}"
|
||||
type="{{contact.contact_type}}"
|
||||
></contact-info>
|
||||
{% for line in business.description.lines() %}
|
||||
<p slot="description">{{line}}</p>
|
||||
{% endfor %}
|
||||
</contact-info-list>
|
||||
|
||||
</local-business>
|
||||
{% for item in business.items %}
|
||||
<local-business-item
|
||||
slot="item"
|
||||
name="{{item.name}}"
|
||||
price="{{item.price}}"
|
||||
picture-url="{{item.picture_url}}"
|
||||
>
|
||||
</local-business-item>
|
||||
{% endfor %}
|
||||
<contact-info-list slot="contacts">
|
||||
{% for contact in business.contacts %}
|
||||
<contact-info
|
||||
mode="icon"
|
||||
contact-id="{{contact.id}}"
|
||||
content="{{h.render_contact(contact.contact_type.as_str(), contact.content.as_str())}}"
|
||||
type="{{contact.contact_type}}"
|
||||
></contact-info>
|
||||
{% endfor %}
|
||||
</contact-info-list>
|
||||
</local-business>
|
||||
</single-local-business>
|
||||
{% endblock %}
|
||||
|
@ -22,20 +22,20 @@ pub enum AccountType {
|
||||
#[derive(Debug, Default, Copy, Clone, Serialize, Deserialize, Type)]
|
||||
pub enum LocalBusinessState {
|
||||
#[default]
|
||||
Pending,
|
||||
Approved,
|
||||
Banned,
|
||||
Pinned,
|
||||
Internal,
|
||||
Pending = 1,
|
||||
Approved = 2,
|
||||
Banned = 3,
|
||||
Pinned = 4,
|
||||
Internal = 5,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Copy, Clone, Serialize, Deserialize, Type)]
|
||||
#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd, Serialize, Deserialize, Type)]
|
||||
pub enum OfferState {
|
||||
#[default]
|
||||
Pending,
|
||||
Approved,
|
||||
Banned,
|
||||
Finished,
|
||||
Pending = 0,
|
||||
Approved = 1,
|
||||
Banned = 2,
|
||||
Finished = 3,
|
||||
}
|
||||
|
||||
impl OfferState {
|
||||
|
@ -88,7 +88,7 @@ pub async fn visible_businesses(t: &mut T<'_>) -> Result<Vec<db::LocalBusiness>>
|
||||
r#"
|
||||
SELECT id, owner_id, name, description, state
|
||||
FROM local_businesses
|
||||
WHERE state != 'Banned'
|
||||
WHERE state != 'Banned' AND state != 'Pending'
|
||||
GROUP BY id, state
|
||||
ORDER BY name ASC
|
||||
"#,
|
||||
|
@ -28,7 +28,8 @@ async fn admin_offers(req: HttpRequest, db: Data<PgPool>, id: Identity) -> HttpR
|
||||
let mut t = ok_or_internal!(&req, pool.begin().await);
|
||||
let account = require_admin!(&req, &mut t, id);
|
||||
|
||||
let offers = queries::all_offers(&mut t).await.unwrap_or_default();
|
||||
let mut offers = queries::all_offers(&mut t).await.unwrap_or_default();
|
||||
offers.sort_by(|a, b| (a.state as u8).cmp(&(b.state as u8)));
|
||||
|
||||
t.commit().await.ok();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user