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/businesses/admin-edit-business";
|
||||||
|
|
||||||
import "./admin/offers/admin-edit-offer";
|
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 {
|
customElements.define('admin-businesses', class extends Component {
|
||||||
|
static get observedAttributes() {
|
||||||
|
return ['state-filter'];
|
||||||
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super(`
|
super(`
|
||||||
<style>
|
<style>
|
||||||
:host { display: block; }
|
: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>
|
</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) {
|
:host(:first-child) {
|
||||||
border-top: 2px solid var(--border-slim-color);
|
border-top: 2px solid var(--border-slim-color);
|
||||||
}
|
}
|
||||||
section {
|
article {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
#state {
|
#state {
|
||||||
min-width: 200px;
|
min-width: 200px;
|
||||||
}
|
}
|
||||||
|
#view {
|
||||||
|
width: calc(100% - 220px);
|
||||||
|
}
|
||||||
|
#actions {
|
||||||
|
width: 200px
|
||||||
|
}
|
||||||
#actions > input:not(:last-child) {
|
#actions > input:not(:last-child) {
|
||||||
margin-right: .5rem;
|
margin-right: .5rem;
|
||||||
}
|
}
|
||||||
@ -38,9 +44,11 @@ customElements.define('admin-edit-business', class extends Component {
|
|||||||
}
|
}
|
||||||
${ BUTTON_STYLE }${ INPUT_STYLE }
|
${ BUTTON_STYLE }${ INPUT_STYLE }
|
||||||
</style>
|
</style>
|
||||||
<section>
|
<article>
|
||||||
<slot></slot>
|
<section id="view">
|
||||||
<div id="actions">
|
<slot></slot>
|
||||||
|
</section>
|
||||||
|
<section id="actions">
|
||||||
<input value="Usuń" type="button" />
|
<input value="Usuń" type="button" />
|
||||||
<form id="change-state" action="/admin/businesses/set-state" method="post">
|
<form id="change-state" action="/admin/businesses/set-state" method="post">
|
||||||
<input name="id" id="id" type="hidden" />
|
<input name="id" id="id" type="hidden" />
|
||||||
@ -52,8 +60,8 @@ customElements.define('admin-edit-business', class extends Component {
|
|||||||
<option value="Internal">Internal</option>
|
<option value="Internal">Internal</option>
|
||||||
</select>
|
</select>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</section>
|
||||||
</section>
|
</article>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
const form = this.shadowRoot.querySelector('#change-state');
|
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-businesses.js";
|
||||||
import "./local-businesses/local-business-item.js";
|
import "./local-businesses/local-business-item.js";
|
||||||
import "./local-businesses/local-business.js";
|
import "./local-businesses/local-business.js";
|
||||||
|
import "./local-businesses/single-local-business.js";
|
||||||
|
|
||||||
import "./login-form.js";
|
import "./login-form.js";
|
||||||
|
|
||||||
import "./register-form.js";
|
import "./register-form.js";
|
||||||
import "./register-form/register-business-account-form";
|
import "./register-form/register-business-account-form";
|
||||||
import "./register-form/register-business-item-form.js";
|
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" %}
|
{% extends "../layout.html" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<ow-admin>
|
<ow-admin>
|
||||||
<ow-offers>
|
<ow-admin-offers>
|
||||||
<h1>Admin - Sprzedaż niepotrzebnych rzeczy</h1>
|
<h1>Admin - Sprzedaż niepotrzebnych rzeczy</h1>
|
||||||
|
|
||||||
{% for offer in offers %}
|
{% for offer in offers %}
|
||||||
@ -27,6 +27,6 @@
|
|||||||
></marketplace-offer>
|
></marketplace-offer>
|
||||||
</admin-edit-offer>
|
</admin-edit-offer>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ow-offers>
|
</ow-admin-offers>
|
||||||
</ow-admin>
|
</ow-admin>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -1,34 +1,34 @@
|
|||||||
{% extends "../base.html" %}
|
{% extends "../base.html" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<local-business
|
<single-local-business {{h.account_id_tag(account)}}>
|
||||||
slot="business"
|
<local-business
|
||||||
business-id="{{business.id}}"
|
business-id="{{business.id}}"
|
||||||
name="{{business.name}}"
|
name="{{business.name}}"
|
||||||
state="{{business.state.as_str()}}"
|
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}}"
|
|
||||||
>
|
>
|
||||||
</local-business-item>
|
{% for line in business.description.lines() %}
|
||||||
{% endfor %}
|
<p slot="description">{{line}}</p>
|
||||||
<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 %}
|
{% 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 %}
|
{% endblock %}
|
||||||
|
@ -22,20 +22,20 @@ pub enum AccountType {
|
|||||||
#[derive(Debug, Default, Copy, Clone, Serialize, Deserialize, Type)]
|
#[derive(Debug, Default, Copy, Clone, Serialize, Deserialize, Type)]
|
||||||
pub enum LocalBusinessState {
|
pub enum LocalBusinessState {
|
||||||
#[default]
|
#[default]
|
||||||
Pending,
|
Pending = 1,
|
||||||
Approved,
|
Approved = 2,
|
||||||
Banned,
|
Banned = 3,
|
||||||
Pinned,
|
Pinned = 4,
|
||||||
Internal,
|
Internal = 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Copy, Clone, Serialize, Deserialize, Type)]
|
#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd, Serialize, Deserialize, Type)]
|
||||||
pub enum OfferState {
|
pub enum OfferState {
|
||||||
#[default]
|
#[default]
|
||||||
Pending,
|
Pending = 0,
|
||||||
Approved,
|
Approved = 1,
|
||||||
Banned,
|
Banned = 2,
|
||||||
Finished,
|
Finished = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OfferState {
|
impl OfferState {
|
||||||
|
@ -88,7 +88,7 @@ pub async fn visible_businesses(t: &mut T<'_>) -> Result<Vec<db::LocalBusiness>>
|
|||||||
r#"
|
r#"
|
||||||
SELECT id, owner_id, name, description, state
|
SELECT id, owner_id, name, description, state
|
||||||
FROM local_businesses
|
FROM local_businesses
|
||||||
WHERE state != 'Banned'
|
WHERE state != 'Banned' AND state != 'Pending'
|
||||||
GROUP BY id, state
|
GROUP BY id, state
|
||||||
ORDER BY name ASC
|
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 mut t = ok_or_internal!(&req, pool.begin().await);
|
||||||
let account = require_admin!(&req, &mut t, id);
|
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();
|
t.commit().await.ok();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user