forked from 1b-agent/opencadstudio-upstream
fix(ui): correct supporter data and labels
This commit is contained in:
1 parent
2c5b7e76fb
commit
feb110404c
4 files changed
+89
-17
No files matched your search
@@ -7,8 +7,6 @@ run-name: ${{ github.event.release.tag_name || github.ref_name }} Web
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
discussion:
|
||||
types: [created, edited, deleted, transferred, pinned, unpinned, labeled, unlabeled, locked, unlocked, category_changed, answered, unanswered]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
@@ -81,11 +79,25 @@ jobs:
|
||||
echo '[]' > dist/supporters.json; exit 0
|
||||
fi
|
||||
curl -sf -H "Authorization: Bearer $OCS_PATREON_TOKEN" \
|
||||
"https://www.patreon.com/api/oauth2/v2/campaigns/$CID/members?fields%5Bmember%5D=full_name,patron_status,currently_entitled_amount_cents&page%5Bcount%5D=200" \
|
||||
| jq -c '[.data[]
|
||||
| select(.attributes.patron_status=="active_patron")
|
||||
| select(.attributes.currently_entitled_amount_cents>0)
|
||||
| {name: .attributes.full_name, cents: .attributes.currently_entitled_amount_cents}]
|
||||
"https://www.patreon.com/api/oauth2/v2/campaigns/$CID/members?include=pledge_history&fields%5Bmember%5D=full_name,patron_status,currently_entitled_amount_cents&fields%5Bpledge-event%5D=amount_cents,date,payment_status&page%5Bcount%5D=200" \
|
||||
| jq -c '
|
||||
(.included // []
|
||||
| map(select(.type == "pledge-event"))
|
||||
| map({key: .id, value: .attributes})
|
||||
| from_entries) as $events
|
||||
| [.data[]
|
||||
| select(.attributes.patron_status == "active_patron")
|
||||
| . as $member
|
||||
| ([($member.relationships.pledge_history.data // [])[]
|
||||
| $events[.id]
|
||||
| select(.payment_status == "Paid")
|
||||
| select(.amount_cents > 0)]
|
||||
| sort_by(.date)
|
||||
| last) as $last_paid
|
||||
| {name: ((.attributes.full_name // "") | gsub("^\\s+|\\s+$"; "")),
|
||||
cents: ($last_paid.amount_cents // .attributes.currently_entitled_amount_cents)}
|
||||
| select(.name != "")
|
||||
| select(.cents > 0)]
|
||||
| sort_by(-.cents)' \
|
||||
> dist/supporters.json || echo '[]' > dist/supporters.json
|
||||
echo "supporters: $(jq 'length' dist/supporters.json)"
|
||||
|
||||
@@ -582,10 +582,10 @@ catalog-browser-storage-73cbc39086 = Tarayıcı depolaması
|
||||
catalog-building-scene-caches-3518c9d139 = Sahne önbellekleri oluşturuluyor…
|
||||
catalog-bump-map-301f0ab5fb = Kabartma Haritası
|
||||
catalog-by-annotation-scale-0aeb536ce3 = Açıklama ölçeğine göre
|
||||
catalog-by-layer-3243a14fc9 = Katmana göre
|
||||
catalog-by-layer-3243a14fc9 = Katmandan
|
||||
catalog-by-style-4697cfbbbf = Stile göre
|
||||
catalog-byblock-a5106d0575 = Bloğa Göre
|
||||
catalog-bylayer-c668f6e29f = Katmana Göre
|
||||
catalog-byblock-a5106d0575 = Bloktan
|
||||
catalog-bylayer-c668f6e29f = Katmandan
|
||||
catalog-c-class-dffdc6893e = C++ Sınıfı
|
||||
catalog-cad-application-for-architecture-engineering-79b5234416 = Mimarlık ve mühendislik için CAD uygulaması
|
||||
catalog-cal-expression-e-g-2-3-4-9d91f1992e = CAL İfade (ör. (2+3)*4):
|
||||
@@ -604,7 +604,7 @@ catalog-chamfer-enter-second-chamfer-distance-d2-2de574d864 = CHAMFER İkinci p
|
||||
catalog-chamfer-select-first-line-d1-d1-d2-d2-3c27011b33 = CHAMFER Birinci çizgiyi seçin [D1=__ocs_arg_d1__ D2=__ocs_arg_d2__]:
|
||||
catalog-chamfer-select-second-line-d1-d1-d2-d2-f2857f4ba8 = CHAMFER İkinci çizgiyi seçin [D1=__ocs_arg_d1__ D2=__ocs_arg_d2__]:
|
||||
catalog-chamfer-select-the-adjacent-polyline-segment-d-0380882c9b = CHAMFER Bitişik çoklu çizgi parçasını seçin [D1=__ocs_arg_d1__ D2=__ocs_arg_d2__]:
|
||||
catalog-chprop-new-colour-name-1-255-bylayer-93afe25036 = CHPROP Yeni renk (ad / 1-255 / Katmana Göre):
|
||||
catalog-chprop-new-colour-name-1-255-bylayer-93afe25036 = CHPROP Yeni renk (ad / 1-255 / Katmandan):
|
||||
catalog-chprop-new-layer-name-f0d35963a9 = CHPROP Yeni katman adı:
|
||||
catalog-chprop-new-linetype-name-45684c2bb8 = CHPROP Yeni çizgi tipi adı:
|
||||
catalog-chprop-new-linetype-scale-6c8dca5d8e = CHPROP Yeni çizgi tipi ölçeği:
|
||||
@@ -633,7 +633,7 @@ catalog-clayer-new-current-layer-name-f0f6991d49 = CLAYER Yeni geçerli katman
|
||||
catalog-clayer-cur-968bad6379 = CLAYER = "__ocs_fmt_0__"
|
||||
catalog-clayer-set-to-name-arg-c1045e6576 = CLAYER "__ocs_fmt_0__" olarak ayarlandı.
|
||||
catalog-clayer-layer-not-found-fb5d0a4e1f = CLAYER: '__ocs_fmt_0__' katmanı bulunamadı.
|
||||
catalog-color-new-object-colour-bylayer-byblock-1-255-fb9a12e441 = COLOR Yeni nesne rengi [Katmana Göre / Bloğa Göre / 1-255 / kırmızı / sarı / yeşil / camgöbeği / mavi / macenta / beyaz]:
|
||||
catalog-color-new-object-colour-bylayer-byblock-1-255-fb9a12e441 = COLOR Yeni nesne rengi [Katmandan / Bloktan / 1-255 / kırmızı / sarı / yeşil / camgöbeği / mavi / macenta / beyaz]:
|
||||
catalog-colorscheme-unknown-theme-type-colorscheme-lis-8bb80164f7 = COLORSCHEME: bilinmeyen tema '__ocs_fmt_0__'. Seçenekler için COLORSCHEME LIST yazın.
|
||||
catalog-convtosurface-converted-n-solid-s-to-surface-s-1f4c640ada = CONVTOSURFACE: __ocs_fmt_0__ katı yüzeye dönüştürüldü.
|
||||
catalog-convtosurface-select-a-solid-created-this-sess-8a3ac96200 = CONVTOSURFACE: bu oturumda oluşturulmuş bir katı seçin.
|
||||
@@ -1447,7 +1447,7 @@ catalog-line-specify-first-point-c01dd86573 = LINE İlk noktayı belirtin:
|
||||
catalog-line-specify-next-point-close-undo-2db6e2e095 = LINE Sonraki noktayı belirtin [Kapat/Geri Al]:
|
||||
catalog-line-specify-next-point-undo-ade411d556 = LINE Sonraki noktayı belirtin [Geri Al]:
|
||||
catalog-linetype-list-set-4a097128f4 = LINETYPE [Listele / Ayarla]:
|
||||
catalog-linetype-set-linetype-name-bylayer-byblock-08f8a9af56 = LINETYPE SET Çizgi tipi adı (Katmana Göre / Bloğa Göre / …):
|
||||
catalog-linetype-set-linetype-name-bylayer-byblock-08f8a9af56 = LINETYPE SET Çizgi tipi adı (Katmandan / Bloktan / …):
|
||||
catalog-linetype-name-is-not-loaded-use-linetype-list-6299789ccf = LINETYPE: "__ocs_fmt_0__" yüklü değil. Kullanılabilir çizgi tipleri için LINETYPE LIST komutunu kullanın.
|
||||
catalog-list-no-entities-selected-select-entities-firs-84fa189d6b = LIST: Nesne seçilmedi. Önce nesneleri seçin.
|
||||
catalog-loft-select-first-cross-section-53660582e4 = LOFT İlk kesiti seçin:
|
||||
@@ -2314,7 +2314,7 @@ catalog-section-solid-modelling-is-unavailable-in-this-da202cedf5 = SECTION: Bu
|
||||
catalog-section-the-plane-does-not-cross-the-solid-dbf07e9f4b = SECTION: Düzlem katıyı kesmiyor.
|
||||
catalog-selectall-object-s-selected-1f84d4cdcd = SELECTALL: __ocs_fmt_0__ nesne seçildi.
|
||||
catalog-selhandles-no-entities-selected-select-entitie-4a7c8d016c = SELHANDLES: Nesne seçilmedi. Önce nesneleri seçin.
|
||||
catalog-setbylayer-reset-changed-entity-entities-to-by-a875faf5fc = SETBYLAYER: __ocs_fmt_0__ nesne Katmana Göre olarak sıfırlandı.
|
||||
catalog-setbylayer-reset-changed-entity-entities-to-by-a875faf5fc = SETBYLAYER: __ocs_fmt_0__ nesne Katmandan özelliklerine sıfırlandı.
|
||||
catalog-setbylayer-select-entities-first-07cb922ea6 = SETBYLAYER: Önce nesneleri seçin.
|
||||
catalog-setvar-new-value-blank-to-read-99412ea9e4 = SETVAR Yeni değer (okumak için boş bırakın):
|
||||
catalog-setvar-variable-name-c09f71bfdc = SETVAR Değişken adı:
|
||||
@@ -3225,7 +3225,7 @@ dimstyle-when-text-is-moved = Metin taşındığında
|
||||
dimstyle-zero-suppression = Sıfırları gizleme
|
||||
dimstyle-add-a-leader = Kılavuz ekle
|
||||
dimstyle-automatic = Otomatik
|
||||
dimstyle-by-block = Bloğa göre
|
||||
dimstyle-by-block = Bloktan
|
||||
dimstyle-comma = Virgül
|
||||
dimstyle-degrees-minutes-seconds = Derece, dakika, saniye
|
||||
dimstyle-keep-dimension-line-with-text = Ölçü çizgisini metinle birlikte taşı
|
||||
|
||||
@@ -2738,6 +2738,10 @@ fn start_page_content<'a>(
|
||||
Space::new().height(iced::Length::Fixed(12.0)),
|
||||
]
|
||||
.spacing(6)
|
||||
.padding(iced::Padding {
|
||||
right: 12.0,
|
||||
..iced::Padding::ZERO
|
||||
})
|
||||
.width(Fill);
|
||||
for (name, cents) in patrons {
|
||||
// Cents → the campaign currency's main unit. Symbol assumed "$";
|
||||
|
||||
+58
-2
@@ -60,12 +60,18 @@ pub fn fetch_patrons() -> Result<Vec<(String, i64)>, String> {
|
||||
let mut patrons: Vec<(String, i64)> = Vec::new();
|
||||
let mut url = format!(
|
||||
"https://www.patreon.com/api/oauth2/v2/campaigns/{campaign_id}/members\
|
||||
?fields%5Bmember%5D=full_name,patron_status,currently_entitled_amount_cents\
|
||||
?include=pledge_history\
|
||||
&fields%5Bmember%5D=full_name,patron_status,currently_entitled_amount_cents\
|
||||
&fields%5Bpledge-event%5D=amount_cents,date,payment_status\
|
||||
&page%5Bcount%5D=200"
|
||||
);
|
||||
// Bound the loop so a malformed `next` link can never spin forever.
|
||||
for _ in 0..50 {
|
||||
let page = get_json(&agent, token, &url)?;
|
||||
let included = page["included"]
|
||||
.as_array()
|
||||
.map(Vec::as_slice)
|
||||
.unwrap_or(&[]);
|
||||
if let Some(arr) = page["data"].as_array() {
|
||||
for m in arr {
|
||||
let attrs = &m["attributes"];
|
||||
@@ -75,7 +81,15 @@ pub fn fetch_patrons() -> Result<Vec<(String, i64)>, String> {
|
||||
if attrs["patron_status"].as_str() != Some("active_patron") {
|
||||
continue;
|
||||
}
|
||||
let cents = attrs["currently_entitled_amount_cents"].as_i64().unwrap_or(0);
|
||||
// The entitlement can retain the previous tier amount after a
|
||||
// pledge change. The latest successful pledge event records
|
||||
// what was actually paid; retain the entitlement as a fallback
|
||||
// for memberships whose history is unavailable.
|
||||
let cents = latest_paid_amount(m, included).unwrap_or_else(|| {
|
||||
attrs["currently_entitled_amount_cents"]
|
||||
.as_i64()
|
||||
.unwrap_or(0)
|
||||
});
|
||||
if cents <= 0 {
|
||||
continue;
|
||||
}
|
||||
@@ -96,6 +110,48 @@ pub fn fetch_patrons() -> Result<Vec<(String, i64)>, String> {
|
||||
Ok(patrons)
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn latest_paid_amount(
|
||||
member: &serde_json::Value,
|
||||
included: &[serde_json::Value],
|
||||
) -> Option<i64> {
|
||||
let history = member["relationships"]["pledge_history"]["data"].as_array()?;
|
||||
let mut latest: Option<(String, i64)> = None;
|
||||
|
||||
for relationship in history {
|
||||
let Some(id) = relationship["id"].as_str() else {
|
||||
continue;
|
||||
};
|
||||
let Some(resource_type) = relationship["type"].as_str() else {
|
||||
continue;
|
||||
};
|
||||
let Some(event) = included.iter().find(|entry| {
|
||||
entry["id"].as_str() == Some(id)
|
||||
&& entry["type"].as_str() == Some(resource_type)
|
||||
}) else {
|
||||
continue;
|
||||
};
|
||||
let attrs = &event["attributes"];
|
||||
if attrs["payment_status"].as_str() != Some("Paid") {
|
||||
continue;
|
||||
}
|
||||
let cents = attrs["amount_cents"].as_i64().unwrap_or(0);
|
||||
if cents <= 0 {
|
||||
continue;
|
||||
}
|
||||
let date = attrs["date"].as_str().unwrap_or("");
|
||||
if latest
|
||||
.as_ref()
|
||||
.map(|(current, _)| date > current.as_str())
|
||||
.unwrap_or(true)
|
||||
{
|
||||
latest = Some((date.to_string(), cents));
|
||||
}
|
||||
}
|
||||
|
||||
latest.map(|(_, cents)| cents)
|
||||
}
|
||||
|
||||
/// Web build: the browser can't call the Patreon API directly (CORS + the
|
||||
/// token would be exposed in the bundle), so it fetches a pre-generated
|
||||
/// `supporters.json` published next to the app on the same origin (produced by
|
||||
|
||||
Reference in new issue
Block a user