Delete contact, start edit

This commit is contained in:
eraden 2022-07-16 17:20:05 +02:00
parent c5ea569727
commit 80be8d2d88
8 changed files with 163 additions and 37 deletions

View File

@ -4,7 +4,7 @@
<contact-info-editor type="email" value="{{h.email(account)}}">
<contact-info-list>
{% for contact in contacts %}
<edit-contact-info contact-id="{{contact.id}}">
<edit-contact-info contact-id="{{contact.id}}" mode="view">
<contact-info
contact-id="{{contact.id}}"
contact-type="{{contact.contact_type}}"

View File

@ -22,6 +22,8 @@ import "./shared/rich-text-editor";
import "./contacts/contact-info-list";
import "./contacts/contact-info";
import "./contacts/contact-info-editor";
import "./contacts/contact-type-icon";
import "./contacts/edit-contact-info";
import { fireFbReady } from "./shared.js";

View File

@ -11,26 +11,14 @@ customElements.define('contact-info-editor', class extends Component {
:host {
display: block;
}
#contact-wrapper svg {
display: none;
#contact-wrapper contact-type-icon {
width: 24px;
margin-right: 8px;
}
#contact-wrapper #input {
display: flex;
justify-content: start;
}
#contact-wrapper #input svg {
margin-right: 8px;
}
:host([type="email"]) #email-icon {
display: block;
}
:host([type="facebook"]) #fb-icon {
display: block;
}
:host([type="other"]) #other-icon {
display: block;
}
${ FORM_STYLE }
</style>
<section>
@ -46,15 +34,7 @@ customElements.define('contact-info-editor', class extends Component {
<div id="contact-wrapper">
<label>E-Mail</label>
<div id="input">
<svg id="email-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 75.294 75.294" xml:space="preserve">
<path d="M66.097 12.089h-56.9C4.126 12.089 0 16.215 0 21.286v32.722c0 5.071 4.126 9.197 9.197 9.197h56.9c5.071 0 9.197-4.126 9.197-9.197V21.287c.001-5.072-4.125-9.198-9.197-9.198zm-4.494 6L37.647 33.523 13.691 18.089h47.912zm4.494 39.117h-56.9A3.201 3.201 0 0 1 6 54.009V21.457l29.796 19.16c.04.025.083.042.124.065.043.024.087.047.131.069.231.119.469.215.712.278.025.007.05.01.075.016.267.063.537.102.807.102h.006c.27 0 .54-.038.807-.102.025-.006.05-.009.075-.016.243-.063.48-.159.712-.278a3.27 3.27 0 0 0 .131-.069c.041-.023.084-.04.124-.065l29.796-19.16v32.551a3.204 3.204 0 0 1-3.199 3.198z"/>
</svg>
<svg id="fb-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 314.652 314.652" xml:space="preserve">
<path d="M157.326 0C70.576 0 0 70.576 0 157.326s70.576 157.326 157.326 157.326 157.326-70.576 157.326-157.326S244.076 0 157.326 0zm0 296.652C80.501 296.652 18 234.15 18 157.326S80.501 18 157.326 18s139.326 62.502 139.326 139.326-62.501 139.326-139.326 139.326z"/><path d="M193.764 71.952H172.43c-17.461 0-31.667 14.206-31.667 31.667v24h-19.875c-4.971 0-9 4.029-9 9s4.029 9 9 9h19.875v83.333c0 4.971 4.029 9 9 9s9-4.029 9-9v-83.333h30.75c4.971 0 9-4.029 9-9s-4.029-9-9-9h-30.75v-24c0-7.536 6.131-13.667 13.667-13.667h21.333c4.971 0 9-4.029 9-9s-4.029-9-8.999-9z"/>
</svg>
<svg id="other-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path fill="none" stroke="#000" stroke-width="2" d="M1 2h21v16h-8l-8 4v-4H1V2Zm5 8h1v1H6v-1Zm5 0h1v1h-1v-1Zm5 0h1v1h-1v-1Z"/>
</svg>
<contact-type-icon contact-type="email"></contact-type-icon>
<input type="email" id="content" name="content" />
</div>
@ -81,6 +61,8 @@ customElements.define('contact-info-editor', class extends Component {
set type(v) {
this.setAttribute('type', v);
const icon = this.shadowRoot.querySelector('contact-type-icon');
icon.setAttribute('contact-type', v);
this.shadowRoot.querySelector('#content').setAttribute('type', v === 'email' ? 'email' : 'text');
}

View File

@ -1,12 +1,52 @@
import { Component } from "../shared";
customElements.define('contact-info', class extends Component {
customElements.define('contact-info',
class extends Component {
static get observedAttributes() {
return ['contact-type', 'content', 'contact-id'];
}
constructor() {
super(`
<style>
:host { display: block; }
section {
display: flex;
justify-content: start;
}
contact-type-icon {
width: 24px;
margin-right: 8px;
}
</style>
<slot></slot>
<section>
<contact-type-icon contact-type="email"></contact-type-icon>
<div id="content"></div>
</section>
`);
}
});
set contact_type(v) {
if (!v) return;
this.setAttribute('contact-type', v);
this.shadowRoot.querySelector('contact-type-icon').setAttribute('contact-type', v);
}
set content(v) {
this.setAttribute('content', v);
this.shadowRoot.querySelector('#content').textContent = v;
}
get content() {
return this.getAttribute('content')
}
get contact_id() {
return this.getAttribute('contact-id')
}
set contact_id(v) {
this.setAttribute('contact-id', v);
}
});

View File

@ -0,0 +1,48 @@
import { Component } from "../shared";
customElements.define('contact-type-icon',
class extends Component {
static get observedAttributes() {
return ['contact-type'];
}
constructor() {
super(`
<style>
:host { display: block; }
svg { display: none; }
:host([contact-type="email"]) #email-icon {
display: block;
}
:host([contact-type="facebook"]) #fb-icon {
display: block;
}
:host([contact-type="other"]) #other-icon {
display: block;
}
</style>
<svg id="email-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 75.294 75.294" xml:space="preserve">
<path d="M66.097 12.089h-56.9C4.126 12.089 0 16.215 0 21.286v32.722c0 5.071 4.126 9.197 9.197 9.197h56.9c5.071 0 9.197-4.126 9.197-9.197V21.287c.001-5.072-4.125-9.198-9.197-9.198zm-4.494 6L37.647 33.523 13.691 18.089h47.912zm4.494 39.117h-56.9A3.201 3.201 0 0 1 6 54.009V21.457l29.796 19.16c.04.025.083.042.124.065.043.024.087.047.131.069.231.119.469.215.712.278.025.007.05.01.075.016.267.063.537.102.807.102h.006c.27 0 .54-.038.807-.102.025-.006.05-.009.075-.016.243-.063.48-.159.712-.278a3.27 3.27 0 0 0 .131-.069c.041-.023.084-.04.124-.065l29.796-19.16v32.551a3.204 3.204 0 0 1-3.199 3.198z"/>
</svg>
<svg id="fb-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 314.652 314.652" xml:space="preserve">
<path d="M157.326 0C70.576 0 0 70.576 0 157.326s70.576 157.326 157.326 157.326 157.326-70.576 157.326-157.326S244.076 0 157.326 0zm0 296.652C80.501 296.652 18 234.15 18 157.326S80.501 18 157.326 18s139.326 62.502 139.326 139.326-62.501 139.326-139.326 139.326z"/><path d="M193.764 71.952H172.43c-17.461 0-31.667 14.206-31.667 31.667v24h-19.875c-4.971 0-9 4.029-9 9s4.029 9 9 9h19.875v83.333c0 4.971 4.029 9 9 9s9-4.029 9-9v-83.333h30.75c4.971 0 9-4.029 9-9s-4.029-9-9-9h-30.75v-24c0-7.536 6.131-13.667 13.667-13.667h21.333c4.971 0 9-4.029 9-9s-4.029-9-8.999-9z"/>
</svg>
<svg id="other-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path fill="none" stroke="#000" stroke-width="2" d="M1 2h21v16h-8l-8 4v-4H1V2Zm5 8h1v1H6v-1Zm5 0h1v1h-1v-1Zm5 0h1v1h-1v-1Z"/>
</svg>
`);
}
set contact_type(v) {
this.contactType = v;
}
set contactType(v) {
this.setAttribute('contact-type', v || 'email');
}
get contact_type() {
return this.getAttribute('contact-type')
}
});

View File

@ -1,8 +1,8 @@
import { Component } from "../shared";
import { Component, BUTTON_STYLE } from "../shared";
customElements.define('edit-contact-info', class extends Component {
static get observedAttributes() {
return ['contact-id'];
return ['contact-id', "mode"];
}
constructor() {
@ -13,18 +13,54 @@ customElements.define('edit-contact-info', class extends Component {
display: flex;
justify-content: space-between;
}
#actions {
display: flex;
justify-content: start;
}
#actions > *:not(:last-child) {
margin-right: 8px;
}
:host([mode = 'view']) contact-info-editor {
display: none;
}
:host([mode = 'edit']) contact-info-editor {
display: block;
}
:host([mode = 'view']) ::slotted(contact-info) {
display: block;
}
:host([mode = 'edit']) ::slotted(contact-info) {
display: none;
}
${ BUTTON_STYLE }
</style>
<article>
<slot></slot>
<section>
<section id="actions">
<contact-info-editor></contact-info-editor>
<input type="button" value="Edytuj" id="edit" />
<form>
<form action="/contacts/delete" method="post">
<input type="hidden" name="id" id="remove-id" />
<input type="button" value="Usuń" id="remove" />
<input type="submit" value="Usuń" id="remove" />
</form>
</section>
</article>
`);
const form = this.shadowRoot.querySelector('contact-info-editor');
this.shadowRoot.querySelector('#edit').addEventListener('click', ev => {
ev.preventDefault();
ev.stopPropagation();
const info = this.querySelector('contact-info');
if (!info) return;
form.contact_id = info.contact_id;
form.contact_type = info.contact_type;
form.context = info.context;
this.mode = 'edit';
});
}
get contact_id() {
@ -35,4 +71,17 @@ customElements.define('edit-contact-info', class extends Component {
this.setAttribute('contact-id', v);
this.shadowRoot.querySelector('#remove-id').value = v;
}
get mode() {
return this.getAttribute('mode');
}
set mode(v) {
if (v !== 'edit' && v !== 'view') {
console.warn('wrong edit contact info mode', v);
this.setAttribute('mode', 'view');
return
}
this.setAttribute('mode', v);
}
});

View File

@ -139,7 +139,7 @@ export class Component extends HTMLElement {
for (const name of observed) {
const field = this.constructor.attr2Field(name);
if (!field) continue;
this[field] = this[field];
this.#setFieldValue(field, this[field]);
}
}
@ -154,7 +154,7 @@ export class Component extends HTMLElement {
const field = this.constructor.attr2Field(name);
if (!field)
return;
this[field] = newV;
this.#setFieldValue(field, newV);
}
static attr2Field(name) {
@ -166,6 +166,11 @@ export class Component extends HTMLElement {
static get attr2FieldBlacklist() {
return []
}
#setFieldValue(name, value) {
if (value === undefined || value === null) return;
this[name] = value;
}
}
export class PseudoForm extends Component {

View File

@ -83,7 +83,7 @@ async fn update_contact(
}
}
#[post("/update")]
#[post("/delete")]
async fn delete_contact(
id: Identity,
db: Data<PgPool>,