Skip to content

Commit

Permalink
feat: Sync settings and stock per-project
Browse files Browse the repository at this point in the history
  • Loading branch information
aklinker1 committed Apr 30, 2024
1 parent 0adc5a5 commit 5ba0b94
Show file tree
Hide file tree
Showing 34 changed files with 347 additions and 193 deletions.
2 changes: 1 addition & 1 deletion web/components/BomTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { BoardLayoutLeftover } from '@aklinker1/cutlist';
const url = useAssemblyUrl();
const { data: doc } = useDocumentQuery(url);
const { data, isLoading } = useBoardLayoutsQuery();
const distanceUnit = useDistanceUnit();
const { distanceUnit } = useProjectSettings();
const formatDistance = useFormatDistance();
const rows = computed(() => {
Expand Down
2 changes: 1 addition & 1 deletion web/components/PartListItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const fontSize = usePx(() =>
),
);
const showPartNumbers = useShowPartNumbers();
const { showPartNumbers } = useProjectSettings();
</script>

<template>
Expand Down
16 changes: 7 additions & 9 deletions web/components/ProjectSidebar.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
<script lang="ts" setup>
import type { HorizontalNavigationLink } from '#ui/types';
const url = useAssemblyUrl();
const { data: doc } = useDocumentQuery();
const { isFetching: isFetchingLayouts } = useBoardLayoutsQuery();
const { data: boardLayouts } = useBoardLayoutsQuery();
const { data: boardLayouts, isFetching: isFetchingLayouts } =
useBoardLayoutsQuery();
const refresh = useRefreshOnshapeQueries();
const warningsBadge = computed(() => {
Expand All @@ -21,10 +19,10 @@ const links = computed<HorizontalNavigationLink[]>(() => [
click: () => void (tab.value = 'bom'),
},
{
label: 'Stock',
icon: 'i-heroicons-truck',
active: tab.value === 'stock',
click: () => void (tab.value = 'stock'),
label: 'Boards',
icon: 'i-fluent-emoji-high-contrast-wood',
active: tab.value === 'boards',
click: () => void (tab.value = 'boards'),
},
{
label: 'Warnings',
Expand Down Expand Up @@ -92,7 +90,7 @@ const editProject = useEditProject();
<div class="relative flex-1">
<div class="absolute inset-0 overflow-auto">
<BomTab v-if="tab === 'bom'" />
<StockTab v-else-if="tab === 'stock'" />
<StockTab v-else-if="tab === 'boards'" />
<WarningsTab v-else-if="tab === 'warnings'" class="p-8" />
<SettingsTab v-else-if="tab === 'settings'" class="p-8" />
</div>
Expand Down
53 changes: 39 additions & 14 deletions web/components/SettingsTab.vue
Original file line number Diff line number Diff line change
@@ -1,33 +1,55 @@
<script lang="ts" setup>
import { Distance } from '@aklinker1/cutlist';
const optimize = useOptimizeForSetting();
const bladeWidth = useBladeWidthSetting();
const distanceUnit = useDistanceUnit();
const showPartNumbers = useShowPartNumbers();
const extraSpace = useExtraSpaceSetting();
const {
bladeWidth,
distanceUnit,
extraSpace,
optimize,
showPartNumbers,
isLoading,
changes,
resetSettings: resetLocal,
} = useProjectSettings();
// Convert values when units change
watch(distanceUnit, (newUnit, oldUnit) => {
if (!newUnit || !oldUnit) return;
const convertValue = (value: Ref<string | number>) => {
const convertDistance = (value: Ref<string | number | undefined>) => {
if (value.value == null) return;
const dist = new Distance(value.value + oldUnit);
value.value = dist[newUnit];
};
convertValue(bladeWidth);
convertValue(extraSpace);
convertDistance(bladeWidth);
convertDistance(extraSpace);
});
const projectId = useProjectId();
const { mutate: _save, isPending: isSaving } = useSetSettingsMutation();
function save() {
_save({
projectId: projectId.value,
changes: toRaw(changes.value),
});
}
const { mutate: _reset, isPending: isResetting } = useDeleteSettingsMutation();
function reset() {
_reset(projectId.value, {
onSettled: () => resetLocal(),
});
}
</script>

<template>
<div class="flex flex-col gap-4">
<form v-if="!isLoading" class="flex flex-col gap-4" @submit.prevent="save">
<UFormGroup label="Distance unit">
<USelect v-model="distanceUnit" :options="['in', 'm', 'mm']" />
</UFormGroup>

<UFormGroup :label="`Blade width (${distanceUnit}):`">
<UInput v-model="bladeWidth" type="number" />
<UInput v-model="bladeWidth" type="number" min="0" step="0.00001" />
</UFormGroup>

<UFormGroup :label="`Extra space (${distanceUnit}):`">
Expand All @@ -40,8 +62,11 @@ watch(distanceUnit, (newUnit, oldUnit) => {

<UCheckbox v-model="showPartNumbers" label="Show part numbers in preview" />

<p class="text-sm opacity-50 text-center pt-8">
Settings are saved when returning to the website.
</p>
</div>
<div class="flex flex-row-reverse gap-4">
<UButton type="submit" :loading="isSaving">Save Changes</UButton>
<UButton color="gray" :loading="isResetting" @click="reset"
>Reset</UButton
>
</div>
</form>
</template>
70 changes: 36 additions & 34 deletions web/components/StockMatrixInput.vue
Original file line number Diff line number Diff line change
@@ -1,46 +1,48 @@
<script lang="ts" setup>
import { StockMatrix } from '@aklinker1/cutlist';
import { z } from 'zod';
import YAML from 'js-yaml';
import { reduceStockMatrix } from '@aklinker1/cutlist';
const model = defineModel<StockMatrix[]>();
const value = defineModel<string>({ required: true });
const getModelString = () =>
YAML.dump(model.value, { indent: 2, flowLevel: 2 });
const text = ref(getModelString());
const internalValue = ref(value.value);
onMounted(() => {
internalValue.value = value.value;
});
const textModel = computed<string>({
get() {
return text.value;
},
set(value) {
const parseStock = useParseStock();
const err = ref<unknown>();
watchThrottled(
internalValue,
(internalValue) => {
try {
text.value = value;
model.value = z.array(StockMatrix).parse(YAML.load(value));
error.value = undefined;
} catch (err) {
error.value = err;
console.log(1);
const stock = reduceStockMatrix(parseStock(internalValue));
console.log(2, stock);
value.value = internalValue;
err.value = undefined;
} catch (error) {
err.value = error;
console.error(error);
}
},
});
const error = ref<unknown>();
{
throttle: 500,
leading: false,
trailing: true,
},
);
</script>

<template>
<div class="absolute inset-0 flex flex-col p-4 overlfow-auto gap-4">
<textarea
v-model="textModel"
class="font-mono flex-1 resize-none bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-700 p-4 outline-none rounded-lg whitespace-pre"
/>
<div
v-if="error"
class="bg-red-900 shrink-0 p-4 rounded-lg border border-red-600"
>
<p class="text-white whitespace-pre-wrap">
{{ error }}
</p>
</div>
<textarea
v-model="internalValue"
class="font-mono flex-1 resize-none bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-700 p-4 outline-none rounded-lg whitespace-pre"
/>
<div
v-if="err"
class="bg-red-900 shrink-0 p-4 rounded-lg border border-red-600"
>
<p class="text-white whitespace-pre-wrap">
{{ err }}
</p>
</div>
</template>
30 changes: 27 additions & 3 deletions web/components/StockTab.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,33 @@
<script lang="ts" setup>
const { data } = useBoardLayoutsQuery();
const { stock, resetStock } = useProjectSettings();
const stock = useStock();
const projectId = useProjectId();
const { mutate: _save, isPending: isSaving } = useSetSettingsMutation();
function save() {
console.log('SAVING...');
_save({
projectId: projectId.value,
changes: { stock: stock.value },
});
}
const { mutate: _reset, isPending: isResetting } = useDeleteSettingsMutation();
function reset() {
_reset(projectId.value, {
onSettled: () => resetStock(),
});
}
</script>

<template>
<StockMatrixInput v-model="stock" />
<div class="absolute inset-0 flex flex-col p-4 gap-4">
<StockMatrixInput v-if="stock != null" v-model="stock" />

<div class="shrink-0 flex flex-row-reverse gap-4">
<UButton type="submit" :loading="isSaving" @click="save">Save</UButton>
<UButton color="gray" :loading="isResetting" @click="reset"
>Reset</UButton
>
</div>
</div>
</template>
10 changes: 0 additions & 10 deletions web/composables/useBladeWidth.ts

This file was deleted.

8 changes: 0 additions & 8 deletions web/composables/useBladeWidthSetting.ts

This file was deleted.

29 changes: 24 additions & 5 deletions web/composables/useBoardLayoutsQuery.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import { useQuery } from '@tanstack/vue-query';
import { generateBoardLayouts } from '@aklinker1/cutlist';
import {
Distance,
generateBoardLayouts,
type Config,
} from '@aklinker1/cutlist';

export default function () {
const loader = useOnshapeLoader();
const url = useAssemblyUrl();
const config = useCutlistConfig();
const stock = useStock();
const { bladeWidth, optimize, extraSpace, distanceUnit, stock } =
useProjectSettings();
const parseStock = useParseStock();

const partsQuery = useQuery({
queryKey: ['onshape', 'board-layouts', url],
Expand All @@ -15,9 +20,23 @@ export default function () {

const layouts = computed(() => {
const parts = partsQuery.data.value;
if (parts == null) return undefined;
if (
parts == null ||
bladeWidth.value == null ||
extraSpace.value == null ||
optimize.value == null ||
distanceUnit.value == null ||
stock.value == null
)
return;

return generateBoardLayouts(toRaw(parts), stock.value, config.value);
const config: Config = {
bladeWidth: new Distance(bladeWidth.value + distanceUnit.value).m,
extraSpace: new Distance(extraSpace.value + distanceUnit.value).m,
optimize: optimize.value === 'Cuts' ? 'cuts' : 'space',
precision: 1e-5,
};
return generateBoardLayouts(toRaw(parts), parseStock(stock.value), config);
});

return {
Expand Down
14 changes: 0 additions & 14 deletions web/composables/useCutlistConfig.ts

This file was deleted.

17 changes: 17 additions & 0 deletions web/composables/useDeleteSettingsMutation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useMutation, useQueryClient } from '@tanstack/vue-query';

export default function () {
const accountService = useAccountService();
const client = useQueryClient();

return useMutation({
mutationFn(projectId: string | undefined) {
return accountService.value.deleteSettings(projectId);
},
onSettled() {
client.invalidateQueries({
queryKey: ['settings'],
});
},
});
}
3 changes: 0 additions & 3 deletions web/composables/useDistanceUnit.ts

This file was deleted.

10 changes: 0 additions & 10 deletions web/composables/useExtraSpace.ts

This file was deleted.

8 changes: 0 additions & 8 deletions web/composables/useExtraSpaceSetting.ts

This file was deleted.

Loading

0 comments on commit 5ba0b94

Please sign in to comment.